1 /* 2 * Copyright (c) 1994 Christian E. Hopps 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by Christian E. Hopps. 16 * 4. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 * 30 * $Id: view.c,v 1.8 1994/05/08 05:53:49 chopps Exp $ 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 48 #include <machine/cpu.h> 49 50 #include <vm/vm.h> 51 #include <vm/vm_kern.h> 52 #include <vm/vm_page.h> 53 #include <vm/vm_pager.h> 54 55 #include <miscfs/specfs/specdev.h> 56 #include <sys/vnode.h> 57 #include <sys/mman.h> 58 59 #include <amiga/dev/grfabs_reg.h> 60 #include <amiga/dev/viewioctl.h> 61 #include <amiga/dev/viewvar.h> 62 #include "view.h" 63 64 static void view_display __P((struct view_softc *)); 65 static void view_remove __P((struct view_softc *)); 66 static int view_setsize __P((struct view_softc *, struct view_size *)); 67 68 void viewclose __P((dev_t, int)); 69 int viewioctl __P((dev_t, int, caddr_t, int, struct proc *)); 70 int viewopen __P((dev_t, int)); 71 int viewmap __P((dev_t, int, int)); 72 73 int view_get_colormap __P((struct view_softc *, colormap_t *)); 74 int view_set_colormap __P((struct view_softc *, colormap_t *)); 75 76 int viewprobe (); 77 78 struct view_softc views[NVIEW]; 79 int view_inited; /* also checked in ite_cc.c */ 80 81 int view_default_x; 82 int view_default_y; 83 int view_default_width = 640; 84 int view_default_height = 400; 85 int view_default_depth = 2; 86 87 /* 88 * functions for probeing. 89 */ 90 91 viewattach(cnt) 92 int cnt; 93 { 94 viewprobe(); 95 printf("%d view%s configured\n", NVIEW, NVIEW > 1 ? "s" : ""); 96 } 97 98 /* this function is called early to set up a display. */ 99 viewprobe() 100 { 101 int i; 102 103 if (view_inited) 104 return(1); 105 106 view_inited = 1; 107 108 for (i=0; i<NVIEW; i++) { 109 views[i].view = NULL; 110 views[i].flags = 0; 111 } 112 return(1); 113 } 114 115 116 /* 117 * Internal functions. 118 */ 119 120 static void 121 view_display (vu) 122 struct view_softc *vu; 123 { 124 int s, i; 125 126 if (vu == NULL) 127 return; 128 129 s = spltty (); 130 131 /* 132 * mark views that share this monitor as not displaying 133 */ 134 for (i=0; i<NVIEW; i++) { 135 if ((views[i].flags & VUF_DISPLAY) && 136 views[i].monitor == vu->monitor) 137 views[i].flags &= ~VUF_DISPLAY; 138 } 139 140 vu->flags |= VUF_ADDED; 141 if (vu->view) { 142 vu->view->display.x = vu->size.x; 143 vu->view->display.y = vu->size.y; 144 145 grf_display_view(vu->view); 146 147 vu->size.x = vu->view->display.x; 148 vu->size.y = vu->view->display.y; 149 vu->flags |= VUF_DISPLAY; 150 } 151 splx(s); 152 } 153 154 /* 155 * remove a view from our added list if it is marked as displaying 156 * switch to a new display. 157 */ 158 static void 159 view_remove(vu) 160 struct view_softc *vu; 161 { 162 int i; 163 164 if ((vu->flags & VUF_ADDED) == 0) 165 return; 166 167 vu->flags &= ~VUF_ADDED; 168 if (vu->flags & VUF_DISPLAY) { 169 for (i = 0; i < NVIEW; i++) { 170 if ((views[i].flags & VUF_ADDED) && &views[i] != vu && 171 views[i].monitor == vu->monitor) { 172 view_display(&views[i]); 173 break; 174 } 175 } 176 } 177 vu->flags &= ~VUF_DISPLAY; 178 grf_remove_view(vu->view); 179 } 180 181 static int 182 view_setsize(vu, vs) 183 struct view_softc *vu; 184 struct view_size *vs; 185 { 186 view_t *new, *old; 187 dimen_t ns; 188 int co, cs; 189 190 co = 0; 191 cs = 0; 192 if (vs->x != vu->size.x || vs->y != vu->size.y) 193 co = 1; 194 195 if (vs->width != vu->size.width || vs->height != vu->size.height || 196 vs->depth != vu->size.depth) 197 cs = 1; 198 199 if (cs == 0 && co == 0) 200 return(0); 201 202 ns.width = vs->width; 203 ns.height = vs->height; 204 205 new = grf_alloc_view(NULL, &ns, vs->depth); 206 if (new == NULL) 207 return(ENOMEM); 208 209 old = vu->view; 210 vu->view = new; 211 vu->size.x = new->display.x; 212 vu->size.y = new->display.y; 213 vu->size.width = new->display.width; 214 vu->size.height = new->display.height; 215 vu->size.depth = new->bitmap->depth; 216 vu->mode = grf_get_display_mode(vu->view); 217 vu->monitor = grf_get_monitor(vu->mode); 218 vu->size.x = vs->x; 219 vu->size.y = vs->y; 220 221 /* 222 * we need a custom remove here to avoid letting 223 * another view display mark as not added or displayed 224 */ 225 if (vu->flags & VUF_DISPLAY) { 226 vu->flags &= ~(VUF_ADDED|VUF_DISPLAY); 227 view_display(vu); 228 } 229 grf_free_view(old); 230 return(0); 231 } 232 233 /* 234 * functions made available by conf.c 235 */ 236 237 /*ARGSUSED*/ 238 int 239 viewopen(dev, flags) 240 dev_t dev; 241 int flags; 242 { 243 dimen_t size; 244 struct view_softc *vu; 245 246 vu = &views[minor(dev)]; 247 248 if (minor(dev) >= NVIEW) 249 return(EXDEV); 250 251 if (vu->flags & VUF_OPEN) 252 return(EBUSY); 253 254 vu->size.x = view_default_x; 255 vu->size.y = view_default_y; 256 size.width = vu->size.width = view_default_width; 257 size.height = vu->size.height = view_default_height; 258 vu->size.depth = view_default_depth; 259 260 vu->view = grf_alloc_view(NULL, &size, vu->size.depth); 261 if (vu->view == NULL) 262 return(ENOMEM); 263 264 vu->size.x = vu->view->display.x; 265 vu->size.y = vu->view->display.y; 266 vu->size.width = vu->view->display.width; 267 vu->size.height = vu->view->display.height; 268 vu->size.depth = vu->view->bitmap->depth; 269 vu->flags |= VUF_OPEN; 270 vu->mode = grf_get_display_mode(vu->view); 271 vu->monitor = grf_get_monitor(vu->mode); 272 return(0); 273 } 274 275 /*ARGSUSED*/ 276 void 277 viewclose (dev, flags) 278 dev_t dev; 279 int flags; 280 { 281 struct view_softc *vu; 282 283 vu = &views[minor(dev)]; 284 285 if ((vu->flags & VUF_OPEN) == 0) 286 return; 287 view_remove (vu); 288 grf_free_view (vu->view); 289 vu->flags = 0; 290 vu->view = NULL; 291 vu->mode = NULL; 292 vu->monitor = NULL; 293 } 294 295 296 /*ARGSUSED*/ 297 int 298 viewioctl (dev, cmd, data, flag, p) 299 dev_t dev; 300 int cmd, flag; 301 caddr_t data; 302 struct proc *p; 303 { 304 struct view_softc *vu; 305 colormap_t *cm; 306 bmap_t *bm; 307 int error; 308 309 vu = &views[minor(dev)]; 310 error = 0; 311 312 switch (cmd) { 313 case VIOCDISPLAY: 314 view_display(vu); 315 break; 316 case VIOCREMOVE: 317 view_remove(vu); 318 break; 319 case VIOCGSIZE: 320 bcopy(&vu->size, data, sizeof (struct view_size)); 321 break; 322 case VIOCSSIZE: 323 error = view_setsize(vu, (struct view_size *)data); 324 break; 325 case VIOCGBMAP: 326 bm = (bmap_t *)data; 327 bcopy(vu->view->bitmap, bm, sizeof(bmap_t)); 328 if ((int)p != -1) { 329 bm->plane = 0; 330 bm->blit_temp = 0; 331 bm->hardware_address = 0; 332 } 333 break; 334 case VIOCGCMAP: 335 error = view_get_colormap(vu, (colormap_t *)data); 336 break; 337 case VIOCSCMAP: 338 error = view_set_colormap(vu, (colormap_t *)data); 339 break; 340 default: 341 error = EINVAL; 342 break; 343 } 344 return(error); 345 } 346 347 int 348 view_get_colormap (vu, ucm) 349 struct view_softc *vu; 350 colormap_t *ucm; 351 { 352 int error; 353 u_long *cme; 354 u_long *uep; 355 356 /* add one incase of zero, ick. */ 357 cme = malloc(sizeof (u_long)*(ucm->size + 1), M_IOCTLOPS, M_WAITOK); 358 if (cme == NULL) 359 return(ENOMEM); 360 361 uep = ucm->entry; 362 error = 0; 363 ucm->entry = cme; /* set entry to out alloc. */ 364 if (vu->view == NULL || grf_get_colormap(vu->view, ucm)) 365 error = EINVAL; 366 else 367 error = copyout(cme, uep, sizeof(u_long) * ucm->size); 368 ucm->entry = uep; /* set entry back to users. */ 369 free(cme, M_IOCTLOPS); 370 return(error); 371 } 372 373 int 374 view_set_colormap(vu, ucm) 375 struct view_softc *vu; 376 colormap_t *ucm; 377 { 378 colormap_t *cm; 379 int error; 380 381 error = 0; 382 cm = malloc(sizeof(u_long) * ucm->size + sizeof (*cm), M_IOCTLOPS, 383 M_WAITOK); 384 if (cm == NULL) 385 return(ENOMEM); 386 387 bcopy (ucm, cm, sizeof(colormap_t)); 388 cm->entry = (u_long *)&cm[1]; /* table directly after. */ 389 if (((error = 390 copyin(ucm->entry, cm->entry, sizeof (u_long) * ucm->size)) == 0) 391 && (vu->view == NULL || grf_use_colormap(vu->view, cm))) 392 error = EINVAL; 393 free(cm, M_IOCTLOPS); 394 return(error); 395 } 396 397 /*ARGSUSED*/ 398 int 399 viewmap(dev, off, prot) 400 dev_t dev; 401 int off, prot; 402 { 403 struct view_softc *vu; 404 bmap_t *bm; 405 u_char *bmd_start; 406 u_long bmd_size; 407 408 vu = &views[minor(dev)]; 409 bm = vu->view->bitmap; 410 bmd_start = bm->hardware_address; 411 bmd_size = bm->bytes_per_row*bm->rows*bm->depth; 412 413 if (off >= 0 && off < bmd_size) 414 return(((u_int)bmd_start + off) >> PGSHIFT); 415 416 return(-1); 417 } 418 419 /*ARGSUSED*/ 420 int 421 viewselect(dev, rw) 422 dev_t dev; 423 int rw; 424 { 425 if (rw == FREAD) 426 return(0); 427 return(1); 428 } 429