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