grf.c revision 1.11 1 /* $NetBSD: grf.c,v 1.11 1996/08/27 21:55:45 cgd Exp $ */
2
3 /*
4 * Copyright (c) 1995 Leo Weppelman
5 * Copyright (c) 1988 University of Utah.
6 * Copyright (c) 1990 The Regents of the University of California.
7 * All rights reserved.
8 *
9 * This code is derived from software contributed to Berkeley by
10 * the Systems Programming Group of the University of Utah Computer
11 * Science Department.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 * 3. All advertising materials mentioning features or use of this software
22 * must display the following acknowledgement:
23 * This product includes software developed by the University of
24 * California, Berkeley and its contributors.
25 * 4. Neither the name of the University nor the names of its contributors
26 * may be used to endorse or promote products derived from this software
27 * without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
30 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 * SUCH DAMAGE.
40 *
41 * from: Utah $Hdr: grf.c 1.31 91/01/21$
42 *
43 * @(#)grf.c 7.8 (Berkeley) 5/7/91
44 */
45
46 /*
47 * Graphics display driver for the Atari
48 * This is the hardware-independent portion of the driver.
49 * Hardware access is through the grf_softc->g_mode routine.
50 */
51
52 #include <sys/param.h>
53 #include <sys/proc.h>
54 #include <sys/ioctl.h>
55 #include <sys/device.h>
56 #include <sys/file.h>
57 #include <sys/malloc.h>
58 #include <sys/conf.h>
59 #include <sys/systm.h>
60 #include <sys/vnode.h>
61 #include <sys/mman.h>
62 #include <vm/vm.h>
63 #include <vm/vm_kern.h>
64 #include <vm/vm_page.h>
65 #include <vm/vm_pager.h>
66 #include <machine/cpu.h>
67 #include <atari/atari/device.h>
68 #include <atari/dev/grfioctl.h>
69 #include <atari/dev/grfabs_reg.h>
70 #include <atari/dev/grfvar.h>
71 #include <atari/dev/itevar.h>
72 #include <atari/dev/viewioctl.h>
73 #include <atari/dev/viewvar.h>
74
75 #include "grf.h"
76 #if NGRF > 0
77
78 #include "ite.h"
79 #if NITE == 0
80 #define ite_on(u,f)
81 #define ite_off(u,f)
82 #define ite_reinit(d)
83 #endif
84
85 dev_type_open(grfopen);
86 dev_type_close(grfclose);
87 dev_type_ioctl(grfioctl);
88 dev_type_select(grfselect);
89 dev_type_mmap(grfmmap);
90
91 int grfon __P((dev_t));
92 int grfoff __P((dev_t));
93 int grfsinfo __P((dev_t, struct grfdyninfo *));
94 #ifdef BANKEDDEVPAGER
95 int grfbanked_get __P((dev_t, off_t, int));
96 int grfbanked_cur __P((dev_t));
97 int grfbanked_set __P((dev_t, int));
98 #endif
99 static void grf_viewsync __P((struct grf_softc *));
100 static int grf_mode __P((struct grf_softc *, int, void *, int, int));
101
102 int grfbusprint __P((void *auxp, const char *));
103 int grfbusmatch __P((struct device *, void *, void *));
104 void grfbusattach __P((struct device *, struct device *, void *));
105
106 void grfattach __P((struct device *, struct device *, void *));
107 int grfmatch __P((struct device *, void *, void *));
108 int grfprint __P((void *, const char *));
109 /*
110 * pointers to grf drivers device structs
111 */
112 struct grf_softc *grfsp[NGRF];
113
114 struct cfattach grfbus_ca = {
115 sizeof(struct device), grfbusmatch, grfbusattach
116 };
117
118 struct cfdriver grfbus_cd = {
119 NULL, "grfbus", DV_DULL
120 };
121
122 struct cfattach grf_ca = {
123 sizeof(struct grf_softc), grfmatch, grfattach
124 };
125
126 struct cfdriver grf_cd = {
127 NULL, "grf", DV_DULL
128 };
129
130 /*
131 * only used in console init.
132 */
133 static struct cfdata *cfdata_gbus = NULL;
134 static struct cfdata *cfdata_grf = NULL;
135
136 int
137 grfbusmatch(pdp, match, auxp)
138 struct device *pdp;
139 void *match, *auxp;
140 {
141 struct cfdata *cfp = match;
142
143 if(strcmp(auxp, grfbus_cd.cd_name))
144 return(0);
145
146 if((atari_realconfig == 0) || (cfdata_gbus == NULL)) {
147 /*
148 * Probe layers we depend on
149 */
150 if(grfabs_probe() == 0)
151 return(0);
152 viewprobe();
153
154 if(atari_realconfig == 0) {
155 /*
156 * XXX: console init opens view 0
157 */
158 if(viewopen(0, 0, 0, NULL))
159 return(0);
160 cfdata_gbus = cfp;
161 }
162 }
163 return(1); /* Always there */
164 }
165
166 void
167 grfbusattach(pdp, dp, auxp)
168 struct device *pdp, *dp;
169 void *auxp;
170 {
171 static int did_cons = 0;
172 int i;
173
174 if(dp == NULL) { /* Console init */
175 did_cons = 1;
176 i = 0;
177 atari_config_found(cfdata_gbus, NULL, (void*)&i, grfbusprint);
178 }
179 else {
180 printf("\n");
181 for(i = 0; i < NGRF; i++) {
182 /*
183 * Skip opening view[0] when we this is the console.
184 */
185 if(!did_cons || (i > 0))
186 if(viewopen(i, 0, 0, NULL))
187 break;
188 config_found(dp, (void*)&i, grfbusprint);
189 }
190 }
191 }
192
193 int
194 grfbusprint(auxp, name)
195 void *auxp;
196 const char *name;
197 {
198 if(name == NULL)
199 return(UNCONF);
200 return(QUIET);
201 }
202
203
204 int
205 grfmatch(pdp, match, auxp)
206 struct device *pdp;
207 void *match, *auxp;
208 {
209 int unit = *(int*)auxp;
210 struct cfdata *cfp = match;
211
212 /*
213 * Match only on unit indicated by grfbus attach.
214 */
215 if(cfp->cf_unit != unit)
216 return(0);
217
218 cfdata_grf = cfp;
219 return(1);
220 }
221
222 /*
223 * attach: initialize the grf-structure and try to attach an ite to us.
224 * note : dp is NULL during early console init.
225 */
226 void
227 grfattach(pdp, dp, auxp)
228 struct device *pdp, *dp;
229 void *auxp;
230 {
231 static struct grf_softc congrf;
232 struct grf_softc *gp;
233 int maj;
234
235 /*
236 * find our major device number
237 */
238 for(maj = 0; maj < nchrdev; maj++)
239 if (cdevsw[maj].d_open == grfopen)
240 break;
241
242 /*
243 * Handle exeption case: early console init
244 */
245 if(dp == NULL) {
246 congrf.g_unit = 0;
247 congrf.g_grfdev = makedev(maj, 0);
248 congrf.g_flags = GF_ALIVE;
249 congrf.g_mode = grf_mode;
250 congrf.g_conpri = grfcc_cnprobe();
251 congrf.g_viewdev = congrf.g_unit;
252 grfcc_iteinit(&congrf);
253 grf_viewsync(&congrf);
254
255 /* Attach console ite */
256 atari_config_found(cfdata_grf, NULL, &congrf, grfprint);
257 return;
258 }
259
260 gp = (struct grf_softc *)dp;
261 gp->g_unit = gp->g_device.dv_unit;
262 grfsp[gp->g_unit] = gp;
263
264 if((cfdata_grf != NULL) && (gp->g_unit == 0)) {
265 /*
266 * We inited earlier just copy the info, take care
267 * not to copy the device struct though.
268 */
269 bcopy(&congrf.g_display, &gp->g_display,
270 (char *)&gp[1] - (char *)&gp->g_display);
271 }
272 else {
273 gp->g_grfdev = makedev(maj, gp->g_unit);
274 gp->g_flags = GF_ALIVE;
275 gp->g_mode = grf_mode;
276 gp->g_conpri = 0;
277 gp->g_viewdev = gp->g_unit;
278 grfcc_iteinit(gp);
279 grf_viewsync(gp);
280 }
281
282 printf(": width %d height %d", gp->g_display.gd_dwidth,
283 gp->g_display.gd_dheight);
284 if(gp->g_display.gd_colors == 2)
285 printf(" monochrome\n");
286 else printf(" colors %d\n", gp->g_display.gd_colors);
287
288 /*
289 * try and attach an ite
290 */
291 config_found(dp, gp, grfprint);
292 }
293
294 int
295 grfprint(auxp, pnp)
296 void *auxp;
297 const char *pnp;
298 {
299 if(pnp)
300 printf("ite at %s", pnp);
301 return(UNCONF);
302 }
303
304 /*ARGSUSED*/
305 int
306 grfopen(dev, flags, devtype, p)
307 dev_t dev;
308 int flags, devtype;
309 struct proc *p;
310 {
311 struct grf_softc *gp;
312
313 if (GRFUNIT(dev) >= NGRF)
314 return(ENXIO);
315
316 gp = grfsp[GRFUNIT(dev)];
317
318 if ((gp->g_flags & GF_ALIVE) == 0)
319 return(ENXIO);
320
321 if ((gp->g_flags & (GF_OPEN|GF_EXCLUDE)) == (GF_OPEN|GF_EXCLUDE))
322 return(EBUSY);
323 grf_viewsync(gp);
324
325 return(0);
326 }
327
328 /*ARGSUSED*/
329 int
330 grfclose(dev, flags, mode, p)
331 dev_t dev;
332 int flags;
333 int mode;
334 struct proc *p;
335 {
336 struct grf_softc *gp;
337
338 gp = grfsp[GRFUNIT(dev)];
339 (void)grfoff(dev);
340 gp->g_flags &= GF_ALIVE;
341 return(0);
342 }
343
344 /*ARGSUSED*/
345 int
346 grfioctl(dev, cmd, data, flag, p)
347 dev_t dev;
348 u_long cmd;
349 int flag;
350 caddr_t data;
351 struct proc *p;
352 {
353 struct grf_softc *gp;
354 int error;
355
356 gp = grfsp[GRFUNIT(dev)];
357 error = 0;
358
359 switch (cmd) {
360 case OGRFIOCGINFO:
361 /* argl.. no bank-member.. */
362 bcopy((caddr_t)&gp->g_display, data, sizeof(struct grfinfo)-4);
363 break;
364 case GRFIOCGINFO:
365 bcopy((caddr_t)&gp->g_display, data, sizeof(struct grfinfo));
366 break;
367 case GRFIOCON:
368 error = grfon(dev);
369 break;
370 case GRFIOCOFF:
371 error = grfoff(dev);
372 break;
373 case GRFIOCSINFO:
374 error = grfsinfo(dev, (struct grfdyninfo *) data);
375 break;
376 case GRFGETVMODE:
377 return(gp->g_mode(gp, GM_GRFGETVMODE, data, 0, 0));
378 case GRFSETVMODE:
379 error = gp->g_mode(gp, GM_GRFSETVMODE, data, 0, 0);
380 if (error == 0 && gp->g_itedev)
381 ite_reinit(gp->g_itedev);
382 break;
383 case GRFGETNUMVM:
384 return(gp->g_mode(gp, GM_GRFGETNUMVM, data, 0, 0));
385 /*
386 * these are all hardware dependant, and have to be resolved
387 * in the respective driver.
388 */
389 case GRFIOCPUTCMAP:
390 case GRFIOCGETCMAP:
391 case GRFIOCSSPRITEPOS:
392 case GRFIOCGSPRITEPOS:
393 case GRFIOCSSPRITEINF:
394 case GRFIOCGSPRITEINF:
395 case GRFIOCGSPRITEMAX:
396 default:
397 /*
398 * check to see whether it's a command recognized by the
399 * view code.
400 */
401 return(viewioctl(gp->g_viewdev, cmd, data, flag, p));
402 error = EINVAL;
403 break;
404
405 }
406 return(error);
407 }
408
409 /*ARGSUSED*/
410 int
411 grfselect(dev, rw, p)
412 dev_t dev;
413 int rw;
414 struct proc *p;
415 {
416 if (rw == FREAD)
417 return(0);
418 return(1);
419 }
420
421 /*
422 * map the contents of a graphics display card into process'
423 * memory space.
424 */
425 int
426 grfmmap(dev, off, prot)
427 dev_t dev;
428 int off, prot;
429 {
430 struct grf_softc *gp;
431 struct grfinfo *gi;
432
433 gp = grfsp[GRFUNIT(dev)];
434 gi = &gp->g_display;
435
436 /*
437 * frame buffer
438 */
439 if ((off >= 0) && (off < gi->gd_fbsize))
440 return (((u_int)gi->gd_fbaddr + off) >> PGSHIFT);
441 return(-1);
442 }
443
444 int
445 grfon(dev)
446 dev_t dev;
447 {
448 struct grf_softc *gp;
449
450 gp = grfsp[GRFUNIT(dev)];
451
452 if (gp->g_flags & GF_GRFON)
453 return(0);
454
455 gp->g_flags |= GF_GRFON;
456 if (gp->g_itedev != NODEV)
457 ite_off(gp->g_itedev, 3);
458
459 return(gp->g_mode(gp, (dev & GRFOVDEV) ? GM_GRFOVON : GM_GRFON,
460 NULL, 0, 0));
461 }
462
463 int
464 grfoff(dev)
465 dev_t dev;
466 {
467 struct grf_softc *gp;
468 int error;
469
470 gp = grfsp[GRFUNIT(dev)];
471
472 if ((gp->g_flags & GF_GRFON) == 0)
473 return(0);
474
475 gp->g_flags &= ~GF_GRFON;
476 error = gp->g_mode(gp, (dev & GRFOVDEV) ? GM_GRFOVOFF : GM_GRFOFF,
477 NULL, 0, 0);
478
479 /*
480 * Closely tied together no X's
481 */
482 if (gp->g_itedev != NODEV)
483 ite_on(gp->g_itedev, 2);
484
485 return(error);
486 }
487
488 int
489 grfsinfo(dev, dyninfo)
490 dev_t dev;
491 struct grfdyninfo *dyninfo;
492 {
493 struct grf_softc *gp;
494 int error;
495
496 gp = grfsp[GRFUNIT(dev)];
497 error = gp->g_mode(gp, GM_GRFCONFIG, dyninfo, 0, 0);
498
499 /*
500 * Closely tied together no X's
501 */
502 if (gp->g_itedev != NODEV)
503 ite_reinit(gp->g_itedev);
504 return(error);
505 }
506
507 /*
508 * Get the grf-info in sync with underlying view.
509 */
510 static void
511 grf_viewsync(gp)
512 struct grf_softc *gp;
513 {
514 struct view_size vs;
515 bmap_t bm;
516 struct grfinfo *gi;
517
518 gi = &gp->g_display;
519
520 viewioctl(gp->g_viewdev, VIOCGBMAP, (caddr_t)&bm, 0, NOPROC);
521
522 gp->g_data = (caddr_t) 0xDeadBeaf; /* not particularly clean.. */
523
524 gi->gd_fbaddr = bm.hw_address;
525 gi->gd_fbsize = bm.depth*bm.bytes_per_row*bm.rows;
526
527 if(viewioctl(gp->g_viewdev, VIOCGSIZE, (caddr_t)&vs, 0, NOPROC)) {
528 /*
529 * fill in some default values...
530 * XXX: Should _never_ happen
531 */
532 vs.width = 640;
533 vs.height = 400;
534 vs.depth = 1;
535 }
536 gi->gd_colors = 1 << vs.depth;
537 gi->gd_planes = vs.depth;
538
539 gi->gd_fbwidth = vs.width;
540 gi->gd_fbheight = vs.height;
541 gi->gd_dyn.gdi_fbx = 0;
542 gi->gd_dyn.gdi_fby = 0;
543 gi->gd_dyn.gdi_dwidth = vs.width;
544 gi->gd_dyn.gdi_dheight = vs.height;
545 gi->gd_dyn.gdi_dx = 0;
546 gi->gd_dyn.gdi_dy = 0;
547 }
548
549 /*
550 * Change the mode of the display.
551 * Right now all we can do is grfon/grfoff.
552 * Return a UNIX error number or 0 for success.
553 */
554 /*ARGSUSED*/
555 static int
556 grf_mode(gp, cmd, arg, a2, a3)
557 struct grf_softc *gp;
558 int cmd, a2, a3;
559 void *arg;
560 {
561 switch (cmd) {
562 case GM_GRFON:
563 /*
564 * Get in sync with view, ite might have changed it.
565 */
566 grf_viewsync(gp);
567 viewioctl(gp->g_viewdev, VIOCDISPLAY, NULL, 0, NOPROC);
568 return(0);
569 case GM_GRFOFF:
570 viewioctl(gp->g_viewdev, VIOCREMOVE, NULL, 0, NOPROC);
571 return(0);
572 case GM_GRFCONFIG:
573 default:
574 break;
575 }
576 return(EINVAL);
577 }
578 #endif /* NGRF > 0 */
579