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