DIRECTORY Basics USING [LongNumber, SwapHalves], CrRPC USING [Error, Handle, CreateClientHandle, DestroyClientHandle], IO, RapunzelP2200V3, Rope USING [Equal, ROPE], SoftcardOps, SoftcardPrivate, XNS USING [Address, GetThisHost, unknownSocket], XNSCH USING [LookupAddressFromRope]; SoftcardOpsImpl: CEDAR PROGRAM IMPORTS Basics, CrRPC, IO, RapunzelP2200V3, Rope, XNS, XNSCH EXPORTS SoftcardOps = BEGIN OPEN SoftcardPrivate, Rapunzel: RapunzelP2200V3; ROPE: TYPE = Rope.ROPE; Addr: TYPE = SoftcardOps.Addr; Rcmo: TYPE = Rapunzel.CmdObject; EUPBusCmd: TYPE = SoftcardOps.EUPBusCmd; -- tbd IFUPBusCmd: TYPE = SoftcardOps.IFUPBusCmd; EUInternal: TYPE = SoftcardOps.EUInternal; EURegister: TYPE = SoftcardOps.EURegister; IFUInternalState: TYPE = SoftcardOps.IFUInternalState; -- tbd ClockControl: TYPE = SoftcardOps.ClockControl; DragonPhase: TYPE = SoftcardOps.DragonPhase; 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; numEUBits: CARD16 = 32; readEUSeq: Rapunzel.SeqCmd; writeEUSeq: Rapunzel.SeqCmd; numIFUBits: CARD16 = 488; readIFUSeq: Rapunzel.SeqCmd; writeIFUSeq: Rapunzel.SeqCmd; resetBoardSeq: Rapunzel.SeqCmd; SCError: PUBLIC SIGNAL[code: ATOM, explanation: ROPE _ NIL] = CODE; EstablishConnection: PUBLIC PROC[host: ROPE] RETURNS[ok: BOOL] = { Ec: PROC = { netAddr: XNS.Address; refNet: REF XNS.Address; IF host.Equal["ME"] THEN netAddr _ [net: [[0,0], [0,3]], host: XNS.GetThisHost[], socket: XNS.unknownSocket ] ELSE { netAddr _ XNSCH.LookupAddressFromRope[host].address; netAddr.socket _ XNS.unknownSocket; }; refNet _ NEW[ XNS.Address _ [netAddr.net, netAddr.host, netAddr.socket] ]; crHandle _ CrRPC.CreateClientHandle[$SPP, refNet]; Rapunzel.SetShftAddrs[crHandle, DebugShiftA, DebugShiftB]; }; CarefullyApply[proc: Ec, nilHandleOK: TRUE]; RETURN[crHandle # NIL]; }; CloseConnection: PUBLIC PROC = { IF crHandle = NIL THEN RETURN; 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] = { user: FullWordifuPBusCmd = LOOPHOLE[ReadShort[SpyCmd2]]; most: FullWordeuPBusCmd = LOOPHOLE[ReadShort[SpyCmd1]]; euPBusCmd.userMode _ user.userMode; euPBusCmd.unspecifiedAsYet _ most.unspecifiedAsYet; }; ReadIFUCmd: PUBLIC PROC RETURNS[ifuPBusCmd: IFUPBusCmd] = { ifuPBusCmd _ LOOPHOLE[ReadShort[SpyCmd2], FullWordifuPBusCmd].ifuPBusCmd }; ReadEUPBusData: PUBLIC PROC RETURNS[value: CARD32] = { value _ ReadLong[SpyEUDataH] }; ReadIFUPBusData: PUBLIC PROC RETURNS[value: CARD32] = { value _ ReadLong[SpyIFUDataH] }; ReadClock: PUBLIC PROC RETURNS[value: CARD32] = { value _ ReadLong[ClockH] }; ReadEURegister: PUBLIC PROC[which: EUInternal] RETURNS[value: CARD32] = { resultSeq: Rapunzel.SeqResult; theBits: PACKED ARRAY [0..32) OF OneBit; seqIndex: CARD16 _ 0; resIndex: CARD16 _ 0; debugInfo: DebugInfoEntry; setEUAddr: Rapunzel.PokeShortCmd; Reur: PROC = { resultSeq _ Rapunzel.DoCmds[crHandle, readEUSeq] }; debugInfo.debugEUAddr _ ORD[which]; setEUAddr.address _ SoftcardPrivate.DebugInfo; setEUAddr.value _ LOOPHOLE[debugInfo]; IF readEUSeq = NIL THEN readEUSeq _ ConstructReadSeq[isEU: TRUE]; TRUSTED { readEUSeq[2] _ NEW[ Rcmo _ [pokeShort[setEUAddr]] ] }; CarefullyApply[Reur]; WHILE seqIndex < resultSeq.length DO res: Rapunzel.Result = resultSeq.body[seqIndex]; one: Rapunzel.Result; WITH res: res SELECT FROM shftRead => { FOR resIndex IN [0..res.shftRead.numRepeats) DO seqIndex _ seqIndex + 1; TRUSTED { one _ resultSeq.body[seqIndex] }; WITH one: one SELECT FROM peekShort => { dI: StatusBits = LOOPHOLE[one.peekShort.value]; theBits[resIndex] _ dI.dOutEU; }; ENDCASE => NULL; ENDLOOP; }; ENDCASE => seqIndex _ seqIndex + 1; ENDLOOP; value _ LOOPHOLE[Basics.SwapHalves[LOOPHOLE[theBits]]]; }; WriteEURegister: PUBLIC PROC[which: EUInternal, value: CARD32] = { theBits: PACKED ARRAY [0..32) OF OneBit; seqIndex: CARD16 _ 0; debugInfo: DebugInfoEntry; setEUAddr: Rapunzel.PokeShortCmd; one: Rapunzel.PokeShortCmd; Weur: PROC = { [] _ Rapunzel.DoCmds[crHandle, writeEUSeq] }; theBits _ LOOPHOLE[Basics.SwapHalves[LOOPHOLE[value]]]; debugInfo.debugEUAddr _ ORD[which]; setEUAddr.address _ SoftcardPrivate.DebugInfo; setEUAddr.value _ LOOPHOLE[debugInfo]; one.address _ DebugWriteEU; IF writeEUSeq = NIL THEN writeEUSeq _ ConstructWriteSeq[isEU: TRUE]; TRUSTED { writeEUSeq[1] _ NEW[ Rcmo _ [pokeShort[setEUAddr] ]] }; WHILE seqIndex < writeEUSeq.length DO this: Rapunzel.Cmd = writeEUSeq.body[seqIndex]; one: Rapunzel.PokeShortCmd; WITH this: this SELECT FROM shftWrite => { FOR valIndex: CARD16 IN [0..this.shftWrite.numRepeats) DO seqIndex _ seqIndex + 1; debugInfo.debugInEU _ theBits[valIndex]; one.value _ LOOPHOLE[debugInfo]; TRUSTED { writeEUSeq.body[seqIndex] _ NEW[ Rcmo _ [pokeShort[one]] ] }; ENDLOOP; }; ENDCASE => seqIndex _ seqIndex + 1; ENDLOOP; CarefullyApply[Weur]; }; ReadIFUState: PUBLIC PROC RETURNS[ifuState: IFUInternalState] = { resultSeq: Rapunzel.SeqResult; seqIndex: CARD16 _ 0; resIndex: CARD16 _ 0; Rifu: PROC = { resultSeq _ Rapunzel.DoCmds[crHandle, readIFUSeq] }; IF readIFUSeq = NIL THEN readIFUSeq _ ConstructReadSeq[isEU: FALSE]; CarefullyApply[Rifu]; WHILE seqIndex < resultSeq.length DO res: Rapunzel.Result = resultSeq.body[seqIndex]; one: Rapunzel.Result; WITH res: res SELECT FROM shftRead => { FOR resIndex IN [0..res.shftRead.numRepeats) DO seqIndex _ seqIndex + 1; TRUSTED { one _ resultSeq.body[seqIndex] }; WITH one: one SELECT FROM peekShort => ifuState[resIndex] _ one.peekShort.value; ENDCASE => NULL; ENDLOOP; }; ENDCASE => seqIndex _ seqIndex + 1; ENDLOOP; }; WriteIFUState: PUBLIC PROC[ifuState: IFUInternalState] = { seqIndex: CARD16 _ 0; one: Rapunzel.PokeShortCmd; Wifu: PROC = { [] _ Rapunzel.DoCmds[crHandle, writeIFUSeq] }; one.address _ DebugWriteIFU; IF writeIFUSeq = NIL THEN writeIFUSeq _ ConstructWriteSeq[isEU: FALSE]; WHILE seqIndex < writeEUSeq.length DO this: Rapunzel.Cmd = writeIFUSeq.body[seqIndex]; one: Rapunzel.PokeShortCmd; WITH this: this SELECT FROM shftWrite => { FOR valIndex: CARD16 IN [0..this.shftWrite.numRepeats) DO seqIndex _ seqIndex + 1; one.value _ ifuState[valIndex]; TRUSTED { writeEUSeq.body[seqIndex] _ NEW[Rcmo _ [pokeShort[one]] ] }; ENDLOOP; }; ENDCASE => seqIndex _ seqIndex + 1; ENDLOOP; CarefullyApply[Wifu]; }; 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, CARD16]] }; CarefullyApply[Wcc]; }; ReadControlBit: PUBLIC PROC[which: ControlBit] RETURNS[current: BOOL] = { isControl1: BOOL = IsControl1[which]; value: CARD16 = ReadShort[IF isControl1 THEN Consult1 ELSE Consult2]; RETURN[ReturnBit[which, isControl1, value]]; }; SetControlBit: PUBLIC PROC[which: ControlBit] RETURNS[previous: BOOL] = { value: CARD16 = ReadShort[GetControlResetAddr[which] + 2]; RETURN[ReturnBit[which, IsControl1[which], value]]; }; ResetControlBit: PUBLIC PROC[which: ControlBit] RETURNS[previous: BOOL] = { value: CARD16 = ReadShort[GetControlResetAddr[which]]; RETURN[ReturnBit[which, IsControl1[which], value]]; }; ResetIFUCacheStateMachine: PUBLIC PROC = { [] _ ReadShort[CasIFUCacheStateMachine]; [] _ ReadShort[CarIFUCacheStateMachine]; }; ResetEUCacheStateMachine: PUBLIC PROC = { [] _ ReadShort[CasEUCacheStateMachine]; [] _ ReadShort[CarEUCacheStateMachine]; }; DisableIFUCache: PUBLIC PROC = { [] _ ReadShort[CarNotResetIFUCache] }; DisableEUCache: PUBLIC PROC = { [] _ ReadShort[CarNotResetEUCache] }; FlushIFUCache: PUBLIC PROC = { [] _ ReadShort[CarNotResetIFUCache]; [] _ ReadShort[CasNotResetIFUCache] }; FlushEUCache: PUBLIC PROC = { [] _ ReadShort[CarNotResetEUCache]; [] _ ReadShort[CasNotResetEUCache] }; DragonHaltInPhase: PUBLIC PROC[phase: DragonPhase _ phaseA] = { isBetween: BOOL; currentPhase: DragonPhase _ phaseA; NextOf: PROC[current: DragonPhase] RETURNS[DragonPhase] = { IF current = LAST[DragonPhase] THEN RETURN[FIRST[DragonPhase]]; RETURN[SUCC[current]]; }; [] _ ReadShort[CarDragonRun]; -- stop if running, noop if stopped IF (currentPhase _ CurrentDragonPhase[].phase) = phase THEN RETURN; -- we got lucky IF (isBetween _ ReadControlBit[dragonStep]) THEN { [] _ ReadShort[CarDragonStep]; IF (currentPhase _ NextOf[currentPhase]) = phase THEN RETURN; [] _ ReadShort[CasDragonStep]; IF (currentPhase _ NextOf[currentPhase]) = phase THEN RETURN; [] _ ReadShort[CarDragonStep]; } ELSE { [] _ ReadShort[CasDragonStep]; IF (currentPhase _ NextOf[currentPhase]) = phase THEN RETURN; [] _ ReadShort[CarDragonStep]; IF (currentPhase _ NextOf[currentPhase]) = phase THEN RETURN; [] _ ReadShort[CasDragonStep]; }; }; DragonStep: PUBLIC PROC[which: SoftcardOps.DragonStepSize] RETURNS[ok: BOOL] = { IF ReadControlBit[dragonRun] THEN RETURN[FALSE]; -- dragon is running IF ReadControlBit[dragonStep] THEN { [] _ ReadShort[CarDragonStep]; IF which = quarter THEN RETURN[TRUE]; [] _ ReadShort[CasDragonStep]; IF which = half THEN RETURN[TRUE]; [] _ ReadShort[CarDragonStep]; [] _ ReadShort[CasDragonStep]; } ELSE { [] _ ReadShort[CasDragonStep]; IF which = quarter THEN RETURN[TRUE]; [] _ ReadShort[CarDragonStep]; IF which = half THEN RETURN[TRUE]; [] _ ReadShort[CasDragonStep]; [] _ ReadShort[CarDragonStep]; }; RETURN[TRUE]; }; CurrentDragonPhase: PUBLIC PROC RETURNS[phase: DragonPhase, ok: BOOL] = { isPhaseA: BOOL; isBetween: BOOL; IF ReadControlBit[dragonRun] THEN RETURN[phaseA, FALSE]; -- dragon is running isBetween _ ReadControlBit[dragonStep]; isPhaseA _ ReadStatusBit[phaseA]; SELECT TRUE FROM isPhaseA AND ~isBetween => phase _ phaseA; isPhaseA AND isBetween => phase _ betweenAandB; ~isPhaseA AND ~isBetween => phase _ phaseB; ~isPhaseA AND isBetween => phase _ betweenBandA; ENDCASE => RETURN[phaseA, FALSE]; RETURN[phase, TRUE]; }; DragonRun: PUBLIC PROC = { [] _ ReadShort[CasDragonRun] }; DragonStop: PUBLIC PROC = { [] _ ReadShort[CarDragonRun] }; ResetClock: PUBLIC PROC = { [] _ ReadShort[CarNotResetClock]; [] _ ReadShort[CasNotResetClock]; }; ResetBoard: PUBLIC PROC = { cc: ClockControl = [reserved: 0, freqSelect: 3, phaseAdjust: 7, delay: 7]; Rb: PROC = { [] _ Rapunzel.DoCmds[crHandle, resetBoardSeq]; Rapunzel.PokeShort[crHandle, ClockControlAddr, LOOPHOLE[cc, CARD16]]; }; IF resetBoardSeq = NIL THEN { psCmd: Rapunzel.PeekShortCmd _ [CarDragonRun]; resetBoardSeq _ NEW[Rapunzel.SeqCmdObject[18]]; resetBoardSeq[0] _ NEW[Rcmo _ [peekShort[psCmd]] ]; resetBoardSeq[1] _ NEW[Rcmo _ [peekShort[psCmd _ [CarDragon+2]] ] ]; resetBoardSeq[2] _ NEW[Rcmo _ [peekShort[psCmd _ [CasIFUCacheStateMachine]] ] ]; resetBoardSeq[3] _ NEW[Rcmo _ [peekShort[psCmd _ [CasEUCacheStateMachine]] ] ]; resetBoardSeq[4] _ NEW[Rcmo _ [peekShort[psCmd _ [CarNotResetIFUCache]] ] ]; resetBoardSeq[5] _ NEW[Rcmo _ [peekShort[psCmd _ [CarNotResetEUCache]] ] ]; resetBoardSeq[6] _ NEW[Rcmo _ [peekShort[psCmd _ [CarIFUCacheStateMachine]] ] ]; resetBoardSeq[7] _ NEW[Rcmo _ [peekShort[psCmd _ [CarEUCacheStateMachine]] ] ]; resetBoardSeq[8] _ NEW[Rcmo _ [peekShort[psCmd _ [CarInterruptDragonToIOP]] ] ]; resetBoardSeq[9] _ NEW[Rcmo _ [peekShort[psCmd _ [CarInterruptDragonToMesa]] ] ]; resetBoardSeq[10] _ NEW[Rcmo _ [peekShort[psCmd _ [CarIOPIntToDragon]] ] ]; resetBoardSeq[11] _ NEW[Rcmo _ [peekShort[psCmd _ [CarMesaIntToDragon]] ] ]; resetBoardSeq[12] _ NEW[Rcmo _ [peekShort[psCmd _ [CarEnableIFUBkpt]] ] ]; resetBoardSeq[13] _ NEW[Rcmo _ [peekShort[psCmd _ [CarEnableEUBkpt]] ] ]; resetBoardSeq[14] _ NEW[Rcmo _ [peekShort[psCmd _ [CarVirtualMemAccessIFU]] ] ]; resetBoardSeq[15] _ NEW[Rcmo _ [peekShort[psCmd _ [CarVirtualMemAccessEU]] ] ]; resetBoardSeq[16] _ NEW[Rcmo _ [peekShort[psCmd _ [CarVirtualMemAccessIOP]] ] ]; resetBoardSeq[17] _ NEW[Rcmo _ [peekShort[psCmd _ [CarVirtualMemAccessMesa]] ] ]; }; CarefullyApply[Rb]; }; IsControl1: PROC[which: ControlBit] RETURNS[BOOL] = { SELECT which FROM iopIntToDragon, mesaIntToDragon, notResetClock => RETURN[FALSE]; ENDCASE => RETURN[TRUE]; }; GetControlResetAddr: PROC[which: ControlBit] RETURNS[Addr] = { SELECT which FROM resetDragon => RETURN[CarDragon]; interruptDragonToIOP => RETURN[CarInterruptDragonToIOP]; interruptDragonToMesa => RETURN[CarInterruptDragonToMesa]; dragonRun => RETURN[CarDragonRun]; dragonStep => RETURN[CarDragonStep]; writeParity => RETURN[CarWriteParity]; virtualMemAccessIOP => RETURN[CarVirtualMemAccessIOP]; virtualMemAccessMesa => RETURN[CarVirtualMemAccessMesa]; virtualMemAccessIFU => RETURN[CarVirtualMemAccessIFU]; virtualMemAccessEU => RETURN[CarVirtualMemAccessEU]; resetIFUCacheStateMachine => RETURN[CarIFUCacheStateMachine]; notResetIFUCache => RETURN[CarNotResetIFUCache]; ifuBreakpointEnabled => RETURN[CarEnableIFUBkpt]; resetEUCacheStateMachine => RETURN[CarEUCacheStateMachine]; euBreakpointEnabled => RETURN[CarEnableEUBkpt]; notResetEUCache => RETURN[CarEnableEUBkpt]; iopIntToDragon => RETURN[CarIOPIntToDragon]; mesaIntToDragon => RETURN[CarMesaIntToDragon]; notResetClock => RETURN[CarNotResetClock]; ENDCASE => ERROR; }; ReturnBit: PROC[which: ControlBit, isControl1: BOOL, value: CARD16] RETURNS[BOOL] = { control1Bits: Control1Bits; control2Bits: Control2Bits; IF isControl1 THEN control1Bits _ LOOPHOLE[value] ELSE control2Bits _ LOOPHOLE[value]; SELECT which FROM resetDragon => RETURN[control1Bits.resetDragon]; interruptDragonToIOP => RETURN[control1Bits.interruptDragonToIOP]; interruptDragonToMesa => RETURN[control1Bits.interruptDragonToMesa]; dragonRun => RETURN[control1Bits.dragonRun]; dragonStep => RETURN[control1Bits.dragonStep]; writeParity => RETURN[control1Bits.writeParity]; virtualMemAccessIOP => RETURN[control1Bits.virtualMemAccessIOP]; virtualMemAccessMesa => RETURN[control1Bits.virtualMemAccessMesa]; virtualMemAccessIFU => RETURN[control1Bits.virtualMemAccessIFU]; resetIFUCacheStateMachine => RETURN[control1Bits.resetIFUCacheStateMachine]; notResetIFUCache => RETURN[control1Bits.notResetIFUCache]; ifuBreakpointEnabled => RETURN[control1Bits.enableIFUBkpt]; resetEUCacheStateMachine => RETURN[control1Bits.resetEUCacheStateMachine]; notResetEUCache => RETURN[control1Bits.notResetEUCache]; euBreakpointEnabled => RETURN[control1Bits.enableEUBkpt]; virtualMemAccessEU => RETURN[control1Bits.virtualMemAccessEU]; iopIntToDragon => RETURN[control2Bits.iopIntToDragon]; mesaIntToDragon => RETURN[control2Bits.mesaIntToDragon]; notResetClock => RETURN[control2Bits.notResetClock]; 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 phaseA => RETURN[all.phaseA]; periodicIntToDragon => RETURN[all.periodicIntToDragon]; notMemoryError => RETURN[all.notMemoryError]; 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[Car1PeriodicIntToDragon]; notMemoryError => RETURN[Car1NotMemoryError]; euBkptReached => RETURN[Car1EUBrkptReached]; ifuBkptReached => RETURN[Car1IFUBrkptReached]; mapError => RETURN[Car1MapError]; ENDCASE => ERROR; }; MesaMapIndex: TYPE = SoftcardOps.MesaMapIndex; MesaMapEntry: TYPE = SoftcardOps.MesaMapEntry; ReadMesaMap: PUBLIC PROC[index: MesaMapIndex] RETURNS[value: MesaMapEntry] = { RETURN[ LOOPHOLE[ReadShort[MesaMapAddr + 4*LONG[index] + 1], MesaMapEntry] ] }; WriteMesaMap: PUBLIC PROC[index: MesaMapIndex, value: MesaMapEntry] = { WriteShort[MesaMapAddr+4*LONG[index]+1, LOOPHOLE[value, CARD16] ] }; 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, CARD16] ] }; CarefullyApply: PROC[proc: PROC, nilHandleOK: BOOL _ FALSE] = { cText: ROPE; cAtom: ATOM; BEGIN ENABLE BEGIN CrRPC.Error => { cText _ text; cAtom _ $crRPCError; GOTO error; }; Rapunzel.Fault => { SELECT code FROM nonexistent => cText _ IO.PutFR[" Nonexistent address %g\n", IO.card[address] ]; protection => cText _ IO.PutFR[" Protection error for address %g\n", IO.card[address] ]; alignmentShort => cText _ IO.PutFR[" AlignmentShort error for address %g\n", IO.card[address] ]; alignmentLong => cText _ IO.PutFR["AlignmentLong error for addr: %g\n", IO.card[address] ]; ENDCASE => cText _ IO.PutFR["Unknown Rapunzel Fault code for address %g\n", IO.card[address] ]; cAtom _ $RapunzelFault; GOTO error; }; END; IF ~nilHandleOK AND crHandle = NIL THEN SIGNAL SCError[$noConnection, "open a connection first"]; proc[]; EXITS error => SIGNAL SCError[cAtom, cText]; END; }; ReadShort: PUBLIC PROC[addr: Addr] RETURNS[value: CARD16] = { Rs: PROC = { value _ Rapunzel.PeekShort[crHandle, addr] }; CarefullyApply[Rs]; }; WriteShort: PUBLIC PROC[addr: Addr, value: CARD16] = { Ws: PROC = { Rapunzel.PokeShort[crHandle, addr, value] }; CarefullyApply[Ws]; }; ReadLong: PUBLIC PROC[addr: Addr] RETURNS[value: CARD32] = { Rl: PROC = { value _ Rapunzel.PeekLong[crHandle, addr]; }; IF AddrIsOdd[addr] THEN SIGNAL SCError[$RapunzelFault, "alignmentLong"]; CarefullyApply[Rl]; }; WriteLong: PUBLIC PROC[addr: Addr, value: CARD32] = { Wl: PROC = { Rapunzel.PokeLong[crHandle, addr, value]; }; IF AddrIsOdd[addr] THEN SIGNAL SCError[$RapunzelFault, "alignmentLong"]; CarefullyApply[Wl]; }; wmlSeq: Rapunzel.SeqCmd; rl0Cmd: Rapunzel.ReturnLengthCmd = [0]; WriteMultipleLong: PUBLIC PROC[ num: CARD16, proc: PROC RETURNS[addr: Addr, value: CARD32]] = { Wml: PROC = { [] _ Rapunzel.DoCmds[crHandle, wmlSeq]; }; plCmd: Rapunzel.PokeLongCmd; IF wmlSeq = NIL OR wmlSeq.length # num THEN { wmlSeq _ NEW[Rapunzel.SeqCmdObject[num]]; }; FOR i: CARD16 IN [0..num) DO [addr: plCmd.address, value: plCmd.value] _ proc[]; wmlSeq[i] _ NEW[Rcmo _ [pokeLong[plCmd]] ]; ENDLOOP; CarefullyApply[Wml]; }; DumpShort: PUBLIC PROC[addr: Addr, num: CARD16] RETURNS[ss: Rapunzel.SeqShort] = { Ds: PROC = { ss _ Rapunzel.PeekSeqShort[crHandle, addr, num] }; CarefullyApply[Ds]; }; DumpLong: PUBLIC PROC[addr: Addr, num: CARD16] RETURNS[sl: Rapunzel.SeqLong] = { Dl: PROC = { sl _ Rapunzel.PeekSeqLong[crHandle, addr, num]; }; IF AddrIsOdd[addr] THEN SIGNAL SCError[$RapunzelFault, "alignmentLong"]; CarefullyApply[Dl]; }; AddrIsOdd: PROC[addr: Addr] RETURNS[BOOL] = { ln: Basics.LongNumber = LOOPHOLE[addr]; RETURN[ln.bits[15]]; }; ConstructReadSeq: PROC[isEU: BOOL] RETURNS[tSeq: Rapunzel.SeqCmd] = { psDragonRun: Rapunzel.PeekShortCmd = [CarDragonRun]; drEU: Rapunzel.PeekShortCmd = [DebugReadEU]; drIFU: Rapunzel.PeekShortCmd = [DebugReadIFU]; seqLen: CARD16 = IF isEU THEN 5 ELSE 4; -- magic here - overhead rlCmd: Rapunzel.ReturnLengthCmd; srCmd: Rapunzel.ShftReadCmd; IF isEU THEN { srCmd.numRepeats _ numEUBits; rlCmd.returnLength _ numEUBits+4 } ELSE { srCmd.numRepeats _ numIFUBits; rlCmd.returnLength _ numIFUBits+3; }; srCmd.address _ ConsultStatusAddr; tSeq _ NEW[Rapunzel.SeqCmdObject[seqLen]]; TRUSTED { tSeq[0] _ NEW[Rcmo _ [returnLength[rlCmd]] ]; -- how long the result is tSeq[1] _ NEW[Rcmo _ [peekShort[psDragonRun]] ]; -- stop the Dragon first IF isEU THEN { tSeq[3] _ NEW[Rcmo _ [peekShort[drEU]] ]; tSeq[4] _ NEW[Rcmo _ [shftRead[srCmd]] ]; } ELSE { tSeq[2] _ NEW[Rcmo _ [peekShort[drIFU]] ]; tSeq[3] _ NEW[Rcmo _ [shftRead[srCmd]] ]; }; }; }; ConstructWriteSeq: PROC[isEU: BOOL] RETURNS[tSeq: Rapunzel.SeqCmd] = { psDragonRun: Rapunzel.PeekShortCmd = [CarDragonRun]; dwEU: Rapunzel.PeekShortCmd = [DebugWriteEU]; dwIFU: Rapunzel.PeekShortCmd = [DebugWriteIFU]; seqLen: CARD16 = IF isEU THEN 5+numEUBits ELSE 4+numEUBits; -- magic here rlCmd: Rapunzel.ReturnLengthCmd; swCmd: Rapunzel.ShftWriteCmd; IF isEU THEN { swCmd.numRepeats _ numEUBits; rlCmd.returnLength _ 4; } ELSE { swCmd.numRepeats _ numIFUBits; rlCmd.returnLength _ 3; }; swCmd.address _ DebugInfo; tSeq _ NEW[Rapunzel.SeqCmdObject[seqLen]]; TRUSTED { tSeq[0] _ NEW[Rcmo _ [returnLength[rlCmd]] ];-- how long the result is IF isEU THEN tSeq[2] _ NEW[Rcmo _ [shftWrite[swCmd]] ] ELSE tSeq[1] _ NEW[Rcmo _ [shftWrite[swCmd]] ]; tSeq[seqLen-2] _ NEW[Rcmo _ [peekShort[psDragonRun]] ]; -- stop the Dragon before the write IF isEU THEN tSeq[seqLen-1] _ NEW[Rcmo _ [peekShort[dwEU]] ] ELSE tSeq[seqLen-1] _ NEW[Rcmo _ [peekShort[dwIFU]] ]; }; }; END. ´SoftcardOpsImpl.Mesa Copyright Ó 1986, 1987 by Xerox Corporation. All rights reserved. Willie-Sue, March 31, 1987 3:58:26 pm PST Bill Jackson (bj) February 3, 1987 7:01:49 pm PST Christophe Cuenod March 23, 1987 12:35:48 pm PST for compiling purposes -- various CmdSeqences to be shared ************************* TRUSTED { SELECT which FROM kReg => value _ [kReg [kVal: LOOPHOLE[theBits]]]; field => value _ [field [fVal: LOOPHOLE[theBits]]]; ENDCASE => value _ [regular [rVal: LOOPHOLE[theBits]]]; }; TRUSTED { WITH value: value SELECT FROM kReg => theBits _ LOOPHOLE[value.kVal]; field => theBits _ LOOPHOLE[value.fVal]; regular => theBits _ LOOPHOLE[value.rVal]; ENDCASE; }; the IFU has only one internal state register format tbd ************************* ************************* 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. stop the dragon disable the CacheStateMachines disable caches enable the CacheStateMachines reset interrupts reset breakpoints, virtualmemory access ***** ***** ***** ***** ***** ***** ***** ***** ************************* ************************* The mapping between 2 megabytes of daybreak physical address space and Dragon memory ************************* Access to the Dragon Map ************************* Utilities swappedVal: CARD32 = Rapunzel.PeekLong[crHandle, addr]; value _ LOOPHOLE[Basics.SwapHalves[LOOPHOLE[swappedVal]]]; swappedVal: CARD32 = LOOPHOLE[Basics.SwapHalves[LOOPHOLE[value]]]; construct a CmdSeq ending with a ShftReadCmd to read n-bits of internal state for EU, tSeq[2] sets the euAddr to read construct a CmdSeq using a ShftWriteCmd to write n-bits of internal state the bits go in the middle *********************************** Ê.˜codešœ™KšœB™BKšœ)™)K™1K™0—K™šÏk ˜ Kšœœ˜&Kšœœ:˜EKšœ˜Kšœ˜Kšœœ œ˜Kšœ ˜ Kšœ˜Kšœœ'˜0Jšœœ˜$—K˜šÏnœœ˜š˜Kšœœœ˜4—š˜Kšœ ˜ —K˜Kšœ œžœ˜8K˜Kšœœœ˜Kšœœ˜K˜Kšœœ˜ K˜Kšœ œÏc˜/Kšœ œ˜*Kšœ œ˜*Kšœ œ˜*Kšœœ!Ÿ˜=Kšœœ˜.Kšœ œ˜,K˜Kšœ œ˜*Kšœ œ˜(K˜Kšœœ˜&Kšœœ ˜2Kšœœ ˜2Kšœ œ˜.K˜Kšœ™K˜š œœœ œœ˜4K˜*K˜ K˜—K˜š œœœ œœ˜5K˜ Kšœ,˜,K˜Kšœœœ˜!Kšœ˜K˜—K˜Kšœ˜K˜KšŸ#™#Kšœ œ˜Kšœ˜Kšœ˜K˜Kšœ œ˜Kšœ˜Kšœ˜Kšœ˜K˜Kšžœœœœœœœ˜CK˜š žœœœœœœ˜Bšžœœ˜ Kšœ œ ˜Kšœœœ ˜šœ˜Kšœ&œœ˜Tšœ˜Kšœ œ%˜4Jšœœ˜#J˜——Jšœ œœ<˜JJšœ2˜2Jšœ:˜:J˜—Jšœ&œ˜,Jšœ œ˜J˜—K˜šžœœœ˜ Kšœ œœœ˜Kšœ$˜$Kšœ œ˜K˜—K˜šžœœœ˜+šžœœ˜ Kšœ5˜5—Kšœ˜K˜K˜—šžœœœ˜,šžœœ˜ Kšœ5˜5—Kšœ˜K˜K˜—šž œœœœ˜8Kšœœ˜8Kšœœ˜7Kšœ#˜#Kšœ3˜3K˜K˜—šž œœœœ˜;Kšœ œ3˜HKšœ˜K˜—š žœœœœœ˜6Kšœ˜Kšœ˜—K˜š žœœœœœ˜7Kšœ˜Kšœ˜—K˜š ž œœœœœ˜1Kšœ˜Kšœ˜—K˜—™K™š žœœœœœ˜IKšœ˜Kšœ œœ œ˜(Kšœ œ˜Kšœ œ˜Kšœ˜Kšœ!˜!šžœœ˜ Kšœ5˜5K˜—šœœ˜#Kšœ.˜.Kšœœ ˜&—Kšœ œœ$œ˜AKšœœ$˜@K˜Kšœ˜K˜šœ˜$Kšœ0˜0Kšœ˜šœ œ˜šœ ˜ šœ œ˜/Kšœ˜Kšœ$˜+šœ œ˜šœ˜Kšœœ˜/Kšœ˜K˜—Kšœœ˜—Kšœ˜—K˜—Kšœ˜#—Kšœ˜—Kšœœœ ˜7K˜šœœ™Kšœœ ™1Kšœœ ™3Kšœœ ™7K™—Kšœ˜K˜—šžœœœœ˜BKšœ œœ œ˜(Kšœ œ˜Kšœ˜Kšœ!˜!Kšœ˜šžœœ˜ Kšœ/˜/—K˜šœœœ™'Kšœœ ™'Kšœœ ™(Kšœœ ™*Kšœ™K™—K˜Kšœ œœ ˜7šœœ˜#Kšœ.˜.Kšœœ ˜&—Kšœ˜Kšœœœ&œ˜DKšœœ$˜Ašœ˜%Kšœ/˜/Kšœ˜šœ œ˜šœ˜šœ œœ ˜9Kšœ˜Kšœ(˜(Kšœ œ ˜ šœ˜%Kšœœ˜"—Kšœ˜—K˜—Kšœ˜#—Kšœ˜—Kšœ˜Kšœ˜—K™šž œœœœ ˜AKšœœ0™7Kšœ˜Kšœ œ˜Kšœ œ˜šžœœ˜ Kšœ6˜6K˜—Kšœœœ%œ˜DK˜Kšœ˜K˜šœ˜$Kšœ0˜0Kšœ˜šœ œ˜šœ ˜ šœ œ˜/Kšœ˜Kšœ$˜+šœ œ˜Kšœ6˜6Kšœœ˜—Kšœ˜—K˜—Kšœ˜#—Kšœ˜—K˜—K˜šž œœœ ˜:Kšœ œ˜Kšœ˜šžœœ˜ Kšœ0˜0—K˜Kšœ˜Kšœœœ'œ˜GK˜šœ˜%Kšœ0˜0Kšœ˜šœ œ˜šœ˜šœ œœ ˜9Kšœ˜Kšœ˜šœ˜%Kšœœ˜!—Kšœ˜—K˜—Kšœ˜#—Kšœ˜—Kšœ˜K˜—K™—™J˜šžœœœœ ˜Ešžœœ˜ Kšœœ3˜L—K˜K˜—K˜šžœœœ ˜>šžœœ˜ Kšœ1œœ˜S—K˜K˜—J˜—™Kšœ:Ïbœõ™³K˜š žœœœœ œ˜IKšœ œ˜%Kš œœ œ œ œ ˜EKšœ&˜,K˜K˜—š ž œœœœ œ˜IKšœœ-˜:Kšœ-˜3K˜K˜—š žœœœœ œ˜KKšœœ)˜6Kšœ-˜3K˜—K˜šžœœœ˜*Kšœ(˜(Kšœ(˜(Kšœ˜—K˜šžÏtœœ˜)Kšœ'˜'Kšœ'˜'Kšœ˜—K˜šžœœœ˜ Kšœ#˜#Kšœ˜—K˜šžœœœ˜Kšœ"˜"Kšœ˜—K˜šž œœœ˜Kšœ$˜$Kšœ#˜#Kšœ˜—K˜šž œœœ˜Kšœ#˜#Kšœ"˜"Kšœ˜—K˜šžœœœ!˜?Kšœ œ˜Kšœ#˜#šžœœœ˜;Kš œ œœœœ˜?Kšœœ ˜K˜—KšœŸ#˜AKšœ5œœŸ˜Sšœ*œ˜2Kšœ˜Kšœ/œœ˜=Kšœ˜Kšœ/œœ˜=Kšœ˜K˜šœ˜Kšœ˜Kšœ/œœ˜=Kšœ˜Kšœ/œœ˜=Kšœ˜K˜——Kšœ˜K˜—š ž œœœ$œœ˜PKš œœœœŸ˜Ešœœ˜$Kšœ˜Kšœœœœ˜%Kšœ˜Kšœœœœ˜"Kšœ˜Kšœ˜K˜šœ˜Kšœ˜Kšœœœœ˜%Kšœ˜Kšœœœœ˜"Kšœ˜Kšœ˜K˜——Kšœœ˜ Kšœ˜K˜—š žœœœœœ˜IKšœ œ˜Kšœ œ˜Kš œœœ œŸ˜NKšœ'˜'Kšœ!˜!šœœ˜Kšœ œ˜*Kšœ œ#˜/Kšœ œ˜+Kšœ œ#˜0Kšœœ œ˜!—Kšœœ˜K˜K˜—šž œœœ˜Kšœ˜Kšœ˜K˜—šž œœœ˜Kšœ˜Kšœ˜K˜—šž œœœ˜Kšœ!˜!Kšœ!˜!Kšœ˜K˜—šž œœœ˜KšœJ˜Jšžœœ˜ Kšœ.˜.Kšœ/œœ˜EKšœ˜—šœœœ˜Kšœ.˜.Kšœœ˜/KšŸ™Kšœœ˜3šœ˜Kšœ.˜1—K™KšŸ™šœ˜Kšœ:˜=—šœ˜Kšœ9˜—šœ˜Kšœ4˜7—šœ˜Kšœ5˜8—K™K™'šœ˜Kšœ3˜6—šœ˜Kšœ2˜5—šœ˜Kšœ9˜<—šœ˜Kšœ8˜;—šœ˜Kšœ9˜<—šœ˜Kšœ:˜=—K˜—K˜K˜—K˜K™0K˜šž œœœœ˜5šœœ˜Kšœ2œœ˜@Kšœœœ˜—K˜—K˜šžœœœ ˜>šœ˜Kšœœ ¡˜!Kšœœ˜8Kšœœ¡˜:Kšœ œ ¡˜"Kšœœ¡˜$Kšœœ¡œ˜&Kšœœ¡œ˜6Kšœœ¡œ˜8Kšœœ¡œ˜6Kšœœ¡œ˜4Kšœœ¡˜=Kšœœ¡˜0Kšœœ¡œ˜1Kšœœ¡˜;Kšœœ¡œ˜/Kšœœ¡œ˜+Kšœœ¡œ˜,Kšœœ¡œ˜.Kšœœ¡œ˜*Kšœœ˜—K˜—K˜š ž œœ œ œœœ˜UK˜K˜Kš œ œœœœ˜Všœ˜Kšœœ˜0Kšœœ$˜BKšœœ#¡˜DKšœ œ˜,Kšœœ˜.Kšœœ¡œ˜0Kšœœ!¡œ˜@Kšœœ"¡œ˜BKšœœ!¡œ˜@Kšœœ)˜LKšœœ ˜:Kšœœ¡œ˜;Kšœœ(˜JKšœœ˜8Kšœœ¡œ˜9Kšœœ ¡œ˜>Kšœœ¡œ˜6Kšœœ¡œ˜8Kšœœ˜4Kšœœ˜—K˜—K™K™K˜š ž œœœœ œ˜GKšœœ˜9Kšœ˜%Kšœ˜—K˜š žœœœœ œ˜IKšœœ*˜DKšœ˜%K˜K˜—šžœœ$œœ˜Jšœ˜Kšœ ¡œ ¡˜Kšœ¡œ¡˜7Kšœ¡œ¡˜-Kšœ¡œ¡˜+Kšœ¡œ¡˜-Kšœ ¡œ¡˜!Kšœœ˜—K˜K˜—šžœœœ ˜?šœ˜Kšœ¡œ¡˜7Kšœ¡œ¡˜-Kšœ¡œ¡˜,Kšœ¡œ¡˜.Kšœ ¡œ¡ ˜!Kšœœ˜—K˜K˜—K™—™K™TK˜Kšœœ˜.Kšœœ˜.K˜šž œœœ˜-Kšœœ˜!šœ˜Kšœœ˜D—Kšœ˜—K˜šž œœœ.˜GKšœœ œœ˜AKšœ˜—K™—™K™K˜Kšœœ˜2Kšœœ˜2K˜šž œœœ˜1Kšœœ˜#Kšœœ6˜EKšœ˜—K˜šžœœœ2˜MKšœ$œœ˜=Kšœ˜——K˜™K™ K™š žœœœœœ˜?Kšœœ˜ Kšœœ˜ šœœ˜šœ˜Kšœ ˜ Kšœœ ˜Kšœ˜ K˜—˜šœ˜šœ˜Jšœ$œ˜9—šœ˜Jšœ-œ˜B—šœ˜Jšœ1œ˜F—šœ˜Jšœ-œ˜B—šœ ˜JšœJ˜L——Kšœœ˜Jšœ˜ J˜—šœ˜K˜—šœœ œ˜'Kšœ3˜9—˜K˜š˜Kšœ œ˜&——Kšœ˜—K˜—K™š ž œœœ œœ˜=šžœœ˜ Kšœ/˜/—K˜K˜K˜—šž œœœœ˜6šžœœ˜ Kšœ.˜.—K˜K˜K˜—š žœœœ œœ˜<šžœœ˜ Kšœ œ%™7Kšœœœ™:Kšœ*˜*K˜—Kšœœœ*˜HK˜K˜—K˜šž œœœœ˜5šžœœ˜ Kšœ œœœ ™BKšœ)˜)K˜—Kšœœœ*˜HK˜K˜K˜—Kšœ˜šœ'˜'K˜—šžœœœ˜Kš œœœœœ˜@šžœœ˜ Kšœ'˜'K˜—K˜šœ œœœ˜-Kšœ œ˜)K˜—šœœœ ˜K˜3Kšœ œ˜+Kšœ˜—K˜K˜K˜—šž œœœœ˜/Kšœœ˜#šžœœ˜ Kšœ4˜4—K˜K˜K˜—šžœœœœ˜.Kšœœ˜"šžœœ˜ Kšœ/˜/K˜—Kšœœœ*˜HK˜K˜K˜—šž œœ œœ˜-Kšœœ˜'Kšœ˜K˜K˜—šžœœœœ˜FK™MKšœ4˜4Kšœ,˜,Kšœ.˜.Kš œœœœœŸ˜@Kšœ ˜ šœ˜šœœ˜Kšœ˜Kšœ ˜ K˜šœ˜Kšœ˜Kšœ"˜"K˜——Kšœ"˜"—K˜Kšœœ ˜*šœ˜ Kšœ œ"Ÿ˜HKšœ œ$Ÿ˜Išœœ˜Kšœ'™'Kšœ œ˜)Kšœ œ˜)K˜šœ˜Kšœ œ˜*Kšœ œ˜)Kšœ˜——K˜—K˜K˜—šžœœœœ˜GK™IKšœ4˜4Kšœ-˜-Kšœ/˜/Kš œœœœ œŸ ˜IKšœ ˜ šœ˜šœœ˜Kšœ˜Kšœ˜K˜šœ˜Kšœ˜Kšœ˜K˜——Kšœ˜—Kšœœ ˜*šœ˜ Kšœ œ Ÿ˜Fšœœ œ˜6Kšœ œ˜/—K™šœ˜Kšœ$Ÿ#˜J—šœœœ˜