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