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