xref: /netbsd-src/sys/arch/amiga/dev/grf.c (revision 1f2744e6e4915c9da2a3f980279398c4cf7d5e6d)
1 /*	$NetBSD: grf.c,v 1.18 1995/02/12 19:19:05 chopps Exp $	*/
2 
3 /*
4  * Copyright (c) 1988 University of Utah.
5  * Copyright (c) 1990 The Regents of the University of California.
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to Berkeley by
9  * the Systems Programming Group of the University of Utah Computer
10  * Science Department.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  * 3. All advertising materials mentioning features or use of this software
21  *    must display the following acknowledgement:
22  *	This product includes software developed by the University of
23  *	California, Berkeley and its contributors.
24  * 4. Neither the name of the University nor the names of its contributors
25  *    may be used to endorse or promote products derived from this software
26  *    without specific prior written permission.
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38  * SUCH DAMAGE.
39  *
40  * from: Utah $Hdr: grf.c 1.31 91/01/21$
41  *
42  *	@(#)grf.c	7.8 (Berkeley) 5/7/91
43  */
44 
45 /*
46  * Graphics display driver for the Amiga
47  * This is the hardware-independent portion of the driver.
48  * Hardware access is through the grf_softc->g_mode routine.
49  */
50 
51 #include <sys/param.h>
52 #include <sys/proc.h>
53 #include <sys/ioctl.h>
54 #include <sys/device.h>
55 #include <sys/file.h>
56 #include <sys/malloc.h>
57 #include <sys/conf.h>
58 #include <sys/systm.h>
59 #include <sys/vnode.h>
60 #include <sys/mman.h>
61 #include <vm/vm.h>
62 #include <vm/vm_kern.h>
63 #include <vm/vm_page.h>
64 #include <vm/vm_pager.h>
65 #include <machine/cpu.h>
66 #include <amiga/amiga/color.h>	/* DEBUG */
67 #include <amiga/amiga/device.h>
68 #include <amiga/dev/grfioctl.h>
69 #include <amiga/dev/grfvar.h>
70 #include <amiga/dev/itevar.h>
71 
72 #include "grf.h"
73 #if NGRF > 0
74 
75 #include "ite.h"
76 #if NITE == 0
77 #define	ite_on(u,f)
78 #define	ite_off(u,f)
79 #define ite_reinit(d)
80 #endif
81 
82 int grfopen __P((dev_t, int, int, struct proc *));
83 int grfclose __P((dev_t, int));
84 int grfioctl __P((dev_t, u_long, caddr_t, int, struct proc *));
85 int grfselect __P((dev_t, int));
86 int grfmap __P((dev_t, int, int));
87 
88 int grfon __P((dev_t));
89 int grfoff __P((dev_t));
90 int grfsinfo __P((dev_t, struct grfdyninfo *));
91 #ifdef BANKEDDEVPAGER
92 int grfbanked_get __P((dev_t, off_t, int));
93 int grfbanked_cur __P((dev_t));
94 int grfbanked_set __P((dev_t, int));
95 #endif
96 
97 void grfattach __P((struct device *, struct device *, void *));
98 int grfmatch __P((struct device *, struct cfdata *, void *));
99 int grfprint __P((void *, char *));
100 /*
101  * pointers to grf drivers device structs
102  */
103 struct grf_softc *grfsp[NGRF];
104 
105 
106 struct cfdriver grfcd = {
107 	NULL, "grf", (cfmatch_t)grfmatch, grfattach, DV_DULL,
108 	sizeof(struct device), NULL, 0 };
109 
110 /*
111  * only used in console init.
112  */
113 static struct cfdata *cfdata;
114 
115 /*
116  * match if the unit of grf matches its perspective
117  * low level board driver.
118  */
119 int
120 grfmatch(pdp, cfp, auxp)
121 	struct device *pdp;
122 	struct cfdata *cfp;
123 	void *auxp;
124 {
125 	if (cfp->cf_unit != ((struct grf_softc *)pdp)->g_unit)
126 		return(0);
127 	cfdata = cfp;
128 	return(1);
129 }
130 
131 /*
132  * attach.. plug pointer in and print some info.
133  * then try and attach an ite to us. note: dp is NULL
134  * durring console init.
135  */
136 void
137 grfattach(pdp, dp, auxp)
138 	struct device *pdp, *dp;
139 	void *auxp;
140 {
141 	struct grf_softc *gp;
142 	int maj;
143 
144 	gp = (struct grf_softc *)pdp;
145 	grfsp[gp->g_unit] = (struct grf_softc *)pdp;
146 
147 	/*
148 	 * find our major device number
149 	 */
150 	for(maj = 0; maj < nchrdev; maj++)
151 		if (cdevsw[maj].d_open == grfopen)
152 			break;
153 
154 	gp->g_grfdev = makedev(maj, gp->g_unit);
155 	if (dp != NULL) {
156 		printf(": width %d height %d", gp->g_display.gd_dwidth,
157 		    gp->g_display.gd_dheight);
158 		if (gp->g_display.gd_colors == 2)
159 			printf(" monochrome\n");
160 		else
161 			printf(" colors %d\n", gp->g_display.gd_colors);
162 	}
163 
164 	/*
165 	 * try and attach an ite
166 	 */
167 	amiga_config_found(cfdata, dp, gp, grfprint);
168 }
169 
170 int
171 grfprint(auxp, pnp)
172 	void *auxp;
173 	char *pnp;
174 {
175 	if (pnp)
176 		printf("ite at %s", pnp);
177 	return(UNCONF);
178 }
179 
180 /*ARGSUSED*/
181 int
182 grfopen(dev, flags, devtype, p)
183 	dev_t dev;
184 	int flags, devtype;
185 	struct proc *p;
186 {
187 	struct grf_softc *gp;
188 
189 	if (GRFUNIT(dev) >= NGRF)
190 		return(ENXIO);
191 
192 	gp = grfsp[GRFUNIT(dev)];
193 
194 	if ((gp->g_flags & GF_ALIVE) == 0)
195 		return(ENXIO);
196 
197 	if ((gp->g_flags & (GF_OPEN|GF_EXCLUDE)) == (GF_OPEN|GF_EXCLUDE))
198 		return(EBUSY);
199 
200 	return(0);
201 }
202 
203 /*ARGSUSED*/
204 int
205 grfclose(dev, flags)
206 	dev_t dev;
207 	int flags;
208 {
209 	struct grf_softc *gp;
210 
211 	gp = grfsp[GRFUNIT(dev)];
212 	(void)grfoff(dev);
213 	gp->g_flags &= GF_ALIVE;
214 	return(0);
215 }
216 
217 /*ARGSUSED*/
218 int
219 grfioctl(dev, cmd, data, flag, p)
220 	dev_t dev;
221 	u_long cmd;
222 	caddr_t data;
223 	int flag;
224 	struct proc *p;
225 {
226 	struct grf_softc *gp;
227 	int error;
228 
229 	gp = grfsp[GRFUNIT(dev)];
230 	error = 0;
231 
232 	switch (cmd) {
233 	case OGRFIOCGINFO:
234 	        /* argl.. no bank-member.. */
235 	  	bcopy((caddr_t)&gp->g_display, data, sizeof(struct grfinfo)-4);
236 		break;
237 	case GRFIOCGINFO:
238 		bcopy((caddr_t)&gp->g_display, data, sizeof(struct grfinfo));
239 		break;
240 	case GRFIOCON:
241 		error = grfon(dev);
242 		break;
243 	case GRFIOCOFF:
244 		error = grfoff(dev);
245 		break;
246 	case GRFIOCSINFO:
247 		error = grfsinfo(dev, (struct grfdyninfo *) data);
248 		break;
249 	case GRFGETVMODE:
250 		return(gp->g_mode(gp, GM_GRFGETVMODE, data));
251 	case GRFSETVMODE:
252 		error = gp->g_mode(gp, GM_GRFSETVMODE, data);
253 		if (error == 0 && gp->g_itedev && !(gp->g_flags & GF_GRFON))
254 			ite_reinit(gp->g_itedev);
255 		break;
256 	case GRFGETNUMVM:
257 		return(gp->g_mode(gp, GM_GRFGETNUMVM, data));
258 	/*
259 	 * these are all hardware dependant, and have to be resolved
260 	 * in the respective driver.
261 	 */
262 	case GRFIOCPUTCMAP:
263 	case GRFIOCGETCMAP:
264 	case GRFIOCSSPRITEPOS:
265 	case GRFIOCGSPRITEPOS:
266 	case GRFIOCSSPRITEINF:
267 	case GRFIOCGSPRITEINF:
268 	case GRFIOCGSPRITEMAX:
269 	case GRFIOCBITBLT:
270 	case GRFTOGGLE: /* Toggles between Cirrus boards and native ECS on
271                      Amiga. 15/11/94 ill */
272 		return(gp->g_mode(gp, GM_GRFIOCTL, cmd, data));
273 	default:
274 		/*
275 		 * check to see whether it's a command recognized by the
276 		 * view code if the unit is 0
277 		 * XXX
278 		 */
279 		if (GRFUNIT(dev) == 0)
280 			return(viewioctl(dev, cmd, data, flag, p));
281 		error = EINVAL;
282 		break;
283 
284 	}
285 	return(error);
286 }
287 
288 /*ARGSUSED*/
289 int
290 grfselect(dev, rw)
291 	dev_t dev;
292 	int rw;
293 {
294 	if (rw == FREAD)
295 		return(0);
296 	return(1);
297 }
298 
299 /*
300  * map the contents of a graphics display card into process'
301  * memory space.
302  */
303 int
304 grfmap(dev, off, prot)
305 	dev_t dev;
306 	int off, prot;
307 {
308 	struct grf_softc *gp;
309 	struct grfinfo *gi;
310 
311 	gp = grfsp[GRFUNIT(dev)];
312 	gi = &gp->g_display;
313 
314 	/*
315 	 * control registers
316 	 */
317 	if (off >= 0 && off < gi->gd_regsize)
318 		return(((u_int)gi->gd_regaddr + off) >> PGSHIFT);
319 
320 	/*
321 	 * frame buffer
322 	 */
323 	if (off >= gi->gd_regsize && off < gi->gd_regsize+gi->gd_fbsize) {
324 		off -= gi->gd_regsize;
325 #ifdef BANKEDDEVPAGER
326 		if (gi->gd_bank_size)
327 			off %= gi->gd_bank_size;
328 #endif
329 		return(((u_int)gi->gd_fbaddr + off) >> PGSHIFT);
330 	}
331 	/* bogus */
332 	return(-1);
333 }
334 
335 int
336 grfon(dev)
337 	dev_t dev;
338 {
339 	struct grf_softc *gp;
340 
341 	gp = grfsp[GRFUNIT(dev)];
342 
343 	if (gp->g_flags & GF_GRFON)
344 		return(0);
345 
346 	gp->g_flags |= GF_GRFON;
347 	if (gp->g_itedev != NODEV)
348 		ite_off(gp->g_itedev, 3);
349 
350 	return(gp->g_mode(gp, (dev & GRFOVDEV) ? GM_GRFOVON : GM_GRFON));
351 }
352 
353 int
354 grfoff(dev)
355 	dev_t dev;
356 {
357 	struct grf_softc *gp;
358 	int error;
359 
360 	gp = grfsp[GRFUNIT(dev)];
361 
362 	if ((gp->g_flags & GF_GRFON) == 0)
363 		return(0);
364 
365 	gp->g_flags &= ~GF_GRFON;
366 	error = gp->g_mode(gp, (dev & GRFOVDEV) ? GM_GRFOVOFF : GM_GRFOFF);
367 
368 	/*
369 	 * Closely tied together no X's
370 	 */
371 	if (gp->g_itedev != NODEV)
372 		ite_on(gp->g_itedev, 2);
373 
374 	return(error);
375 }
376 
377 int
378 grfsinfo(dev, dyninfo)
379 	dev_t dev;
380 	struct grfdyninfo *dyninfo;
381 {
382 	struct grf_softc *gp;
383 	int error;
384 
385 	gp = grfsp[GRFUNIT(dev)];
386 	error = gp->g_mode(gp, GM_GRFCONFIG, dyninfo);
387 
388 	/*
389 	 * Closely tied together no X's
390 	 */
391 	if (gp->g_itedev != NODEV)
392 		ite_reinit(gp->g_itedev);
393 	return(error);
394 }
395 
396 #ifdef BANKEDDEVPAGER
397 
398 int
399 grfbanked_get (dev, off, prot)
400      dev_t dev;
401      off_t off;
402      int   prot;
403 {
404 	struct grf_softc *gp;
405 	struct grfinfo *gi;
406 	int error, bank;
407 
408 	gp = grfsp[GRFUNIT(dev)];
409 	gi = &gp->g_display;
410 
411 	off -= gi->gd_regsize;
412 	if (off < 0 || off >= gi->gd_fbsize)
413 		return -1;
414 
415 	error = gp->g_mode(gp, GM_GRFGETBANK, &bank, off, prot);
416 	return error ? -1 : bank;
417 }
418 
419 int
420 grfbanked_cur (dev)
421 	dev_t dev;
422 {
423 	struct grf_softc *gp;
424 	int error, bank;
425 
426 	gp = grfsp[GRFUNIT(dev)];
427 
428 	error = gp->g_mode(gp, GM_GRFGETCURBANK, &bank);
429 	return(error ? -1 : bank);
430 }
431 
432 int
433 grfbanked_set (dev, bank)
434 	dev_t dev;
435 	int bank;
436 {
437 	struct grf_softc *gp;
438 
439 	gp = grfsp[GRFUNIT(dev)];
440 	return(gp->g_mode(gp, GM_GRFSETBANK, bank) ? -1 : 0);
441 }
442 
443 #endif /* BANKEDDEVPAGER */
444 #endif	/* NGRF > 0 */
445