1 /* $NetBSD: grf.c,v 1.38 2001/09/19 18:10:33 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 1988 University of Utah. 5 * Copyright (c) 1990 The Regents of the University of California. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * the Systems Programming Group of the University of Utah Computer 10 * Science Department. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by the University of 23 * California, Berkeley and its contributors. 24 * 4. Neither the name of the University nor the names of its contributors 25 * may be used to endorse or promote products derived from this software 26 * without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 * 40 * from: Utah $Hdr: grf.c 1.31 91/01/21$ 41 * 42 * @(#)grf.c 7.8 (Berkeley) 5/7/91 43 */ 44 45 /* 46 * Graphics display driver for the Amiga 47 * This is the hardware-independent portion of the driver. 48 * Hardware access is through the grf_softc->g_mode routine. 49 */ 50 51 #include <sys/param.h> 52 #include <sys/proc.h> 53 #include <sys/ioctl.h> 54 #include <sys/device.h> 55 #include <sys/file.h> 56 #include <sys/malloc.h> 57 #include <sys/systm.h> 58 #include <sys/vnode.h> 59 #include <sys/mman.h> 60 #include <sys/poll.h> 61 #include <uvm/uvm_extern.h> 62 #include <machine/cpu.h> 63 #include <dev/sun/fbio.h> 64 #include <amiga/amiga/color.h> /* DEBUG */ 65 #include <amiga/amiga/device.h> 66 #include <amiga/dev/grfioctl.h> 67 #include <amiga/dev/grfvar.h> 68 #include <amiga/dev/itevar.h> 69 #include <amiga/dev/viewioctl.h> 70 71 #include <sys/conf.h> 72 #include <machine/conf.h> 73 74 #include "view.h" 75 #include "grf.h" 76 77 #if NGRF > 0 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 grfon __P((dev_t)); 86 int grfoff __P((dev_t)); 87 int grfsinfo __P((dev_t, struct grfdyninfo *)); 88 #ifdef BANKEDDEVPAGER 89 int grfbanked_get __P((dev_t, off_t, int)); 90 int grfbanked_cur __P((dev_t)); 91 int grfbanked_set __P((dev_t, int)); 92 #endif 93 94 void grfattach __P((struct device *, struct device *, void *)); 95 int grfmatch __P((struct device *, struct cfdata *, void *)); 96 int grfprint __P((void *, const char *)); 97 /* 98 * pointers to grf drivers device structs 99 */ 100 struct grf_softc *grfsp[NGRF]; 101 102 struct cfattach grf_ca = { 103 sizeof(struct device), grfmatch, grfattach 104 }; 105 106 /* 107 * only used in console init. 108 */ 109 static struct cfdata *cfdata; 110 111 /* 112 * match if the unit of grf matches its perspective 113 * low level board driver. 114 */ 115 int 116 grfmatch(pdp, cfp, auxp) 117 struct device *pdp; 118 struct cfdata *cfp; 119 void *auxp; 120 { 121 122 if (cfp->cf_unit != ((struct grf_softc *)pdp)->g_unit) 123 return(0); 124 cfdata = cfp; 125 return(1); 126 } 127 128 /* 129 * attach.. plug pointer in and print some info. 130 * then try and attach an ite to us. note: dp is NULL 131 * durring console init. 132 */ 133 void 134 grfattach(pdp, dp, auxp) 135 struct device *pdp, *dp; 136 void *auxp; 137 { 138 struct grf_softc *gp; 139 int maj; 140 141 gp = (struct grf_softc *)pdp; 142 grfsp[gp->g_unit] = (struct grf_softc *)pdp; 143 144 /* 145 * find our major device number 146 */ 147 for(maj = 0; maj < nchrdev; maj++) 148 if (cdevsw[maj].d_open == grfopen) 149 break; 150 151 gp->g_grfdev = makedev(maj, gp->g_unit); 152 if (dp != NULL) { 153 printf(": width %d height %d", gp->g_display.gd_dwidth, 154 gp->g_display.gd_dheight); 155 if (gp->g_display.gd_colors == 2) 156 printf(" monochrome\n"); 157 else 158 printf(" colors %d\n", gp->g_display.gd_colors); 159 } 160 161 /* 162 * try and attach an ite 163 */ 164 amiga_config_found(cfdata, dp, gp, grfprint); 165 } 166 167 int 168 grfprint(auxp, pnp) 169 void *auxp; 170 const char *pnp; 171 { 172 if (pnp) 173 printf("ite at %s", pnp); 174 return(UNCONF); 175 } 176 177 /*ARGSUSED*/ 178 int 179 grfopen(dev, flags, devtype, p) 180 dev_t dev; 181 int flags, devtype; 182 struct proc *p; 183 { 184 struct grf_softc *gp; 185 186 if (GRFUNIT(dev) >= NGRF || (gp = grfsp[GRFUNIT(dev)]) == NULL) 187 return(ENXIO); 188 189 if ((gp->g_flags & GF_ALIVE) == 0) 190 return(ENXIO); 191 192 if ((gp->g_flags & (GF_OPEN|GF_EXCLUDE)) == (GF_OPEN|GF_EXCLUDE)) 193 return(EBUSY); 194 195 return(0); 196 } 197 198 /*ARGSUSED*/ 199 int 200 grfclose(dev, flags, mode, p) 201 dev_t dev; 202 int flags; 203 int mode; 204 struct proc *p; 205 { 206 struct grf_softc *gp; 207 208 gp = grfsp[GRFUNIT(dev)]; 209 (void)grfoff(dev); 210 gp->g_flags &= GF_ALIVE; 211 return(0); 212 } 213 214 /*ARGSUSED*/ 215 int 216 grfioctl(dev, cmd, data, flag, p) 217 dev_t dev; 218 u_long cmd; 219 caddr_t data; 220 int flag; 221 struct proc *p; 222 { 223 struct grf_softc *gp; 224 int error; 225 226 gp = grfsp[GRFUNIT(dev)]; 227 error = 0; 228 229 switch (cmd) { 230 case OGRFIOCGINFO: 231 /* argl.. no bank-member.. */ 232 bcopy((caddr_t)&gp->g_display, data, sizeof(struct grfinfo)-4); 233 break; 234 case GRFIOCGINFO: 235 bcopy((caddr_t)&gp->g_display, data, sizeof(struct grfinfo)); 236 break; 237 case GRFIOCON: 238 error = grfon(dev); 239 break; 240 case GRFIOCOFF: 241 error = grfoff(dev); 242 break; 243 case GRFIOCSINFO: 244 error = grfsinfo(dev, (struct grfdyninfo *) data); 245 break; 246 case GRFGETVMODE: 247 return(gp->g_mode(gp, GM_GRFGETVMODE, data, 0, 0)); 248 case GRFSETVMODE: 249 error = gp->g_mode(gp, GM_GRFSETVMODE, data, 0, 0); 250 if (error == 0 && gp->g_itedev && !(gp->g_flags & GF_GRFON)) 251 ite_reinit(gp->g_itedev); 252 break; 253 case GRFGETNUMVM: 254 return(gp->g_mode(gp, GM_GRFGETNUMVM, data, 0, 0)); 255 /* 256 * these are all hardware dependant, and have to be resolved 257 * in the respective driver. 258 */ 259 case GRFIOCPUTCMAP: 260 case GRFIOCGETCMAP: 261 case GRFIOCSSPRITEPOS: 262 case GRFIOCGSPRITEPOS: 263 case GRFIOCSSPRITEINF: 264 case GRFIOCGSPRITEINF: 265 case GRFIOCGSPRITEMAX: 266 case GRFIOCBITBLT: 267 case GRFIOCSETMON: 268 case GRFTOGGLE: /* Toggles between Cirrus boards and native ECS on 269 Amiga. 15/11/94 ill */ 270 /* 271 * We need the minor dev number to get the overlay/image 272 * information for grf_ul. 273 */ 274 return(gp->g_mode(gp, GM_GRFIOCTL, data, cmd, dev)); 275 276 case GRFIOCBLANK: /* blank ioctl, IOCON/OFF will turn ite on */ 277 case FBIOSVIDEO: 278 error = gp->g_mode(gp, GM_GRFIOCTL, data, GRFIOCBLANK, dev); 279 if (!error) 280 gp->g_blank = *(int *)data; 281 return (error); 282 283 case FBIOGVIDEO: 284 *(int *)data = gp->g_blank; 285 return (0); 286 287 default: 288 #if NVIEW > 0 289 /* 290 * check to see whether it's a command recognized by the 291 * view code if the unit is 0 292 * XXX 293 */ 294 if (GRFUNIT(dev) == 0) 295 return(viewioctl(dev, cmd, data, flag, p)); 296 #endif 297 error = EINVAL; 298 break; 299 300 } 301 return(error); 302 } 303 304 /*ARGSUSED*/ 305 int 306 grfpoll(dev, events, p) 307 dev_t dev; 308 int events; 309 struct proc *p; 310 { 311 return(events & (POLLOUT | POLLWRNORM)); 312 } 313 314 /* 315 * map the contents of a graphics display card into process' 316 * memory space. 317 */ 318 paddr_t 319 grfmmap(dev, off, prot) 320 dev_t dev; 321 off_t off; 322 int prot; 323 { 324 struct grf_softc *gp; 325 struct grfinfo *gi; 326 327 gp = grfsp[GRFUNIT(dev)]; 328 gi = &gp->g_display; 329 330 /* 331 * control registers 332 */ 333 if (off >= 0 && off < gi->gd_regsize) 334 return(((paddr_t)gi->gd_regaddr + off) >> PGSHIFT); 335 336 /* 337 * frame buffer 338 */ 339 if (off >= gi->gd_regsize && off < gi->gd_regsize+gi->gd_fbsize) { 340 off -= gi->gd_regsize; 341 #ifdef BANKEDDEVPAGER 342 if (gi->gd_bank_size) 343 off %= gi->gd_bank_size; 344 #endif 345 return(((paddr_t)gi->gd_fbaddr + off) >> PGSHIFT); 346 } 347 /* bogus */ 348 return(-1); 349 } 350 351 int 352 grfon(dev) 353 dev_t dev; 354 { 355 struct grf_softc *gp; 356 357 gp = grfsp[GRFUNIT(dev)]; 358 359 if (gp->g_flags & GF_GRFON) 360 return(0); 361 362 gp->g_flags |= GF_GRFON; 363 if (gp->g_itedev != NODEV) 364 ite_off(gp->g_itedev, 3); 365 366 return(gp->g_mode(gp, (dev & GRFOVDEV) ? GM_GRFOVON : GM_GRFON, 367 NULL, 0, 0)); 368 } 369 370 int 371 grfoff(dev) 372 dev_t dev; 373 { 374 struct grf_softc *gp; 375 int error; 376 377 gp = grfsp[GRFUNIT(dev)]; 378 379 if ((gp->g_flags & GF_GRFON) == 0) 380 return(0); 381 382 gp->g_flags &= ~GF_GRFON; 383 error = gp->g_mode(gp, (dev & GRFOVDEV) ? GM_GRFOVOFF : GM_GRFOFF, 384 NULL, 0, 0); 385 386 /* 387 * Closely tied together no X's 388 */ 389 if (gp->g_itedev != NODEV) 390 ite_on(gp->g_itedev, 2); 391 392 return(error); 393 } 394 395 int 396 grfsinfo(dev, dyninfo) 397 dev_t dev; 398 struct grfdyninfo *dyninfo; 399 { 400 struct grf_softc *gp; 401 int error; 402 403 gp = grfsp[GRFUNIT(dev)]; 404 error = gp->g_mode(gp, GM_GRFCONFIG, dyninfo, 0, 0); 405 406 /* 407 * Closely tied together no X's 408 */ 409 if (gp->g_itedev != NODEV) 410 ite_reinit(gp->g_itedev); 411 return(error); 412 } 413 414 #ifdef BANKEDDEVPAGER 415 416 int 417 grfbanked_get (dev, off, prot) 418 dev_t dev; 419 off_t off; 420 int prot; 421 { 422 struct grf_softc *gp; 423 struct grfinfo *gi; 424 int error, bank; 425 426 gp = grfsp[GRFUNIT(dev)]; 427 gi = &gp->g_display; 428 429 off -= gi->gd_regsize; 430 if (off < 0 || off >= gi->gd_fbsize) 431 return -1; 432 433 error = gp->g_mode(gp, GM_GRFGETBANK, &bank, off, prot); 434 return error ? -1 : bank; 435 } 436 437 int 438 grfbanked_cur (dev) 439 dev_t dev; 440 { 441 struct grf_softc *gp; 442 int error, bank; 443 444 gp = grfsp[GRFUNIT(dev)]; 445 446 error = gp->g_mode(gp, GM_GRFGETCURBANK, &bank, 0, 0); 447 return(error ? -1 : bank); 448 } 449 450 int 451 grfbanked_set (dev, bank) 452 dev_t dev; 453 int bank; 454 { 455 struct grf_softc *gp; 456 457 gp = grfsp[GRFUNIT(dev)]; 458 return(gp->g_mode(gp, GM_GRFSETBANK, &bank, 0, 0) ? -1 : 0); 459 } 460 461 #endif /* BANKEDDEVPAGER */ 462 #endif /* NGRF > 0 */ 463