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