grf.c revision 1.1
1/* 2 * Copyright (c) 1988 University of Utah. 3 * Copyright (c) 1990 The Regents of the University of California. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * the Systems Programming Group of the University of Utah Computer 8 * Science Department. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * from: Utah $Hdr: grf.c 1.31 91/01/21$ 39 * 40 * @(#)grf.c 7.8 (Berkeley) 5/7/91 41 */ 42 43/* 44 * Graphics display driver for the AMIGA 45 * This is the hardware-independent portion of the driver. 46 * Hardware access is through the grfdev routines below. 47 */ 48 49#include "grf.h" 50#if NGRF > 0 51 52#include "param.h" 53#include "proc.h" 54#include "ioctl.h" 55#include "file.h" 56#include "malloc.h" 57 58#include "device.h" 59#include "grfioctl.h" 60#include "grfvar.h" 61 62#include "machine/cpu.h" 63 64#include "vm/vm.h" 65#include "vm/vm_kern.h" 66#include "vm/vm_page.h" 67#include "vm/vm_pager.h" 68 69#include "specdev.h" 70#include "vnode.h" 71#include "mman.h" 72 73#include "ite.h" 74#if NITE == 0 75#define iteon(u,f) 76#define iteoff(u,f) 77#endif 78 79int grfprobe(); 80int cc_init(), cc_mode(); 81int tg_init(), tg_mode(); 82 83struct grfdev grfdev[] = { 84 MANUF_BUILTIN, PROD_BUILTIN_DISPLAY, 85 cc_init, cc_mode, "custom chips", 86 MANUF_UNILOWELL, PROD_UNILOWELL_A2410, 87 tg_init, tg_mode, "A2410 TIGA board", 88}; 89int ngrfdev = sizeof(grfdev) / sizeof(grfdev[0]); 90 91struct driver grfdriver = { grfprobe, "grf" }; 92struct grf_softc grf_softc[NGRF]; 93 94#ifdef DEBUG 95int grfdebug = 0; 96#define GDB_DEVNO 0x01 97#define GDB_MMAP 0x02 98#define GDB_IOMAP 0x04 99#define GDB_LOCK 0x08 100#endif 101 102/* 103 * XXX: called from ite console init routine. 104 * Does just what configure will do later but without printing anything. 105 */ 106grfconfig() 107{ 108 register caddr_t addr; 109 register struct amiga_hw *hw; 110 register struct amiga_device *ad, *nad; 111 112 for (hw = sc_table; hw->hw_type; hw++) { 113 if (!HW_ISDEV(hw, D_BITMAP)) 114 continue; 115 /* 116 * Found one, now match up with a logical unit number 117 */ 118 nad = NULL; 119 addr = hw->hw_kva; 120 for (ad = amiga_dinit; ad->amiga_driver; ad++) { 121 if (ad->amiga_driver != &grfdriver || ad->amiga_alive) 122 continue; 123 /* 124 * Wildcarded. If first, remember as possible match. 125 */ 126 if (ad->amiga_addr == NULL) { 127 if (nad == NULL) 128 nad = ad; 129 continue; 130 } 131 /* 132 * Not wildcarded. 133 * If exact match done searching, else keep looking. 134 */ 135 if (((hw->hw_manufacturer << 16) | hw->hw_product) 136 == ad->amiga_addr) { 137 nad = ad; 138 break; 139 } 140 } 141 /* 142 * Found a match, initialize 143 */ 144 if (nad && grfinit (nad)) 145 nad->amiga_addr = addr; 146 } 147} 148 149/* 150 * Normal init routine called by configure() code 151 */ 152grfprobe(ad) 153 struct amiga_device *ad; 154{ 155 struct grf_softc *gp = &grf_softc[ad->amiga_unit]; 156 157 if ((gp->g_flags & GF_ALIVE) == 0 && 158 !grfinit (ad)) 159 return(0); 160 printf("grf%d: %d x %d ", ad->amiga_unit, 161 gp->g_display.gd_dwidth, gp->g_display.gd_dheight); 162 if (gp->g_display.gd_colors == 2) 163 printf("monochrome"); 164 else 165 printf("%d color", gp->g_display.gd_colors); 166 printf(" %s display\n", grfdev[gp->g_type].gd_desc); 167 return(1); 168} 169 170grfinit(ad) 171 struct amiga_device *ad; 172{ 173 struct grf_softc *gp = &grf_softc[ad->amiga_unit]; 174 register struct grfdev *gd; 175 176 for (gd = grfdev; gd < &grfdev[ngrfdev]; gd++) 177 if (((gd->gd_manuf << 16) | gd->gd_prod) == ad->amiga_addr) 178 break; 179 180 if (gd < &grfdev[ngrfdev] && (*gd->gd_init)(gp, ad)) { 181 gp->g_type = gd - grfdev; 182 gp->g_flags = GF_ALIVE; 183 return(1); 184 } 185 return(0); 186} 187 188/*ARGSUSED*/ 189grfopen(dev, flags) 190 dev_t dev; 191{ 192 int unit = GRFUNIT(dev); 193 register struct grf_softc *gp = &grf_softc[unit]; 194 int error = 0; 195 196 if (unit >= NGRF || (gp->g_flags & GF_ALIVE) == 0) 197 return(ENXIO); 198 if ((gp->g_flags & (GF_OPEN|GF_EXCLUDE)) == (GF_OPEN|GF_EXCLUDE)) 199 return(EBUSY); 200 /* 201 * First open. 202 * XXX: always put in graphics mode. 203 */ 204 error = 0; 205 if ((gp->g_flags & GF_OPEN) == 0) { 206 gp->g_flags |= GF_OPEN; 207 error = grfon(dev); 208 } 209 return(error); 210} 211 212/*ARGSUSED*/ 213grfclose(dev, flags) 214 dev_t dev; 215{ 216 register struct grf_softc *gp = &grf_softc[GRFUNIT(dev)]; 217 218 (void) grfoff(dev); 219 (void) grfunlock(gp); 220 gp->g_flags &= GF_ALIVE; 221 return(0); 222} 223 224/*ARGSUSED*/ 225grfioctl(dev, cmd, data, flag, p) 226 dev_t dev; 227 caddr_t data; 228 struct proc *p; 229{ 230 register struct grf_softc *gp = &grf_softc[GRFUNIT(dev)]; 231 int error; 232 233 error = 0; 234 switch (cmd) { 235 236 case GRFIOCGINFO: 237 bcopy((caddr_t)&gp->g_display, data, sizeof(struct grfinfo)); 238 break; 239 240 case GRFIOCON: 241 error = grfon(dev); 242 break; 243 244 case GRFIOCOFF: 245 error = grfoff(dev); 246 break; 247 248 case GRFIOCMAP: 249 error = grfmmap(dev, (caddr_t *)data, p); 250 break; 251 252 case GRFIOCUNMAP: 253 error = grfunmmap(dev, *(caddr_t *)data, p); 254 break; 255 256 case GRFIOCSINFO: 257 error = grfsinfo (dev, (struct grfdyninfo *) data); 258 break; 259 260 default: 261 error = EINVAL; 262 break; 263 264 } 265 return(error); 266} 267 268/*ARGSUSED*/ 269grfselect(dev, rw) 270 dev_t dev; 271{ 272 if (rw == FREAD) 273 return(0); 274 return(1); 275} 276 277grflock(gp, block) 278 register struct grf_softc *gp; 279 int block; 280{ 281 struct proc *p = curproc; /* XXX */ 282 int error; 283 extern char devioc[]; 284 285#ifdef DEBUG 286 if (grfdebug & GDB_LOCK) 287 printf("grflock(%d): dev %x flags %x lockpid %x\n", 288 p->p_pid, gp-grf_softc, gp->g_flags, 289 gp->g_lockp ? gp->g_lockp->p_pid : -1); 290#endif 291 if (gp->g_lockp) { 292 if (gp->g_lockp == p) 293 return(EBUSY); 294 if (!block) 295 return(EAGAIN); 296 do { 297 gp->g_flags |= GF_WANTED; 298 if (error = tsleep((caddr_t)&gp->g_flags, 299 (PZERO+1) | PCATCH, devioc, 0)) 300 return (error); 301 } while (gp->g_lockp); 302 } 303 gp->g_lockp = p; 304 return(0); 305} 306 307grfunlock(gp) 308 register struct grf_softc *gp; 309{ 310#ifdef DEBUG 311 if (grfdebug & GDB_LOCK) 312 printf("grfunlock(%d): dev %x flags %x lockpid %d\n", 313 curproc->p_pid, gp-grf_softc, gp->g_flags, 314 gp->g_lockp ? gp->g_lockp->p_pid : -1); 315#endif 316 if (gp->g_lockp != curproc) 317 return(EBUSY); 318 if (gp->g_flags & GF_WANTED) { 319 wakeup((caddr_t)&gp->g_flags); 320 gp->g_flags &= ~GF_WANTED; 321 } 322 gp->g_lockp = NULL; 323 return(0); 324} 325 326/*ARGSUSED*/ 327grfmap(dev, off, prot) 328 dev_t dev; 329{ 330 return(grfaddr(&grf_softc[GRFUNIT(dev)], off)); 331} 332 333 334grfon(dev) 335 dev_t dev; 336{ 337 int unit = GRFUNIT(dev); 338 struct grf_softc *gp = &grf_softc[unit]; 339 340 /* 341 * XXX: iteoff call relies on devices being in same order 342 * as ITEs and the fact that iteoff only uses the minor part 343 * of the dev arg. 344 */ 345 iteoff(unit, 3); 346 return((*grfdev[gp->g_type].gd_mode) 347 (gp, (dev&GRFOVDEV) ? GM_GRFOVON : GM_GRFON)); 348} 349 350grfoff(dev) 351 dev_t dev; 352{ 353 int unit = GRFUNIT(dev); 354 struct grf_softc *gp = &grf_softc[unit]; 355 int error; 356 357 (void) grfunmmap(dev, (caddr_t)0, curproc); 358 error = (*grfdev[gp->g_type].gd_mode) 359 (gp, (dev&GRFOVDEV) ? GM_GRFOVOFF : GM_GRFOFF); 360 /* XXX: see comment for iteoff above */ 361 iteon(unit, 2); 362 return(error); 363} 364 365grfsinfo(dev, dyninfo) 366 dev_t dev; 367 struct grfdyninfo *dyninfo; 368{ 369 int unit = GRFUNIT(dev); 370 struct grf_softc *gp = &grf_softc[unit]; 371 int error; 372 373 error = grfdev[gp->g_type].gd_mode (gp, GM_GRFCONFIG, dyninfo); 374 /* XXX: see comment for iteoff above */ 375 itereinit (unit); 376 return(error); 377} 378 379grfaddr(gp, off) 380 struct grf_softc *gp; 381 register int off; 382{ 383 register struct grfinfo *gi = &gp->g_display; 384 385#if 0 386 /* control registers */ 387 if (off >= 0 && off < gi->gd_regsize) 388 return(((u_int)gi->gd_regaddr + off) >> PGSHIFT); 389 390 /* frame buffer */ 391 if (off >= gi->gd_regsize && off < gi->gd_regsize+gi->gd_fbsize) { 392 off -= gi->gd_regsize; 393 return(((u_int)gi->gd_fbaddr + off) >> PGSHIFT); 394 } 395#endif 396 /* bogus */ 397 return(-1); 398} 399 400grfmmap(dev, addrp, p) 401 dev_t dev; 402 caddr_t *addrp; 403 struct proc *p; 404{ 405 struct grf_softc *gp = &grf_softc[GRFUNIT(dev)]; 406 int len, error; 407 struct vnode vn; 408 struct specinfo si; 409 int flags; 410 411#ifdef DEBUG 412 if (grfdebug & GDB_MMAP) 413 printf("grfmmap(%d): addr %x\n", p->p_pid, *addrp); 414#endif 415 len = gp->g_display.gd_regsize + gp->g_display.gd_fbsize; 416 flags = MAP_FILE|MAP_SHARED; 417 if (*addrp) 418 flags |= MAP_FIXED; 419 else 420 *addrp = (caddr_t)0x1000000; /* XXX */ 421 vn.v_type = VCHR; /* XXX */ 422 vn.v_specinfo = &si; /* XXX */ 423 vn.v_rdev = dev; /* XXX */ 424 error = vm_mmap(&p->p_vmspace->vm_map, (vm_offset_t *)addrp, 425 (vm_size_t)len, VM_PROT_ALL, flags, (caddr_t)&vn, 0); 426 return(error); 427} 428 429grfunmmap(dev, addr, p) 430 dev_t dev; 431 caddr_t addr; 432 struct proc *p; 433{ 434 struct grf_softc *gp = &grf_softc[GRFUNIT(dev)]; 435 vm_size_t size; 436 int rv; 437 438#ifdef DEBUG 439 if (grfdebug & GDB_MMAP) 440 printf("grfunmmap(%d): dev %x addr %x\n", p->p_pid, dev, addr); 441#endif 442 if (addr == 0) 443 return(EINVAL); /* XXX: how do we deal with this? */ 444 size = round_page(gp->g_display.gd_regsize + gp->g_display.gd_fbsize); 445 rv = vm_deallocate(p->p_vmspace->vm_map, (vm_offset_t)addr, size); 446 return(rv == KERN_SUCCESS ? 0 : EINVAL); 447} 448 449 450#endif /* NGRF > 0 */ 451