Subversion Repositories planix.SVN

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
 *      ``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;
}