grf.c revision 1.7 1 /* $NetBSD: grf.c,v 1.7 1996/02/22 10:11:23 leo 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 int grfopen __P((dev_t, int, int, struct proc *));
86 int grfclose __P((dev_t, int));
87 int grfioctl __P((dev_t, u_long, caddr_t, int, struct proc *));
88 int grfselect __P((dev_t, int));
89 int grfmmap __P((dev_t, int, int));
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, char *));
103 int grfbusmatch __P((struct device *, struct cfdata *, 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 *, struct cfdata *, void *));
108 int grfprint __P((void *, char *));
109 /*
110 * pointers to grf drivers device structs
111 */
112 struct grf_softc *grfsp[NGRF];
113
114
115 struct cfdriver grfbuscd = {
116 NULL, "grfbus", (cfmatch_t)grfbusmatch, grfbusattach, DV_DULL,
117 sizeof(struct device)
118 };
119
120 struct cfdriver grfcd = {
121 NULL, "grf", (cfmatch_t)grfmatch, grfattach, DV_DULL,
122 sizeof(struct grf_softc), NULL, 0
123 };
124
125 /*
126 * only used in console init.
127 */
128 static struct cfdata *cfdata_gbus = NULL;
129 static struct cfdata *cfdata_grf = NULL;
130
131 int
132 grfbusmatch(pdp, cfp, auxp)
133 struct device *pdp;
134 struct cfdata *cfp;
135 void *auxp;
136 {
137 if(strcmp(auxp, grfbuscd.cd_name))
138 return(0);
139
140 if((atari_realconfig == 0) || (cfdata_gbus == NULL)) {
141 /*
142 * Probe layers we depend on
143 */
144 if(grfabs_probe() == 0)
145 return(0);
146 viewprobe();
147
148 if(atari_realconfig == 0) {
149 /*
150 * XXX: console init opens view 0
151 */
152 if(viewopen(0, 0))
153 return(0);
154 cfdata_gbus = cfp;
155 }
156 }
157 return(1); /* Always there */
158 }
159
160 void
161 grfbusattach(pdp, dp, auxp)
162 struct device *pdp, *dp;
163 void *auxp;
164 {
165 static int did_cons = 0;
166 int i;
167
168 if(dp == NULL) { /* Console init */
169 did_cons = 1;
170 i = 0;
171 atari_config_found(cfdata_gbus, NULL, (void*)&i, grfbusprint);
172 }
173 else {
174 printf("\n");
175 for(i = 0; i < NGRF; i++) {
176 /*
177 * Skip opening view[0] when we this is the console.
178 */
179 if(!did_cons || (i > 0))
180 if(viewopen(i, 0))
181 break;
182 config_found(dp, (void*)&i, grfbusprint);
183 }
184 }
185 }
186
187 int
188 grfbusprint(auxp, name)
189 void *auxp;
190 char *name;
191 {
192 if(name == NULL)
193 return(UNCONF);
194 return(QUIET);
195 }
196
197
198 int
199 grfmatch(pdp, cfp, auxp)
200 struct device *pdp;
201 struct cfdata *cfp;
202 void *auxp;
203 {
204 int unit = *(int*)auxp;
205
206 /*
207 * Match only on unit indicated by grfbus attach.
208 */
209 if(cfp->cf_unit != unit)
210 return(0);
211
212 cfdata_grf = cfp;
213 return(1);
214 }
215
216 /*
217 * attach: initialize the grf-structure and try to attach an ite to us.
218 * note : dp is NULL during early console init.
219 */
220 void
221 grfattach(pdp, dp, auxp)
222 struct device *pdp, *dp;
223 void *auxp;
224 {
225 static struct grf_softc congrf;
226 struct grf_softc *gp;
227 int maj;
228
229 /*
230 * find our major device number
231 */
232 for(maj = 0; maj < nchrdev; maj++)
233 if (cdevsw[maj].d_open == grfopen)
234 break;
235
236 /*
237 * Handle exeption case: early console init
238 */
239 if(dp == NULL) {
240 congrf.g_unit = 0;
241 congrf.g_grfdev = makedev(maj, 0);
242 congrf.g_flags = GF_ALIVE;
243 congrf.g_mode = grf_mode;
244 congrf.g_conpri = grfcc_cnprobe();
245 congrf.g_viewdev = congrf.g_unit;
246 grfcc_iteinit(&congrf);
247 grf_viewsync(&congrf);
248
249 /* Attach console ite */
250 atari_config_found(cfdata_grf, NULL, &congrf, grfprint);
251 return;
252 }
253
254 gp = (struct grf_softc *)dp;
255 gp->g_unit = gp->g_device.dv_unit;
256 grfsp[gp->g_unit] = gp;
257
258 if((cfdata_grf != NULL) && (gp->g_unit == 0)) {
259 /*
260 * We inited earlier just copy the info, take care
261 * not to copy the device struct though.
262 */
263 bcopy(&congrf.g_display, &gp->g_display,
264 (char *)&gp[1] - (char *)&gp->g_display);
265 }
266 else {
267 gp->g_grfdev = makedev(maj, gp->g_unit);
268 gp->g_flags = GF_ALIVE;
269 gp->g_mode = grf_mode;
270 gp->g_conpri = 0;
271 gp->g_viewdev = gp->g_unit;
272 grfcc_iteinit(gp);
273 grf_viewsync(gp);
274 }
275
276 printf(": width %d height %d", gp->g_display.gd_dwidth,
277 gp->g_display.gd_dheight);
278 if(gp->g_display.gd_colors == 2)
279 printf(" monochrome\n");
280 else printf(" colors %d\n", gp->g_display.gd_colors);
281
282 /*
283 * try and attach an ite
284 */
285 config_found(dp, gp, grfprint);
286 }
287
288 int
289 grfprint(auxp, pnp)
290 void *auxp;
291 char *pnp;
292 {
293 if(pnp)
294 printf("ite at %s", pnp);
295 return(UNCONF);
296 }
297
298 /*ARGSUSED*/
299 int
300 grfopen(dev, flags, devtype, p)
301 dev_t dev;
302 int flags, devtype;
303 struct proc *p;
304 {
305 struct grf_softc *gp;
306
307 if (GRFUNIT(dev) >= NGRF)
308 return(ENXIO);
309
310 gp = grfsp[GRFUNIT(dev)];
311
312 if ((gp->g_flags & GF_ALIVE) == 0)
313 return(ENXIO);
314
315 if ((gp->g_flags & (GF_OPEN|GF_EXCLUDE)) == (GF_OPEN|GF_EXCLUDE))
316 return(EBUSY);
317 grf_viewsync(gp);
318
319 return(0);
320 }
321
322 /*ARGSUSED*/
323 int
324 grfclose(dev, flags)
325 dev_t dev;
326 int flags;
327 {
328 struct grf_softc *gp;
329
330 gp = grfsp[GRFUNIT(dev)];
331 (void)grfoff(dev);
332 gp->g_flags &= GF_ALIVE;
333 return(0);
334 }
335
336 /*ARGSUSED*/
337 int
338 grfioctl(dev, cmd, data, flag, p)
339 dev_t dev;
340 u_long cmd;
341 int flag;
342 caddr_t data;
343 struct proc *p;
344 {
345 struct grf_softc *gp;
346 int error;
347
348 gp = grfsp[GRFUNIT(dev)];
349 error = 0;
350
351 switch (cmd) {
352 case OGRFIOCGINFO:
353 /* argl.. no bank-member.. */
354 bcopy((caddr_t)&gp->g_display, data, sizeof(struct grfinfo)-4);
355 break;
356 case GRFIOCGINFO:
357 bcopy((caddr_t)&gp->g_display, data, sizeof(struct grfinfo));
358 break;
359 case GRFIOCON:
360 error = grfon(dev);
361 break;
362 case GRFIOCOFF:
363 error = grfoff(dev);
364 break;
365 case GRFIOCSINFO:
366 error = grfsinfo(dev, (struct grfdyninfo *) data);
367 break;
368 case GRFGETVMODE:
369 return(gp->g_mode(gp, GM_GRFGETVMODE, data, 0, 0));
370 case GRFSETVMODE:
371 error = gp->g_mode(gp, GM_GRFSETVMODE, data, 0, 0);
372 if (error == 0 && gp->g_itedev)
373 ite_reinit(gp->g_itedev);
374 break;
375 case GRFGETNUMVM:
376 return(gp->g_mode(gp, GM_GRFGETNUMVM, data, 0, 0));
377 /*
378 * these are all hardware dependant, and have to be resolved
379 * in the respective driver.
380 */
381 case GRFIOCPUTCMAP:
382 case GRFIOCGETCMAP:
383 case GRFIOCSSPRITEPOS:
384 case GRFIOCGSPRITEPOS:
385 case GRFIOCSSPRITEINF:
386 case GRFIOCGSPRITEINF:
387 case GRFIOCGSPRITEMAX:
388 default:
389 /*
390 * check to see whether it's a command recognized by the
391 * view code.
392 */
393 return(viewioctl(gp->g_viewdev, cmd, data, flag, p));
394 error = EINVAL;
395 break;
396
397 }
398 return(error);
399 }
400
401 /*ARGSUSED*/
402 int
403 grfselect(dev, rw)
404 dev_t dev;
405 int rw;
406 {
407 if (rw == FREAD)
408 return(0);
409 return(1);
410 }
411
412 /*
413 * map the contents of a graphics display card into process'
414 * memory space.
415 */
416 int
417 grfmmap(dev, off, prot)
418 dev_t dev;
419 int off, prot;
420 {
421 struct grf_softc *gp;
422 struct grfinfo *gi;
423
424 gp = grfsp[GRFUNIT(dev)];
425 gi = &gp->g_display;
426
427 /*
428 * frame buffer
429 */
430 if ((off >= 0) && (off < gi->gd_fbsize))
431 return (((u_int)gi->gd_fbaddr + off) >> PGSHIFT);
432 return(-1);
433 }
434
435 int
436 grfon(dev)
437 dev_t dev;
438 {
439 struct grf_softc *gp;
440
441 gp = grfsp[GRFUNIT(dev)];
442
443 if (gp->g_flags & GF_GRFON)
444 return(0);
445
446 gp->g_flags |= GF_GRFON;
447 if (gp->g_itedev != NODEV)
448 ite_off(gp->g_itedev, 3);
449
450 return(gp->g_mode(gp, (dev & GRFOVDEV) ? GM_GRFOVON : GM_GRFON,
451 NULL, 0, 0));
452 }
453
454 int
455 grfoff(dev)
456 dev_t dev;
457 {
458 struct grf_softc *gp;
459 int error;
460
461 gp = grfsp[GRFUNIT(dev)];
462
463 if ((gp->g_flags & GF_GRFON) == 0)
464 return(0);
465
466 gp->g_flags &= ~GF_GRFON;
467 error = gp->g_mode(gp, (dev & GRFOVDEV) ? GM_GRFOVOFF : GM_GRFOFF,
468 NULL, 0, 0);
469
470 /*
471 * Closely tied together no X's
472 */
473 if (gp->g_itedev != NODEV)
474 ite_on(gp->g_itedev, 2);
475
476 return(error);
477 }
478
479 int
480 grfsinfo(dev, dyninfo)
481 dev_t dev;
482 struct grfdyninfo *dyninfo;
483 {
484 struct grf_softc *gp;
485 int error;
486
487 gp = grfsp[GRFUNIT(dev)];
488 error = gp->g_mode(gp, GM_GRFCONFIG, dyninfo, 0, 0);
489
490 /*
491 * Closely tied together no X's
492 */
493 if (gp->g_itedev != NODEV)
494 ite_reinit(gp->g_itedev);
495 return(error);
496 }
497
498 /*
499 * Get the grf-info in sync with underlying view.
500 */
501 static void
502 grf_viewsync(gp)
503 struct grf_softc *gp;
504 {
505 struct view_size vs;
506 bmap_t bm;
507 struct grfinfo *gi;
508
509 gi = &gp->g_display;
510
511 viewioctl(gp->g_viewdev, VIOCGBMAP, &bm, 0, -1);
512
513 gp->g_data = (caddr_t) 0xDeadBeaf; /* not particularly clean.. */
514
515 gi->gd_fbaddr = bm.hw_address;
516 gi->gd_fbsize = bm.depth*bm.bytes_per_row*bm.rows;
517
518 if(viewioctl(gp->g_viewdev, VIOCGSIZE, &vs, 0, -1)) {
519 /*
520 * fill in some default values...
521 * XXX: Should _never_ happen
522 */
523 vs.width = 640;
524 vs.height = 400;
525 vs.depth = 1;
526 }
527 gi->gd_colors = 1 << vs.depth;
528 gi->gd_planes = vs.depth;
529
530 gi->gd_fbwidth = vs.width;
531 gi->gd_fbheight = vs.height;
532 gi->gd_dyn.gdi_fbx = 0;
533 gi->gd_dyn.gdi_fby = 0;
534 gi->gd_dyn.gdi_dwidth = vs.width;
535 gi->gd_dyn.gdi_dheight = vs.height;
536 gi->gd_dyn.gdi_dx = 0;
537 gi->gd_dyn.gdi_dy = 0;
538 }
539
540 /*
541 * Change the mode of the display.
542 * Right now all we can do is grfon/grfoff.
543 * Return a UNIX error number or 0 for success.
544 */
545 /*ARGSUSED*/
546 static int
547 grf_mode(gp, cmd, arg, a2, a3)
548 struct grf_softc *gp;
549 int cmd, a2, a3;
550 void *arg;
551 {
552 switch (cmd) {
553 case GM_GRFON:
554 /*
555 * Get in sync with view, ite might have changed it.
556 */
557 grf_viewsync(gp);
558 viewioctl(gp->g_viewdev, VIOCDISPLAY, NULL, 0, -1);
559 return(0);
560 case GM_GRFOFF:
561 viewioctl(gp->g_viewdev, VIOCREMOVE, NULL, 0, -1);
562 return(0);
563 case GM_GRFCONFIG:
564 default:
565 break;
566 }
567 return(EINVAL);
568 }
569 #endif /* NGRF > 0 */
570