xref: /plan9-contrib/sys/src/9k/k10/devvga.c (revision 45e6af3b6d7025ef7184352bb3f6852edd8de07e)
1*45e6af3bSDavid du Colombier /*
2*45e6af3bSDavid du Colombier  * VGA controller
3*45e6af3bSDavid du Colombier  */
4*45e6af3bSDavid du Colombier #include "u.h"
5*45e6af3bSDavid du Colombier #include "../port/lib.h"
6*45e6af3bSDavid du Colombier #include "mem.h"
7*45e6af3bSDavid du Colombier #include "dat.h"
8*45e6af3bSDavid du Colombier #include "fns.h"
9*45e6af3bSDavid du Colombier #include "io.h"
10*45e6af3bSDavid du Colombier #include "../port/error.h"
11*45e6af3bSDavid du Colombier 
12*45e6af3bSDavid du Colombier #define	Image	IMAGE
13*45e6af3bSDavid du Colombier #include <draw.h>
14*45e6af3bSDavid du Colombier #include <memdraw.h>
15*45e6af3bSDavid du Colombier #include <cursor.h>
16*45e6af3bSDavid du Colombier #include "screen.h"
17*45e6af3bSDavid du Colombier 
18*45e6af3bSDavid du Colombier enum {
19*45e6af3bSDavid du Colombier 	Qdir,
20*45e6af3bSDavid du Colombier 	Qvgabios,
21*45e6af3bSDavid du Colombier 	Qvgactl,
22*45e6af3bSDavid du Colombier 	Qvgaovl,
23*45e6af3bSDavid du Colombier 	Qvgaovlctl,
24*45e6af3bSDavid du Colombier };
25*45e6af3bSDavid du Colombier 
26*45e6af3bSDavid du Colombier static Dirtab vgadir[] = {
27*45e6af3bSDavid du Colombier 	".",	{ Qdir, 0, QTDIR },		0,	0550,
28*45e6af3bSDavid du Colombier 	"vgabios",	{ Qvgabios, 0 },	0x100000, 0440,
29*45e6af3bSDavid du Colombier 	"vgactl",		{ Qvgactl, 0 },		0,	0660,
30*45e6af3bSDavid du Colombier 	"vgaovl",		{ Qvgaovl, 0 },		0,	0660,
31*45e6af3bSDavid du Colombier 	"vgaovlctl",	{ Qvgaovlctl, 0 },	0, 	0660,
32*45e6af3bSDavid du Colombier };
33*45e6af3bSDavid du Colombier 
34*45e6af3bSDavid du Colombier enum {
35*45e6af3bSDavid du Colombier 	CMactualsize,
36*45e6af3bSDavid du Colombier 	CMblank,
37*45e6af3bSDavid du Colombier 	CMblanktime,
38*45e6af3bSDavid du Colombier 	CMdrawinit,
39*45e6af3bSDavid du Colombier 	CMhwaccel,
40*45e6af3bSDavid du Colombier 	CMhwblank,
41*45e6af3bSDavid du Colombier 	CMhwgc,
42*45e6af3bSDavid du Colombier 	CMlinear,
43*45e6af3bSDavid du Colombier 	CMpalettedepth,
44*45e6af3bSDavid du Colombier 	CMpanning,
45*45e6af3bSDavid du Colombier 	CMsize,
46*45e6af3bSDavid du Colombier 	CMtextmode,
47*45e6af3bSDavid du Colombier 	CMtype,
48*45e6af3bSDavid du Colombier 	CMunblank,
49*45e6af3bSDavid du Colombier };
50*45e6af3bSDavid du Colombier 
51*45e6af3bSDavid du Colombier static Cmdtab vgactlmsg[] = {
52*45e6af3bSDavid du Colombier 	CMactualsize,	"actualsize",	2,
53*45e6af3bSDavid du Colombier 	CMblank,	"blank",	1,
54*45e6af3bSDavid du Colombier 	CMblanktime,	"blanktime",	2,
55*45e6af3bSDavid du Colombier 	CMdrawinit,	"drawinit",	1,
56*45e6af3bSDavid du Colombier 	CMhwaccel,	"hwaccel",	2,
57*45e6af3bSDavid du Colombier 	CMhwblank,	"hwblank",	2,
58*45e6af3bSDavid du Colombier 	CMhwgc,		"hwgc",		2,
59*45e6af3bSDavid du Colombier 	CMlinear,	"linear",	0,
60*45e6af3bSDavid du Colombier 	CMpalettedepth,	"palettedepth",	2,
61*45e6af3bSDavid du Colombier 	CMpanning,	"panning",	2,
62*45e6af3bSDavid du Colombier 	CMsize,		"size",		3,
63*45e6af3bSDavid du Colombier 	CMtextmode,	"textmode",	1,
64*45e6af3bSDavid du Colombier 	CMtype,		"type",		2,
65*45e6af3bSDavid du Colombier 	CMunblank,	"unblank",	1,
66*45e6af3bSDavid du Colombier };
67*45e6af3bSDavid du Colombier 
68*45e6af3bSDavid du Colombier static void
vgareset(void)69*45e6af3bSDavid du Colombier vgareset(void)
70*45e6af3bSDavid du Colombier {
71*45e6af3bSDavid du Colombier 	/* reserve the 'standard' vga registers */
72*45e6af3bSDavid du Colombier 	if(ioalloc(0x2b0, 0x2df-0x2b0+1, 0, "vga") < 0)
73*45e6af3bSDavid du Colombier 		panic("vga ports already allocated");
74*45e6af3bSDavid du Colombier 	if(ioalloc(0x3c0, 0x3da-0x3c0+1, 0, "vga") < 0)
75*45e6af3bSDavid du Colombier 		panic("vga ports already allocated");
76*45e6af3bSDavid du Colombier }
77*45e6af3bSDavid du Colombier 
78*45e6af3bSDavid du Colombier static Chan*
vgaattach(char * spec)79*45e6af3bSDavid du Colombier vgaattach(char* spec)
80*45e6af3bSDavid du Colombier {
81*45e6af3bSDavid du Colombier 	if(*spec && strcmp(spec, "0"))
82*45e6af3bSDavid du Colombier 		error(Eio);
83*45e6af3bSDavid du Colombier 	return devattach('v', spec);
84*45e6af3bSDavid du Colombier }
85*45e6af3bSDavid du Colombier 
86*45e6af3bSDavid du Colombier Walkqid*
vgawalk(Chan * c,Chan * nc,char ** name,int nname)87*45e6af3bSDavid du Colombier vgawalk(Chan* c, Chan *nc, char** name, int nname)
88*45e6af3bSDavid du Colombier {
89*45e6af3bSDavid du Colombier 	return devwalk(c, nc, name, nname, vgadir, nelem(vgadir), devgen);
90*45e6af3bSDavid du Colombier }
91*45e6af3bSDavid du Colombier 
92*45e6af3bSDavid du Colombier static long
vgastat(Chan * c,uchar * dp,long n)93*45e6af3bSDavid du Colombier vgastat(Chan* c, uchar* dp, long n)
94*45e6af3bSDavid du Colombier {
95*45e6af3bSDavid du Colombier 	return devstat(c, dp, n, vgadir, nelem(vgadir), devgen);
96*45e6af3bSDavid du Colombier }
97*45e6af3bSDavid du Colombier 
98*45e6af3bSDavid du Colombier static Chan*
vgaopen(Chan * c,int omode)99*45e6af3bSDavid du Colombier vgaopen(Chan* c, int omode)
100*45e6af3bSDavid du Colombier {
101*45e6af3bSDavid du Colombier 	VGAscr *scr;
102*45e6af3bSDavid du Colombier 	static char *openctl = "openctl\n";
103*45e6af3bSDavid du Colombier 
104*45e6af3bSDavid du Colombier 	scr = &vgascreen[0];
105*45e6af3bSDavid du Colombier 	if ((ulong)c->qid.path == Qvgaovlctl) {
106*45e6af3bSDavid du Colombier 		if (scr->dev && scr->dev->ovlctl)
107*45e6af3bSDavid du Colombier 			scr->dev->ovlctl(scr, c, openctl, strlen(openctl));
108*45e6af3bSDavid du Colombier 		else
109*45e6af3bSDavid du Colombier 			error(Enonexist);
110*45e6af3bSDavid du Colombier 	}
111*45e6af3bSDavid du Colombier 	return devopen(c, omode, vgadir, nelem(vgadir), devgen);
112*45e6af3bSDavid du Colombier }
113*45e6af3bSDavid du Colombier 
114*45e6af3bSDavid du Colombier static void
vgaclose(Chan * c)115*45e6af3bSDavid du Colombier vgaclose(Chan* c)
116*45e6af3bSDavid du Colombier {
117*45e6af3bSDavid du Colombier 	VGAscr *scr;
118*45e6af3bSDavid du Colombier 	static char *closectl = "closectl\n";
119*45e6af3bSDavid du Colombier 
120*45e6af3bSDavid du Colombier 	scr = &vgascreen[0];
121*45e6af3bSDavid du Colombier 	if((ulong)c->qid.path == Qvgaovlctl)
122*45e6af3bSDavid du Colombier 		if(scr->dev && scr->dev->ovlctl){
123*45e6af3bSDavid du Colombier 			if(waserror()){
124*45e6af3bSDavid du Colombier 				print("ovlctl error: %s\n", up->errstr);
125*45e6af3bSDavid du Colombier 				return;
126*45e6af3bSDavid du Colombier 			}
127*45e6af3bSDavid du Colombier 			scr->dev->ovlctl(scr, c, closectl, strlen(closectl));
128*45e6af3bSDavid du Colombier 			poperror();
129*45e6af3bSDavid du Colombier 		}
130*45e6af3bSDavid du Colombier }
131*45e6af3bSDavid du Colombier 
132*45e6af3bSDavid du Colombier static long
vgaread(Chan * c,void * a,long n,vlong off)133*45e6af3bSDavid du Colombier vgaread(Chan* c, void* a, long n, vlong off)
134*45e6af3bSDavid du Colombier {
135*45e6af3bSDavid du Colombier 	int len;
136*45e6af3bSDavid du Colombier 	char *p, *s;
137*45e6af3bSDavid du Colombier 	VGAscr *scr;
138*45e6af3bSDavid du Colombier 	ulong offset = off;
139*45e6af3bSDavid du Colombier 	char chbuf[30];
140*45e6af3bSDavid du Colombier 
141*45e6af3bSDavid du Colombier 	switch((ulong)c->qid.path){
142*45e6af3bSDavid du Colombier 
143*45e6af3bSDavid du Colombier 	case Qdir:
144*45e6af3bSDavid du Colombier 		return devdirread(c, a, n, vgadir, nelem(vgadir), devgen);
145*45e6af3bSDavid du Colombier 
146*45e6af3bSDavid du Colombier 	case Qvgabios:
147*45e6af3bSDavid du Colombier 		if(offset >= 0x100000)
148*45e6af3bSDavid du Colombier 			return 0;
149*45e6af3bSDavid du Colombier 		if(offset+n >= 0x100000)
150*45e6af3bSDavid du Colombier 			n = 0x100000 - offset;
151*45e6af3bSDavid du Colombier 		memmove(a, (uchar*)KADDR(0)+offset, n);
152*45e6af3bSDavid du Colombier 		return n;
153*45e6af3bSDavid du Colombier 
154*45e6af3bSDavid du Colombier 	case Qvgactl:
155*45e6af3bSDavid du Colombier 		scr = &vgascreen[0];
156*45e6af3bSDavid du Colombier 
157*45e6af3bSDavid du Colombier 		p = malloc(READSTR);
158*45e6af3bSDavid du Colombier 		if(p == nil)
159*45e6af3bSDavid du Colombier 			error(Enomem);
160*45e6af3bSDavid du Colombier 		if(waserror()){
161*45e6af3bSDavid du Colombier 			free(p);
162*45e6af3bSDavid du Colombier 			nexterror();
163*45e6af3bSDavid du Colombier 		}
164*45e6af3bSDavid du Colombier 
165*45e6af3bSDavid du Colombier 		len = 0;
166*45e6af3bSDavid du Colombier 
167*45e6af3bSDavid du Colombier 		if(scr->dev)
168*45e6af3bSDavid du Colombier 			s = scr->dev->name;
169*45e6af3bSDavid du Colombier 		else
170*45e6af3bSDavid du Colombier 			s = "cga";
171*45e6af3bSDavid du Colombier 		len += snprint(p+len, READSTR-len, "type %s\n", s);
172*45e6af3bSDavid du Colombier 
173*45e6af3bSDavid du Colombier 		if(scr->gscreen) {
174*45e6af3bSDavid du Colombier 			len += snprint(p+len, READSTR-len, "size %dx%dx%d %s\n",
175*45e6af3bSDavid du Colombier 				scr->gscreen->r.max.x, scr->gscreen->r.max.y,
176*45e6af3bSDavid du Colombier 				scr->gscreen->depth, chantostr(chbuf, scr->gscreen->chan));
177*45e6af3bSDavid du Colombier 
178*45e6af3bSDavid du Colombier 			if(Dx(scr->gscreen->r) != Dx(physgscreenr)
179*45e6af3bSDavid du Colombier 			|| Dy(scr->gscreen->r) != Dy(physgscreenr))
180*45e6af3bSDavid du Colombier 				len += snprint(p+len, READSTR-len, "actualsize %dx%d\n",
181*45e6af3bSDavid du Colombier 					physgscreenr.max.x, physgscreenr.max.y);
182*45e6af3bSDavid du Colombier 		}
183*45e6af3bSDavid du Colombier 
184*45e6af3bSDavid du Colombier 		len += snprint(p+len, READSTR-len, "blank time %lud idle %d state %s\n",
185*45e6af3bSDavid du Colombier 			blanktime, drawidletime(), scr->isblank ? "off" : "on");
186*45e6af3bSDavid du Colombier 		len += snprint(p+len, READSTR-len, "hwaccel %s\n", hwaccel ? "on" : "off");
187*45e6af3bSDavid du Colombier 		len += snprint(p+len, READSTR-len, "hwblank %s\n", hwblank ? "on" : "off");
188*45e6af3bSDavid du Colombier 		len += snprint(p+len, READSTR-len, "panning %s\n", panning ? "on" : "off");
189*45e6af3bSDavid du Colombier 		len += snprint(p+len, READSTR-len, "addr p 0x%lux v 0x%p size 0x%ux\n", scr->paddr, scr->vaddr, scr->apsize);
190*45e6af3bSDavid du Colombier 		USED(len);
191*45e6af3bSDavid du Colombier 
192*45e6af3bSDavid du Colombier 		n = readstr(offset, a, n, p);
193*45e6af3bSDavid du Colombier 		poperror();
194*45e6af3bSDavid du Colombier 		free(p);
195*45e6af3bSDavid du Colombier 
196*45e6af3bSDavid du Colombier 		return n;
197*45e6af3bSDavid du Colombier 
198*45e6af3bSDavid du Colombier 	case Qvgaovl:
199*45e6af3bSDavid du Colombier 	case Qvgaovlctl:
200*45e6af3bSDavid du Colombier 		error(Ebadusefd);
201*45e6af3bSDavid du Colombier 		break;
202*45e6af3bSDavid du Colombier 
203*45e6af3bSDavid du Colombier 	default:
204*45e6af3bSDavid du Colombier 		error(Egreg);
205*45e6af3bSDavid du Colombier 		break;
206*45e6af3bSDavid du Colombier 	}
207*45e6af3bSDavid du Colombier 
208*45e6af3bSDavid du Colombier 	return 0;
209*45e6af3bSDavid du Colombier }
210*45e6af3bSDavid du Colombier 
211*45e6af3bSDavid du Colombier static void
vgactl(Cmdbuf * cb)212*45e6af3bSDavid du Colombier vgactl(Cmdbuf *cb)
213*45e6af3bSDavid du Colombier {
214*45e6af3bSDavid du Colombier 	int align, i, size, x, y, z;
215*45e6af3bSDavid du Colombier 	char *chanstr, *p;
216*45e6af3bSDavid du Colombier 	ulong chan;
217*45e6af3bSDavid du Colombier 	Cmdtab *ct;
218*45e6af3bSDavid du Colombier 	VGAscr *scr;
219*45e6af3bSDavid du Colombier 	extern VGAdev *vgadev[];
220*45e6af3bSDavid du Colombier 	extern VGAcur *vgacur[];
221*45e6af3bSDavid du Colombier 
222*45e6af3bSDavid du Colombier 	scr = &vgascreen[0];
223*45e6af3bSDavid du Colombier 	ct = lookupcmd(cb, vgactlmsg, nelem(vgactlmsg));
224*45e6af3bSDavid du Colombier 	switch(ct->index){
225*45e6af3bSDavid du Colombier 	case CMhwgc:
226*45e6af3bSDavid du Colombier 		if(strcmp(cb->f[1], "off") == 0){
227*45e6af3bSDavid du Colombier 			lock(&cursor);
228*45e6af3bSDavid du Colombier 			if(scr->cur){
229*45e6af3bSDavid du Colombier 				if(scr->cur->disable)
230*45e6af3bSDavid du Colombier 					scr->cur->disable(scr);
231*45e6af3bSDavid du Colombier 				scr->cur = nil;
232*45e6af3bSDavid du Colombier 			}
233*45e6af3bSDavid du Colombier 			unlock(&cursor);
234*45e6af3bSDavid du Colombier 			return;
235*45e6af3bSDavid du Colombier 		}
236*45e6af3bSDavid du Colombier 		if(strcmp(cb->f[1], "soft") == 0){
237*45e6af3bSDavid du Colombier 			lock(&cursor);
238*45e6af3bSDavid du Colombier 			swcursorinit();
239*45e6af3bSDavid du Colombier 			if(scr->cur && scr->cur->disable)
240*45e6af3bSDavid du Colombier 				scr->cur->disable(scr);
241*45e6af3bSDavid du Colombier 			scr->cur = &swcursor;
242*45e6af3bSDavid du Colombier 			if(scr->cur->enable)
243*45e6af3bSDavid du Colombier 				scr->cur->enable(scr);
244*45e6af3bSDavid du Colombier 			unlock(&cursor);
245*45e6af3bSDavid du Colombier 			return;
246*45e6af3bSDavid du Colombier 		}
247*45e6af3bSDavid du Colombier 		for(i = 0; vgacur[i]; i++){
248*45e6af3bSDavid du Colombier 			if(strcmp(cb->f[1], vgacur[i]->name))
249*45e6af3bSDavid du Colombier 				continue;
250*45e6af3bSDavid du Colombier 			lock(&cursor);
251*45e6af3bSDavid du Colombier 			if(scr->cur && scr->cur->disable)
252*45e6af3bSDavid du Colombier 				scr->cur->disable(scr);
253*45e6af3bSDavid du Colombier 			scr->cur = vgacur[i];
254*45e6af3bSDavid du Colombier 			if(scr->cur->enable)
255*45e6af3bSDavid du Colombier 				scr->cur->enable(scr);
256*45e6af3bSDavid du Colombier 			unlock(&cursor);
257*45e6af3bSDavid du Colombier 			return;
258*45e6af3bSDavid du Colombier 		}
259*45e6af3bSDavid du Colombier 		break;
260*45e6af3bSDavid du Colombier 
261*45e6af3bSDavid du Colombier 	case CMtype:
262*45e6af3bSDavid du Colombier 		for(i = 0; vgadev[i]; i++){
263*45e6af3bSDavid du Colombier 			if(strcmp(cb->f[1], vgadev[i]->name))
264*45e6af3bSDavid du Colombier 				continue;
265*45e6af3bSDavid du Colombier 			if(scr->dev && scr->dev->disable)
266*45e6af3bSDavid du Colombier 				scr->dev->disable(scr);
267*45e6af3bSDavid du Colombier 			scr->dev = vgadev[i];
268*45e6af3bSDavid du Colombier 			if(scr->dev->enable)
269*45e6af3bSDavid du Colombier 				scr->dev->enable(scr);
270*45e6af3bSDavid du Colombier 			return;
271*45e6af3bSDavid du Colombier 		}
272*45e6af3bSDavid du Colombier 		break;
273*45e6af3bSDavid du Colombier 
274*45e6af3bSDavid du Colombier 	case CMtextmode:
275*45e6af3bSDavid du Colombier 		cgainit();
276*45e6af3bSDavid du Colombier 		return;
277*45e6af3bSDavid du Colombier 
278*45e6af3bSDavid du Colombier 	case CMsize:
279*45e6af3bSDavid du Colombier 		x = strtoul(cb->f[1], &p, 0);
280*45e6af3bSDavid du Colombier 		if(x == 0 || x > 10240)
281*45e6af3bSDavid du Colombier 			error(Ebadarg);
282*45e6af3bSDavid du Colombier 		if(*p)
283*45e6af3bSDavid du Colombier 			p++;
284*45e6af3bSDavid du Colombier 
285*45e6af3bSDavid du Colombier 		y = strtoul(p, &p, 0);
286*45e6af3bSDavid du Colombier 		if(y == 0 || y > 10240)
287*45e6af3bSDavid du Colombier 			error(Ebadarg);
288*45e6af3bSDavid du Colombier 		if(*p)
289*45e6af3bSDavid du Colombier 			p++;
290*45e6af3bSDavid du Colombier 
291*45e6af3bSDavid du Colombier 		z = strtoul(p, &p, 0);
292*45e6af3bSDavid du Colombier 
293*45e6af3bSDavid du Colombier 		chanstr = cb->f[2];
294*45e6af3bSDavid du Colombier 		if((chan = strtochan(chanstr)) == 0)
295*45e6af3bSDavid du Colombier 			error("bad channel");
296*45e6af3bSDavid du Colombier 
297*45e6af3bSDavid du Colombier 		if(chantodepth(chan) != z)
298*45e6af3bSDavid du Colombier 			error("depth, channel do not match");
299*45e6af3bSDavid du Colombier 
300*45e6af3bSDavid du Colombier 		cursoroff(1);
301*45e6af3bSDavid du Colombier 		deletescreenimage();
302*45e6af3bSDavid du Colombier 		if(screensize(x, y, z, chan))
303*45e6af3bSDavid du Colombier 			error(Egreg);
304*45e6af3bSDavid du Colombier 		vgascreenwin(scr);
305*45e6af3bSDavid du Colombier 		resetscreenimage();
306*45e6af3bSDavid du Colombier 		cursoron(1);
307*45e6af3bSDavid du Colombier 		return;
308*45e6af3bSDavid du Colombier 
309*45e6af3bSDavid du Colombier 	case CMactualsize:
310*45e6af3bSDavid du Colombier 		if(scr->gscreen == nil)
311*45e6af3bSDavid du Colombier 			error("set the screen size first");
312*45e6af3bSDavid du Colombier 
313*45e6af3bSDavid du Colombier 		x = strtoul(cb->f[1], &p, 0);
314*45e6af3bSDavid du Colombier 		if(x == 0 || x > 2048)
315*45e6af3bSDavid du Colombier 			error(Ebadarg);
316*45e6af3bSDavid du Colombier 		if(*p)
317*45e6af3bSDavid du Colombier 			p++;
318*45e6af3bSDavid du Colombier 
319*45e6af3bSDavid du Colombier 		y = strtoul(p, nil, 0);
320*45e6af3bSDavid du Colombier 		if(y == 0 || y > 2048)
321*45e6af3bSDavid du Colombier 			error(Ebadarg);
322*45e6af3bSDavid du Colombier 
323*45e6af3bSDavid du Colombier 		if(x > scr->gscreen->r.max.x || y > scr->gscreen->r.max.y)
324*45e6af3bSDavid du Colombier 			error("physical screen bigger than virtual");
325*45e6af3bSDavid du Colombier 
326*45e6af3bSDavid du Colombier 		physgscreenr = Rect(0,0,x,y);
327*45e6af3bSDavid du Colombier 		scr->gscreen->clipr = physgscreenr;
328*45e6af3bSDavid du Colombier 		return;
329*45e6af3bSDavid du Colombier 
330*45e6af3bSDavid du Colombier 	case CMpalettedepth:
331*45e6af3bSDavid du Colombier 		x = strtoul(cb->f[1], &p, 0);
332*45e6af3bSDavid du Colombier 		if(x != 8 && x != 6)
333*45e6af3bSDavid du Colombier 			error(Ebadarg);
334*45e6af3bSDavid du Colombier 
335*45e6af3bSDavid du Colombier 		scr->palettedepth = x;
336*45e6af3bSDavid du Colombier 		return;
337*45e6af3bSDavid du Colombier 
338*45e6af3bSDavid du Colombier 	case CMdrawinit:
339*45e6af3bSDavid du Colombier 		if(scr->gscreen == nil)
340*45e6af3bSDavid du Colombier 			error("drawinit: no gscreen");
341*45e6af3bSDavid du Colombier 		if(scr->dev && scr->dev->drawinit)
342*45e6af3bSDavid du Colombier 			scr->dev->drawinit(scr);
343*45e6af3bSDavid du Colombier 		return;
344*45e6af3bSDavid du Colombier 
345*45e6af3bSDavid du Colombier 	case CMlinear:
346*45e6af3bSDavid du Colombier 		if(cb->nf!=2 && cb->nf!=3)
347*45e6af3bSDavid du Colombier 			error(Ebadarg);
348*45e6af3bSDavid du Colombier 		size = strtoul(cb->f[1], 0, 0);
349*45e6af3bSDavid du Colombier 		if(cb->nf == 2)
350*45e6af3bSDavid du Colombier 			align = 0;
351*45e6af3bSDavid du Colombier 		else
352*45e6af3bSDavid du Colombier 			align = strtoul(cb->f[2], 0, 0);
353*45e6af3bSDavid du Colombier 		if(screenaperture(size, align) < 0)
354*45e6af3bSDavid du Colombier 			error("not enough free address space");
355*45e6af3bSDavid du Colombier 		return;
356*45e6af3bSDavid du Colombier /*
357*45e6af3bSDavid du Colombier 	case CMmemset:
358*45e6af3bSDavid du Colombier 		memset((void*)strtoul(cb->f[1], 0, 0), atoi(cb->f[2]), atoi(cb->f[3]));
359*45e6af3bSDavid du Colombier 		return;
360*45e6af3bSDavid du Colombier */
361*45e6af3bSDavid du Colombier 
362*45e6af3bSDavid du Colombier 	case CMblank:
363*45e6af3bSDavid du Colombier 		drawblankscreen(1);
364*45e6af3bSDavid du Colombier 		return;
365*45e6af3bSDavid du Colombier 
366*45e6af3bSDavid du Colombier 	case CMunblank:
367*45e6af3bSDavid du Colombier 		drawblankscreen(0);
368*45e6af3bSDavid du Colombier 		return;
369*45e6af3bSDavid du Colombier 
370*45e6af3bSDavid du Colombier 	case CMblanktime:
371*45e6af3bSDavid du Colombier 		blanktime = strtoul(cb->f[1], 0, 0);
372*45e6af3bSDavid du Colombier 		return;
373*45e6af3bSDavid du Colombier 
374*45e6af3bSDavid du Colombier 	case CMpanning:
375*45e6af3bSDavid du Colombier 		if(strcmp(cb->f[1], "on") == 0){
376*45e6af3bSDavid du Colombier 			if(scr == nil || scr->cur == nil)
377*45e6af3bSDavid du Colombier 				error("set screen first");
378*45e6af3bSDavid du Colombier 			if(!scr->cur->doespanning)
379*45e6af3bSDavid du Colombier 				error("panning not supported");
380*45e6af3bSDavid du Colombier 			scr->gscreen->clipr = scr->gscreen->r;
381*45e6af3bSDavid du Colombier 			panning = 1;
382*45e6af3bSDavid du Colombier 		}
383*45e6af3bSDavid du Colombier 		else if(strcmp(cb->f[1], "off") == 0){
384*45e6af3bSDavid du Colombier 			scr->gscreen->clipr = physgscreenr;
385*45e6af3bSDavid du Colombier 			panning = 0;
386*45e6af3bSDavid du Colombier 		}else
387*45e6af3bSDavid du Colombier 			break;
388*45e6af3bSDavid du Colombier 		return;
389*45e6af3bSDavid du Colombier 
390*45e6af3bSDavid du Colombier 	case CMhwaccel:
391*45e6af3bSDavid du Colombier 		if(strcmp(cb->f[1], "on") == 0)
392*45e6af3bSDavid du Colombier 			hwaccel = 1;
393*45e6af3bSDavid du Colombier 		else if(strcmp(cb->f[1], "off") == 0)
394*45e6af3bSDavid du Colombier 			hwaccel = 0;
395*45e6af3bSDavid du Colombier 		else
396*45e6af3bSDavid du Colombier 			break;
397*45e6af3bSDavid du Colombier 		return;
398*45e6af3bSDavid du Colombier 
399*45e6af3bSDavid du Colombier 	case CMhwblank:
400*45e6af3bSDavid du Colombier 		if(strcmp(cb->f[1], "on") == 0)
401*45e6af3bSDavid du Colombier 			hwblank = 1;
402*45e6af3bSDavid du Colombier 		else if(strcmp(cb->f[1], "off") == 0)
403*45e6af3bSDavid du Colombier 			hwblank = 0;
404*45e6af3bSDavid du Colombier 		else
405*45e6af3bSDavid du Colombier 			break;
406*45e6af3bSDavid du Colombier 		return;
407*45e6af3bSDavid du Colombier 	}
408*45e6af3bSDavid du Colombier 
409*45e6af3bSDavid du Colombier 	cmderror(cb, "bad VGA control message");
410*45e6af3bSDavid du Colombier }
411*45e6af3bSDavid du Colombier 
412*45e6af3bSDavid du Colombier char Enooverlay[] = "No overlay support";
413*45e6af3bSDavid du Colombier 
414*45e6af3bSDavid du Colombier static long
vgawrite(Chan * c,void * a,long n,vlong off)415*45e6af3bSDavid du Colombier vgawrite(Chan* c, void* a, long n, vlong off)
416*45e6af3bSDavid du Colombier {
417*45e6af3bSDavid du Colombier 	ulong offset = off;
418*45e6af3bSDavid du Colombier 	Cmdbuf *cb;
419*45e6af3bSDavid du Colombier 	VGAscr *scr;
420*45e6af3bSDavid du Colombier 
421*45e6af3bSDavid du Colombier 	switch((ulong)c->qid.path){
422*45e6af3bSDavid du Colombier 
423*45e6af3bSDavid du Colombier 	case Qdir:
424*45e6af3bSDavid du Colombier 		error(Eperm);
425*45e6af3bSDavid du Colombier 
426*45e6af3bSDavid du Colombier 	case Qvgactl:
427*45e6af3bSDavid du Colombier 		if(offset || n >= READSTR)
428*45e6af3bSDavid du Colombier 			error(Ebadarg);
429*45e6af3bSDavid du Colombier 		cb = parsecmd(a, n);
430*45e6af3bSDavid du Colombier 		if(waserror()){
431*45e6af3bSDavid du Colombier 			free(cb);
432*45e6af3bSDavid du Colombier 			nexterror();
433*45e6af3bSDavid du Colombier 		}
434*45e6af3bSDavid du Colombier 		vgactl(cb);
435*45e6af3bSDavid du Colombier 		poperror();
436*45e6af3bSDavid du Colombier 		free(cb);
437*45e6af3bSDavid du Colombier 		return n;
438*45e6af3bSDavid du Colombier 
439*45e6af3bSDavid du Colombier 	case Qvgaovl:
440*45e6af3bSDavid du Colombier 		scr = &vgascreen[0];
441*45e6af3bSDavid du Colombier 		if (scr->dev == nil || scr->dev->ovlwrite == nil) {
442*45e6af3bSDavid du Colombier 			error(Enooverlay);
443*45e6af3bSDavid du Colombier 			break;
444*45e6af3bSDavid du Colombier 		}
445*45e6af3bSDavid du Colombier 		return scr->dev->ovlwrite(scr, a, n, off);
446*45e6af3bSDavid du Colombier 
447*45e6af3bSDavid du Colombier 	case Qvgaovlctl:
448*45e6af3bSDavid du Colombier 		scr = &vgascreen[0];
449*45e6af3bSDavid du Colombier 		if (scr->dev == nil || scr->dev->ovlctl == nil) {
450*45e6af3bSDavid du Colombier 			error(Enooverlay);
451*45e6af3bSDavid du Colombier 			break;
452*45e6af3bSDavid du Colombier 		}
453*45e6af3bSDavid du Colombier 		scr->dev->ovlctl(scr, c, a, n);
454*45e6af3bSDavid du Colombier 		return n;
455*45e6af3bSDavid du Colombier 
456*45e6af3bSDavid du Colombier 	default:
457*45e6af3bSDavid du Colombier 		error(Egreg);
458*45e6af3bSDavid du Colombier 		break;
459*45e6af3bSDavid du Colombier 	}
460*45e6af3bSDavid du Colombier 
461*45e6af3bSDavid du Colombier 	return 0;
462*45e6af3bSDavid du Colombier }
463*45e6af3bSDavid du Colombier 
464*45e6af3bSDavid du Colombier Dev vgadevtab = {
465*45e6af3bSDavid du Colombier 	'v',
466*45e6af3bSDavid du Colombier 	"vga",
467*45e6af3bSDavid du Colombier 
468*45e6af3bSDavid du Colombier 	vgareset,
469*45e6af3bSDavid du Colombier 	devinit,
470*45e6af3bSDavid du Colombier 	devshutdown,
471*45e6af3bSDavid du Colombier 	vgaattach,
472*45e6af3bSDavid du Colombier 	vgawalk,
473*45e6af3bSDavid du Colombier 	vgastat,
474*45e6af3bSDavid du Colombier 	vgaopen,
475*45e6af3bSDavid du Colombier 	devcreate,
476*45e6af3bSDavid du Colombier 	vgaclose,
477*45e6af3bSDavid du Colombier 	vgaread,
478*45e6af3bSDavid du Colombier 	devbread,
479*45e6af3bSDavid du Colombier 	vgawrite,
480*45e6af3bSDavid du Colombier 	devbwrite,
481*45e6af3bSDavid du Colombier 	devremove,
482*45e6af3bSDavid du Colombier 	devwstat,
483*45e6af3bSDavid du Colombier };
484