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