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