1*41480Smckusick /* 2*41480Smckusick * Copyright (c) 1988 University of Utah. 3*41480Smckusick * Copyright (c) 1990 The Regents of the University of California. 4*41480Smckusick * All rights reserved. 5*41480Smckusick * 6*41480Smckusick * This code is derived from software contributed to Berkeley by 7*41480Smckusick * the Systems Programming Group of the University of Utah Computer 8*41480Smckusick * Science Department. 9*41480Smckusick * 10*41480Smckusick * %sccs.include.redist.c% 11*41480Smckusick * 12*41480Smckusick * from: Utah $Hdr: grf.c 1.28 89/08/14$ 13*41480Smckusick * 14*41480Smckusick * @(#)grf.c 7.1 (Berkeley) 05/08/90 15*41480Smckusick */ 16*41480Smckusick 17*41480Smckusick /* 18*41480Smckusick * Graphics display driver for the HP300. 19*41480Smckusick * This is the hardware-independent portion of the driver. 20*41480Smckusick * Hardware access is through the grfdev routines below. 21*41480Smckusick */ 22*41480Smckusick 23*41480Smckusick #include "grf.h" 24*41480Smckusick #if NGRF > 0 25*41480Smckusick 26*41480Smckusick #include "param.h" 27*41480Smckusick #include "user.h" 28*41480Smckusick #include "proc.h" 29*41480Smckusick #include "ioctl.h" 30*41480Smckusick #include "file.h" 31*41480Smckusick #include "mapmem.h" 32*41480Smckusick #include "malloc.h" 33*41480Smckusick 34*41480Smckusick #include "device.h" 35*41480Smckusick #include "grfioctl.h" 36*41480Smckusick #include "grfvar.h" 37*41480Smckusick 38*41480Smckusick #include "machine/cpu.h" 39*41480Smckusick 40*41480Smckusick #ifdef HPUXCOMPAT 41*41480Smckusick #include "../hpux/hpux.h" 42*41480Smckusick #endif 43*41480Smckusick 44*41480Smckusick #include "ite.h" 45*41480Smckusick #if NITE == 0 46*41480Smckusick #define iteon(u,f) 47*41480Smckusick #define iteoff(u,f) 48*41480Smckusick #endif 49*41480Smckusick 50*41480Smckusick int grfprobe(); 51*41480Smckusick int tc_init(), tc_mode(); 52*41480Smckusick int gb_init(), gb_mode(); 53*41480Smckusick int rb_init(), rb_mode(); 54*41480Smckusick int dv_init(), dv_mode(); 55*41480Smckusick 56*41480Smckusick struct grfdev grfdev[] = { 57*41480Smckusick GID_TOPCAT, GRFBOBCAT, tc_init, tc_mode, 58*41480Smckusick "topcat", 59*41480Smckusick GID_GATORBOX, GRFGATOR, gb_init, gb_mode, 60*41480Smckusick "gatorbox", 61*41480Smckusick GID_RENAISSANCE,GRFRBOX, rb_init, rb_mode, 62*41480Smckusick "renaissance", 63*41480Smckusick GID_LRCATSEYE, GRFCATSEYE, tc_init, tc_mode, 64*41480Smckusick "lo-res catseye", 65*41480Smckusick GID_HRCCATSEYE, GRFCATSEYE, tc_init, tc_mode, 66*41480Smckusick "hi-res catseye", 67*41480Smckusick GID_HRMCATSEYE, GRFCATSEYE, tc_init, tc_mode, 68*41480Smckusick "hi-res catseye", 69*41480Smckusick GID_DAVINCI, GRFDAVINCI, dv_init, dv_mode, 70*41480Smckusick "davinci", 71*41480Smckusick }; 72*41480Smckusick int ngrfdev = sizeof(grfdev) / sizeof(grfdev[0]); 73*41480Smckusick 74*41480Smckusick struct driver grfdriver = { grfprobe, "grf" }; 75*41480Smckusick struct grf_softc grf_softc[NGRF]; 76*41480Smckusick 77*41480Smckusick #ifdef MAPMEM 78*41480Smckusick int grfexit(); 79*41480Smckusick struct mapmemops grfops = { (int (*)())0, (int (*)())0, grfexit, grfexit }; 80*41480Smckusick #ifdef HPUXCOMPAT 81*41480Smckusick struct mapmemops grflckops = { (int (*)())0, (int (*)())0, grfexit, grfexit }; 82*41480Smckusick struct mapmemops grfiomops = { (int (*)())0, (int (*)())0, grfexit, grfexit }; 83*41480Smckusick #endif 84*41480Smckusick #endif 85*41480Smckusick 86*41480Smckusick #ifdef DEBUG 87*41480Smckusick int grfdebug = 0; 88*41480Smckusick #define GDB_DEVNO 0x01 89*41480Smckusick #define GDB_MMAP 0x02 90*41480Smckusick #define GDB_IOMAP 0x04 91*41480Smckusick #define GDB_LOCK 0x08 92*41480Smckusick #endif 93*41480Smckusick 94*41480Smckusick /* 95*41480Smckusick * XXX: called from ite console init routine. 96*41480Smckusick * Does just what configure will do later but without printing anything. 97*41480Smckusick */ 98*41480Smckusick grfconfig() 99*41480Smckusick { 100*41480Smckusick register caddr_t addr; 101*41480Smckusick register struct hp_hw *hw; 102*41480Smckusick register struct hp_device *hd, *nhd; 103*41480Smckusick 104*41480Smckusick for (hw = sc_table; hw->hw_type; hw++) { 105*41480Smckusick if (hw->hw_type != BITMAP) 106*41480Smckusick continue; 107*41480Smckusick /* 108*41480Smckusick * Found one, now match up with a logical unit number 109*41480Smckusick */ 110*41480Smckusick nhd = NULL; 111*41480Smckusick addr = hw->hw_addr; 112*41480Smckusick for (hd = hp_dinit; hd->hp_driver; hd++) { 113*41480Smckusick if (hd->hp_driver != &grfdriver || hd->hp_alive) 114*41480Smckusick continue; 115*41480Smckusick /* 116*41480Smckusick * Wildcarded. If first, remember as possible match. 117*41480Smckusick */ 118*41480Smckusick if (hd->hp_addr == NULL) { 119*41480Smckusick if (nhd == NULL) 120*41480Smckusick nhd = hd; 121*41480Smckusick continue; 122*41480Smckusick } 123*41480Smckusick /* 124*41480Smckusick * Not wildcarded. 125*41480Smckusick * If exact match done searching, else keep looking. 126*41480Smckusick */ 127*41480Smckusick if ((caddr_t)sctoaddr(hd->hp_addr) == addr) { 128*41480Smckusick nhd = hd; 129*41480Smckusick break; 130*41480Smckusick } 131*41480Smckusick } 132*41480Smckusick /* 133*41480Smckusick * Found a match, initialize 134*41480Smckusick */ 135*41480Smckusick if (nhd && grfinit(addr, nhd->hp_unit)) { 136*41480Smckusick nhd->hp_addr = addr; 137*41480Smckusick } 138*41480Smckusick } 139*41480Smckusick } 140*41480Smckusick 141*41480Smckusick /* 142*41480Smckusick * Normal init routine called by configure() code 143*41480Smckusick */ 144*41480Smckusick grfprobe(hd) 145*41480Smckusick struct hp_device *hd; 146*41480Smckusick { 147*41480Smckusick struct grf_softc *gp = &grf_softc[hd->hp_unit]; 148*41480Smckusick 149*41480Smckusick if ((gp->g_flags & GF_ALIVE) == 0 && 150*41480Smckusick !grfinit(hd->hp_addr, hd->hp_unit)) 151*41480Smckusick return(0); 152*41480Smckusick printf("grf%d: %d x %d ", hd->hp_unit, 153*41480Smckusick gp->g_display.gd_dwidth, gp->g_display.gd_dheight); 154*41480Smckusick if (gp->g_display.gd_colors == 2) 155*41480Smckusick printf("monochrome"); 156*41480Smckusick else 157*41480Smckusick printf("%d color", gp->g_display.gd_colors); 158*41480Smckusick printf(" %s display\n", grfdev[gp->g_type].gd_desc); 159*41480Smckusick return(1); 160*41480Smckusick } 161*41480Smckusick 162*41480Smckusick grfinit(addr, unit) 163*41480Smckusick caddr_t addr; 164*41480Smckusick { 165*41480Smckusick struct grf_softc *gp = &grf_softc[unit]; 166*41480Smckusick struct grfreg *gr; 167*41480Smckusick register struct grfdev *gd; 168*41480Smckusick 169*41480Smckusick gr = (struct grfreg *) addr; 170*41480Smckusick if (gr->gr_id != GRFHWID) 171*41480Smckusick return(0); 172*41480Smckusick for (gd = grfdev; gd < &grfdev[ngrfdev]; gd++) 173*41480Smckusick if (gd->gd_hardid == gr->gr_id2) 174*41480Smckusick break; 175*41480Smckusick if (gd < &grfdev[ngrfdev] && (*gd->gd_init)(gp, addr)) { 176*41480Smckusick gp->g_display.gd_id = gd->gd_softid; 177*41480Smckusick gp->g_type = gd - grfdev; 178*41480Smckusick gp->g_flags = GF_ALIVE; 179*41480Smckusick return(1); 180*41480Smckusick } 181*41480Smckusick return(0); 182*41480Smckusick } 183*41480Smckusick 184*41480Smckusick /*ARGSUSED*/ 185*41480Smckusick grfopen(dev, flags) 186*41480Smckusick dev_t dev; 187*41480Smckusick { 188*41480Smckusick int unit = GRFUNIT(dev); 189*41480Smckusick register struct grf_softc *gp = &grf_softc[unit]; 190*41480Smckusick int error = 0; 191*41480Smckusick 192*41480Smckusick if (unit >= NGRF || (gp->g_flags & GF_ALIVE) == 0) 193*41480Smckusick return(ENXIO); 194*41480Smckusick if ((gp->g_flags & (GF_OPEN|GF_EXCLUDE)) == (GF_OPEN|GF_EXCLUDE)) 195*41480Smckusick return(EBUSY); 196*41480Smckusick #ifdef HPUXCOMPAT 197*41480Smckusick /* 198*41480Smckusick * XXX: cannot handle both HPUX and BSD processes at the same time 199*41480Smckusick */ 200*41480Smckusick if (u.u_procp->p_flag & SHPUX) 201*41480Smckusick if (gp->g_flags & GF_BSDOPEN) 202*41480Smckusick return(EBUSY); 203*41480Smckusick else 204*41480Smckusick gp->g_flags |= GF_HPUXOPEN; 205*41480Smckusick else 206*41480Smckusick if (gp->g_flags & GF_HPUXOPEN) 207*41480Smckusick return(EBUSY); 208*41480Smckusick else 209*41480Smckusick gp->g_flags |= GF_BSDOPEN; 210*41480Smckusick #endif 211*41480Smckusick /* 212*41480Smckusick * First open. 213*41480Smckusick * XXX: always put in graphics mode. 214*41480Smckusick */ 215*41480Smckusick error = 0; 216*41480Smckusick if ((gp->g_flags & GF_OPEN) == 0) { 217*41480Smckusick gp->g_flags |= GF_OPEN; 218*41480Smckusick error = grfon(dev); 219*41480Smckusick } 220*41480Smckusick return(error); 221*41480Smckusick } 222*41480Smckusick 223*41480Smckusick /*ARGSUSED*/ 224*41480Smckusick grfclose(dev, flags) 225*41480Smckusick dev_t dev; 226*41480Smckusick { 227*41480Smckusick register struct grf_softc *gp = &grf_softc[GRFUNIT(dev)]; 228*41480Smckusick 229*41480Smckusick (void) grfoff(dev); 230*41480Smckusick (void) grfunlock(gp); 231*41480Smckusick gp->g_flags &= GF_ALIVE; 232*41480Smckusick return(0); 233*41480Smckusick } 234*41480Smckusick 235*41480Smckusick /*ARGSUSED*/ 236*41480Smckusick grfioctl(dev, cmd, data, flag) 237*41480Smckusick dev_t dev; 238*41480Smckusick caddr_t data; 239*41480Smckusick { 240*41480Smckusick register struct grf_softc *gp = &grf_softc[GRFUNIT(dev)]; 241*41480Smckusick int error; 242*41480Smckusick 243*41480Smckusick #ifdef HPUXCOMPAT 244*41480Smckusick if (u.u_procp->p_flag & SHPUX) 245*41480Smckusick return(hpuxgrfioctl(dev, cmd, data, flag)); 246*41480Smckusick #endif 247*41480Smckusick error = 0; 248*41480Smckusick switch (cmd) { 249*41480Smckusick 250*41480Smckusick /* XXX: compatibility hack */ 251*41480Smckusick case OGRFIOCGINFO: 252*41480Smckusick bcopy((caddr_t)&gp->g_display, data, sizeof(struct ogrfinfo)); 253*41480Smckusick break; 254*41480Smckusick 255*41480Smckusick case GRFIOCGINFO: 256*41480Smckusick bcopy((caddr_t)&gp->g_display, data, sizeof(struct grfinfo)); 257*41480Smckusick break; 258*41480Smckusick 259*41480Smckusick case GRFIOCON: 260*41480Smckusick error = grfon(dev); 261*41480Smckusick break; 262*41480Smckusick 263*41480Smckusick case GRFIOCOFF: 264*41480Smckusick error = grfoff(dev); 265*41480Smckusick break; 266*41480Smckusick 267*41480Smckusick #ifdef MAPMEM 268*41480Smckusick case GRFIOCMAP: 269*41480Smckusick error = grfmmap(dev, (caddr_t *)data); 270*41480Smckusick break; 271*41480Smckusick 272*41480Smckusick case GRFIOCUNMAP: 273*41480Smckusick error = grfunmmap(dev, *(caddr_t *)data); 274*41480Smckusick break; 275*41480Smckusick #endif 276*41480Smckusick 277*41480Smckusick default: 278*41480Smckusick error = EINVAL; 279*41480Smckusick break; 280*41480Smckusick 281*41480Smckusick } 282*41480Smckusick return(error); 283*41480Smckusick } 284*41480Smckusick 285*41480Smckusick /*ARGSUSED*/ 286*41480Smckusick grfselect(dev, rw) 287*41480Smckusick dev_t dev; 288*41480Smckusick { 289*41480Smckusick if (rw == FREAD) 290*41480Smckusick return(0); 291*41480Smckusick return(1); 292*41480Smckusick } 293*41480Smckusick 294*41480Smckusick grflock(gp, block) 295*41480Smckusick register struct grf_softc *gp; 296*41480Smckusick int block; 297*41480Smckusick { 298*41480Smckusick #ifdef DEBUG 299*41480Smckusick if (grfdebug & GDB_LOCK) 300*41480Smckusick printf("grflock(%d): dev %x flags %x lockpid %x\n", 301*41480Smckusick u.u_procp->p_pid, gp-grf_softc, gp->g_flags, 302*41480Smckusick gp->g_lockp ? gp->g_lockp->p_pid : -1); 303*41480Smckusick #endif 304*41480Smckusick #ifdef HPUXCOMPAT 305*41480Smckusick if (gp->g_pid) { 306*41480Smckusick #ifdef DEBUG 307*41480Smckusick if (grfdebug & GDB_LOCK) 308*41480Smckusick printf(" lock[0] %d lockslot %d lock[lockslot] %d\n", 309*41480Smckusick gp->g_locks[0], gp->g_lockpslot, 310*41480Smckusick gp->g_locks[gp->g_lockpslot]); 311*41480Smckusick #endif 312*41480Smckusick gp->g_locks[0] = 0; 313*41480Smckusick if (gp->g_locks[gp->g_lockpslot] == 0) { 314*41480Smckusick gp->g_lockp = NULL; 315*41480Smckusick gp->g_lockpslot = 0; 316*41480Smckusick } 317*41480Smckusick } 318*41480Smckusick #endif 319*41480Smckusick if (gp->g_lockp) { 320*41480Smckusick if (gp->g_lockp == u.u_procp) 321*41480Smckusick return(EBUSY); 322*41480Smckusick if (!block) 323*41480Smckusick return(EAGAIN); 324*41480Smckusick do { 325*41480Smckusick gp->g_flags |= GF_WANTED; 326*41480Smckusick sleep((caddr_t)&gp->g_flags, PZERO+1); 327*41480Smckusick } while (gp->g_lockp); 328*41480Smckusick } 329*41480Smckusick gp->g_lockp = u.u_procp; 330*41480Smckusick #ifdef HPUXCOMPAT 331*41480Smckusick if (gp->g_pid) { 332*41480Smckusick int slot = grffindpid(gp); 333*41480Smckusick #ifdef DEBUG 334*41480Smckusick if (grfdebug & GDB_LOCK) 335*41480Smckusick printf(" slot %d\n", slot); 336*41480Smckusick #endif 337*41480Smckusick gp->g_lockpslot = gp->g_locks[0] = slot; 338*41480Smckusick gp->g_locks[slot] = 1; 339*41480Smckusick } 340*41480Smckusick #endif 341*41480Smckusick return(0); 342*41480Smckusick } 343*41480Smckusick 344*41480Smckusick grfunlock(gp) 345*41480Smckusick register struct grf_softc *gp; 346*41480Smckusick { 347*41480Smckusick #ifdef DEBUG 348*41480Smckusick if (grfdebug & GDB_LOCK) 349*41480Smckusick printf("grfunlock(%d): dev %x flags %x lockpid %d\n", 350*41480Smckusick u.u_procp->p_pid, gp-grf_softc, gp->g_flags, 351*41480Smckusick gp->g_lockp ? gp->g_lockp->p_pid : -1); 352*41480Smckusick #endif 353*41480Smckusick if (gp->g_lockp != u.u_procp) 354*41480Smckusick return(EBUSY); 355*41480Smckusick #ifdef HPUXCOMPAT 356*41480Smckusick if (gp->g_pid) { 357*41480Smckusick #ifdef DEBUG 358*41480Smckusick if (grfdebug & GDB_LOCK) 359*41480Smckusick printf(" lock[0] %d lockslot %d lock[lockslot] %d\n", 360*41480Smckusick gp->g_locks[0], gp->g_lockpslot, 361*41480Smckusick gp->g_locks[gp->g_lockpslot]); 362*41480Smckusick #endif 363*41480Smckusick gp->g_locks[gp->g_lockpslot] = gp->g_locks[0] = 0; 364*41480Smckusick gp->g_lockpslot = 0; 365*41480Smckusick } 366*41480Smckusick #endif 367*41480Smckusick if (gp->g_flags & GF_WANTED) { 368*41480Smckusick wakeup((caddr_t)&gp->g_flags); 369*41480Smckusick gp->g_flags &= ~GF_WANTED; 370*41480Smckusick } 371*41480Smckusick gp->g_lockp = NULL; 372*41480Smckusick return(0); 373*41480Smckusick } 374*41480Smckusick 375*41480Smckusick /*ARGSUSED*/ 376*41480Smckusick grfmap(dev, off, prot) 377*41480Smckusick dev_t dev; 378*41480Smckusick { 379*41480Smckusick return(grfaddr(&grf_softc[GRFUNIT(dev)], off)); 380*41480Smckusick } 381*41480Smckusick 382*41480Smckusick #ifdef HPUXCOMPAT 383*41480Smckusick 384*41480Smckusick /*ARGSUSED*/ 385*41480Smckusick hpuxgrfioctl(dev, cmd, data, flag) 386*41480Smckusick dev_t dev; 387*41480Smckusick caddr_t data; 388*41480Smckusick { 389*41480Smckusick register struct grf_softc *gp = &grf_softc[GRFUNIT(dev)]; 390*41480Smckusick int error; 391*41480Smckusick 392*41480Smckusick error = 0; 393*41480Smckusick switch (cmd) { 394*41480Smckusick 395*41480Smckusick case GCID: 396*41480Smckusick *(int *)data = gp->g_display.gd_id; 397*41480Smckusick break; 398*41480Smckusick 399*41480Smckusick case GCON: 400*41480Smckusick error = grfon(dev); 401*41480Smckusick break; 402*41480Smckusick 403*41480Smckusick case GCOFF: 404*41480Smckusick error = grfoff(dev); 405*41480Smckusick break; 406*41480Smckusick 407*41480Smckusick case GCLOCK: 408*41480Smckusick error = grflock(gp, 1); 409*41480Smckusick break; 410*41480Smckusick 411*41480Smckusick case GCUNLOCK: 412*41480Smckusick error = grfunlock(gp); 413*41480Smckusick break; 414*41480Smckusick 415*41480Smckusick case GCAON: 416*41480Smckusick case GCAOFF: 417*41480Smckusick break; 418*41480Smckusick 419*41480Smckusick /* GCSTATIC is implied by our implementation */ 420*41480Smckusick case GCSTATIC_CMAP: 421*41480Smckusick case GCVARIABLE_CMAP: 422*41480Smckusick break; 423*41480Smckusick 424*41480Smckusick #ifdef MAPMEM 425*41480Smckusick /* map in control regs and frame buffer */ 426*41480Smckusick case GCMAP: 427*41480Smckusick error = grfmmap(dev, (caddr_t *)data); 428*41480Smckusick break; 429*41480Smckusick 430*41480Smckusick case GCUNMAP: 431*41480Smckusick error = grfunmmap(dev, *(caddr_t *)data); 432*41480Smckusick /* XXX: HP-UX uses GCUNMAP to get rid of GCSLOT memory */ 433*41480Smckusick if (error) 434*41480Smckusick error = grflckunmmap(dev, *(caddr_t *)data); 435*41480Smckusick break; 436*41480Smckusick 437*41480Smckusick case GCSLOT: 438*41480Smckusick { 439*41480Smckusick struct grf_slot *sp = (struct grf_slot *)data; 440*41480Smckusick 441*41480Smckusick sp->slot = grffindpid(gp); 442*41480Smckusick if (sp->slot) 443*41480Smckusick error = grflckmmap(dev, (caddr_t *)&sp->addr); 444*41480Smckusick else 445*41480Smckusick error = EINVAL; /* XXX */ 446*41480Smckusick break; 447*41480Smckusick } 448*41480Smckusick 449*41480Smckusick /* 450*41480Smckusick * XXX: only used right now to map in rbox control registers 451*41480Smckusick * Will be replaced in the future with a real IOMAP interface. 452*41480Smckusick */ 453*41480Smckusick case IOMAPMAP: 454*41480Smckusick error = iommap(dev, (caddr_t *)data); 455*41480Smckusick if (!error) 456*41480Smckusick u.u_r.r_val1 = *(int *)data; /* XXX: this sux */ 457*41480Smckusick break; 458*41480Smckusick 459*41480Smckusick case IOMAPUNMAP: 460*41480Smckusick error = iounmmap(dev, *(caddr_t *)data); 461*41480Smckusick break; 462*41480Smckusick #endif 463*41480Smckusick 464*41480Smckusick default: 465*41480Smckusick error = EINVAL; 466*41480Smckusick break; 467*41480Smckusick } 468*41480Smckusick return(error); 469*41480Smckusick } 470*41480Smckusick 471*41480Smckusick #endif 472*41480Smckusick 473*41480Smckusick grfon(dev) 474*41480Smckusick dev_t dev; 475*41480Smckusick { 476*41480Smckusick int unit = GRFUNIT(dev); 477*41480Smckusick struct grf_softc *gp = &grf_softc[unit]; 478*41480Smckusick 479*41480Smckusick /* 480*41480Smckusick * XXX: iteoff call relies on devices being in same order 481*41480Smckusick * as ITEs and the fact that iteoff only uses the minor part 482*41480Smckusick * of the dev arg. 483*41480Smckusick */ 484*41480Smckusick iteoff(unit, 3); 485*41480Smckusick return((*grfdev[gp->g_type].gd_mode) 486*41480Smckusick (gp, (dev&GRFOVDEV) ? GM_GRFOVON : GM_GRFON)); 487*41480Smckusick } 488*41480Smckusick 489*41480Smckusick grfoff(dev) 490*41480Smckusick dev_t dev; 491*41480Smckusick { 492*41480Smckusick int unit = GRFUNIT(dev); 493*41480Smckusick struct grf_softc *gp = &grf_softc[unit]; 494*41480Smckusick int error; 495*41480Smckusick 496*41480Smckusick #ifdef MAPMEM 497*41480Smckusick (void) grfunmmap(dev, (caddr_t)0); 498*41480Smckusick #endif 499*41480Smckusick error = (*grfdev[gp->g_type].gd_mode) 500*41480Smckusick (gp, (dev&GRFOVDEV) ? GM_GRFOVOFF : GM_GRFOFF); 501*41480Smckusick /* XXX: see comment for iteoff above */ 502*41480Smckusick iteon(unit, 2); 503*41480Smckusick return(error); 504*41480Smckusick } 505*41480Smckusick 506*41480Smckusick grfaddr(gp, off) 507*41480Smckusick struct grf_softc *gp; 508*41480Smckusick register int off; 509*41480Smckusick { 510*41480Smckusick #ifdef MAPMEM 511*41480Smckusick register struct grfinfo *gi = &gp->g_display; 512*41480Smckusick 513*41480Smckusick /* control registers */ 514*41480Smckusick if (off >= 0 && off < gi->gd_regsize) 515*41480Smckusick return(((u_int)gi->gd_regaddr + off) >> PGSHIFT); 516*41480Smckusick 517*41480Smckusick /* frame buffer */ 518*41480Smckusick if (off >= gi->gd_regsize && off < gi->gd_regsize+gi->gd_fbsize) { 519*41480Smckusick off -= gi->gd_regsize; 520*41480Smckusick return(((u_int)gi->gd_fbaddr + off) >> PGSHIFT); 521*41480Smckusick } 522*41480Smckusick #endif 523*41480Smckusick /* bogus */ 524*41480Smckusick return(-1); 525*41480Smckusick } 526*41480Smckusick 527*41480Smckusick #ifdef HPUXCOMPAT 528*41480Smckusick /* 529*41480Smckusick * Convert a BSD style minor devno to HPUX style. 530*41480Smckusick * We cannot just create HPUX style nodes as they require 24 bits 531*41480Smckusick * of minor device number and we only have 8. 532*41480Smckusick * XXX: This may give the wrong result for remote stats of other 533*41480Smckusick * machines where device 10 exists. 534*41480Smckusick */ 535*41480Smckusick grfdevno(dev) 536*41480Smckusick dev_t dev; 537*41480Smckusick { 538*41480Smckusick int unit = GRFUNIT(dev); 539*41480Smckusick struct grf_softc *gp = &grf_softc[unit]; 540*41480Smckusick int newdev; 541*41480Smckusick 542*41480Smckusick if (unit >= NGRF || (gp->g_flags&GF_ALIVE) == 0) 543*41480Smckusick return(bsdtohpuxdev(dev)); 544*41480Smckusick /* magic major number */ 545*41480Smckusick newdev = 12 << 24; 546*41480Smckusick /* now construct minor number */ 547*41480Smckusick #if defined(HP360) || defined(HP370) 548*41480Smckusick if (gp->g_display.gd_regaddr == (caddr_t)DIOIIBASE) 549*41480Smckusick newdev |= 0x840200; 550*41480Smckusick else 551*41480Smckusick #endif 552*41480Smckusick if (gp->g_display.gd_regaddr != (caddr_t)GRFIADDR) 553*41480Smckusick newdev |= ((u_int)gp->g_display.gd_regaddr-EXTIOBASE) | 0x200; 554*41480Smckusick if (dev & GRFIMDEV) 555*41480Smckusick newdev |= 0x02; 556*41480Smckusick else if (dev & GRFOVDEV) 557*41480Smckusick newdev |= 0x01; 558*41480Smckusick #ifdef DEBUG 559*41480Smckusick if (grfdebug & GDB_DEVNO) 560*41480Smckusick printf("grfdevno: dev %x newdev %x\n", dev, newdev); 561*41480Smckusick #endif 562*41480Smckusick return(newdev); 563*41480Smckusick } 564*41480Smckusick #endif 565*41480Smckusick 566*41480Smckusick #ifdef MAPMEM 567*41480Smckusick grfmapin(mp, off) 568*41480Smckusick struct mapmem *mp; 569*41480Smckusick { 570*41480Smckusick return(grfaddr(&grf_softc[GRFUNIT(mp->mm_id)], off)); 571*41480Smckusick } 572*41480Smckusick 573*41480Smckusick grfmmap(dev, addrp) 574*41480Smckusick dev_t dev; 575*41480Smckusick caddr_t *addrp; 576*41480Smckusick { 577*41480Smckusick struct grf_softc *gp = &grf_softc[GRFUNIT(dev)]; 578*41480Smckusick register struct mapmem *mp; 579*41480Smckusick int len, grfmapin(); 580*41480Smckusick 581*41480Smckusick #ifdef DEBUG 582*41480Smckusick if (grfdebug & GDB_MMAP) 583*41480Smckusick printf("grfmmap(%d): addr %x\n", u.u_procp->p_pid, *addrp); 584*41480Smckusick #endif 585*41480Smckusick len = gp->g_display.gd_regsize + gp->g_display.gd_fbsize; 586*41480Smckusick mp = mmalloc(minor(dev), addrp, len, MM_RW|MM_CI|MM_NOCORE, &grfops); 587*41480Smckusick if (mp == MMNIL) 588*41480Smckusick return(u.u_error); 589*41480Smckusick if (!mmmapin(mp, grfmapin)) { 590*41480Smckusick mmfree(mp); 591*41480Smckusick return(u.u_error); 592*41480Smckusick } 593*41480Smckusick return(0); 594*41480Smckusick } 595*41480Smckusick 596*41480Smckusick grfunmmap(dev, addr) 597*41480Smckusick dev_t dev; 598*41480Smckusick caddr_t addr; 599*41480Smckusick { 600*41480Smckusick register struct mapmem *mp, **mpp; 601*41480Smckusick int found, unit = minor(dev); 602*41480Smckusick 603*41480Smckusick #ifdef DEBUG 604*41480Smckusick if (grfdebug & GDB_MMAP) 605*41480Smckusick printf("grfunmmap(%d): id %d addr %x\n", 606*41480Smckusick u.u_procp->p_pid, unit, addr); 607*41480Smckusick #endif 608*41480Smckusick found = 0; 609*41480Smckusick mpp = &u.u_mmap; 610*41480Smckusick for (mp = *mpp; mp; mp = *mpp) { 611*41480Smckusick if (mp->mm_ops != &grfops || mp->mm_id != unit) { 612*41480Smckusick mpp = &mp->mm_next; 613*41480Smckusick continue; 614*41480Smckusick } 615*41480Smckusick if (addr && 616*41480Smckusick (addr < mp->mm_uva || addr >= mp->mm_uva+mp->mm_size)) { 617*41480Smckusick mpp = &mp->mm_next; 618*41480Smckusick continue; 619*41480Smckusick } 620*41480Smckusick grfexit(mp); 621*41480Smckusick found++; 622*41480Smckusick } 623*41480Smckusick return(found ? 0 : EINVAL); 624*41480Smckusick } 625*41480Smckusick 626*41480Smckusick grfexit(mp) 627*41480Smckusick struct mapmem *mp; 628*41480Smckusick { 629*41480Smckusick struct grf_softc *gp = &grf_softc[GRFUNIT(mp->mm_id)]; 630*41480Smckusick 631*41480Smckusick #ifdef DEBUG 632*41480Smckusick if (grfdebug & GDB_MMAP) 633*41480Smckusick printf("grfexit(%d): id %d %x@%x\n", 634*41480Smckusick u.u_procp->p_pid, mp->mm_id, mp->mm_size, mp->mm_uva); 635*41480Smckusick #endif 636*41480Smckusick (void) grfunlock(gp); 637*41480Smckusick #ifdef HPUXCOMPAT 638*41480Smckusick grfrmpid(gp); 639*41480Smckusick #endif 640*41480Smckusick mmmapout(mp); 641*41480Smckusick mmfree(mp); 642*41480Smckusick } 643*41480Smckusick 644*41480Smckusick #ifdef HPUXCOMPAT 645*41480Smckusick iommap(dev, addrp) 646*41480Smckusick dev_t dev; 647*41480Smckusick caddr_t *addrp; 648*41480Smckusick { 649*41480Smckusick struct grf_softc *gp = &grf_softc[GRFUNIT(dev)]; 650*41480Smckusick register struct mapmem *mp; 651*41480Smckusick int len, grfmapin(); 652*41480Smckusick 653*41480Smckusick #ifdef DEBUG 654*41480Smckusick if (grfdebug & (GDB_MMAP|GDB_IOMAP)) 655*41480Smckusick printf("iommap(%d): addr %x\n", u.u_procp->p_pid, *addrp); 656*41480Smckusick #endif 657*41480Smckusick len = gp->g_display.gd_regsize; 658*41480Smckusick mp = mmalloc(minor(dev), addrp, len, MM_RW|MM_CI|MM_NOCORE, &grfiomops); 659*41480Smckusick if (mp == MMNIL) 660*41480Smckusick return(u.u_error); 661*41480Smckusick if (!mmmapin(mp, grfmapin)) { 662*41480Smckusick mmfree(mp); 663*41480Smckusick return(u.u_error); 664*41480Smckusick } 665*41480Smckusick return(0); 666*41480Smckusick } 667*41480Smckusick 668*41480Smckusick iounmmap(dev, addr) 669*41480Smckusick dev_t dev; 670*41480Smckusick caddr_t addr; 671*41480Smckusick { 672*41480Smckusick struct grf_softc *gp = &grf_softc[GRFUNIT(dev)]; 673*41480Smckusick register struct mapmem *mp, **mpp; 674*41480Smckusick int found, len, unit = minor(dev); 675*41480Smckusick 676*41480Smckusick #ifdef DEBUG 677*41480Smckusick if (grfdebug & (GDB_MMAP|GDB_IOMAP)) 678*41480Smckusick printf("iounmmap(%d): id %d addr %x\n", 679*41480Smckusick u.u_procp->p_pid, unit, addr); 680*41480Smckusick #endif 681*41480Smckusick found = 0; 682*41480Smckusick len = gp->g_display.gd_regsize; 683*41480Smckusick mpp = &u.u_mmap; 684*41480Smckusick for (mp = *mpp; mp; mp = *mpp) { 685*41480Smckusick if (mp->mm_ops != &grfiomops || mp->mm_id != unit) { 686*41480Smckusick mpp = &mp->mm_next; 687*41480Smckusick continue; 688*41480Smckusick } 689*41480Smckusick if (addr && 690*41480Smckusick (addr < mp->mm_uva || addr >= mp->mm_uva+mp->mm_size || 691*41480Smckusick len != mp->mm_size)) { 692*41480Smckusick mpp = &mp->mm_next; 693*41480Smckusick continue; 694*41480Smckusick } 695*41480Smckusick grfexit(mp); 696*41480Smckusick found++; 697*41480Smckusick } 698*41480Smckusick return(found ? 0 : EINVAL); 699*41480Smckusick } 700*41480Smckusick 701*41480Smckusick /* 702*41480Smckusick * Processes involved in framebuffer mapping via GCSLOT are recorded in 703*41480Smckusick * an array of pids. The first element is used to record the last slot used 704*41480Smckusick * (for faster lookups). The remaining elements record up to GRFMAXLCK-1 705*41480Smckusick * process ids. Returns a slot number between 1 and GRFMAXLCK or 0 if no 706*41480Smckusick * slot is available. 707*41480Smckusick */ 708*41480Smckusick grffindpid(gp) 709*41480Smckusick struct grf_softc *gp; 710*41480Smckusick { 711*41480Smckusick register short pid, *sp; 712*41480Smckusick register int i, limit; 713*41480Smckusick int ni; 714*41480Smckusick 715*41480Smckusick if (gp->g_pid == NULL) { 716*41480Smckusick gp->g_pid = (short *) 717*41480Smckusick malloc(GRFMAXLCK * sizeof(short), M_DEVBUF, M_WAITOK); 718*41480Smckusick bzero((caddr_t)gp->g_pid, GRFMAXLCK * sizeof(short)); 719*41480Smckusick } 720*41480Smckusick pid = u.u_procp->p_pid; 721*41480Smckusick ni = limit = gp->g_pid[0]; 722*41480Smckusick for (i = 1, sp = &gp->g_pid[1]; i <= limit; i++, sp++) { 723*41480Smckusick if (*sp == pid) 724*41480Smckusick goto done; 725*41480Smckusick if (*sp == 0) 726*41480Smckusick ni = i; 727*41480Smckusick } 728*41480Smckusick i = ni; 729*41480Smckusick if (i < limit) { 730*41480Smckusick gp->g_pid[i] = pid; 731*41480Smckusick goto done; 732*41480Smckusick } 733*41480Smckusick if (++i == GRFMAXLCK) 734*41480Smckusick return(0); 735*41480Smckusick gp->g_pid[0] = i; 736*41480Smckusick gp->g_pid[i] = pid; 737*41480Smckusick done: 738*41480Smckusick #ifdef DEBUG 739*41480Smckusick if (grfdebug & GDB_LOCK) 740*41480Smckusick printf("grffindpid(%d): slot %d of %d\n", 741*41480Smckusick pid, i, gp->g_pid[0]); 742*41480Smckusick #endif 743*41480Smckusick return(i); 744*41480Smckusick } 745*41480Smckusick 746*41480Smckusick grfrmpid(gp) 747*41480Smckusick struct grf_softc *gp; 748*41480Smckusick { 749*41480Smckusick register short pid, *sp; 750*41480Smckusick register int limit, i; 751*41480Smckusick int mi; 752*41480Smckusick 753*41480Smckusick if (gp->g_pid == NULL || (limit = gp->g_pid[0]) == 0) 754*41480Smckusick return; 755*41480Smckusick pid = u.u_procp->p_pid; 756*41480Smckusick limit = gp->g_pid[0]; 757*41480Smckusick mi = 0; 758*41480Smckusick for (i = 1, sp = &gp->g_pid[1]; i <= limit; i++, sp++) { 759*41480Smckusick if (*sp == pid) 760*41480Smckusick *sp = 0; 761*41480Smckusick else if (*sp) 762*41480Smckusick mi = i; 763*41480Smckusick } 764*41480Smckusick i = mi; 765*41480Smckusick if (i < limit) 766*41480Smckusick gp->g_pid[0] = i; 767*41480Smckusick #ifdef DEBUG 768*41480Smckusick if (grfdebug & GDB_LOCK) 769*41480Smckusick printf("grfrmpid(%d): slot %d of %d\n", 770*41480Smckusick pid, sp-gp->g_pid, gp->g_pid[0]); 771*41480Smckusick #endif 772*41480Smckusick } 773*41480Smckusick 774*41480Smckusick /*ARGSUSED*/ 775*41480Smckusick grflckmapin(mp, off) 776*41480Smckusick struct mapmem *mp; 777*41480Smckusick { 778*41480Smckusick u_int pa = kvtop((u_int)grf_softc[GRFUNIT(mp->mm_id)].g_locks); 779*41480Smckusick 780*41480Smckusick #ifdef DEBUG 781*41480Smckusick if (grfdebug & GDB_LOCK) 782*41480Smckusick printf("grflckmapin(%d): va %x pa %x\n", u.u_procp->p_pid, 783*41480Smckusick grf_softc[GRFUNIT(mp->mm_id)].g_locks, pa); 784*41480Smckusick #endif 785*41480Smckusick return(pa >> PGSHIFT); 786*41480Smckusick } 787*41480Smckusick 788*41480Smckusick grflckmmap(dev, addrp) 789*41480Smckusick dev_t dev; 790*41480Smckusick caddr_t *addrp; 791*41480Smckusick { 792*41480Smckusick struct grf_softc *gp = &grf_softc[GRFUNIT(dev)]; 793*41480Smckusick register struct mapmem *mp; 794*41480Smckusick int grflckmapin(); 795*41480Smckusick 796*41480Smckusick #ifdef DEBUG 797*41480Smckusick if (grfdebug & (GDB_MMAP|GDB_LOCK)) 798*41480Smckusick printf("grflckmmap(%d): addr %x\n", 799*41480Smckusick u.u_procp->p_pid, *addrp); 800*41480Smckusick #endif 801*41480Smckusick if (gp->g_locks == NULL) { 802*41480Smckusick gp->g_locks = (u_char *) cialloc(NBPG); 803*41480Smckusick if (gp->g_locks == NULL) 804*41480Smckusick return(ENOMEM); 805*41480Smckusick } 806*41480Smckusick mp = mmalloc(minor(dev), addrp, NBPG, MM_RW|MM_CI, &grflckops); 807*41480Smckusick if (mp == MMNIL) 808*41480Smckusick return(u.u_error); 809*41480Smckusick if (!mmmapin(mp, grflckmapin)) { 810*41480Smckusick mmfree(mp); 811*41480Smckusick return(u.u_error); 812*41480Smckusick } 813*41480Smckusick return(0); 814*41480Smckusick } 815*41480Smckusick 816*41480Smckusick grflckunmmap(dev, addr) 817*41480Smckusick dev_t dev; 818*41480Smckusick caddr_t addr; 819*41480Smckusick { 820*41480Smckusick register struct mapmem *mp; 821*41480Smckusick int unit = minor(dev); 822*41480Smckusick 823*41480Smckusick #ifdef DEBUG 824*41480Smckusick if (grfdebug & (GDB_MMAP|GDB_LOCK)) 825*41480Smckusick printf("grflckunmmap(%d): id %d addr %x\n", 826*41480Smckusick u.u_procp->p_pid, unit, addr); 827*41480Smckusick #endif 828*41480Smckusick for (mp = u.u_mmap; mp; mp = mp->mm_next) 829*41480Smckusick if (mp->mm_ops == &grflckops && mp->mm_id == unit && 830*41480Smckusick mp->mm_uva == addr) { 831*41480Smckusick grfexit(mp); 832*41480Smckusick return(0); 833*41480Smckusick } 834*41480Smckusick return(EINVAL); 835*41480Smckusick } 836*41480Smckusick #endif /* HPUXCOMPAT */ 837*41480Smckusick #endif /* MAPMEM */ 838*41480Smckusick #endif /* NGRF > 0 */ 839