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