summaryrefslogtreecommitdiff
path: root/sys/src/9/mtx/raven.c
blob: d6fcb017943d0a355441560a4a1b28ebc88b20b3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/*
 *	``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;
}