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.
Reading: the internal register is transfered to a shift register internal to the chip, then the bits are shifted out one 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 EU/IFU internal registers, the Dragon may be running. But to read or write the internal register, the Dragon must be stopped.
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)
The following locations are read locations on the softcard
DebugReadEU: Addr = SCBaseAddr+800h; -- Read EU internal register into shift register
DebugWriteEU: Addr = SCBaseAddr+0h; -- Write shift register into EU internal
DebugReadIFU: Addr = SCBaseAddr+1800h; -- Read IFU internal state into shift register
DebugWriteIFU: Addr = SCBaseAddr+1000h; -- Write shift 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..3): [0..3B] ← 0,
debugEUAddr (0: 4..7): [0..17B] ← 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.
For bits starting with not, the sense is reversed.
Control1Bits:
TYPE =
MACHINE
DEPENDENT
RECORD [
resetDragon(0: 0..0): BOOL,
interruptDragonToIOP(0: 1..1): BOOL,
interruptDragonToMesa(0: 2..2): BOOL,
dragonRun(0: 3..3): BOOL,
dragonStep(0: 4..4): BOOL,
writeParity(0: 5..5): BOOL,
virtualMemAccessIOP(0: 6..6): BOOL,
virtualMemAccessMesa(0: 7..7): BOOL,
resetIFUCacheStateMachine(0: 8..8): BOOL,
notResetIFUCache(0: 9..9): BOOL,
enableIFUBkpt(0: 10..10): BOOL,
virtualMemAccessIFU(0: 11..11): BOOL,
resetEUCacheStateMachine(0: 12..12): BOOL,
notResetEUCache(0: 13..13): BOOL,
enableEUBkpt(0: 14..14): BOOL,
virtualMemAccessEU(0: 15..15): BOOL
];
Control2Bits:
TYPE =
MACHINE
DEPENDENT
RECORD[
reserved (0: 0..7): [0..377B],
iopIntToDragon (0: 8..8): BOOL,
mesaIntToDragon (0: 9..9): BOOL,
notResetClock (0: 10..10): BOOL,
unused (0: 11..15): [0..37B] ← 0
];
ControlBits1Addr: Addr = SCBaseAddr+0c841h; -- read the control1 bits
Consult1: Addr = ControlBits1Addr;
ConsultAndChange1Base: Addr = SCBaseAddr+0c801h;
CarDragon: Addr = ConsultAndChange1Base+0;
CarInterruptDragonToIOP
: Addr = ConsultAndChange1Base+
4;
consulting this address will interrupt the Dragon
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.
CasDragonRun: Addr = CarDragonRun+2;
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
CasDragonStep: Addr = CarDragonStep+2;
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;
CarNotResetIFUCache: Addr = ConsultAndChange1Base+36;
CasNotResetIFUCache
: Addr = CarNotResetIFUCache+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;
CarNotResetEUCache: Addr = ConsultAndChange1Base+52;
CasNotResetEUCache
: Addr = CarNotResetEUCache+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
ControlBits2Addr: Addr = SCBaseAddr+0c041h; -- read the control2 bits
Consult2: Addr = ControlBits2Addr;
ConsultAndChange2Base: Addr = SCBaseAddr+0c021h;
CarIOPIntToDragon: Addr = ConsultAndChange2Base+0;
CarMesaIntToDragon: Addr = ConsultAndChange2Base+4;
CarNotResetClock: Addr = ConsultAndChange2Base+8;
CasNotResetClock: Addr = CarNotResetClock+2;
*************************
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. All the resets take place in two steps: Car1xx and Car2xx; the Car2xx address is always Car1xx+2.
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
notMemoryError (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+0c041h;
CarStatusBase: Addr = SCBaseAddr+0c001h;
Car1PeriodicIntToDragon: Addr = CarStatusBase+0;
Car1NotMemoryError: Addr = CarStatusBase+10h;
Car1EUBrkptReached: Addr = CarStatusBase+14h;
Car1IFUBrkptReached: Addr = CarStatusBase+18h;
Car1MapError: Addr = CarStatusBase+1ch;
*************************
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[
unused (0: 0..11): [0..3777B] ← 0,
dp (0: 12..14): [0..7B] ← 0,
ignored (0: 15..15): [0..1] ← 0
];
MesaMapIndex: TYPE = [0..3];
MesaMapRec:
TYPE =
MACHINE
DEPENDENT
RECORD[
reserved0 (0: 0..15): [0..177777B] ← 0,
mapEntry (1: 0..15): MesaMapEntry,
reserved2 (2: 0..15): [0..177777B] ← 0,
reserved3 (3: 0..15): [0..177777B] ← 0
];
MesaMapAddr: Addr = SCBaseAddr + 0d000h;
-- RW, 4 locations
actually 4*4 locations are allocated but only the MOD 1 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): BOOL ← TRUE,
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*2;
-- 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.