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