87 lines
1.7 KiB
C
87 lines
1.7 KiB
C
#include "u.h"
|
|
#include "../port/lib.h"
|
|
#include "mem.h"
|
|
#include "dat.h"
|
|
#include "fns.h"
|
|
#include "../port/error.h"
|
|
#include "ureg.h"
|
|
|
|
/*
|
|
* GISB arbiter registers
|
|
*/
|
|
static u32int *regs = (u32int*)(VIRTIO2 + 0x400000);
|
|
|
|
enum {
|
|
ArbMasterMask = 0x004/4,
|
|
ArbTimer = 0x008/4,
|
|
TimerFreq = 216000000, // 216MHz
|
|
|
|
ArbErrCapClear = 0x7e4/4,
|
|
ArbErrCapAddrHi = 0x7e8/4,
|
|
ArbErrCapAddr = 0x7ec/4,
|
|
ArbErrCapData = 0x7f0/4,
|
|
ArbErrCapStatus = 0x7f4/4,
|
|
CapStatusTimeout = 1<<12,
|
|
CapStatusAbort = 1<<11,
|
|
CapStatusStrobe = 15<<2,
|
|
CapStatusWrite = 1<<1,
|
|
CapStatusValid = 1<<0,
|
|
ArbErrCapMaster = 0x7f8/4,
|
|
|
|
ArbIntrSts = 0x3000/4,
|
|
ArbIntrSet = 0x3004/4,
|
|
ArbIntrClr = 0x3008/4,
|
|
|
|
ArbCpuMaskSet = 0x3010/4,
|
|
};
|
|
|
|
static int
|
|
arberror(Ureg*)
|
|
{
|
|
u32int status, intr;
|
|
u32int master, data;
|
|
uvlong addr;
|
|
|
|
status = regs[ArbErrCapStatus];
|
|
if((status & CapStatusValid) == 0)
|
|
return 0;
|
|
intr = regs[ArbIntrSts];
|
|
master = regs[ArbErrCapMaster];
|
|
addr = regs[ArbErrCapAddr];
|
|
addr |= (uvlong)regs[ArbErrCapAddrHi]<<32;
|
|
data = regs[ArbErrCapData];
|
|
if(intr)
|
|
regs[ArbIntrClr] = intr;
|
|
regs[ArbErrCapClear] = CapStatusValid;
|
|
|
|
iprint("cpu%d: GISB arbiter error: %s%s %s bus addr %llux data %.8ux, "
|
|
"master %.8ux, status %.8ux, intr %.8ux\n",
|
|
m->machno,
|
|
(status & CapStatusTimeout) ? "timeout" : "",
|
|
(status & CapStatusAbort) ? "abort" : "",
|
|
(status & CapStatusWrite) ? "writing" : "reading",
|
|
addr, data,
|
|
master, status, intr);
|
|
|
|
return 1;
|
|
}
|
|
|
|
static void
|
|
arbclock(void)
|
|
{
|
|
arberror(nil);
|
|
}
|
|
|
|
void
|
|
gisblink(void)
|
|
{
|
|
extern int (*buserror)(Ureg*); // trap.c
|
|
|
|
regs[ArbErrCapClear] = CapStatusValid;
|
|
regs[ArbIntrClr] = -1;
|
|
|
|
addclock0link(arbclock, 100);
|
|
|
|
buserror = arberror;
|
|
}
|