grf_compat.c revision 1.12.2.1 1 /* $NetBSD: grf_compat.c,v 1.12.2.1 2004/08/03 10:37:05 skrll 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/cdefs.h>
35 __KERNEL_RCSID(0, "$NetBSD: grf_compat.c,v 1.12.2.1 2004/08/03 10:37:05 skrll Exp $");
36
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/cdefs.h>
40 #include <sys/conf.h>
41 #include <sys/device.h>
42 #include <sys/errno.h>
43 #include <sys/ioctl.h>
44 #include <sys/malloc.h>
45 #include <sys/mman.h>
46 #include <sys/proc.h>
47 #include <sys/resourcevar.h>
48 #include <sys/vnode.h>
49
50 #include <machine/autoconf.h>
51 #include <machine/bus.h>
52 #include <machine/grfioctl.h>
53
54 #include <mac68k/nubus/nubus.h>
55 #include <mac68k/dev/grfvar.h>
56 #include <mac68k/dev/macfbvar.h>
57
58 #include <miscfs/specfs/specdev.h>
59
60 #include <uvm/uvm_extern.h>
61 #include <uvm/uvm_map.h>
62
63 dev_type_open(grfopen);
64 dev_type_close(grfclose);
65 dev_type_ioctl(grfioctl);
66 dev_type_mmap(grfmmap);
67
68 const struct cdevsw grf_cdevsw = {
69 grfopen, grfclose, noread, nowrite, grfioctl,
70 nostop, notty, nopoll, grfmmap, nokqfilter,
71 };
72
73 void grf_scinit __P((struct grf_softc *, const char *, int));
74 void grf_init __P((int));
75 void grfattach __P((int));
76 int grfmap __P((dev_t, struct macfb_softc *, caddr_t *, struct proc *));
77 int grfunmap __P((dev_t, struct macfb_softc *, caddr_t, struct proc *));
78
79 /* Non-private for the benefit of libkvm. */
80 struct grf_softc *grf_softc;
81 int numgrf = 0;
82
83 /*
84 * Initialize a softc to sane defaults.
85 */
86 void
87 grf_scinit(sc, name, unit)
88 struct grf_softc *sc;
89 const char *name;
90 int unit;
91 {
92 memset(sc, 0, sizeof(struct grf_softc));
93 snprintf(sc->sc_xname, sizeof(sc->sc_xname), "%s%d", name, unit);
94 sc->mfb_sc = NULL;
95 }
96
97 /*
98 * (Re-)initialize the grf_softc block so that at least the requested
99 * number of elements has been allocated. If this results in more
100 * elements than we had prior to getting here, we initialize each of
101 * them to avoid problems down the road.
102 */
103 void
104 grf_init(n)
105 int n;
106 {
107 struct grf_softc *sc;
108 int i;
109
110 if (n >= numgrf) {
111 i = numgrf;
112 numgrf = n + 1;
113
114 if (grf_softc == NULL)
115 sc = (struct grf_softc *)
116 malloc(numgrf * sizeof(*sc),
117 M_DEVBUF, M_NOWAIT);
118 else
119 sc = (struct grf_softc *)
120 realloc(grf_softc, numgrf * sizeof(*sc),
121 M_DEVBUF, M_NOWAIT);
122 if (sc == NULL) {
123 printf("WARNING: no memory for grf emulation\n");
124 if (grf_softc != NULL)
125 free(grf_softc, M_DEVBUF);
126 return;
127 }
128 grf_softc = sc;
129
130 /* Initialize per-softc structures. */
131 while (i < numgrf) {
132 grf_scinit(&grf_softc[i], "grf", i);
133 i++;
134 }
135 }
136 }
137
138 /*
139 * Called by main() during pseudo-device attachment. If we had a
140 * way to configure additional grf devices later, this would actually
141 * allocate enough space for them. As it stands, it's nonsensical,
142 * so other than a basic sanity check we do nothing.
143 */
144 void
145 grfattach(n)
146 int n;
147 {
148 if (n <= 0) {
149 #ifdef DIAGNOSTIC
150 panic("grfattach: count <= 0");
151 #endif
152 return;
153 }
154
155 #if 0 /* XXX someday, if we implement a way to attach after autoconfig */
156 grf_init(n);
157 #endif
158 }
159
160 /*
161 * Called from macfb_attach() after setting up the frame buffer. Since
162 * there is a 1:1 correspondence between the macfb device and the grf
163 * device, the only bit of information we really need is the macfb_softc.
164 */
165 void
166 grf_attach(sc, unit)
167 struct macfb_softc *sc;
168 int unit;
169 {
170 grf_init(unit);
171
172 if (unit < numgrf)
173 grf_softc[unit].mfb_sc = sc;
174 }
175
176 /*
177 * Standard device ops
178 */
179 int
180 grfopen(dev, flag, mode, p)
181 dev_t dev;
182 int flag;
183 int mode;
184 struct proc *p;
185 {
186 struct grf_softc *sc;
187 int unit = GRFUNIT(dev);
188 int rv = 0;
189
190 if (grf_softc == NULL || unit >= numgrf)
191 return ENXIO;
192
193 sc = &grf_softc[unit];
194 if (sc->mfb_sc == NULL)
195 rv = ENXIO;
196
197 return rv;
198 }
199
200 int
201 grfclose(dev, flag, mode, p)
202 dev_t dev;
203 int flag;
204 int mode;
205 struct proc *p;
206 {
207 struct grf_softc *sc;
208 int unit = GRFUNIT(dev);
209 int rv = 0;
210
211 if (grf_softc == NULL || unit >= numgrf)
212 return ENXIO;
213
214 sc = &grf_softc[unit];
215 if (sc->mfb_sc != NULL)
216 macfb_clear(sc->mfb_sc->sc_dc); /* clear the display */
217 else
218 rv = ENXIO;
219
220 return rv;
221 }
222
223 int
224 grfioctl(dev, cmd, data, flag, p)
225 dev_t dev;
226 u_long cmd;
227 caddr_t data;
228 int flag;
229 struct proc *p;
230 {
231 struct grf_softc *sc;
232 struct macfb_devconfig *dc;
233 #if defined(GRF_COMPAT) || (NGRF > 0)
234 struct grfinfo *gd;
235 #endif /* GRF_COMPAT || (NGRF > 0) */
236 struct grfmode *gm;
237 int unit = GRFUNIT(dev);
238 int rv;
239
240 if (grf_softc == NULL || unit >= numgrf)
241 return ENXIO;
242
243 sc = &grf_softc[unit];
244 if (sc->mfb_sc == NULL)
245 return ENXIO;
246
247 dc = sc->mfb_sc->sc_dc;
248
249 switch (cmd) {
250 #if defined(GRF_COMPAT) || (NGRF > 0)
251 case GRFIOCGINFO:
252 gd = (struct grfinfo *)data;
253 memset(gd, 0, sizeof(struct grfinfo));
254 gd->gd_fbaddr = (caddr_t)dc->dc_paddr;
255 gd->gd_fbsize = dc->dc_size;
256 gd->gd_colors = (short)(1 << dc->dc_depth);
257 gd->gd_planes = (short)dc->dc_depth;
258 gd->gd_fbwidth = dc->dc_wid;
259 gd->gd_fbheight = dc->dc_ht;
260 gd->gd_fbrowbytes = dc->dc_rowbytes;
261 gd->gd_dwidth = dc->dc_raster.width;
262 gd->gd_dheight = dc->dc_raster.height;
263 rv = 0;
264 break;
265 #endif /* GRF_COMPAT || (NGRF > 0) */
266
267 case GRFIOCON:
268 case GRFIOCOFF:
269 /* Nothing to do */
270 rv = 0;
271 break;
272
273 #if defined(GRF_COMPAT) || (NGRF > 0)
274 case GRFIOCMAP:
275 rv = grfmap(dev, sc->mfb_sc, (caddr_t *)data, p);
276 break;
277
278 case GRFIOCUNMAP:
279 rv = grfunmap(dev, sc->mfb_sc, *(caddr_t *)data, p);
280 break;
281 #endif /* GRF_COMPAT || (NGRF > 0) */
282
283 case GRFIOCGMODE:
284 gm = (struct grfmode *)data;
285 memset(gm, 0, sizeof(struct grfmode));
286 gm->fbbase = (char *)dc->dc_vaddr;
287 gm->fbsize = dc->dc_size;
288 gm->fboff = dc->dc_offset;
289 gm->rowbytes = dc->dc_rowbytes;
290 gm->width = dc->dc_wid;
291 gm->height = dc->dc_ht;
292 gm->psize = dc->dc_depth;
293 rv = 0;
294 break;
295
296 case GRFIOCLISTMODES:
297 case GRFIOCGETMODE:
298 case GRFIOCSETMODE:
299 /* NONE of these operations are (officially) supported. */
300 default:
301 rv = EINVAL;
302 break;
303 }
304 return rv;
305 }
306
307 paddr_t
308 grfmmap(dev, off, prot)
309 dev_t dev;
310 off_t off;
311 int prot;
312 {
313 struct grf_softc *sc;
314 struct macfb_devconfig *dc;
315 paddr_t addr;
316 int unit = GRFUNIT(dev);
317
318 if (grf_softc == NULL || unit >= numgrf)
319 return ENXIO;
320
321 sc = &grf_softc[unit];
322 if (sc->mfb_sc == NULL)
323 return ENXIO;
324
325 dc = sc->mfb_sc->sc_dc;
326
327 if (off >= 0 &&
328 off < m68k_round_page(dc->dc_offset + dc->dc_size))
329 addr = m68k_btop(dc->dc_paddr + off);
330 else
331 addr = (-1); /* XXX bogus */
332
333 return addr;
334 }
335
336 int
337 grfmap(dev, sc, addrp, p)
338 dev_t dev;
339 struct macfb_softc *sc;
340 caddr_t *addrp;
341 struct proc *p;
342 {
343 struct specinfo si;
344 struct vnode vn;
345 u_long len;
346 int error, flags;
347
348 len = m68k_round_page(sc->sc_dc->dc_offset + sc->sc_dc->dc_size);
349 *addrp = (caddr_t)VM_DEFAULT_ADDRESS(p->p_vmspace->vm_daddr, len);
350 flags = MAP_SHARED | MAP_FIXED;
351
352 vn.v_type = VCHR; /* XXX */
353 vn.v_specinfo = &si; /* XXX */
354 vn.v_rdev = dev; /* XXX */
355
356 error = uvm_mmap(&p->p_vmspace->vm_map, (vaddr_t *)addrp,
357 (vsize_t)len, VM_PROT_ALL, VM_PROT_ALL,
358 flags, (caddr_t)&vn, 0, p->p_rlimit[RLIMIT_MEMLOCK].rlim_cur);
359
360 /* Offset into page: */
361 *addrp += sc->sc_dc->dc_offset;
362
363 return (error);
364 }
365
366 int
367 grfunmap(dev, sc, addr, p)
368 dev_t dev;
369 struct macfb_softc *sc;
370 caddr_t addr;
371 struct proc *p;
372 {
373 vm_size_t size;
374
375 addr -= sc->sc_dc->dc_offset;
376
377 if (addr <= 0)
378 return (-1);
379
380 size = m68k_round_page(sc->sc_dc->dc_offset + sc->sc_dc->dc_size);
381 uvm_unmap(&p->p_vmspace->vm_map, (vaddr_t)addr, (vaddr_t)addr + size);
382 return 0;
383 }
384