1 /* $NetBSD: grf.c,v 1.1.1.1 1995/03/26 07:12:12 leo Exp $ */ 2 3 /* 4 * Copyright (c) 1995 Leo Weppelman 5 * Copyright (c) 1988 University of Utah. 6 * Copyright (c) 1990 The Regents of the University of California. 7 * All rights reserved. 8 * 9 * This code is derived from software contributed to Berkeley by 10 * the Systems Programming Group of the University of Utah Computer 11 * Science Department. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 3. All advertising materials mentioning features or use of this software 22 * must display the following acknowledgement: 23 * This product includes software developed by the University of 24 * California, Berkeley and its contributors. 25 * 4. Neither the name of the University nor the names of its contributors 26 * may be used to endorse or promote products derived from this software 27 * without specific prior written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 30 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 32 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 * SUCH DAMAGE. 40 * 41 * from: Utah $Hdr: grf.c 1.31 91/01/21$ 42 * 43 * @(#)grf.c 7.8 (Berkeley) 5/7/91 44 */ 45 46 /* 47 * Graphics display driver for the Atari 48 * This is the hardware-independent portion of the driver. 49 * Hardware access is through the grf_softc->g_mode routine. 50 */ 51 52 #include <sys/param.h> 53 #include <sys/proc.h> 54 #include <sys/ioctl.h> 55 #include <sys/device.h> 56 #include <sys/file.h> 57 #include <sys/malloc.h> 58 #include <sys/conf.h> 59 #include <sys/systm.h> 60 #include <sys/vnode.h> 61 #include <sys/mman.h> 62 #include <vm/vm.h> 63 #include <vm/vm_kern.h> 64 #include <vm/vm_page.h> 65 #include <vm/vm_pager.h> 66 #include <machine/cpu.h> 67 #include <atari/atari/device.h> 68 #include <atari/dev/grfioctl.h> 69 #include <atari/dev/grfabs_reg.h> 70 #include <atari/dev/grfvar.h> 71 #include <atari/dev/itevar.h> 72 #include <atari/dev/viewioctl.h> 73 #include <atari/dev/viewvar.h> 74 75 #include "grf.h" 76 #if NGRF > 0 77 78 #include "ite.h" 79 #if NITE == 0 80 #define ite_on(u,f) 81 #define ite_off(u,f) 82 #define ite_reinit(d) 83 #endif 84 85 int grfopen __P((dev_t, int, int, struct proc *)); 86 int grfclose __P((dev_t, int)); 87 int grfioctl __P((dev_t, u_long, caddr_t, int, struct proc *)); 88 int grfselect __P((dev_t, int)); 89 int grfmap __P((dev_t, int, int)); 90 91 int grfon __P((dev_t)); 92 int grfoff __P((dev_t)); 93 int grfsinfo __P((dev_t, struct grfdyninfo *)); 94 #ifdef BANKEDDEVPAGER 95 int grfbanked_get __P((dev_t, off_t, int)); 96 int grfbanked_cur __P((dev_t)); 97 int grfbanked_set __P((dev_t, int)); 98 #endif 99 static void grf_viewsync __P((struct grf_softc *)); 100 static int grf_mode __P((struct grf_softc *, int, void *, int, int)); 101 102 int grfbusprint __P((void *auxp, char *)); 103 int grfbusmatch __P((struct device *, struct cfdata *, void *)); 104 void grfbusattach __P((struct device *, struct device *, void *)); 105 106 void grfattach __P((struct device *, struct device *, void *)); 107 int grfmatch __P((struct device *, struct cfdata *, void *)); 108 int grfprint __P((void *, char *)); 109 /* 110 * pointers to grf drivers device structs 111 */ 112 struct grf_softc *grfsp[NGRF]; 113 114 115 struct cfdriver grfbuscd = { 116 NULL, "grfbus", (cfmatch_t)grfbusmatch, grfbusattach, DV_DULL, 117 sizeof(struct device) 118 }; 119 120 struct cfdriver grfcd = { 121 NULL, "grf", (cfmatch_t)grfmatch, grfattach, DV_DULL, 122 sizeof(struct grf_softc), NULL, 0 123 }; 124 125 /* 126 * only used in console init. 127 */ 128 static struct cfdata *cfdata_gbus = NULL; 129 static struct cfdata *cfdata_grf = NULL; 130 131 int 132 grfbusmatch(pdp, cfp, auxp) 133 struct device *pdp; 134 struct cfdata *cfp; 135 void *auxp; 136 { 137 if(strcmp(auxp, grfbuscd.cd_name)) 138 return(0); 139 140 if((atari_realconfig == 0) || (cfdata_gbus == NULL)) { 141 /* 142 * Probe layers we depend on 143 */ 144 if(grfabs_probe() == 0) 145 return(0); 146 viewprobe(); 147 148 if(atari_realconfig == 0) { 149 /* 150 * XXX: console init opens view 0 151 */ 152 if(viewopen(0, 0)) 153 return(0); 154 cfdata_gbus = cfp; 155 } 156 } 157 return(1); /* Always there */ 158 } 159 160 void 161 grfbusattach(pdp, dp, auxp) 162 struct device *pdp, *dp; 163 void *auxp; 164 { 165 static int did_cons = 0; 166 int i; 167 168 if(dp == NULL) { /* Console init */ 169 did_cons = 1; 170 i = 0; 171 atari_config_found(cfdata_gbus, NULL, (void*)&i, grfbusprint); 172 } 173 else { 174 printf("\n"); 175 for(i = 0; i < NGRF; i++) { 176 /* 177 * Skip opening view[0] when we this is the console. 178 */ 179 if(!did_cons || (i > 0)) 180 if(viewopen(i, 0)) 181 break; 182 config_found(dp, (void*)&i, grfbusprint); 183 } 184 } 185 } 186 187 int 188 grfbusprint(auxp, name) 189 void *auxp; 190 char *name; 191 { 192 if(name == NULL) 193 return(UNCONF); 194 return(QUIET); 195 } 196 197 198 int 199 grfmatch(pdp, cfp, auxp) 200 struct device *pdp; 201 struct cfdata *cfp; 202 void *auxp; 203 { 204 int unit = *(int*)auxp; 205 206 /* 207 * Match only on unit indicated by grfbus attach. 208 */ 209 if(cfp->cf_unit != unit) 210 return(0); 211 212 cfdata_grf = cfp; 213 return(1); 214 } 215 216 /* 217 * attach: initialize the grf-structure and try to attach an ite to us. 218 * note : dp is NULL during early console init. 219 */ 220 void 221 grfattach(pdp, dp, auxp) 222 struct device *pdp, *dp; 223 void *auxp; 224 { 225 extern struct view_softc views[]; 226 static struct grf_softc congrf; 227 struct grf_softc *gp; 228 int maj; 229 230 /* 231 * find our major device number 232 */ 233 for(maj = 0; maj < nchrdev; maj++) 234 if (cdevsw[maj].d_open == grfopen) 235 break; 236 237 /* 238 * Handle exeption case: early console init 239 */ 240 if(dp == NULL) { 241 congrf.g_unit = 0; 242 congrf.g_grfdev = makedev(maj, 0); 243 congrf.g_flags = GF_ALIVE; 244 congrf.g_mode = grf_mode; 245 congrf.g_conpri = grfcc_cnprobe(); 246 congrf.g_view = views[0].view; /* XXX */ 247 congrf.g_viewdev = congrf.g_unit; 248 grfcc_iteinit(&congrf); 249 grf_viewsync(&congrf); 250 251 /* Attach console ite */ 252 atari_config_found(cfdata_grf, NULL, &congrf, grfprint); 253 return; 254 } 255 256 gp = (struct grf_softc *)dp; 257 gp->g_unit = gp->g_device.dv_unit; 258 grfsp[gp->g_unit] = gp; 259 260 if((cfdata_grf != NULL) && (gp->g_unit == 0)) { 261 /* 262 * We inited earlier just copy the info, take care 263 * not to copy the device struct though. 264 */ 265 bcopy(&congrf.g_display, &gp->g_display, 266 (char *)&gp[1] - (char *)&gp->g_display); 267 } 268 else { 269 gp->g_grfdev = makedev(maj, gp->g_unit); 270 gp->g_flags = GF_ALIVE; 271 gp->g_mode = grf_mode; 272 gp->g_conpri = 0; 273 gp->g_view = views[gp->g_unit].view; /* XXX */ 274 gp->g_viewdev = gp->g_unit; 275 grfcc_iteinit(gp); 276 grf_viewsync(gp); 277 } 278 279 printf(": width %d height %d", gp->g_display.gd_dwidth, 280 gp->g_display.gd_dheight); 281 if(gp->g_display.gd_colors == 2) 282 printf(" monochrome\n"); 283 else printf(" colors %d\n", gp->g_display.gd_colors); 284 285 /* 286 * try and attach an ite 287 */ 288 config_found(dp, gp, grfprint); 289 } 290 291 int 292 grfprint(auxp, pnp) 293 void *auxp; 294 char *pnp; 295 { 296 if(pnp) 297 printf("ite at %s", pnp); 298 return(UNCONF); 299 } 300 301 /*ARGSUSED*/ 302 int 303 grfopen(dev, flags, devtype, p) 304 dev_t dev; 305 int flags, devtype; 306 struct proc *p; 307 { 308 struct grf_softc *gp; 309 310 if (GRFUNIT(dev) >= NGRF) 311 return(ENXIO); 312 313 gp = grfsp[GRFUNIT(dev)]; 314 315 if ((gp->g_flags & GF_ALIVE) == 0) 316 return(ENXIO); 317 318 if ((gp->g_flags & (GF_OPEN|GF_EXCLUDE)) == (GF_OPEN|GF_EXCLUDE)) 319 return(EBUSY); 320 321 return(0); 322 } 323 324 /*ARGSUSED*/ 325 int 326 grfclose(dev, flags) 327 dev_t dev; 328 int flags; 329 { 330 struct grf_softc *gp; 331 332 gp = grfsp[GRFUNIT(dev)]; 333 (void)grfoff(dev); 334 gp->g_flags &= GF_ALIVE; 335 return(0); 336 } 337 338 /*ARGSUSED*/ 339 int 340 grfioctl(dev, cmd, data, flag, p) 341 dev_t dev; 342 u_long cmd; 343 int flag; 344 caddr_t data; 345 struct proc *p; 346 { 347 struct grf_softc *gp; 348 int error; 349 350 gp = grfsp[GRFUNIT(dev)]; 351 error = 0; 352 353 switch (cmd) { 354 case OGRFIOCGINFO: 355 /* argl.. no bank-member.. */ 356 bcopy((caddr_t)&gp->g_display, data, sizeof(struct grfinfo)-4); 357 break; 358 case GRFIOCGINFO: 359 bcopy((caddr_t)&gp->g_display, data, sizeof(struct grfinfo)); 360 break; 361 case GRFIOCON: 362 error = grfon(dev); 363 break; 364 case GRFIOCOFF: 365 error = grfoff(dev); 366 break; 367 case GRFIOCSINFO: 368 error = grfsinfo(dev, (struct grfdyninfo *) data); 369 break; 370 case GRFGETVMODE: 371 return(gp->g_mode(gp, GM_GRFGETVMODE, data)); 372 case GRFSETVMODE: 373 error = gp->g_mode(gp, GM_GRFSETVMODE, data); 374 if (error == 0 && gp->g_itedev) 375 ite_reinit(gp->g_itedev); 376 break; 377 case GRFGETNUMVM: 378 return(gp->g_mode(gp, GM_GRFGETNUMVM, data)); 379 /* 380 * these are all hardware dependant, and have to be resolved 381 * in the respective driver. 382 */ 383 case GRFIOCPUTCMAP: 384 case GRFIOCGETCMAP: 385 case GRFIOCSSPRITEPOS: 386 case GRFIOCGSPRITEPOS: 387 case GRFIOCSSPRITEINF: 388 case GRFIOCGSPRITEINF: 389 case GRFIOCGSPRITEMAX: 390 default: 391 /* 392 * check to see whether it's a command recognized by the 393 * view code. 394 */ 395 if(gp->g_view != NULL) 396 return(viewioctl(gp->g_viewdev, cmd, data, flag, p)); 397 error = EINVAL; 398 break; 399 400 } 401 return(error); 402 } 403 404 /*ARGSUSED*/ 405 int 406 grfselect(dev, rw) 407 dev_t dev; 408 int rw; 409 { 410 if (rw == FREAD) 411 return(0); 412 return(1); 413 } 414 415 /* 416 * map the contents of a graphics display card into process' 417 * memory space. 418 */ 419 int 420 grfmap(dev, off, prot) 421 dev_t dev; 422 int off, prot; 423 { 424 panic("No grfmap\n"); /* LWP */ 425 } 426 427 int 428 grfon(dev) 429 dev_t dev; 430 { 431 struct grf_softc *gp; 432 433 gp = grfsp[GRFUNIT(dev)]; 434 435 if (gp->g_flags & GF_GRFON) 436 return(0); 437 438 gp->g_flags |= GF_GRFON; 439 if (gp->g_itedev != NODEV) 440 ite_off(gp->g_itedev, 3); 441 442 return(gp->g_mode(gp, (dev & GRFOVDEV) ? GM_GRFOVON : GM_GRFON)); 443 } 444 445 int 446 grfoff(dev) 447 dev_t dev; 448 { 449 struct grf_softc *gp; 450 int error; 451 452 gp = grfsp[GRFUNIT(dev)]; 453 454 if ((gp->g_flags & GF_GRFON) == 0) 455 return(0); 456 457 gp->g_flags &= ~GF_GRFON; 458 error = gp->g_mode(gp, (dev & GRFOVDEV) ? GM_GRFOVOFF : GM_GRFOFF); 459 460 /* 461 * Closely tied together no X's 462 */ 463 if (gp->g_itedev != NODEV) 464 ite_on(gp->g_itedev, 2); 465 466 return(error); 467 } 468 469 int 470 grfsinfo(dev, dyninfo) 471 dev_t dev; 472 struct grfdyninfo *dyninfo; 473 { 474 struct grf_softc *gp; 475 int error; 476 477 gp = grfsp[GRFUNIT(dev)]; 478 error = gp->g_mode(gp, GM_GRFCONFIG, dyninfo); 479 480 /* 481 * Closely tied together no X's 482 */ 483 if (gp->g_itedev != NODEV) 484 ite_reinit(gp->g_itedev); 485 return(error); 486 } 487 488 /* 489 * Get the grf-info in sync with underlying view. 490 */ 491 static void 492 grf_viewsync(gp) 493 struct grf_softc *gp; 494 { 495 struct view_size vs; 496 bmap_t bm; 497 struct grfinfo *gi; 498 499 gi = &gp->g_display; 500 501 viewioctl(gp->g_viewdev, VIOCGBMAP, &bm, 0, -1); 502 503 gp->g_data = (caddr_t) 0xDeadBeaf; /* not particularly clean.. */ 504 505 gi->gd_fbaddr = bm.hw_address; 506 gi->gd_fbsize = bm.depth*bm.bytes_per_row*bm.rows; 507 508 if(viewioctl(gp->g_viewdev, VIOCGSIZE, &vs, 0, -1)) { 509 /* 510 * fill in some default values... 511 * XXX: Should _never_ happen 512 */ 513 vs.width = 640; 514 vs.height = 400; 515 vs.depth = 2; 516 } 517 gi->gd_colors = 1 << vs.depth; 518 gi->gd_planes = vs.depth; 519 520 gi->gd_fbwidth = vs.width; 521 gi->gd_fbheight = vs.height; 522 gi->gd_dyn.gdi_fbx = 0; 523 gi->gd_dyn.gdi_fby = 0; 524 gi->gd_dyn.gdi_dwidth = vs.width; 525 gi->gd_dyn.gdi_dheight = vs.height; 526 gi->gd_dyn.gdi_dx = 0; 527 gi->gd_dyn.gdi_dy = 0; 528 } 529 530 /* 531 * Change the mode of the display. 532 * Right now all we can do is grfon/grfoff. 533 * Return a UNIX error number or 0 for success. 534 */ 535 /*ARGSUSED*/ 536 static int 537 grf_mode(gp, cmd, arg, a2, a3) 538 struct grf_softc *gp; 539 int cmd, a2, a3; 540 void *arg; 541 { 542 switch (cmd) { 543 case GM_GRFON: 544 /* 545 * Get in sync with view, ite might have changed it. 546 */ 547 grf_viewsync(gp); 548 viewioctl(gp->g_viewdev, VIOCDISPLAY, NULL, 0, -1); 549 return(0); 550 case GM_GRFOFF: 551 viewioctl(gp->g_viewdev, VIOCREMOVE, NULL, 0, -1); 552 return(0); 553 case GM_GRFCONFIG: 554 default: 555 break; 556 } 557 return(EINVAL); 558 } 559 #endif /* NGRF > 0 */ 560