NewSoftcardPrivate.mesa
Copyright Ó 1986, 1987 by Xerox Corporation. All rights reserved.
Willie-Sue, October 13, 1986 2:46:56 pm PDT
Defs used by SoftcardOpsImpl to access the appropriate addresses
Christophe Cuenod February 3, 1987 7:34:08 pm PST
DIRECTORY
SoftcardOps USING [
Addr, DragonMapEntry, DragonMapIndex, MesaMapEntry, MesaMapIndex];
SoftcardPrivate: CEDAR DEFINITIONS = BEGIN
Addr: TYPE = SoftcardOps.Addr;
OneBit: TYPE = [0..1];
SCBaseAddr: Addr = (LONG[28]*256*256);  -- 3.5MB;
SCBaseAddr: Addr = 0;   -- for testing
conventions for the comments following the addresses
R = ReadOnly register
W = WriteOnly register
RW = Read/Write register
MS-part = most significant part
LS-part = least significant part
bit numbers refer to bits in a Dragon word
(a) when bits indicated are fewer than 16, only those bits get used - others are ignored
(b) The Softcard ignores the 8 most significant bits of the MS-part of a Dragon address
e.g. the value written into BkptEUH is 16 bits, but the high 8 bits are ignored
The dragon memory is "mapped" into 2 Megabytes of the Daybreak physical address space, at addresses 1.5 to 3.5 megabytes. The next .5 megabytes of Daybreak physical address space are used for memory-mapped I/O.
addresses for accessing registers of the Dragon
BkptEUH: Addr = SCBaseAddr+0b800h; -- W [8..16); MS-part of brkp register for EU
BkptEUL: Addr = SCBaseAddr+0b000h; -- W [16..32); LS-part of brkp register for EU
BkptIFUH: Addr = SCBaseAddr+0a800h; -- W [8..16); MS-part of brkp register for IFU
BkptIFUL: Addr = SCBaseAddr+0a000h; -- W[16..32); LS-part of brkp register for IFU
SpyCmd1: Addr = SCBaseAddr+9800h; -- R [0..8); 8-bit PBus command of the EU
SpyCmd2: Addr = SCBaseAddr+8800h; -- R [0..8); 2 bits used
bit 3: 1-bit PBus command of the IFU (cache access in this cycle or not)
bit 7: User Mode (part of EU PBus command)
SpyEUDataH: Addr = SCBaseAddr+9000h; -- R [0..16); MS-part of PBus data of the EU
SpyEUDataL: Addr = SCBaseAddr+9001h; -- R [16..32); LS-part of PBus data of the EU
SpyIFUDataH: Addr = SCBaseAddr+8000h; -- R [0..16); MS-part of PBus data of the IFU
SpyIFUDataL: Addr = SCBaseAddr+8001h; -- R [16..32); LS-part of PBus data of the IFU
ClockH: Addr = SCBaseAddr+7800h; -- R [0..16); MS-part of Clock
ClockL: Addr = SCBaseAddr+7801h; -- R [16..32); LS-part of Clock
Note: since the 32-bits of the clock cannot be read atomically (by the mesa processor), care must be taken
*************************
The Debug operations allow one to read or write the internal registers of the EU and the IFU.
For IFU:
Reading: the internal register is transfered to a shift register internal to the chip, then the bits are shifted out one bit at a time.
Writing: the bits are shifted one at a time into the shift register internal to the chip and then written into the internal register.
While the Softcard is shifting bits into or outof the IFU internal registers, the Dragon may be running. But to read or write the internal register, the Dragon must be stopped.
The EU has up to 16 addressable internal registers (details to be supplied later).
To access the EU internal registers for reading or writing, one must assert (set) DebugFreeze. Then one must assert DebugSelectEU. Then one shifts bits into the EU internal shift register using (reading) DebugShiftEU; these bits include the command, address, and data (if writing). Reading DebugExecuteEU causes the EU to do the command in its shift register. If the command was read, one then shifts the bits out by accessing DebugShiftEU. Finally one drops (resets) DebugSelectEU, then drops DebugFreeze. (Whew)
The 3 commands are:
Read => copy the specified internal state of the chip into the chip shift register
Write => write the chip shift register into the internal state of the chip
Shift => shift one bit into or out of the chip shift register
(depends on previous operation)
The shift operations must be done in two steps (ShiftA & ShiftB)
DebugShiftEU: Addr = SCBaseAddr+17;
-- shift one bit of EU internal state into/outof EU register
DebugExecuteEU: Addr = SCBaseAddr+18;
-- Cause the EU to read its internal register and do a command
DebugReadIFU: Addr = SCBaseAddr+1800h; -- Read IFU internal state into IFU register
DebugWriteIFU: Addr = SCBaseAddr+1000h; -- Write IFU register into IFU
DebugShiftA: Addr = SCBaseAddr+4000h;
DebugShiftB: Addr = SCBaseAddr+4800h;
DebugInfo: Addr = SCBaseAddr+2001h; -- RW [0..8); 8-bits of debugging info
DebugInfoEntry: TYPE = MACHINE DEPENDENT RECORD[
debugInIFU (0: 0..0): OneBit ← 0, -- bit to shift into the IFU shift register
debugInEU (0: 1..1): OneBit ← 0, -- bit to shift into the EU shift register
unused (0: 2..7): [0..77B] ← 0,
reserved (0: 8..15): [0..377B] ← 0
];
*************************
ClockControlAddr: Addr = SCBaseAddr+3001h; -- RW [8..16); 8-bits of clock control info
ClockControl: TYPE = MACHINE DEPENDENT RECORD[
reserved (0: 0..7): [0..377B],
freqSelect (0: 8..9): [0..3],  -- choice of four frequencies for the Dragon clock
phaseAdjust (0: 10..12): [0..7], -- adjust phase between Dragon and Softcard
delay (0: 13..15): [0..7]  -- adjust the delay between FA and FB
];
*************************
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 returning the previous value of all the bits.
CarXXX => ConsultAndResetXXX
The set address for a bit is always the reset address + 2.
Control1Bits: TYPE = MACHINE DEPENDENT RECORD [
resetDragon(0: 0..0): BOOL,
interrurptDragonToIOP(0: 1..1): BOOLFALSE,
interrurptDragonToMesa(0: 2..2): BOOLFALSE,
dragonRun(0: 3..3): BOOLFALSE,
dragonStep(0: 4..4): BOOLFALSE,
writeParity(0: 5..5): BOOLFALSE,
virtualMemAccessIOP(0: 6..6): BOOLFALSE,
virtualMemAccessMesa(0: 7..7): BOOLFALSE,
resetIFUCacheStateMachine(0: 8..8): BOOLFALSE,
resetIFUCache(0: 9..9): BOOLFALSE,
enableIFUBkpt(0: 10..10): BOOLFALSE,
virtualMemAccessIFU(0: 11..11): BOOLFALSE,
resetEUCacheStateMachine(0: 12..12): BOOLFALSE,
resetEUCache(0: 13..13): BOOLFALSE,
enableEUBkpt(0: 14..14): BOOLFALSE,
virtualMemAccessEU(0: 15..15): BOOLFALSE
];
Control2Bits: TYPE = MACHINE DEPENDENT RECORD[
reserved (0: 0..7): [0..377B],
iopIntToDragon (0: 8..8): BOOL,
mesaIntToDragon (0: 9..9): BOOL,
resetCounter (0: 10..10): BOOL,
unused (0: 11..15): [0..37B] ← 0
];
ControlBits1Addr: Addr = SCBaseAddr+128 + 1; -- read the control1 bits
   this address must be 1 MOD 128
Consult1: Addr = ControlBits1Addr;
ConsultAndChange1Base: Addr = ControlBits1Addr + 64;
CarDragon: Addr = ConsultAndChange1Base+0;
CarInterrurptDragonToIOP: Addr = ConsultAndChange1Base+4;
CarInterruptDragonToMesa: Addr = ConsultAndChange1Base+8;
CarDragonRun: Addr = ConsultAndChange1Base+12;
setting this bit allows the Dragon to run; resetting it stops the processor and enables you to then single step it.
Certain other operations can only be done when the Dragon is halted.
CarDragonStep: Addr = ConsultAndChange1Base+16;
setting this bit moves the Dragon to FA or FB; resetting this bit moves the Dragon to between FA/FB or FB/FA
CarWriteParity: Addr = ConsultAndChange1Base+20;
allows selection of even or odd parity for subsequent writes; reads are always done with TDB parity; thus one can create a parity error
CarVirtualMemAccessIOP: Addr = ConsultAndChange1Base+24;
if set, the IOP accesses to Dragon memory are using virtual addresses; if reset, physical addresses are being used
CarVirtualMemAccessMesa: Addr = ConsultAndChange1Base+28;
if set, the Mesa processor accesses to Dragon memory are using virtual addresses; if reset, physical addresses are being used
CarIFUCacheStateMachine: Addr = ConsultAndChange1Base+32;
CasIFUCacheStateMachine: Addr = CarIFUCacheStateMachine+2;
CarIFUCache: Addr = ConsultAndChange1Base+36;
CasIFUCache: Addr = CarIFUCache+2;
a reset and set flushes the IFU cache
CarEnableIFUBkpt: Addr = ConsultAndChange1Base+40;
CarVirtualMemAccessIFU: Addr = ConsultAndChange1Base+44;
if set, the IFU accesses to Dragon memory are using virtual addresses; if reset, physical addresses are being used
CarEUCacheStateMachine: Addr = ConsultAndChange1Base+48;
CasEUCacheStateMachine: Addr = CarEUCacheStateMachine+2;
CarEUCache: Addr = ConsultAndChange1Base+52;
CasEUCache: Addr = CarEUCache+2;
a reset and set flushes the EU cache
CarEnableEUBkpt: Addr = ConsultAndChange1Base+56;
CarVirtualMemAccessEU: Addr = ConsultAndChange1Base+60;
if set, the EU accesses to Dragon memory are using virtual addresses; if reset, physical addresses are being used
ControlBits2Entry: TYPE = MACHINE DEPENDENT RECORD[
reserved (0: 0..7): [0..377B],
iopIntToDragon (0: 8..8): BOOL,
mesaIntToDragon (0: 9..9): BOOL,
resetCounter (0: 10..10): BOOL,
debugSelectEU (0: 11..11): BOOL,
debugFreeze (0: 12..12): BOOL,
unused (0: 13..15): [0..7B] ← 0
];
ControlBits2Addr: Addr = SCBaseAddr + 256 + 1; -- read the control2 bits
   this address must be 1 MOD 64
Consult2: Addr = ControlBits2Addr;
ConsultAndChange2Base: Addr = ControlBits2Addr + 32;
CarIOPIntToDragon: Addr = ConsultAndChange2Base+0;
CarMesaIntToDragon: Addr = ConsultAndChange2Base+4;
CarCounter: Addr = ConsultAndChange2Base+8;
CarDebugSelectEU: Addr = ConsultAndChange2Base+10;
CarDebugFreeze: Addr = ConsultAndChange2Base+12;
*************************
The status bits are similar to the control bits, except that some of them are readOnly and the others can be reset but not set.
StatusBits: TYPE = MACHINE DEPENDENT RECORD[
dOutIFU (0: 0..0): OneBit, -- bit shifted out of the IFU shift register
dOutEU (0: 1..1): OneBit,  -- bit shifted out of the EU shift register
phaseA (0: 2..2): BOOL,  -- is the Dragon in FA
periodicIntToDragon (0: 3..3): BOOL, -- 16HZ periodic interrupt
memoryError (0: 4..4): BOOL, -- IOP access to Dragon memory saw a parity error
euBkptReached (0: 5..5): BOOL,
ifuBkptReached (0: 6..6): BOOL,
mapError (0: 7..7): BOOL,
reserved (0: 8..15): [0..377B]
];
ConsultStatusAddr: Addr = SCBaseAddr+256+64+1; -- R, 1 MOD 64
CarStatusBase: Addr = ConsultStatusAddr+32;
CarPeriodicIntToDragon: Addr = CarStatusBase+0;
CarMemoryError: Addr = CarStatusBase+2;
CarEUBrkptReached: Addr = CarStatusBase+4;
CarIFUBrkptReached: Addr = CarStatusBase+6;
CarMapError: Addr = CarStatusBase+8;
*************************
The mapping between 2 megabytes of daybreak physical address space and Dragon memory
MesaMapEntry: TYPE = SoftcardOps.MesaMapEntry;
MesaMapIndex: TYPE = SoftcardOps.MesaMapIndex;
MesaMapEntry: TYPE = MACHINE DEPENDENT RECORD[
reserved (0: 0..15): [0..177777B],
unused (1: 0..11): [0..3777B] ← 0,
dp (1: 12..15): [0..17B] ← 0
];
MesaMapIndex: TYPE = [0..7];
MesaMapRec: TYPE = MACHINE DEPENDENT RECORD[
reserved (0: 0..15): [0..177777B],
mapEntry (1: 0..15): MesaMapEntry
];
MesaMapAddr: Addr = SCBaseAddr + 512; -- RW, 8 locations
actually 2*8 locations are allocated but only the odd locations only used
MesaMap: TYPE = ARRAY MesaMapIndex OF MesaMapRec;
MesaMapBase: LONG POINTER TO MesaMap = LOOPHOLE[MesaMapAddr];
*************************
Access to the Dragon Map
DragonMapEntry: TYPE = SoftcardOps.DragonMapEntry;
DragonMapIndex: TYPE = SoftcardOps.DragonMapIndex;
DragonMapEntry: TYPE = MACHINE DEPENDENT RECORD[
fault (1: 0..0): BOOLTRUE,
unused (1: 1..5): [0..37B] ← 0,
rp (1: 6..15): [0..1777B] ← 0
];
DragonMapIndex: TYPE = [0..37777B];
DragonMapRec: TYPE = MACHINE DEPENDENT RECORD[
reserved (0: 0..15): [0..177777B],
mapEntry (1: 0..15): DragonMapEntry
];
DragonMapAddr: Addr = SCBaseAddr+LONG[256]*256; -- RW, 16K locations
-- actually, 2*16K locations are allocated but only the odd locations are used
DragonMap: TYPE = ARRAY DragonMapIndex OF DragonMapRec;
DragonMapBase: LONG POINTER TO DragonMap = LOOPHOLE[DragonMapAddr];
END.