xref: /netbsd-src/sys/arch/atari/dev/view.c (revision 9573504567626934c7ee01c7dce0c4bb1dfe7403)
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