xref: /netbsd-src/sys/arch/mac68k/dev/grf_compat.c (revision 4472dbe5e3bd91ef2540bada7a7ca7384627ff9b)
1 /*	$NetBSD: grf_compat.c,v 1.2 2000/02/14 07:01:46 scottr Exp $	*/
2 
3 /*
4  * Copyright (C) 1999 Scott Reynolds
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 /*
31  * macfb compatibility with legacy grf devices
32  */
33 
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/cdefs.h>
37 #include <sys/conf.h>
38 #include <sys/device.h>
39 #include <sys/errno.h>
40 #include <sys/ioctl.h>
41 #include <sys/malloc.h>
42 #include <sys/mman.h>
43 #include <sys/proc.h>
44 #include <sys/resourcevar.h>
45 #include <sys/vnode.h>
46 
47 #include <machine/autoconf.h>
48 #include <machine/bus.h>
49 #include <machine/grfioctl.h>
50 
51 #include <mac68k/nubus/nubus.h>
52 #include <mac68k/dev/grfvar.h>
53 #include <mac68k/dev/macfbvar.h>
54 
55 #include <miscfs/specfs/specdev.h>
56 
57 #include <vm/vm.h>
58 #include <uvm/uvm_extern.h>
59 #include <uvm/uvm_map.h>
60 
61 cdev_decl(grf);
62 
63 void	grf_scinit __P((struct grf_softc *, const char *, int));
64 void	grf_init __P((int));
65 void	grfattach __P((int));
66 int	grfmap __P((dev_t, struct macfb_softc *, caddr_t *, struct proc *));
67 int	grfunmap __P((dev_t, struct macfb_softc *, caddr_t, struct proc *));
68 
69 /* Non-private for the benefit of libkvm. */
70 struct	grf_softc *grf_softc;
71 int	numgrf = 0;
72 
73 /*
74  * Initialize a softc to sane defaults.
75  */
76 void
77 grf_scinit(sc, name, unit)
78 	struct grf_softc *sc;
79 	const char *name;
80 	int unit;
81 {
82 	memset(sc, 0, sizeof(struct grf_softc));
83 	snprintf(sc->sc_xname, sizeof(sc->sc_xname), "%s%d", name, unit);
84 	sc->mfb_sc = NULL;
85 }
86 
87 /*
88  * (Re-)initialize the grf_softc block so that at least the requested
89  * number of elements has been allocated.  If this results in more
90  * elements than we had prior to getting here, we initialize each of
91  * them to avoid problems down the road.
92  */
93 void
94 grf_init(n)
95 	int n;
96 {
97 	struct grf_softc *sc;
98 	int i;
99 
100 	if (n >= numgrf) {
101 		i = numgrf;
102 		numgrf = n + 1;
103 
104 		if (grf_softc == NULL)
105 			sc = (struct grf_softc *)
106 			    malloc(numgrf * sizeof(*sc),
107 			    M_DEVBUF, M_NOWAIT);
108 		else
109 			sc = (struct grf_softc *)
110 			    realloc(grf_softc, numgrf * sizeof(*sc),
111 			    M_DEVBUF, M_NOWAIT);
112 		if (sc == NULL) {
113 			printf("WARNING: no memory for grf emulation\n");
114 			if (grf_softc != NULL)
115 				free(grf_softc, M_DEVBUF);
116 			return;
117 		}
118 		grf_softc = sc;
119 
120 		/* Initialize per-softc structures. */
121 		while (i < numgrf) {
122 			grf_scinit(&grf_softc[i], "grf", i);
123 			i++;
124 		}
125 	}
126 }
127 
128 /*
129  * Called by main() during pseudo-device attachment.  If we had a
130  * way to configure additional grf devices later, this would actually
131  * allocate enough space for them.  As it stands, it's nonsensical,
132  * so other than a basic sanity check we do nothing.
133  */
134 void
135 grfattach(n)
136 	int n;
137 {
138 	if (n <= 0) {
139 #ifdef DIAGNOSTIC
140 		panic("grfattach: count <= 0");
141 #endif
142 		return;
143 	}
144 
145 #if 0 /* XXX someday, if we implement a way to attach after autoconfig */
146 	grf_init(n);
147 #endif
148 }
149 
150 /*
151  * Called from macfb_attach() after setting up the frame buffer.  Since
152  * there is a 1:1 correspondence between the macfb device and the grf
153  * device, the only bit of information we really need is the macfb_softc.
154  */
155 void
156 grf_attach(sc, unit)
157 	struct macfb_softc *sc;
158 	int unit;
159 {
160 	grf_init(unit);
161 
162 	if (unit < numgrf)
163 		grf_softc[unit].mfb_sc = sc;
164 }
165 
166 /*
167  * Standard device ops
168  */
169 int
170 grfopen(dev, flag, mode, p)
171 	dev_t dev;
172 	int flag;
173 	int mode;
174 	struct proc *p;
175 {
176 	struct grf_softc *sc;
177 	int unit = GRFUNIT(dev);
178 	int rv = 0;
179 
180 	if (grf_softc == NULL || unit >= numgrf)
181 		return ENXIO;
182 
183 	sc = &grf_softc[unit];
184 	if (sc->mfb_sc == NULL)
185 		rv = ENXIO;
186 
187 	return rv;
188 }
189 
190 int
191 grfclose(dev, flag, mode, p)
192 	dev_t dev;
193 	int flag;
194 	int mode;
195 	struct proc *p;
196 {
197 	struct grf_softc *sc;
198 	int unit = GRFUNIT(dev);
199 	int rv = 0;
200 
201 	if (grf_softc == NULL || unit >= numgrf)
202 		return ENXIO;
203 
204 	sc = &grf_softc[unit];
205 	if (sc->mfb_sc != NULL)
206 		macfb_clear(sc->mfb_sc->sc_dc);	/* clear the display */
207 	else
208 		rv = ENXIO;
209 
210 	return rv;
211 }
212 
213 int
214 grfread(dev, uio, ioflag)
215 	dev_t dev;
216 	struct uio *uio;
217 	int ioflag;
218 {
219 	return ENXIO;
220 }
221 
222 int
223 grfwrite(dev, uio, ioflag)
224 	dev_t dev;
225 	struct uio *uio;
226 	int ioflag;
227 {
228 	return ENXIO;
229 }
230 
231 int
232 grfioctl(dev, cmd, data, flag, p)
233 	dev_t dev;
234 	u_long cmd;
235 	caddr_t data;
236 	int flag;
237 	struct proc *p;
238 {
239 	struct grf_softc *sc;
240 	struct macfb_devconfig *dc;
241 	struct grfinfo *gd;
242 	struct grfmode *gm;
243 	int unit = GRFUNIT(dev);
244 	int rv;
245 
246 	if (grf_softc == NULL || unit >= numgrf)
247 		return ENXIO;
248 
249 	sc = &grf_softc[unit];
250 	if (sc->mfb_sc == NULL)
251 		return ENXIO;
252 
253 	dc = sc->mfb_sc->sc_dc;
254 
255 	switch (cmd) {
256 	case GRFIOCGINFO:
257 		gd = (struct grfinfo *)data;
258 		memset(gd, 0, sizeof(struct grfinfo));
259 		gd->gd_fbaddr     = (caddr_t)dc->dc_paddr;
260 		gd->gd_fbsize     = dc->dc_size;
261 		gd->gd_colors     = (short)(1 << dc->dc_depth);
262 		gd->gd_planes     = (short)dc->dc_depth;
263 		gd->gd_fbwidth    = dc->dc_wid;
264 		gd->gd_fbheight   = dc->dc_ht;
265 		gd->gd_fbrowbytes = dc->dc_rowbytes;
266 		gd->gd_dwidth     = dc->dc_raster.width;
267 		gd->gd_dheight    = dc->dc_raster.height;
268 		rv = 0;
269 		break;
270 
271 	case GRFIOCON:
272 	case GRFIOCOFF:
273 		/* Nothing to do */
274 		rv = 0;
275 		break;
276 
277 	case GRFIOCMAP:
278 		rv = grfmap(dev, sc->mfb_sc, (caddr_t *)data, p);
279 		break;
280 
281 	case GRFIOCUNMAP:
282 		rv = grfunmap(dev, sc->mfb_sc, *(caddr_t *)data, p);
283 		break;
284 
285 	case GRFIOCGMODE:
286 		gm = (struct grfmode *)data;
287 		memset(gm, 0, sizeof(struct grfmode));
288 		gm->fbbase   = (char *)dc->dc_vaddr;
289 		gm->fbsize   = dc->dc_size;
290 		gm->fboff    = dc->dc_offset;
291 		gm->rowbytes = dc->dc_rowbytes;
292 		gm->width    = dc->dc_wid;
293 		gm->height   = dc->dc_ht;
294 		gm->psize    = dc->dc_depth;
295 		rv = 0;
296 		break;
297 
298 	case GRFIOCLISTMODES:
299 	case GRFIOCGETMODE:
300 	case GRFIOCSETMODE:
301 		/* NONE of these operations are (officially) supported. */
302 	default:
303 		rv = EINVAL;
304 		break;
305 	}
306 	return rv;
307 }
308 
309 int
310 grfpoll(dev, events, p)
311 	dev_t dev;
312 	int events;
313 	struct proc *p;
314 {
315 	return EINVAL;
316 }
317 
318 int
319 grfmmap(dev, off, prot)
320 	dev_t dev;
321 	int off;
322 	int prot;
323 {
324 	struct grf_softc *sc;
325 	struct macfb_devconfig *dc;
326 	u_long addr;
327 	int unit = GRFUNIT(dev);
328 
329 	if (grf_softc == NULL || unit >= numgrf)
330 		return ENXIO;
331 
332 	sc = &grf_softc[unit];
333 	if (sc->mfb_sc == NULL)
334 		return ENXIO;
335 
336 	dc = sc->mfb_sc->sc_dc;
337 
338 	if (off >= 0 &&
339 	    off < m68k_round_page(dc->dc_offset + dc->dc_size))
340 		addr = m68k_btop(dc->dc_paddr + off);
341 	else
342 		addr = (-1);	/* XXX bogus */
343 
344 	return (int)addr;
345 }
346 
347 int
348 grfmap(dev, sc, addrp, p)
349 	dev_t dev;
350 	struct macfb_softc *sc;
351 	caddr_t *addrp;
352 	struct proc *p;
353 {
354 	struct specinfo si;
355 	struct vnode vn;
356 	u_long len;
357 	int error, flags;
358 
359 	*addrp = (caddr_t)sc->sc_dc->dc_paddr;
360 	len = m68k_round_page(sc->sc_dc->dc_offset + sc->sc_dc->dc_size);
361 	flags = MAP_SHARED | MAP_FIXED;
362 
363 	vn.v_type = VCHR;		/* XXX */
364 	vn.v_specinfo = &si;		/* XXX */
365 	vn.v_rdev = dev;		/* XXX */
366 
367 	error = uvm_mmap(&p->p_vmspace->vm_map, (vaddr_t *)addrp,
368 	    (vsize_t)len, VM_PROT_ALL, VM_PROT_ALL,
369 	    flags, (caddr_t)&vn, 0, p->p_rlimit[RLIMIT_MEMLOCK].rlim_cur);
370 
371 	/* Offset into page: */
372 	*addrp += sc->sc_dc->dc_offset;
373 
374 	return (error);
375 }
376 
377 int
378 grfunmap(dev, sc, addr, p)
379 	dev_t dev;
380 	struct macfb_softc *sc;
381 	caddr_t addr;
382 	struct proc *p;
383 {
384 	vm_size_t size;
385 	int     rv;
386 
387 	addr -= sc->sc_dc->dc_offset;
388 
389 	if (addr <= 0)
390 		return (-1);
391 
392 	size = m68k_round_page(sc->sc_dc->dc_offset + sc->sc_dc->dc_size);
393 
394 	rv = uvm_unmap(&p->p_vmspace->vm_map, (vaddr_t)addr,
395 	    (vaddr_t)addr + size);
396 
397 	return (rv == KERN_SUCCESS ? 0 : EINVAL);
398 }
399