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