view.c revision 1.26 1 /* $NetBSD: view.c,v 1.26 2009/03/14 14:45:56 dsl Exp $ */
2
3 /*
4 * Copyright (c) 1994 Christian E. Hopps
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. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Christian E. Hopps.
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 /* The view major device is a placeholder device. It serves
34 * simply to map the semantics of a graphics dipslay to
35 * the semantics of a character block device. In other
36 * words the graphics system as currently built does not like to be
37 * refered to by open/close/ioctl. This device serves as
38 * a interface to graphics. */
39
40 #include <sys/cdefs.h>
41 __KERNEL_RCSID(0, "$NetBSD: view.c,v 1.26 2009/03/14 14:45:56 dsl Exp $");
42
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/proc.h>
46 #include <sys/ioctl.h>
47 #include <sys/file.h>
48 #include <sys/device.h>
49 #include <sys/malloc.h>
50 #include <sys/queue.h>
51 #include <sys/conf.h>
52 #include <machine/cpu.h>
53 #include <atari/dev/grfabs_reg.h>
54 #include <atari/dev/viewioctl.h>
55 #include <atari/dev/viewvar.h>
56 #include "view.h"
57
58 static void view_display(struct view_softc *);
59 static void view_remove(struct view_softc *);
60 static int view_setsize(struct view_softc *, struct view_size *);
61 static int view_get_colormap(struct view_softc *, colormap_t *);
62 static int view_set_colormap(struct view_softc *, colormap_t *);
63
64 struct view_softc views[NVIEW];
65 static int view_inited;
66
67 int view_default_x;
68 int view_default_y;
69 int view_default_width = 640;
70 int view_default_height = 400;
71 int view_default_depth = 1;
72
73 dev_type_open(viewopen);
74 dev_type_close(viewclose);
75 dev_type_ioctl(viewioctl);
76 dev_type_mmap(viewmmap);
77
78 const struct cdevsw view_cdevsw = {
79 viewopen, viewclose, nullread, nullwrite, viewioctl,
80 nostop, notty, nopoll, viewmmap, nokqfilter,
81 };
82
83 /*
84 * functions for probeing.
85 */
86 void viewattach(int);
87
88 void
89 viewattach(cnt)
90 int cnt;
91 {
92 viewprobe();
93 printf("%d view%s configured\n", NVIEW, NVIEW > 1 ? "s" : "");
94 }
95
96 /* this function is called early to set up a display. */
97 int
98 viewprobe()
99 {
100 int i;
101
102 if(view_inited)
103 return(1);
104
105 view_inited = 1;
106
107 for(i=0; i<NVIEW; i++) {
108 views[i].view = NULL;
109 views[i].flags = 0;
110 }
111 return(1);
112 }
113
114
115 /*
116 * Internal functions.
117 */
118
119 static void
120 view_display (vu)
121 struct view_softc *vu;
122 {
123 int s, i;
124
125 if (vu == NULL)
126 return;
127
128 s = spltty();
129
130 /*
131 * mark views that share this monitor as not displaying
132 */
133 for (i = 0; i < NVIEW; i++) {
134 if(views[i].flags & VUF_DISPLAY) {
135 if (vu->view && (vu->view == views[i].view)) {
136 splx(s);
137 return;
138 }
139 if (views[i].view) {
140 grf_save_view(views[i].view);
141 views[i].view->flags &= ~VF_DISPLAY;
142 }
143 views[i].flags &= ~VUF_DISPLAY;
144 }
145 }
146
147 vu->flags |= VUF_ADDED;
148 if (vu->view) {
149 vu->view->display.x = vu->size.x;
150 vu->view->display.y = vu->size.y;
151
152 grf_display_view(vu->view);
153 vu->view->flags |= VF_DISPLAY;
154
155 vu->size.x = vu->view->display.x;
156 vu->size.y = vu->view->display.y;
157 vu->flags |= VUF_DISPLAY;
158 }
159 splx(s);
160 }
161
162 /*
163 * remove a view from our added list if it is marked as displaying
164 * switch to a new display.
165 */
166 static void
167 view_remove(vu)
168 struct view_softc *vu;
169 {
170 int i;
171
172 if ((vu->flags & VUF_ADDED) == 0)
173 return;
174
175 vu->flags &= ~VUF_ADDED;
176 if (vu->flags & VUF_DISPLAY) {
177 for (i = 0; i < NVIEW; i++) {
178 if((views[i].flags & VUF_ADDED) && &views[i] != vu) {
179 view_display(&views[i]);
180 break;
181 }
182 }
183 }
184 vu->flags &= ~VUF_DISPLAY;
185 grf_remove_view(vu->view);
186 }
187
188 static int
189 view_setsize(vu, vs)
190 struct view_softc *vu;
191 struct view_size *vs;
192 {
193 view_t *new, *old;
194 dmode_t *dmode;
195 dimen_t ns;
196 int co, cs;
197
198 co = 0;
199 cs = 0;
200 if (vs->x != vu->size.x || vs->y != vu->size.y)
201 co = 1;
202
203 if (vs->width != vu->size.width || vs->height != vu->size.height ||
204 vs->depth != vu->size.depth)
205 cs = 1;
206
207 if (cs == 0 && co == 0)
208 return(0);
209
210 ns.width = vs->width;
211 ns.height = vs->height;
212
213 if((dmode = grf_get_best_mode(&ns, vs->depth)) != NULL) {
214 /*
215 * If we can't do better, leave it
216 */
217 if(dmode == vu->view->mode)
218 return(0);
219 }
220 new = grf_alloc_view(dmode, &ns, vs->depth);
221 if (new == NULL)
222 return(ENOMEM);
223
224 old = vu->view;
225 vu->view = new;
226 vu->size.x = new->display.x;
227 vu->size.y = new->display.y;
228 vu->size.width = new->display.width;
229 vu->size.height = new->display.height;
230 vu->size.depth = new->bitmap->depth;
231
232 /*
233 * we need a custom remove here to avoid letting
234 * another view display mark as not added or displayed
235 */
236 if (vu->flags & VUF_DISPLAY) {
237 vu->flags &= ~(VUF_ADDED|VUF_DISPLAY);
238 view_display(vu);
239 }
240 grf_free_view(old);
241 return(0);
242 }
243
244 static int
245 view_get_colormap (vu, ucm)
246 struct view_softc *vu;
247 colormap_t *ucm;
248 {
249 int error;
250 long *cme;
251 long *uep;
252
253 if(ucm->size > MAX_CENTRIES)
254 return(EINVAL);
255
256 /* add one incase of zero, ick. */
257 cme = malloc(sizeof(ucm->entry[0])*(ucm->size+1), M_TEMP,M_WAITOK);
258 if (cme == NULL)
259 return(ENOMEM);
260
261 error = 0;
262 uep = ucm->entry;
263 ucm->entry = cme; /* set entry to out alloc. */
264 if(vu->view == NULL || grf_get_colormap(vu->view, ucm))
265 error = EINVAL;
266 else error = copyout(cme, uep, sizeof(ucm->entry[0]) * ucm->size);
267 ucm->entry = uep; /* set entry back to users. */
268 free(cme, M_TEMP);
269 return(error);
270 }
271
272 static int
273 view_set_colormap(vu, ucm)
274 struct view_softc *vu;
275 colormap_t *ucm;
276 {
277 colormap_t *cm;
278 int error = 0;
279
280 if(ucm->size > MAX_CENTRIES)
281 return(EINVAL);
282
283 cm = malloc(sizeof(ucm->entry[0])*ucm->size + sizeof(*cm), M_TEMP,
284 M_WAITOK);
285 if(cm == NULL)
286 return(ENOMEM);
287
288 bcopy(ucm, cm, sizeof(colormap_t));
289 cm->entry = (long *)&cm[1]; /* table directly after. */
290 if (((error =
291 copyin(ucm->entry,cm->entry,sizeof(ucm->entry[0])*ucm->size)) == 0)
292 && (vu->view == NULL || grf_use_colormap(vu->view, cm)))
293 error = EINVAL;
294 free(cm, M_TEMP);
295 return(error);
296 }
297
298 /*
299 * functions made available by conf.c
300 */
301
302 /*ARGSUSED*/
303 int
304 viewopen(dev, flags, mode, l)
305 dev_t dev;
306 int flags;
307 int mode;
308 struct lwp *l;
309 {
310 dimen_t size;
311 struct view_softc *vu;
312
313 vu = &views[minor(dev)];
314
315 if(minor(dev) >= NVIEW)
316 return(EXDEV);
317 if(vu->flags & VUF_OPEN)
318 return(EBUSY);
319
320 vu->size.x = view_default_x;
321 vu->size.y = view_default_y;
322 size.width = vu->size.width = view_default_width;
323 size.height = vu->size.height = view_default_height;
324 vu->size.depth = view_default_depth;
325 vu->view = grf_alloc_view(NULL, &size, vu->size.depth);
326 if (vu->view == NULL)
327 return(ENOMEM);
328
329 vu->size.x = vu->view->display.x;
330 vu->size.y = vu->view->display.y;
331 vu->size.width = vu->view->display.width;
332 vu->size.height = vu->view->display.height;
333 vu->size.depth = vu->view->bitmap->depth;
334 vu->flags |= VUF_OPEN;
335 return(0);
336 }
337
338 /*ARGSUSED*/
339 int
340 viewclose (dev, flags, mode, l)
341 dev_t dev;
342 int flags;
343 int mode;
344 struct lwp *l;
345 {
346 struct view_softc *vu;
347
348 vu = &views[minor(dev)];
349
350 if ((vu->flags & VUF_OPEN) == 0)
351 return (0); /* XXX not open? */
352 view_remove (vu);
353 grf_free_view (vu->view);
354 vu->flags = 0;
355 vu->view = NULL;
356 return (0);
357 }
358
359
360 /*ARGSUSED*/
361 int
362 viewioctl (dev, cmd, data, flag, l)
363 dev_t dev;
364 u_long cmd;
365 void * data;
366 int flag;
367 struct lwp *l;
368 {
369 struct view_softc *vu;
370 bmap_t *bm;
371 int error;
372
373 vu = &views[minor(dev)];
374 error = 0;
375
376 switch (cmd) {
377 case VIOCDISPLAY:
378 view_display(vu);
379 break;
380 case VIOCREMOVE:
381 view_remove(vu);
382 break;
383 case VIOCGSIZE:
384 bcopy(&vu->size, data, sizeof (struct view_size));
385 break;
386 case VIOCSSIZE:
387 error = view_setsize(vu, (struct view_size *)data);
388 break;
389 case VIOCGBMAP:
390 bm = (bmap_t *)data;
391 bcopy(vu->view->bitmap, bm, sizeof(bmap_t));
392 if (l != NOLWP) {
393 bm->plane = NULL;
394 bm->hw_address = NULL;
395 bm->regs = NULL;
396 bm->hw_regs = NULL;
397 }
398 break;
399 case VIOCGCMAP:
400 error = view_get_colormap(vu, (colormap_t *)data);
401 break;
402 case VIOCSCMAP:
403 error = view_set_colormap(vu, (colormap_t *)data);
404 break;
405 default:
406 error = EPASSTHROUGH;
407 break;
408 }
409 return(error);
410 }
411
412 /*ARGSUSED*/
413 paddr_t
414 viewmmap(dev, off, prot)
415 dev_t dev;
416 off_t off;
417 int prot;
418 {
419 struct view_softc *vu;
420 bmap_t *bm;
421 u_char *bmd_start;
422 u_long bmd_lin, bmd_vga;
423
424 vu = &views[minor(dev)];
425 bm = vu->view->bitmap;
426 bmd_start = bm->hw_address;
427 bmd_lin = bm->lin_base;
428 bmd_vga = bm->vga_base;
429
430 /*
431 * control registers
432 */
433 if (off >= 0 && off < bm->reg_size)
434 return(((paddr_t)bm->hw_regs + off) >> PGSHIFT);
435
436 /*
437 * VGA memory
438 */
439 if (off >= bmd_vga && off < (bmd_vga + bm->vga_mappable))
440 return(((paddr_t)bm->vga_address - bmd_vga + off) >> PGSHIFT);
441
442 /*
443 * frame buffer
444 */
445 if (off >= bmd_lin && off < (bmd_lin + bm->phys_mappable))
446 return(((paddr_t)bmd_start - bmd_lin + off) >> PGSHIFT);
447
448 return(-1);
449 }
450
451 view_t *
452 viewview(dev)
453 dev_t dev;
454 {
455 return(views[minor(dev)].view);
456 }
457