]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/alphapc/devvga.c
pci: add intel qm67 pch
[plan9front.git] / sys / src / 9 / alphapc / devvga.c
1 /*
2  * VGA controller
3  */
4 #include "u.h"
5 #include "../port/lib.h"
6 #include "mem.h"
7 #include "dat.h"
8 #include "fns.h"
9 #include "io.h"
10 #include "../port/error.h"
11
12 #define Image   IMAGE
13 #include <draw.h>
14 #include <memdraw.h>
15 #include <cursor.h>
16 #include "screen.h"
17
18 extern uchar    *vgabios;
19
20 enum {
21         Qdir,
22         Qvgactl,
23         Qvgabios,
24 };
25
26 static Dirtab vgadir[] = {
27         ".",    { Qdir, 0, QTDIR },             0,      0550,
28         "vgactl",       { Qvgactl, 0 },         0,      0660,
29         "vgabios",      { Qvgabios, 0 },                0x10000,        0440,
30 };
31
32 static void
33 vgareset(void)
34 {
35         /* reserve the 'standard' vga registers */
36         if(ioalloc(0x2b0, 0x2df-0x2b0+1, 0, "vga") < 0)
37                 panic("vga ports already allocated"); 
38         if(ioalloc(0x3c0, 0x3da-0x3c0+1, 0, "vga") < 0)
39                 panic("vga ports already allocated"); 
40         conf.monitor = 1;
41 }
42
43 static Chan*
44 vgaattach(char* spec)
45 {
46         if(*spec && strcmp(spec, "0"))
47                 error(Eio);
48         return devattach('v', spec);
49 }
50
51 Walkqid*
52 vgawalk(Chan* c, Chan *nc, char** name, int nname)
53 {
54         return devwalk(c, nc, name, nname, vgadir, nelem(vgadir), devgen);
55 }
56
57 static int
58 vgastat(Chan* c, uchar* dp, int n)
59 {
60         return devstat(c, dp, n, vgadir, nelem(vgadir), devgen);
61 }
62
63 static Chan*
64 vgaopen(Chan* c, int omode)
65 {
66         return devopen(c, omode, vgadir, nelem(vgadir), devgen);
67 }
68
69 static void
70 vgaclose(Chan*)
71 {
72 }
73
74 static void
75 checkport(int start, int end)
76 {
77         /* standard vga regs are OK */
78         if(start >= 0x2b0 && end <= 0x2df+1)
79                 return;
80         if(start >= 0x3c0 && end <= 0x3da+1)
81                 return;
82
83         if(iounused(start, end))
84                 return;
85         error(Eperm);
86 }
87
88 static long
89 vgaread(Chan* c, void* a, long n, vlong off)
90 {
91         int len;
92         char *p, *s;
93         VGAscr *scr;
94         ulong offset = off;
95         char chbuf[30];
96
97         switch((ulong)c->qid.path){
98
99         case Qdir:
100                 return devdirread(c, a, n, vgadir, nelem(vgadir), devgen);
101
102         case Qvgactl:
103                 scr = &vgascreen[0];
104
105                 p = malloc(READSTR);
106                 if(waserror()){
107                         free(p);
108                         nexterror();
109                 }
110
111                 len = 0;
112
113                 if(scr->dev)
114                         s = scr->dev->name;
115                 else
116                         s = "cga";
117                 len += snprint(p+len, READSTR-len, "type %s\n", s);
118
119                 if(scr->gscreen) {
120                         len += snprint(p+len, READSTR-len, "size %dx%dx%d %s\n",
121                                 scr->gscreen->r.max.x, scr->gscreen->r.max.y,
122                                 scr->gscreen->depth, chantostr(chbuf, scr->gscreen->chan));
123
124                         if(Dx(scr->gscreen->r) != Dx(physgscreenr) 
125                         || Dy(scr->gscreen->r) != Dy(physgscreenr))
126                                 len += snprint(p+len, READSTR-len, "actualsize %dx%d\n",
127                                         physgscreenr.max.x, physgscreenr.max.y);
128                 }
129
130                 len += snprint(p+len, READSTR-len, "blanktime %lud\n", blanktime);
131                 len += snprint(p+len, READSTR-len, "hwaccel %s\n", hwaccel ? "on" : "off");
132                 len += snprint(p+len, READSTR-len, "hwblank %s\n", hwblank ? "on" : "off");
133                 snprint(p+len, READSTR-len, "addr 0x%lux\n", scr->paddr);
134                 n = readstr(offset, a, n, p);
135                 poperror();
136                 free(p);
137
138                 return n;
139
140         case Qvgabios:
141                 if(vgabios == nil)
142                         error(Egreg);
143                 if(offset&0x80000000)
144                         offset &= ~0x800E0000;
145                 if(offset+n > 0x10000)
146                         n = 0x10000-offset;
147                 if(n < 0)
148                         return 0;
149                 memmove(a, vgabios+offset, n);
150                 return n;
151
152         default:
153                 error(Egreg);
154                 break;
155         }
156
157         return 0;
158 }
159
160 static char Ebusy[] = "vga already configured";
161
162 static void
163 vgactl(char* a)
164 {
165         int align, i, n, size, x, y, z;
166         char *chanstr, *field[6], *p;
167         ulong chan;
168         VGAscr *scr;
169         extern VGAdev *vgadev[];
170         extern VGAcur *vgacur[];
171         Rectangle r;
172
173         n = tokenize(a, field, nelem(field));
174         if(n < 1)
175                 error(Ebadarg);
176
177         scr = &vgascreen[0];
178         if(strcmp(field[0], "hwgc") == 0){
179                 if(n < 2)
180                         error(Ebadarg);
181
182                 if(strcmp(field[1], "off") == 0){
183                         lock(&cursor);
184                         if(scr->cur){
185                                 if(scr->cur->disable)
186                                         scr->cur->disable(scr);
187                                 scr->cur = nil;
188                         }
189                         unlock(&cursor);
190                         return;
191                 }
192
193                 for(i = 0; vgacur[i]; i++){
194                         if(strcmp(field[1], vgacur[i]->name))
195                                 continue;
196                         lock(&cursor);
197                         if(scr->cur && scr->cur->disable)
198                                 scr->cur->disable(scr);
199                         scr->cur = vgacur[i];
200                         if(scr->cur->enable)
201                                 scr->cur->enable(scr);
202                         unlock(&cursor);
203                         return;
204                 }
205         }
206         else if(strcmp(field[0], "type") == 0){
207                 if(n < 2)
208                         error(Ebadarg);
209
210                 for(i = 0; vgadev[i]; i++){
211                         if(strcmp(field[1], vgadev[i]->name))
212                                 continue;
213                         if(scr->dev && scr->dev->disable)
214                                 scr->dev->disable(scr);
215                         scr->dev = vgadev[i];
216                         if(scr->dev->enable)
217                                 scr->dev->enable(scr);
218                         return;
219                 }
220         }
221         else if(strcmp(field[0], "size") == 0){
222                 if(n < 3)
223                         error(Ebadarg);
224                 if(drawhasclients())
225                         error(Ebusy);
226
227                 x = strtoul(field[1], &p, 0);
228                 if(x == 0 || x > 2048)
229                         error(Ebadarg);
230                 if(*p)
231                         p++;
232
233                 y = strtoul(p, &p, 0);
234                 if(y == 0 || y > 2048)
235                         error(Ebadarg);
236                 if(*p)
237                         p++;
238
239                 z = strtoul(p, &p, 0);
240
241                 chanstr = field[2];
242                 if((chan = strtochan(chanstr)) == 0)
243                         error("bad channel");
244
245                 if(chantodepth(chan) != z)
246                         error("depth, channel do not match");
247
248                 cursoroff(1);
249                 deletescreenimage();
250                 if(screensize(x, y, z, chan))
251                         error(Egreg);
252                 vgascreenwin(scr);
253                 cursoron(1);
254                 return;
255         }
256         else if(strcmp(field[0], "actualsize") == 0){
257                 if(scr->gscreen == nil)
258                         error("set the screen size first");
259
260                 if(n < 2)
261                         error(Ebadarg);
262                 x = strtoul(field[1], &p, 0);
263                 if(x == 0 || x > 2048)
264                         error(Ebadarg);
265                 if(*p)
266                         p++;
267
268                 y = strtoul(p, nil, 0);
269                 if(y == 0 || y > 2048)
270                         error(Ebadarg);
271
272                 if(x > scr->gscreen->r.max.x || y > scr->gscreen->r.max.y)
273                         error("physical screen bigger than virtual");
274
275                 r = Rect(0,0,x,y);
276                 if(!eqrect(r, scr->gscreen->r)){
277                         if(scr->cur == nil || scr->cur->doespanning == 0)
278                                 error("virtual screen not supported");
279                 }
280
281                 physgscreenr = r;
282                 return;
283         }
284         else if(strcmp(field[0], "palettedepth") == 0){
285                 if(n < 2)
286                         error(Ebadarg);
287
288                 x = strtoul(field[1], &p, 0);
289                 if(x != 8 && x != 6)
290                         error(Ebadarg);
291
292                 scr->palettedepth = x;
293                 return;
294         }
295         else if(strcmp(field[0], "drawinit") == 0){
296                 if(scr && scr->dev && scr->dev->drawinit)
297                         scr->dev->drawinit(scr);
298                 return;
299         }
300         else if(strcmp(field[0], "linear") == 0){
301                 if(n < 2)
302                         error(Ebadarg);
303
304                 size = strtoul(field[1], 0, 0);
305                 if(n < 3)
306                         align = 0;
307                 else
308                         align = strtoul(field[2], 0, 0);
309                 if(screenaperture(size, align))
310                         error("not enough free address space");
311                 return;
312         }
313 /*      else if(strcmp(field[0], "memset") == 0){
314                 if(n < 4)
315                         error(Ebadarg);
316                 memset((void*)strtoul(field[1], 0, 0), atoi(field[2]), atoi(field[3]));
317                 return;
318         }
319 */
320         else if(strcmp(field[0], "blank") == 0){
321                 if(n < 1)
322                         error(Ebadarg);
323                 drawblankscreen(1);
324                 return;
325         }
326         else if(strcmp(field[0], "blanktime") == 0){
327                 if(n < 2)
328                         error(Ebadarg);
329                 blanktime = strtoul(field[1], 0, 0);
330                 return;
331         }
332         else if(strcmp(field[0], "hwaccel") == 0){
333                 if(n < 2)
334                         error(Ebadarg);
335                 if(strcmp(field[1], "on") == 0)
336                         hwaccel = 1;
337                 else if(strcmp(field[1], "off") == 0)
338                         hwaccel = 0;
339                 return;
340         }
341         else if(strcmp(field[0], "hwblank") == 0){
342                 if(n < 2)
343                         error(Ebadarg);
344                 if(strcmp(field[1], "on") == 0)
345                         hwblank = 1;
346                 else if(strcmp(field[1], "off") == 0)
347                         hwblank = 0;
348                 return;
349         }
350
351         error(Ebadarg);
352 }
353
354 static long
355 vgawrite(Chan* c, void* a, long n, vlong off)
356 {
357         char *p;
358         ulong offset = off;
359
360         switch((ulong)c->qid.path){
361
362         case Qdir:
363                 error(Eperm);
364
365         case Qvgactl:
366                 if(offset || n >= READSTR)
367                         error(Ebadarg);
368                 p = malloc(READSTR);
369                 if(waserror()){
370                         free(p);
371                         nexterror();
372                 }
373                 memmove(p, a, n);
374                 p[n] = 0;
375                 vgactl(p);
376                 poperror();
377                 free(p);
378                 return n;
379
380         default:
381                 error(Egreg);
382                 break;
383         }
384
385         return 0;
386 }
387
388 Dev vgadevtab = {
389         'v',
390         "vga",
391
392         vgareset,
393         devinit,        
394         devshutdown,
395         vgaattach,
396         vgawalk,
397         vgastat,
398         vgaopen,
399         devcreate,
400         vgaclose,
401         vgaread,
402         devbread,
403         vgawrite,
404         devbwrite,
405         devremove,
406         devwstat,
407 };