Subversion Repositories planix.SVN

Rev

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

Rev Author Line No. Line
2 - 1
#include "u.h"
2
#include "../port/lib.h"
3
#include "mem.h"
4
#include "dat.h"
5
#include "fns.h"
6
 
7
/*
8
 * Mailbox interface with videocore gpu
9
 */
10
 
11
#define	MAILBOX		(VIRTIO+0xB880)
12
 
13
typedef struct Prophdr Prophdr;
14
typedef struct Fbinfo Fbinfo;
15
 
16
enum {
17
	Read		= 0x00>>2,
18
	Write		= 0x00>>2,
19
	Peek		= 0x10>>2,
20
	Sender		= 0x14>>2,
21
	Status		= 0x18>>2,
22
		Full		= 1<<31,
23
		Empty		= 1<<30,
24
	Config		= 0x1C>>2,
25
	NRegs		= 0x20>>2,
26
 
27
	ChanMask	= 0xF,
28
	ChanProps	= 8,
29
	ChanFb		= 1,
30
 
31
	Req			= 0x0,
32
	RspOk		= 0x80000000,
33
	TagResp		= 1<<31,
34
 
35
	TagGetfwrev	= 0x00000001,
36
	TagGetmac	= 0x00010003,
37
	TagGetram	= 0x00010005,
38
	TagGetpower	= 0x00020001,
39
	TagSetpower	= 0x00028001,
40
		Powerwait	= 1<<1,
41
	TagGetclkspd= 0x00030002,
42
	TagFballoc	= 0x00040001,
43
	TagFbfree	= 0x00048001,
44
	TagFbblank	= 0x00040002,
45
	TagGetres	= 0x00040003,
46
	TagSetres	= 0x00048003,
47
	TagGetvres	= 0x00040004,
48
	TagSetvres	= 0x00048004,
49
	TagGetdepth	= 0x00040005,
50
	TagSetdepth	= 0x00048005,
51
	TagGetrgb	= 0x00044006,
52
	TagSetrgb	= 0x00048006,
53
};
54
 
55
struct Fbinfo {
56
	u32int	xres;
57
	u32int	yres;
58
	u32int	xresvirtual;
59
	u32int	yresvirtual;
60
	u32int	pitch;			/* returned by gpu */
61
	u32int	bpp;
62
	u32int	xoffset;
63
	u32int	yoffset;
64
	u32int	base;			/* returned by gpu */
65
	u32int	screensize;		/* returned by gpu */
66
};
67
 
68
 
69
struct Prophdr {
70
	u32int	len;
71
	u32int	req;
72
	u32int	tag;
73
	u32int	tagbuflen;
74
	u32int	taglen;
75
	u32int	data[1];
76
};
77
 
78
static void
79
vcwrite(uint chan, int val)
80
{
81
	u32int *r;
82
 
83
	r = (u32int*)MAILBOX + NRegs;
84
	val &= ~ChanMask;
85
	while(r[Status]&Full)
86
		;
87
	coherence();
88
	r[Write] = val | chan;
89
}
90
 
91
static int
92
vcread(uint chan)
93
{
94
	u32int *r;
95
	int x;
96
 
97
	r = (u32int*)MAILBOX;
98
	do{
99
		while(r[Status]&Empty)
100
			;
101
		coherence();
102
		x = r[Read];
103
	}while((x&ChanMask) != chan);
104
	return x & ~ChanMask;
105
}
106
 
107
/*
108
 * Property interface
109
 */
110
 
111
static int
112
vcreq(int tag, void *buf, int vallen, int rsplen)
113
{
114
	uintptr r;
115
	int n;
116
	Prophdr *prop;
117
	static uintptr base = BUSDRAM;
118
 
119
	if(rsplen < vallen)
120
		rsplen = vallen;
121
	rsplen = (rsplen+3) & ~3;
122
	prop = (Prophdr*)(VCBUFFER);
123
	n = sizeof(Prophdr) + rsplen + 8;
124
	memset(prop, 0, n);
125
	prop->len = n;
126
	prop->req = Req;
127
	prop->tag = tag;
128
	prop->tagbuflen = rsplen;
129
	prop->taglen = vallen;
130
	if(vallen > 0)
131
		memmove(prop->data, buf, vallen);
132
	cachedwbinvse(prop, prop->len);
133
	for(;;){
134
		vcwrite(ChanProps, PADDR(prop) + base);
135
		r = vcread(ChanProps);
136
		if(r == PADDR(prop) + base)
137
			break;
138
		if(base == 0)
139
			return -1;
140
		base = 0;
141
	}
142
	if(prop->req == RspOk &&
143
	   prop->tag == tag &&
144
	   (prop->taglen&TagResp)) {
145
		if((n = prop->taglen & ~TagResp) < rsplen)
146
			rsplen = n;
147
		memmove(buf, prop->data, rsplen);
148
	}else
149
		rsplen = -1;
150
 
151
	return rsplen;
152
}
153
 
154
/*
155
 * Framebuffer
156
 */
157
 
158
static int
159
fbdefault(int *width, int *height, int *depth)
160
{
161
	u32int buf[3];
162
 
163
	if(vcreq(TagGetres, &buf[0], 0, 2*4) != 2*4 ||
164
	   vcreq(TagGetdepth, &buf[2], 0, 4) != 4)
165
		return -1;
166
	*width = buf[0];
167
	*height = buf[1];
168
	*depth = buf[2];
169
	return 0;
170
}
171
 
172
void*
173
fbinit(int set, int *width, int *height, int *depth)
174
{
175
	Fbinfo *fi;
176
	uintptr va;
177
 
178
	if(!set)
179
		fbdefault(width, height, depth);
180
	/* Screen width must be a multiple of 16 */
181
	*width &= ~0xF;
182
	fi = (Fbinfo*)(VCBUFFER);
183
	memset(fi, 0, sizeof(*fi));
184
	fi->xres = fi->xresvirtual = *width;
185
	fi->yres = fi->yresvirtual = *height;
186
	fi->bpp = *depth;
187
	cachedwbinvse(fi, sizeof(*fi));
188
	vcwrite(ChanFb, DMAADDR(fi));
189
	if(vcread(ChanFb) != 0)
190
		return 0;
191
	va = mmukmap(FRAMEBUFFER, PADDR(fi->base), fi->screensize);
192
	if(va)
193
		memset((char*)va, 0x7F, fi->screensize);
194
	return (void*)va;
195
}
196
 
197
int
198
fbblank(int blank)
199
{
200
	u32int buf[1];
201
 
202
	buf[0] = blank;
203
	if(vcreq(TagFbblank, buf, sizeof buf, sizeof buf) != sizeof buf)
204
		return -1;
205
	return buf[0] & 1;
206
}
207
 
208
/*
209
 * Power management
210
 */
211
void
212
setpower(int dev, int on)
213
{
214
	u32int buf[2];
215
 
216
	buf[0] = dev;
217
	buf[1] = Powerwait | (on? 1 : 0);
218
	vcreq(TagSetpower, buf, sizeof buf, sizeof buf);
219
}
220
 
221
int
222
getpower(int dev)
223
{
224
	u32int buf[2];
225
 
226
	buf[0] = dev;
227
	buf[1] = 0;
228
	if(vcreq(TagGetpower, buf, sizeof buf[0], sizeof buf) != sizeof buf)
229
		return -1;
230
	return buf[0] & 1;
231
}
232
 
233
/*
234
 * Get ethernet address (as hex string)
235
 *	 [not reentrant]
236
 */
237
char *
238
getethermac(void)
239
{
240
	uchar ea[8];
241
	char *p;
242
	int i;
243
	static char buf[16];
244
 
245
	memset(ea, 0, sizeof ea);
246
	vcreq(TagGetmac, ea, 0, sizeof ea);
247
	p = buf;
248
	for(i = 0; i < 6; i++)
249
		p += sprint(p, "%.2x", ea[i]);
250
	return buf;
251
}
252
 
253
/*
254
 * Get firmware revision
255
 */
256
uint
257
getfirmware(void)
258
{
259
	u32int buf[1];
260
 
261
	if(vcreq(TagGetfwrev, buf, 0, sizeof buf) != sizeof buf)
262
		return 0;
263
	return buf[0];
264
}
265
 
266
/*
267
 * Get ARM ram
268
 */
269
void
270
getramsize(Confmem *mem)
271
{
272
	u32int buf[2];
273
 
274
	if(vcreq(TagGetram, buf, 0, sizeof buf) != sizeof buf)
275
		return;
276
	mem->base = buf[0];
277
	mem->limit = buf[1];
278
}
279
 
280
/*
281
 * Get clock rate
282
 */
283
ulong
284
getclkrate(int clkid)
285
{
286
	u32int buf[2];
287
 
288
	buf[0] = clkid;
289
	if(vcreq(TagGetclkspd, buf, sizeof(buf[0]), sizeof(buf)) != sizeof buf)
290
		return 0;
291
	return buf[1];
292
}