/*
* ``Nevermore!''
*/
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
typedef struct Raven Raven;
struct Raven
{
ushort vid;
ushort did;
uchar _pad4;
uchar rev;
uchar _pad6[2];
ushort gcsr;
ushort feat;
uchar _padC[7];
uchar padj;
uchar _pad14[12];
ushort errtst;
ushort erren;
uchar _pad24[3];
uchar errst;
ulong errad;
uchar _pad2C[2];
ushort errat;
ulong piack;
uchar _pad34[12];
struct {
ushort start;
ushort end;
ushort off;
uchar _pad;
uchar attr;
} map[4];
struct {
ulong cntl;
uchar _pad[3];
uchar stat;
} wdt[2];
ulong gpr[4];
};
enum {
/* map[] attr bits */
Iom = (1<<0),
Mem = (1<<1),
Wpen = (1<<4),
Wen = (1<<6),
Ren = (1<<7),
};
static Raven *raven = (Raven*)RAVEN;
static ulong mpic;
static void
setmap(int i, ulong addr, ulong len, ulong busaddr, int attr)
{
raven->map[i].start = addr>>16;
raven->map[i].end = (addr+len-1)>>16;
raven->map[i].off = (busaddr-addr)>>16;
raven->map[i].attr = attr;
}
static ulong
swap32(ulong x)
{
return (x>>24)|((x>>8)&0xff00)|((x<<8)&0xff0000)|(x<<24);
}
static ulong
mpic32r(int rno)
{
return swap32(*(ulong*)(mpic+rno));
}
static void
mpic32w(int rno, ulong x)
{
*(ulong*)(mpic+rno) = swap32(x);
eieio();
}
void
raveninit(void)
{
int i;
Pcidev *p;
if(raven->vid != 0x1057 || raven->did !=0x4801)
panic("raven not found");
/* set up a sensible hardware memory/IO map */
setmap(0, PCIMEM0, PCISIZE0, 0, Wen|Ren|Mem);
setmap(1, KZERO, IOSIZE, 0, Wen|Ren); /* keeps PPCbug happy */
setmap(2, PCIMEM1, PCISIZE1, PCISIZE0, Wen|Ren|Mem);
setmap(3, IOMEM, IOSIZE, 0, Wen|Ren); /* I/O must be slot 3 for PCI cfg space */
p = pcimatch(nil, 0x1057, 0x4801);
if(p == nil)
panic("raven PCI regs not found");
mpic = (p->mem[1].bar+PCIMEM0);
/* ensure all interrupts are off, and routed to cpu 0 */
for(i = 0; i < 16; i++) {
mpic32w(0x10000+0x20*i, (1<<31)); /* mask */
mpic32w(0x10010+0x20*i, 1); /* route to cpu 0 */
}
mpic32w(0x20080, 1); /* cpu 0 task pri */
// mpic32w(0x21080, 1); /* cpu 1 task pri */
mpic32w(0x1020, (1<<29)); /* Mixed mode (8259 & Raven intrs both available) */
}
void
mpicenable(int vec, Vctl *v)
{
ulong x;
x = (1<<22)|(15<<16)|vec;
if(vec == 0)
x |= (1<<23);
mpic32w(0x10000+0x20*vec, x);
if(vec != 0)
v->eoi = mpiceoi;
}
void
mpicdisable(int vec)
{
mpic32w(0x10000+0x20*vec, (1<<31));
}
int
mpicintack(void)
{
return mpic32r(0x200A0 + (m->machno<<12));
}
int
mpiceoi(int vec)
{
USED(vec);
mpic32w(0x200B0 + (m->machno<<12), 0);
return 0;
}
|