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