<> <> <> <> <> <<>> 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; <<-- various CmdSeqences to be shared>> 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]]]; <> < value _ [kReg [kVal: LOOPHOLE[theBits]]];>> < value _ [field [fVal: LOOPHOLE[theBits]]];>> < value _ [regular [rVal: 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[value.kVal];>> < theBits _ LOOPHOLE[value.fVal];>> < theBits _ LOOPHOLE[value.rVal];>> <> <<};>> 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.