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