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