view.c revision 1.8 1 /* $NetBSD: view.c,v 1.8 1996/04/18 08:52:11 leo 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/param.h>
41 #include <sys/systm.h>
42 #include <sys/proc.h>
43 #include <sys/ioctl.h>
44 #include <sys/file.h>
45 #include <sys/device.h>
46 #include <sys/malloc.h>
47 #include <sys/queue.h>
48 #include <sys/conf.h>
49 #include <machine/cpu.h>
50 #include <atari/dev/grfabs_reg.h>
51 #include <atari/dev/viewioctl.h>
52 #include <atari/dev/viewvar.h>
53 #include "view.h"
54
55 static void view_display __P((struct view_softc *));
56 static void view_remove __P((struct view_softc *));
57 static int view_setsize __P((struct view_softc *, struct view_size *));
58 static int view_get_colormap __P((struct view_softc *, colormap_t *));
59 static int view_set_colormap __P((struct view_softc *, colormap_t *));
60
61 struct view_softc views[NVIEW];
62 static int view_inited;
63
64 int view_default_x;
65 int view_default_y;
66 int view_default_width = 640;
67 int view_default_height = 400;
68 int view_default_depth = 1;
69
70 /*
71 * functions for probeing.
72 */
73 void viewattach __P((int));
74
75 void
76 viewattach(cnt)
77 int cnt;
78 {
79 viewprobe();
80 printf("%d view%s configured\n", NVIEW, NVIEW > 1 ? "s" : "");
81 }
82
83 /* this function is called early to set up a display. */
84 int
85 viewprobe()
86 {
87 int i;
88
89 if(view_inited)
90 return(1);
91
92 view_inited = 1;
93
94 for(i=0; i<NVIEW; i++) {
95 views[i].view = NULL;
96 views[i].flags = 0;
97 }
98 return(1);
99 }
100
101
102 /*
103 * Internal functions.
104 */
105
106 static void
107 view_display (vu)
108 struct view_softc *vu;
109 {
110 int s, i;
111
112 if (vu == NULL)
113 return;
114
115 s = spltty ();
116
117 /*
118 * mark views that share this monitor as not displaying
119 */
120 for (i=0; i<NVIEW; i++) {
121 if(views[i].flags & VUF_DISPLAY)
122 views[i].flags &= ~VUF_DISPLAY;
123 }
124
125 vu->flags |= VUF_ADDED;
126 if (vu->view) {
127 vu->view->display.x = vu->size.x;
128 vu->view->display.y = vu->size.y;
129
130 grf_display_view(vu->view);
131
132 vu->size.x = vu->view->display.x;
133 vu->size.y = vu->view->display.y;
134 vu->flags |= VUF_DISPLAY;
135 }
136 splx(s);
137 }
138
139 /*
140 * remove a view from our added list if it is marked as displaying
141 * switch to a new display.
142 */
143 static void
144 view_remove(vu)
145 struct view_softc *vu;
146 {
147 int i;
148
149 if ((vu->flags & VUF_ADDED) == 0)
150 return;
151
152 vu->flags &= ~VUF_ADDED;
153 if (vu->flags & VUF_DISPLAY) {
154 for (i = 0; i < NVIEW; i++) {
155 if((views[i].flags & VUF_ADDED) && &views[i] != vu) {
156 view_display(&views[i]);
157 break;
158 }
159 }
160 }
161 vu->flags &= ~VUF_DISPLAY;
162 grf_remove_view(vu->view);
163 }
164
165 static int
166 view_setsize(vu, vs)
167 struct view_softc *vu;
168 struct view_size *vs;
169 {
170 view_t *new, *old;
171 dmode_t *dmode;
172 dimen_t ns;
173 int co, cs;
174
175 co = 0;
176 cs = 0;
177 if (vs->x != vu->size.x || vs->y != vu->size.y)
178 co = 1;
179
180 if (vs->width != vu->size.width || vs->height != vu->size.height ||
181 vs->depth != vu->size.depth)
182 cs = 1;
183
184 if (cs == 0 && co == 0)
185 return(0);
186
187 ns.width = vs->width;
188 ns.height = vs->height;
189
190 if((dmode = grf_get_best_mode(&ns, vs->depth)) != NULL) {
191 /*
192 * If we can't do better, leave it
193 */
194 if(dmode == vu->view->mode)
195 return(0);
196 }
197 new = grf_alloc_view(dmode, &ns, vs->depth);
198 if (new == NULL)
199 return(ENOMEM);
200
201 old = vu->view;
202 vu->view = new;
203 vu->size.x = new->display.x;
204 vu->size.y = new->display.y;
205 vu->size.width = new->display.width;
206 vu->size.height = new->display.height;
207 vu->size.depth = new->bitmap->depth;
208
209 /*
210 * we need a custom remove here to avoid letting
211 * another view display mark as not added or displayed
212 */
213 if (vu->flags & VUF_DISPLAY) {
214 vu->flags &= ~(VUF_ADDED|VUF_DISPLAY);
215 view_display(vu);
216 }
217 grf_free_view(old);
218 return(0);
219 }
220
221 static int
222 view_get_colormap (vu, ucm)
223 struct view_softc *vu;
224 colormap_t *ucm;
225 {
226 int error;
227 long *cme;
228 long *uep;
229
230 if(ucm->size > MAX_CENTRIES)
231 return(EINVAL);
232
233 /* add one incase of zero, ick. */
234 cme = malloc(sizeof(ucm->entry[0])*(ucm->size+1), M_IOCTLOPS,M_WAITOK);
235 if (cme == NULL)
236 return(ENOMEM);
237
238 error = 0;
239 uep = ucm->entry;
240 ucm->entry = cme; /* set entry to out alloc. */
241 if(vu->view == NULL || grf_get_colormap(vu->view, ucm))
242 error = EINVAL;
243 else error = copyout(cme, uep, sizeof(ucm->entry[0]) * ucm->size);
244 ucm->entry = uep; /* set entry back to users. */
245 free(cme, M_IOCTLOPS);
246 return(error);
247 }
248
249 static int
250 view_set_colormap(vu, ucm)
251 struct view_softc *vu;
252 colormap_t *ucm;
253 {
254 colormap_t *cm;
255 int error = 0;
256
257 if(ucm->size > MAX_CENTRIES)
258 return(EINVAL);
259
260 cm = malloc(sizeof(ucm->entry[0])*ucm->size + sizeof(*cm), M_IOCTLOPS,
261 M_WAITOK);
262 if(cm == NULL)
263 return(ENOMEM);
264
265 bcopy(ucm, cm, sizeof(colormap_t));
266 cm->entry = (long *)&cm[1]; /* table directly after. */
267 if (((error =
268 copyin(ucm->entry,cm->entry,sizeof(ucm->entry[0])*ucm->size)) == 0)
269 && (vu->view == NULL || grf_use_colormap(vu->view, cm)))
270 error = EINVAL;
271 free(cm, M_IOCTLOPS);
272 return(error);
273 }
274
275 /*
276 * functions made available by conf.c
277 */
278
279 /*ARGSUSED*/
280 int
281 viewopen(dev, flags, mode, p)
282 dev_t dev;
283 int flags;
284 int mode;
285 struct proc *p;
286 {
287 dimen_t size;
288 struct view_softc *vu;
289
290 vu = &views[minor(dev)];
291
292 if(minor(dev) >= NVIEW)
293 return(EXDEV);
294 if(vu->flags & VUF_OPEN)
295 return(EBUSY);
296
297 vu->size.x = view_default_x;
298 vu->size.y = view_default_y;
299 size.width = vu->size.width = view_default_width;
300 size.height = vu->size.height = view_default_height;
301 vu->size.depth = view_default_depth;
302 vu->view = grf_alloc_view(NULL, &size, vu->size.depth);
303 if (vu->view == NULL)
304 return(ENOMEM);
305
306 vu->size.x = vu->view->display.x;
307 vu->size.y = vu->view->display.y;
308 vu->size.width = vu->view->display.width;
309 vu->size.height = vu->view->display.height;
310 vu->size.depth = vu->view->bitmap->depth;
311 vu->flags |= VUF_OPEN;
312 return(0);
313 }
314
315 /*ARGSUSED*/
316 int
317 viewclose (dev, flags, mode, p)
318 dev_t dev;
319 int flags;
320 int mode;
321 struct proc *p;
322 {
323 struct view_softc *vu;
324
325 vu = &views[minor(dev)];
326
327 if ((vu->flags & VUF_OPEN) == 0)
328 return (0); /* XXX not open? */
329 view_remove (vu);
330 grf_free_view (vu->view);
331 vu->flags = 0;
332 vu->view = NULL;
333 return (0);
334 }
335
336
337 /*ARGSUSED*/
338 int
339 viewioctl (dev, cmd, data, flag, p)
340 dev_t dev;
341 u_long cmd;
342 caddr_t data;
343 int flag;
344 struct proc *p;
345 {
346 struct view_softc *vu;
347 bmap_t *bm;
348 int error;
349
350 vu = &views[minor(dev)];
351 error = 0;
352
353 switch (cmd) {
354 case VIOCDISPLAY:
355 view_display(vu);
356 break;
357 case VIOCREMOVE:
358 view_remove(vu);
359 break;
360 case VIOCGSIZE:
361 bcopy(&vu->size, data, sizeof (struct view_size));
362 break;
363 case VIOCSSIZE:
364 error = view_setsize(vu, (struct view_size *)data);
365 break;
366 case VIOCGBMAP:
367 bm = (bmap_t *)data;
368 bcopy(vu->view->bitmap, bm, sizeof(bmap_t));
369 if (p != NOPROC) {
370 bm->plane = NULL;
371 bm->hw_address = NULL;
372 }
373 break;
374 case VIOCGCMAP:
375 error = view_get_colormap(vu, (colormap_t *)data);
376 break;
377 case VIOCSCMAP:
378 error = view_set_colormap(vu, (colormap_t *)data);
379 break;
380 default:
381 error = EINVAL;
382 break;
383 }
384 return(error);
385 }
386
387 /*ARGSUSED*/
388 int
389 viewmmap(dev, off, prot)
390 dev_t dev;
391 int off, prot;
392 {
393 struct view_softc *vu;
394 bmap_t *bm;
395 u_char *bmd_start;
396 u_long bmd_size;
397
398 vu = &views[minor(dev)];
399 bm = vu->view->bitmap;
400 bmd_start = bm->hw_address;
401 bmd_size = bm->bytes_per_row*bm->rows*bm->depth;
402
403 if (off >= 0 && off < bmd_size)
404 return(((u_int)bmd_start + off) >> PGSHIFT);
405
406 return(-1);
407 }
408
409 /*ARGSUSED*/
410 int
411 viewselect(dev, rw, p)
412 dev_t dev;
413 int rw;
414 struct proc *p;
415 {
416 if(rw == FREAD)
417 return(0);
418 return(1);
419 }
420
421 view_t *
422 viewview(dev)
423 dev_t dev;
424 {
425 return(views[minor(dev)].view);
426 }
427