add support for simple character input via the system console
dev/alpha_access.h: - use our standard types instead of this extra typedef - advance the ALPHA_ACCESS version since the interface has changed. *this means you need a new console binary* - shuffle a couple things around to pack the data structure a bit better - add a placeholder for character input dev/alpha_console.cc: Clean up the read code path a bit and add support for character input via the console Clean up the write path and use a switch instead of a bunch of if statements --HG-- extra : convert_revision : a1a5bc8fed9ec9c4c46548fdf79604661668b81a
This commit is contained in:
parent
c3ba166e65
commit
318e0c93ed
4 changed files with 105 additions and 76 deletions
|
@ -33,52 +33,44 @@
|
|||
* System Console Memory Mapped Register Definition
|
||||
*/
|
||||
|
||||
#define ALPHA_ACCESS_VERSION (1291+1) /* CH++*/
|
||||
|
||||
#ifdef CONSOLE
|
||||
typedef uint32 UINT32;
|
||||
typedef uint64 UINT64;
|
||||
#else
|
||||
typedef uint32_t UINT32;
|
||||
typedef uint64_t UINT64;
|
||||
#define ALPHA_ACCESS_VERSION (1301) /* CH++*/
|
||||
|
||||
#ifndef CONSOLE
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
class Checkpoint;
|
||||
|
||||
#endif
|
||||
|
||||
// This structure hacked up from simos
|
||||
struct AlphaAccess
|
||||
{
|
||||
UINT32 last_offset; // 00: must be first field
|
||||
UINT32 version; // 04:
|
||||
UINT32 numCPUs; // 08:
|
||||
UINT32 align0; // 0C: Placeholder for alignment
|
||||
UINT64 mem_size; // 10:
|
||||
UINT64 cpuClock; // 18: MHz
|
||||
UINT32 intrClockFrequency; // 20: Hz
|
||||
UINT32 align1; // 24: Placeholder for alignment
|
||||
uint32_t last_offset; // 00: must be first field
|
||||
uint32_t version; // 04:
|
||||
uint32_t numCPUs; // 08:
|
||||
uint32_t intrClockFrequency; // 0C: Hz
|
||||
uint64_t cpuClock; // 10: MHz
|
||||
uint64_t mem_size; // 18:
|
||||
|
||||
// Loaded kernel
|
||||
UINT64 kernStart; // 28:
|
||||
UINT64 kernEnd; // 30:
|
||||
UINT64 entryPoint; // 38:
|
||||
uint64_t kernStart; // 20:
|
||||
uint64_t kernEnd; // 28:
|
||||
uint64_t entryPoint; // 30:
|
||||
|
||||
// console disk stuff
|
||||
UINT64 diskUnit; // 40:
|
||||
UINT64 diskCount; // 48:
|
||||
UINT64 diskPAddr; // 50:
|
||||
UINT64 diskBlock; // 58:
|
||||
UINT64 diskOperation; // 60:
|
||||
uint64_t diskUnit; // 38:
|
||||
uint64_t diskCount; // 40:
|
||||
uint64_t diskPAddr; // 48:
|
||||
uint64_t diskBlock; // 50:
|
||||
uint64_t diskOperation; // 58:
|
||||
|
||||
// console simple output stuff
|
||||
UINT64 outputChar; // 68:
|
||||
uint64_t outputChar; // 60: Placeholder for output
|
||||
uint64_t inputChar; // 68: Placeholder for input
|
||||
|
||||
// MP boot
|
||||
UINT64 bootStrapImpure; // 70:
|
||||
UINT32 bootStrapCPU; // 78:
|
||||
UINT32 align2; // 7C: Dummy placeholder for alignment
|
||||
uint64_t bootStrapImpure; // 70:
|
||||
uint32_t bootStrapCPU; // 78:
|
||||
uint32_t align2; // 7C: Dummy placeholder for alignment
|
||||
|
||||
#ifndef CONSOLE
|
||||
void serialize(std::ostream &os);
|
||||
|
|
|
@ -76,17 +76,35 @@ Fault
|
|||
AlphaConsole::read(MemReqPtr req, uint8_t *data)
|
||||
{
|
||||
memset(data, 0, req->size);
|
||||
uint64_t val;
|
||||
|
||||
if (req->size == sizeof(uint32_t)) {
|
||||
Addr daddr = req->paddr & addr_mask;
|
||||
*(uint32_t *)data = *(uint32_t *)(consoleData + daddr);
|
||||
switch (daddr) {
|
||||
case offsetof(AlphaAccess, inputChar):
|
||||
val = console->in();
|
||||
break;
|
||||
|
||||
#if 0
|
||||
DPRINTF(AlphaConsole, "read: offset=%#x val=%#x\n",
|
||||
daddr, *(uint32_t *)data);
|
||||
#endif
|
||||
default:
|
||||
val = *(uint64_t *)(consoleData + daddr);
|
||||
break;
|
||||
}
|
||||
|
||||
DPRINTF(AlphaConsole, "read: offset=%#x val=%#x\n", daddr, val);
|
||||
|
||||
switch (req->size) {
|
||||
case sizeof(uint32_t):
|
||||
*(uint32_t *)data = (uint32_t)val;
|
||||
break;
|
||||
|
||||
case sizeof(uint64_t):
|
||||
*(uint64_t *)data = val;
|
||||
break;
|
||||
|
||||
default:
|
||||
return Machine_Check_Fault;
|
||||
}
|
||||
|
||||
|
||||
return No_Fault;
|
||||
}
|
||||
|
||||
|
@ -99,6 +117,7 @@ AlphaConsole::write(MemReqPtr req, const uint8_t *data)
|
|||
case sizeof(uint32_t):
|
||||
val = *(uint32_t *)data;
|
||||
break;
|
||||
|
||||
case sizeof(uint64_t):
|
||||
val = *(uint64_t *)data;
|
||||
break;
|
||||
|
@ -106,60 +125,57 @@ AlphaConsole::write(MemReqPtr req, const uint8_t *data)
|
|||
return Machine_Check_Fault;
|
||||
}
|
||||
|
||||
Addr paddr = req->paddr & addr_mask;
|
||||
Addr daddr = req->paddr & addr_mask;
|
||||
ExecContext *other_xc;
|
||||
|
||||
if (paddr == offsetof(AlphaAccess, diskUnit)) {
|
||||
switch (daddr) {
|
||||
case offsetof(AlphaAccess, diskUnit):
|
||||
alphaAccess->diskUnit = val;
|
||||
return No_Fault;
|
||||
}
|
||||
break;
|
||||
|
||||
if (paddr == offsetof(AlphaAccess, diskCount)) {
|
||||
case offsetof(AlphaAccess, diskCount):
|
||||
alphaAccess->diskCount = val;
|
||||
return No_Fault;
|
||||
}
|
||||
break;
|
||||
|
||||
if (paddr == offsetof(AlphaAccess, diskPAddr)) {
|
||||
case offsetof(AlphaAccess, diskPAddr):
|
||||
alphaAccess->diskPAddr = val;
|
||||
return No_Fault;
|
||||
}
|
||||
break;
|
||||
|
||||
if (paddr == offsetof(AlphaAccess, diskBlock)) {
|
||||
case offsetof(AlphaAccess, diskBlock):
|
||||
alphaAccess->diskBlock = val;
|
||||
return No_Fault;
|
||||
}
|
||||
break;
|
||||
|
||||
if (paddr == offsetof(AlphaAccess, diskOperation)) {
|
||||
case offsetof(AlphaAccess, diskOperation):
|
||||
if (val == 0x13)
|
||||
disk->read(alphaAccess->diskPAddr, alphaAccess->diskBlock,
|
||||
alphaAccess->diskCount);
|
||||
else
|
||||
panic("Invalid disk operation!");
|
||||
|
||||
return No_Fault;
|
||||
}
|
||||
break;
|
||||
|
||||
if (paddr == offsetof(AlphaAccess, outputChar)) {
|
||||
case offsetof(AlphaAccess, outputChar):
|
||||
console->out((char)(val & 0xff), false);
|
||||
return No_Fault;
|
||||
}
|
||||
break;
|
||||
|
||||
if (paddr == offsetof(AlphaAccess, bootStrapImpure)) {
|
||||
case offsetof(AlphaAccess, bootStrapImpure):
|
||||
alphaAccess->bootStrapImpure = val;
|
||||
return No_Fault;
|
||||
}
|
||||
break;
|
||||
|
||||
if (paddr == offsetof(AlphaAccess, bootStrapCPU)) {
|
||||
case offsetof(AlphaAccess, bootStrapCPU):
|
||||
warn("%d: Trying to launch another CPU!", curTick);
|
||||
int cpu = val;
|
||||
assert(cpu > 0 && "Must not access primary cpu");
|
||||
assert(val > 0 && "Must not access primary cpu");
|
||||
|
||||
ExecContext *other_xc = req->xc->system->execContexts[cpu];
|
||||
other_xc->regs.intRegFile[16] = cpu;
|
||||
other_xc->regs.ipr[TheISA::IPR_PALtemp16] = cpu;
|
||||
other_xc->regs.intRegFile[0] = cpu;
|
||||
other_xc = req->xc->system->execContexts[val];
|
||||
other_xc->regs.intRegFile[16] = val;
|
||||
other_xc->regs.ipr[TheISA::IPR_PALtemp16] = val;
|
||||
other_xc->regs.intRegFile[0] = val;
|
||||
other_xc->regs.intRegFile[30] = alphaAccess->bootStrapImpure;
|
||||
other_xc->activate(); //Start the cpu
|
||||
return No_Fault;
|
||||
break;
|
||||
|
||||
default:
|
||||
return Machine_Check_Fault;
|
||||
}
|
||||
|
||||
return No_Fault;
|
||||
|
@ -183,6 +199,7 @@ AlphaAccess::serialize(ostream &os)
|
|||
SERIALIZE_SCALAR(diskBlock);
|
||||
SERIALIZE_SCALAR(diskOperation);
|
||||
SERIALIZE_SCALAR(outputChar);
|
||||
SERIALIZE_SCALAR(inputChar);
|
||||
SERIALIZE_SCALAR(bootStrapImpure);
|
||||
SERIALIZE_SCALAR(bootStrapCPU);
|
||||
}
|
||||
|
@ -205,6 +222,7 @@ AlphaAccess::unserialize(Checkpoint *cp, const std::string §ion)
|
|||
UNSERIALIZE_SCALAR(diskBlock);
|
||||
UNSERIALIZE_SCALAR(diskOperation);
|
||||
UNSERIALIZE_SCALAR(outputChar);
|
||||
UNSERIALIZE_SCALAR(inputChar);
|
||||
UNSERIALIZE_SCALAR(bootStrapImpure);
|
||||
UNSERIALIZE_SCALAR(bootStrapCPU);
|
||||
}
|
||||
|
|
|
@ -223,21 +223,32 @@ SimConsole::configTerm()
|
|||
}
|
||||
}
|
||||
|
||||
int
|
||||
#define MORE_PENDING (ULL(1) << 61)
|
||||
#define RECEIVE_SUCCESS (ULL(0) << 62)
|
||||
#define RECEIVE_NONE (ULL(2) << 62)
|
||||
#define RECEIVE_ERROR (ULL(3) << 62)
|
||||
|
||||
uint64_t
|
||||
SimConsole::in()
|
||||
{
|
||||
char c = 0;
|
||||
uint64_t val = 0;
|
||||
if (rxbuf.empty()) {
|
||||
clearInt(ReceiveInterrupt);
|
||||
return -1;
|
||||
val |= RECEIVE_NONE;
|
||||
return 0x8;
|
||||
} else {
|
||||
uint64_t val;
|
||||
rxbuf.read(&c, 1);
|
||||
val |= RECEIVE_SUCCESS | c;
|
||||
if (!rxbuf.empty())
|
||||
val |= MORE_PENDING;
|
||||
}
|
||||
|
||||
char c;
|
||||
rxbuf.read(&c, 1);
|
||||
DPRINTF(ConsoleVerbose, "in: \'%c\' %#02x retval: %#x\n",
|
||||
isprint(c) ? c : ' ', c, val);
|
||||
|
||||
DPRINTF(ConsoleVerbose, "in: \'%c\' %#02x status: %#x\n",
|
||||
isprint(c) ? c : ' ', c, _status);
|
||||
|
||||
return c;
|
||||
return val;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -109,9 +109,17 @@ class SimConsole : public SimObject
|
|||
// OS interface
|
||||
|
||||
// Get a character from the console.
|
||||
// return of -1 means there is no character pending.
|
||||
// the return value corresponds to the console GETC return value:
|
||||
// retval<63:61>
|
||||
// 000: success: character received
|
||||
// 001: success: character received, more pending
|
||||
// 100: failure: no character ready
|
||||
// 110: failure: character received with error
|
||||
// 111: failure: character received with error, more pending
|
||||
// retval<31:0>
|
||||
// character read from console
|
||||
// Interrupts are cleared when the buffer is empty.
|
||||
int in();
|
||||
uint64_t in();
|
||||
|
||||
// Send a character to the console
|
||||
void out(char c, bool raise_int = true);
|
||||
|
|
Loading…
Reference in a new issue