grf.c revision 1.5 1 /* $NetBSD: grf.c,v 1.5 1995/06/09 19:55:13 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
318 return(0);
319 }
320
321 /*ARGSUSED*/
322 int
323 grfclose(dev, flags)
324 dev_t dev;
325 int flags;
326 {
327 struct grf_softc *gp;
328
329 gp = grfsp[GRFUNIT(dev)];
330 (void)grfoff(dev);
331 gp->g_flags &= GF_ALIVE;
332 return(0);
333 }
334
335 /*ARGSUSED*/
336 int
337 grfioctl(dev, cmd, data, flag, p)
338 dev_t dev;
339 u_long cmd;
340 int flag;
341 caddr_t data;
342 struct proc *p;
343 {
344 struct grf_softc *gp;
345 int error;
346
347 gp = grfsp[GRFUNIT(dev)];
348 error = 0;
349
350 switch (cmd) {
351 case OGRFIOCGINFO:
352 /* argl.. no bank-member.. */
353 bcopy((caddr_t)&gp->g_display, data, sizeof(struct grfinfo)-4);
354 break;
355 case GRFIOCGINFO:
356 bcopy((caddr_t)&gp->g_display, data, sizeof(struct grfinfo));
357 break;
358 case GRFIOCON:
359 error = grfon(dev);
360 break;
361 case GRFIOCOFF:
362 error = grfoff(dev);
363 break;
364 case GRFIOCSINFO:
365 error = grfsinfo(dev, (struct grfdyninfo *) data);
366 break;
367 case GRFGETVMODE:
368 return(gp->g_mode(gp, GM_GRFGETVMODE, data));
369 case GRFSETVMODE:
370 error = gp->g_mode(gp, GM_GRFSETVMODE, data);
371 if (error == 0 && gp->g_itedev)
372 ite_reinit(gp->g_itedev);
373 break;
374 case GRFGETNUMVM:
375 return(gp->g_mode(gp, GM_GRFGETNUMVM, data));
376 /*
377 * these are all hardware dependant, and have to be resolved
378 * in the respective driver.
379 */
380 case GRFIOCPUTCMAP:
381 case GRFIOCGETCMAP:
382 case GRFIOCSSPRITEPOS:
383 case GRFIOCGSPRITEPOS:
384 case GRFIOCSSPRITEINF:
385 case GRFIOCGSPRITEINF:
386 case GRFIOCGSPRITEMAX:
387 default:
388 /*
389 * check to see whether it's a command recognized by the
390 * view code.
391 */
392 return(viewioctl(gp->g_viewdev, cmd, data, flag, p));
393 error = EINVAL;
394 break;
395
396 }
397 return(error);
398 }
399
400 /*ARGSUSED*/
401 int
402 grfselect(dev, rw)
403 dev_t dev;
404 int rw;
405 {
406 if (rw == FREAD)
407 return(0);
408 return(1);
409 }
410
411 /*
412 * map the contents of a graphics display card into process'
413 * memory space.
414 */
415 int
416 grfmmap(dev, off, prot)
417 dev_t dev;
418 int off, prot;
419 {
420 struct grf_softc *gp;
421 struct grfinfo *gi;
422
423 gp = grfsp[GRFUNIT(dev)];
424 gi = &gp->g_display;
425
426 /*
427 * frame buffer
428 */
429 if ((off >= 0) && (off < gi->gd_fbsize))
430 return (((u_int)gi->gd_fbaddr + off) >> PGSHIFT);
431 return(-1);
432 }
433
434 int
435 grfon(dev)
436 dev_t dev;
437 {
438 struct grf_softc *gp;
439
440 gp = grfsp[GRFUNIT(dev)];
441
442 if (gp->g_flags & GF_GRFON)
443 return(0);
444
445 gp->g_flags |= GF_GRFON;
446 if (gp->g_itedev != NODEV)
447 ite_off(gp->g_itedev, 3);
448
449 return(gp->g_mode(gp, (dev & GRFOVDEV) ? GM_GRFOVON : GM_GRFON));
450 }
451
452 int
453 grfoff(dev)
454 dev_t dev;
455 {
456 struct grf_softc *gp;
457 int error;
458
459 gp = grfsp[GRFUNIT(dev)];
460
461 if ((gp->g_flags & GF_GRFON) == 0)
462 return(0);
463
464 gp->g_flags &= ~GF_GRFON;
465 error = gp->g_mode(gp, (dev & GRFOVDEV) ? GM_GRFOVOFF : GM_GRFOFF);
466
467 /*
468 * Closely tied together no X's
469 */
470 if (gp->g_itedev != NODEV)
471 ite_on(gp->g_itedev, 2);
472
473 return(error);
474 }
475
476 int
477 grfsinfo(dev, dyninfo)
478 dev_t dev;
479 struct grfdyninfo *dyninfo;
480 {
481 struct grf_softc *gp;
482 int error;
483
484 gp = grfsp[GRFUNIT(dev)];
485 error = gp->g_mode(gp, GM_GRFCONFIG, dyninfo);
486
487 /*
488 * Closely tied together no X's
489 */
490 if (gp->g_itedev != NODEV)
491 ite_reinit(gp->g_itedev);
492 return(error);
493 }
494
495 /*
496 * Get the grf-info in sync with underlying view.
497 */
498 static void
499 grf_viewsync(gp)
500 struct grf_softc *gp;
501 {
502 struct view_size vs;
503 bmap_t bm;
504 struct grfinfo *gi;
505
506 gi = &gp->g_display;
507
508 viewioctl(gp->g_viewdev, VIOCGBMAP, &bm, 0, -1);
509
510 gp->g_data = (caddr_t) 0xDeadBeaf; /* not particularly clean.. */
511
512 gi->gd_fbaddr = bm.hw_address;
513 gi->gd_fbsize = bm.depth*bm.bytes_per_row*bm.rows;
514
515 if(viewioctl(gp->g_viewdev, VIOCGSIZE, &vs, 0, -1)) {
516 /*
517 * fill in some default values...
518 * XXX: Should _never_ happen
519 */
520 vs.width = 640;
521 vs.height = 400;
522 vs.depth = 1;
523 }
524 gi->gd_colors = 1 << vs.depth;
525 gi->gd_planes = vs.depth;
526
527 gi->gd_fbwidth = vs.width;
528 gi->gd_fbheight = vs.height;
529 gi->gd_dyn.gdi_fbx = 0;
530 gi->gd_dyn.gdi_fby = 0;
531 gi->gd_dyn.gdi_dwidth = vs.width;
532 gi->gd_dyn.gdi_dheight = vs.height;
533 gi->gd_dyn.gdi_dx = 0;
534 gi->gd_dyn.gdi_dy = 0;
535 }
536
537 /*
538 * Change the mode of the display.
539 * Right now all we can do is grfon/grfoff.
540 * Return a UNIX error number or 0 for success.
541 */
542 /*ARGSUSED*/
543 static int
544 grf_mode(gp, cmd, arg, a2, a3)
545 struct grf_softc *gp;
546 int cmd, a2, a3;
547 void *arg;
548 {
549 switch (cmd) {
550 case GM_GRFON:
551 /*
552 * Get in sync with view, ite might have changed it.
553 */
554 grf_viewsync(gp);
555 viewioctl(gp->g_viewdev, VIOCDISPLAY, NULL, 0, -1);
556 return(0);
557 case GM_GRFOFF:
558 viewioctl(gp->g_viewdev, VIOCREMOVE, NULL, 0, -1);
559 return(0);
560 case GM_GRFCONFIG:
561 default:
562 break;
563 }
564 return(EINVAL);
565 }
566 #endif /* NGRF > 0 */
567