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