xref: /netbsd-src/sys/arch/atari/dev/view.c (revision 81b108b45f75f89f1e3ffad9fb6f074e771c0935)
1 /*	$NetBSD: view.c,v 1.9 1996/09/16 06:43:42 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 			if (vu->view && (vu->view == views[i].view)) {
123 				splx(s);
124 				return;
125 			}
126 			views[i].flags &= ~VUF_DISPLAY;
127 		}
128 	}
129 
130 	vu->flags |= VUF_ADDED;
131 	if (vu->view) {
132 		vu->view->display.x = vu->size.x;
133 		vu->view->display.y = vu->size.y;
134 
135 		grf_display_view(vu->view);
136 
137 		vu->size.x = vu->view->display.x;
138 		vu->size.y = vu->view->display.y;
139 		vu->flags |= VUF_DISPLAY;
140 	}
141 	splx(s);
142 }
143 
144 /*
145  * remove a view from our added list if it is marked as displaying
146  * switch to a new display.
147  */
148 static void
149 view_remove(vu)
150 	struct view_softc *vu;
151 {
152 	int i;
153 
154 	if ((vu->flags & VUF_ADDED) == 0)
155 		return;
156 
157 	vu->flags &= ~VUF_ADDED;
158 	if (vu->flags & VUF_DISPLAY) {
159 		for (i = 0; i < NVIEW; i++) {
160 			if((views[i].flags & VUF_ADDED) && &views[i] != vu) {
161 				view_display(&views[i]);
162 				break;
163 			}
164 		}
165 	}
166 	vu->flags &= ~VUF_DISPLAY;
167 	grf_remove_view(vu->view);
168 }
169 
170 static int
171 view_setsize(vu, vs)
172 	struct view_softc *vu;
173 	struct view_size *vs;
174 {
175 	view_t	*new, *old;
176 	dmode_t	*dmode;
177 	dimen_t ns;
178 	int	co, cs;
179 
180 	co = 0;
181 	cs = 0;
182 	if (vs->x != vu->size.x || vs->y != vu->size.y)
183 		co = 1;
184 
185 	if (vs->width != vu->size.width || vs->height != vu->size.height ||
186 	    vs->depth != vu->size.depth)
187 		cs = 1;
188 
189 	if (cs == 0 && co == 0)
190 		return(0);
191 
192 	ns.width  = vs->width;
193 	ns.height = vs->height;
194 
195 	if((dmode = grf_get_best_mode(&ns, vs->depth)) != NULL) {
196 		/*
197 		 * If we can't do better, leave it
198 		 */
199 		if(dmode == vu->view->mode)
200 			return(0);
201 	}
202 	new = grf_alloc_view(dmode, &ns, vs->depth);
203 	if (new == NULL)
204 		return(ENOMEM);
205 
206 	old = vu->view;
207 	vu->view = new;
208 	vu->size.x = new->display.x;
209 	vu->size.y = new->display.y;
210 	vu->size.width = new->display.width;
211 	vu->size.height = new->display.height;
212 	vu->size.depth = new->bitmap->depth;
213 
214 	/*
215 	 * we need a custom remove here to avoid letting
216 	 * another view display mark as not added or displayed
217 	 */
218 	if (vu->flags & VUF_DISPLAY) {
219 		vu->flags &= ~(VUF_ADDED|VUF_DISPLAY);
220 		view_display(vu);
221 	}
222 	grf_free_view(old);
223 	return(0);
224 }
225 
226 static int
227 view_get_colormap (vu, ucm)
228 struct view_softc	*vu;
229 colormap_t		*ucm;
230 {
231 	int	error;
232 	long	*cme;
233 	long	*uep;
234 
235 	if(ucm->size > MAX_CENTRIES)
236 		return(EINVAL);
237 
238 	/* add one incase of zero, ick. */
239 	cme = malloc(sizeof(ucm->entry[0])*(ucm->size+1), M_IOCTLOPS,M_WAITOK);
240 	if (cme == NULL)
241 		return(ENOMEM);
242 
243 	error      = 0;
244 	uep        = ucm->entry;
245 	ucm->entry = cme;	  /* set entry to out alloc. */
246 	if(vu->view == NULL || grf_get_colormap(vu->view, ucm))
247 		error = EINVAL;
248 	else error = copyout(cme, uep, sizeof(ucm->entry[0]) * ucm->size);
249 	ucm->entry = uep;	  /* set entry back to users. */
250 	free(cme, M_IOCTLOPS);
251 	return(error);
252 }
253 
254 static int
255 view_set_colormap(vu, ucm)
256 struct view_softc	*vu;
257 colormap_t		*ucm;
258 {
259 	colormap_t	*cm;
260 	int		error = 0;
261 
262 	if(ucm->size > MAX_CENTRIES)
263 		return(EINVAL);
264 
265 	cm = malloc(sizeof(ucm->entry[0])*ucm->size + sizeof(*cm), M_IOCTLOPS,
266 								M_WAITOK);
267 	if(cm == NULL)
268 		return(ENOMEM);
269 
270 	bcopy(ucm, cm, sizeof(colormap_t));
271 	cm->entry = (long *)&cm[1];		 /* table directly after. */
272 	if (((error =
273 	    copyin(ucm->entry,cm->entry,sizeof(ucm->entry[0])*ucm->size)) == 0)
274 	    && (vu->view == NULL || grf_use_colormap(vu->view, cm)))
275 		error = EINVAL;
276 	free(cm, M_IOCTLOPS);
277 	return(error);
278 }
279 
280 /*
281  *  functions made available by conf.c
282  */
283 
284 /*ARGSUSED*/
285 int
286 viewopen(dev, flags, mode, p)
287 dev_t		dev;
288 int		flags;
289 int		mode;
290 struct proc	*p;
291 {
292 	dimen_t			size;
293 	struct view_softc	*vu;
294 
295 	vu = &views[minor(dev)];
296 
297 	if(minor(dev) >= NVIEW)
298 		return(EXDEV);
299 	if(vu->flags & VUF_OPEN)
300 		return(EBUSY);
301 
302 	vu->size.x = view_default_x;
303 	vu->size.y = view_default_y;
304 	size.width = vu->size.width = view_default_width;
305 	size.height = vu->size.height = view_default_height;
306 	vu->size.depth = view_default_depth;
307 	vu->view = grf_alloc_view(NULL, &size, vu->size.depth);
308 	if (vu->view == NULL)
309 		return(ENOMEM);
310 
311 	vu->size.x = vu->view->display.x;
312 	vu->size.y = vu->view->display.y;
313 	vu->size.width = vu->view->display.width;
314 	vu->size.height = vu->view->display.height;
315 	vu->size.depth = vu->view->bitmap->depth;
316        	vu->flags |= VUF_OPEN;
317        	return(0);
318 }
319 
320 /*ARGSUSED*/
321 int
322 viewclose (dev, flags, mode, p)
323 	dev_t		dev;
324 	int 		flags;
325 	int		mode;
326 	struct proc	*p;
327 {
328 	struct view_softc *vu;
329 
330 	vu = &views[minor(dev)];
331 
332 	if ((vu->flags & VUF_OPEN) == 0)
333 		return (0); /* XXX not open? */
334 	view_remove (vu);
335 	grf_free_view (vu->view);
336 	vu->flags = 0;
337 	vu->view = NULL;
338 	return (0);
339 }
340 
341 
342 /*ARGSUSED*/
343 int
344 viewioctl (dev, cmd, data, flag, p)
345 dev_t		dev;
346 u_long		cmd;
347 caddr_t		data;
348 int		flag;
349 struct proc	*p;
350 {
351 	struct view_softc	*vu;
352 	bmap_t			*bm;
353 	int			error;
354 
355 	vu = &views[minor(dev)];
356 	error = 0;
357 
358 	switch (cmd) {
359 	case VIOCDISPLAY:
360 		view_display(vu);
361 		break;
362 	case VIOCREMOVE:
363 		view_remove(vu);
364 		break;
365 	case VIOCGSIZE:
366 		bcopy(&vu->size, data, sizeof (struct view_size));
367 		break;
368 	case VIOCSSIZE:
369 		error = view_setsize(vu, (struct view_size *)data);
370 		break;
371 	case VIOCGBMAP:
372 		bm = (bmap_t *)data;
373 		bcopy(vu->view->bitmap, bm, sizeof(bmap_t));
374 		if (p != NOPROC) {
375 			bm->plane      = NULL;
376 			bm->hw_address = NULL;
377 			bm->regs       = NULL;
378 			bm->hw_regs    = NULL;
379 		}
380 		break;
381 	case VIOCGCMAP:
382 		error = view_get_colormap(vu, (colormap_t *)data);
383 		break;
384 	case VIOCSCMAP:
385 		error = view_set_colormap(vu, (colormap_t *)data);
386 		break;
387 	default:
388 		error = EINVAL;
389 		break;
390 	}
391 	return(error);
392 }
393 
394 /*ARGSUSED*/
395 int
396 viewmmap(dev, off, prot)
397 dev_t	dev;
398 int	off, prot;
399 {
400 	struct view_softc	*vu;
401 	bmap_t			*bm;
402 	u_char			*bmd_start;
403 	u_long			bmd_size;
404 
405 	vu = &views[minor(dev)];
406 	bm = vu->view->bitmap;
407 	bmd_start = bm->hw_address;
408 	bmd_size = bm->bytes_per_row*bm->rows*bm->depth;
409 
410 	if (off >= 0 && off < bmd_size)
411 		return(((u_int)bmd_start + off) >> PGSHIFT);
412 
413 	return(-1);
414 }
415 
416 /*ARGSUSED*/
417 int
418 viewselect(dev, rw, p)
419 dev_t		dev;
420 int		rw;
421 struct proc	*p;
422 {
423 	if(rw == FREAD)
424 		return(0);
425 	return(1);
426 }
427 
428 view_t	*
429 viewview(dev)
430 dev_t	dev;
431 {
432 	return(views[minor(dev)].view);
433 }
434