1 /* $NetBSD: view.c,v 1.3 1995/04/10 09:13:20 mycroft 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 view_get_colormap __P((struct view_softc *, colormap_t *)); 65 int view_set_colormap __P((struct view_softc *, colormap_t *)); 66 67 int viewprobe (); 68 69 struct view_softc views[NVIEW]; 70 static int view_inited; 71 72 int view_default_x; 73 int view_default_y; 74 int view_default_width = 640; 75 int view_default_height = 400; 76 int view_default_depth = 1; 77 78 /* 79 * functions for probeing. 80 */ 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 viewprobe() 90 { 91 int i; 92 93 if(view_inited) 94 return(1); 95 96 view_inited = 1; 97 98 for(i=0; i<NVIEW; i++) { 99 views[i].view = NULL; 100 views[i].flags = 0; 101 } 102 return(1); 103 } 104 105 106 /* 107 * Internal functions. 108 */ 109 110 static void 111 view_display (vu) 112 struct view_softc *vu; 113 { 114 int s, i; 115 116 if (vu == NULL) 117 return; 118 119 s = spltty (); 120 121 /* 122 * mark views that share this monitor as not displaying 123 */ 124 for (i=0; i<NVIEW; i++) { 125 if(views[i].flags & VUF_DISPLAY) 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 view_display(&views[i]); 161 break; 162 } 163 } 164 } 165 vu->flags &= ~VUF_DISPLAY; 166 grf_remove_view(vu->view); 167 } 168 169 static int 170 view_setsize(vu, vs) 171 struct view_softc *vu; 172 struct view_size *vs; 173 { 174 view_t *new, *old; 175 dimen_t ns; 176 int co, cs; 177 178 co = 0; 179 cs = 0; 180 if (vs->x != vu->size.x || vs->y != vu->size.y) 181 co = 1; 182 183 if (vs->width != vu->size.width || vs->height != vu->size.height || 184 vs->depth != vu->size.depth) 185 cs = 1; 186 187 if (cs == 0 && co == 0) 188 return(0); 189 190 ns.width = vs->width; 191 ns.height = vs->height; 192 193 new = grf_alloc_view(NULL, &ns, vs->depth); 194 if (new == NULL) 195 return(ENOMEM); 196 197 old = vu->view; 198 vu->view = new; 199 vu->size.x = new->display.x; 200 vu->size.y = new->display.y; 201 vu->size.width = new->display.width; 202 vu->size.height = new->display.height; 203 vu->size.depth = new->bitmap->depth; 204 vu->size.x = vs->x; 205 vu->size.y = vs->y; 206 207 /* 208 * we need a custom remove here to avoid letting 209 * another view display mark as not added or displayed 210 */ 211 if (vu->flags & VUF_DISPLAY) { 212 vu->flags &= ~(VUF_ADDED|VUF_DISPLAY); 213 view_display(vu); 214 } 215 grf_free_view(old); 216 return(0); 217 } 218 219 static int 220 view_get_colormap (vu, ucm) 221 struct view_softc *vu; 222 colormap_t *ucm; 223 { 224 int error; 225 long *cme; 226 long *uep; 227 228 if(ucm->size > MAX_CENTRIES) 229 return(EINVAL); 230 231 /* add one incase of zero, ick. */ 232 cme = malloc(sizeof(ucm->entry[0])*(ucm->size+1), M_IOCTLOPS,M_WAITOK); 233 if (cme == NULL) 234 return(ENOMEM); 235 236 error = 0; 237 uep = ucm->entry; 238 ucm->entry = cme; /* set entry to out alloc. */ 239 if(vu->view == NULL || grf_get_colormap(vu->view, ucm)) 240 error = EINVAL; 241 else error = copyout(cme, uep, sizeof(ucm->entry[0]) * ucm->size); 242 ucm->entry = uep; /* set entry back to users. */ 243 free(cme, M_IOCTLOPS); 244 return(error); 245 } 246 247 static int 248 view_set_colormap(vu, ucm) 249 struct view_softc *vu; 250 colormap_t *ucm; 251 { 252 colormap_t *cm; 253 int error = 0; 254 255 if(ucm->size > MAX_CENTRIES) 256 return(EINVAL); 257 258 cm = malloc(sizeof(ucm->entry[0])*ucm->size + sizeof(*cm), M_IOCTLOPS, 259 M_WAITOK); 260 if(cm == NULL) 261 return(ENOMEM); 262 263 bcopy(ucm, cm, sizeof(colormap_t)); 264 cm->entry = (long *)&cm[1]; /* table directly after. */ 265 if (((error = 266 copyin(ucm->entry,cm->entry,sizeof(ucm->entry[0])*ucm->size)) == 0) 267 && (vu->view == NULL || grf_use_colormap(vu->view, cm))) 268 error = EINVAL; 269 free(cm, M_IOCTLOPS); 270 return(error); 271 } 272 273 /* 274 * functions made available by conf.c 275 */ 276 277 /*ARGSUSED*/ 278 int viewopen(dev, flags) 279 dev_t dev; 280 int flags; 281 { 282 dimen_t size; 283 struct view_softc *vu; 284 285 vu = &views[minor(dev)]; 286 287 if(minor(dev) >= NVIEW) 288 return(EXDEV); 289 if(vu->flags & VUF_OPEN) 290 return(EBUSY); 291 292 vu->size.x = view_default_x; 293 vu->size.y = view_default_y; 294 size.width = vu->size.width = view_default_width; 295 size.height = vu->size.height = view_default_height; 296 vu->size.depth = view_default_depth; 297 298 vu->view = grf_alloc_view(NULL, &size, vu->size.depth); 299 if (vu->view == NULL) 300 return(ENOMEM); 301 302 vu->size.x = vu->view->display.x; 303 vu->size.y = vu->view->display.y; 304 vu->size.width = vu->view->display.width; 305 vu->size.height = vu->view->display.height; 306 vu->size.depth = vu->view->bitmap->depth; 307 vu->flags |= VUF_OPEN; 308 return(0); 309 } 310 311 /*ARGSUSED*/ 312 void 313 viewclose (dev, flags) 314 dev_t dev; 315 int flags; 316 { 317 struct view_softc *vu; 318 319 vu = &views[minor(dev)]; 320 321 if ((vu->flags & VUF_OPEN) == 0) 322 return; 323 view_remove (vu); 324 grf_free_view (vu->view); 325 vu->flags = 0; 326 vu->view = NULL; 327 } 328 329 330 /*ARGSUSED*/ 331 int 332 viewioctl (dev, cmd, data, flag, p) 333 dev_t dev; 334 u_long cmd; 335 caddr_t data; 336 int flag; 337 struct proc *p; 338 { 339 struct view_softc *vu; 340 bmap_t *bm; 341 int error; 342 343 vu = &views[minor(dev)]; 344 error = 0; 345 346 switch (cmd) { 347 case VIOCDISPLAY: 348 view_display(vu); 349 break; 350 case VIOCREMOVE: 351 view_remove(vu); 352 break; 353 case VIOCGSIZE: 354 bcopy(&vu->size, data, sizeof (struct view_size)); 355 break; 356 case VIOCSSIZE: 357 error = view_setsize(vu, (struct view_size *)data); 358 break; 359 case VIOCGBMAP: 360 bm = (bmap_t *)data; 361 bcopy(vu->view->bitmap, bm, sizeof(bmap_t)); 362 if ((int)p != -1) { 363 bm->plane = NULL; 364 bm->hw_address = NULL; 365 } 366 break; 367 case VIOCGCMAP: 368 error = view_get_colormap(vu, (colormap_t *)data); 369 break; 370 case VIOCSCMAP: 371 error = view_set_colormap(vu, (colormap_t *)data); 372 break; 373 default: 374 error = EINVAL; 375 break; 376 } 377 return(error); 378 } 379 380 /*ARGSUSED*/ 381 int 382 viewmmap(dev, off, prot) 383 dev_t dev; 384 int off, prot; 385 { 386 struct view_softc *vu; 387 bmap_t *bm; 388 u_char *bmd_start; 389 u_long bmd_size; 390 391 vu = &views[minor(dev)]; 392 bm = vu->view->bitmap; 393 bmd_start = bm->hw_address; 394 bmd_size = bm->bytes_per_row*bm->rows*bm->depth; 395 396 if (off >= 0 && off < bmd_size) 397 return(((u_int)bmd_start + off) >> PGSHIFT); 398 399 return(-1); 400 } 401 402 /*ARGSUSED*/ 403 int 404 viewselect(dev, rw) 405 dev_t dev; 406 int rw; 407 { 408 if(rw == FREAD) 409 return(0); 410 return(1); 411 } 412