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