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