141480Smckusick /* 241480Smckusick * Copyright (c) 1988 University of Utah. 341480Smckusick * Copyright (c) 1990 The Regents of the University of California. 441480Smckusick * All rights reserved. 541480Smckusick * 641480Smckusick * This code is derived from software contributed to Berkeley by 741480Smckusick * the Systems Programming Group of the University of Utah Computer 841480Smckusick * Science Department. 941480Smckusick * 1041480Smckusick * %sccs.include.redist.c% 1141480Smckusick * 1241480Smckusick * from: Utah $Hdr: grf.c 1.28 89/08/14$ 1341480Smckusick * 14*43410Shibler * @(#)grf.c 7.4 (Berkeley) 06/22/90 1541480Smckusick */ 1641480Smckusick 1741480Smckusick /* 1841480Smckusick * Graphics display driver for the HP300. 1941480Smckusick * This is the hardware-independent portion of the driver. 2041480Smckusick * Hardware access is through the grfdev routines below. 2141480Smckusick */ 2241480Smckusick 2341480Smckusick #include "grf.h" 2441480Smckusick #if NGRF > 0 2541480Smckusick 2641480Smckusick #include "param.h" 2741480Smckusick #include "user.h" 2841480Smckusick #include "proc.h" 2941480Smckusick #include "ioctl.h" 3041480Smckusick #include "file.h" 3141480Smckusick #include "mapmem.h" 3241480Smckusick #include "malloc.h" 3341480Smckusick 3441480Smckusick #include "device.h" 3541480Smckusick #include "grfioctl.h" 3641480Smckusick #include "grfvar.h" 3741480Smckusick 3841480Smckusick #include "machine/cpu.h" 3941480Smckusick 4041480Smckusick #ifdef HPUXCOMPAT 4141480Smckusick #include "../hpux/hpux.h" 4241480Smckusick #endif 4341480Smckusick 4441480Smckusick #include "ite.h" 4541480Smckusick #if NITE == 0 4641480Smckusick #define iteon(u,f) 4741480Smckusick #define iteoff(u,f) 4841480Smckusick #endif 4941480Smckusick 5041480Smckusick int grfprobe(); 5141480Smckusick int tc_init(), tc_mode(); 5241480Smckusick int gb_init(), gb_mode(); 5341480Smckusick int rb_init(), rb_mode(); 5441480Smckusick int dv_init(), dv_mode(); 5541480Smckusick 5641480Smckusick struct grfdev grfdev[] = { 5741480Smckusick GID_TOPCAT, GRFBOBCAT, tc_init, tc_mode, 5841480Smckusick "topcat", 5941480Smckusick GID_GATORBOX, GRFGATOR, gb_init, gb_mode, 6041480Smckusick "gatorbox", 6141480Smckusick GID_RENAISSANCE,GRFRBOX, rb_init, rb_mode, 6241480Smckusick "renaissance", 6341480Smckusick GID_LRCATSEYE, GRFCATSEYE, tc_init, tc_mode, 6441480Smckusick "lo-res catseye", 6541480Smckusick GID_HRCCATSEYE, GRFCATSEYE, tc_init, tc_mode, 6641480Smckusick "hi-res catseye", 6741480Smckusick GID_HRMCATSEYE, GRFCATSEYE, tc_init, tc_mode, 6841480Smckusick "hi-res catseye", 6941480Smckusick GID_DAVINCI, GRFDAVINCI, dv_init, dv_mode, 7041480Smckusick "davinci", 7141480Smckusick }; 7241480Smckusick int ngrfdev = sizeof(grfdev) / sizeof(grfdev[0]); 7341480Smckusick 7441480Smckusick struct driver grfdriver = { grfprobe, "grf" }; 7541480Smckusick struct grf_softc grf_softc[NGRF]; 7641480Smckusick 7741480Smckusick #ifdef MAPMEM 7841480Smckusick int grfexit(); 7941480Smckusick struct mapmemops grfops = { (int (*)())0, (int (*)())0, grfexit, grfexit }; 8041480Smckusick #ifdef HPUXCOMPAT 8141480Smckusick struct mapmemops grflckops = { (int (*)())0, (int (*)())0, grfexit, grfexit }; 8241480Smckusick struct mapmemops grfiomops = { (int (*)())0, (int (*)())0, grfexit, grfexit }; 8341480Smckusick #endif 8441480Smckusick #endif 8541480Smckusick 8641480Smckusick #ifdef DEBUG 8741480Smckusick int grfdebug = 0; 8841480Smckusick #define GDB_DEVNO 0x01 8941480Smckusick #define GDB_MMAP 0x02 9041480Smckusick #define GDB_IOMAP 0x04 9141480Smckusick #define GDB_LOCK 0x08 9241480Smckusick #endif 9341480Smckusick 9441480Smckusick /* 9541480Smckusick * XXX: called from ite console init routine. 9641480Smckusick * Does just what configure will do later but without printing anything. 9741480Smckusick */ 9841480Smckusick grfconfig() 9941480Smckusick { 10041480Smckusick register caddr_t addr; 10141480Smckusick register struct hp_hw *hw; 10241480Smckusick register struct hp_device *hd, *nhd; 10341480Smckusick 10441480Smckusick for (hw = sc_table; hw->hw_type; hw++) { 10541480Smckusick if (hw->hw_type != BITMAP) 10641480Smckusick continue; 10741480Smckusick /* 10841480Smckusick * Found one, now match up with a logical unit number 10941480Smckusick */ 11041480Smckusick nhd = NULL; 11141480Smckusick addr = hw->hw_addr; 11241480Smckusick for (hd = hp_dinit; hd->hp_driver; hd++) { 11341480Smckusick if (hd->hp_driver != &grfdriver || hd->hp_alive) 11441480Smckusick continue; 11541480Smckusick /* 11641480Smckusick * Wildcarded. If first, remember as possible match. 11741480Smckusick */ 11841480Smckusick if (hd->hp_addr == NULL) { 11941480Smckusick if (nhd == NULL) 12041480Smckusick nhd = hd; 12141480Smckusick continue; 12241480Smckusick } 12341480Smckusick /* 12441480Smckusick * Not wildcarded. 12541480Smckusick * If exact match done searching, else keep looking. 12641480Smckusick */ 12741480Smckusick if ((caddr_t)sctoaddr(hd->hp_addr) == addr) { 12841480Smckusick nhd = hd; 12941480Smckusick break; 13041480Smckusick } 13141480Smckusick } 13241480Smckusick /* 13341480Smckusick * Found a match, initialize 13441480Smckusick */ 13541480Smckusick if (nhd && grfinit(addr, nhd->hp_unit)) { 13641480Smckusick nhd->hp_addr = addr; 13741480Smckusick } 13841480Smckusick } 13941480Smckusick } 14041480Smckusick 14141480Smckusick /* 14241480Smckusick * Normal init routine called by configure() code 14341480Smckusick */ 14441480Smckusick grfprobe(hd) 14541480Smckusick struct hp_device *hd; 14641480Smckusick { 14741480Smckusick struct grf_softc *gp = &grf_softc[hd->hp_unit]; 14841480Smckusick 14941480Smckusick if ((gp->g_flags & GF_ALIVE) == 0 && 15041480Smckusick !grfinit(hd->hp_addr, hd->hp_unit)) 15141480Smckusick return(0); 15241480Smckusick printf("grf%d: %d x %d ", hd->hp_unit, 15341480Smckusick gp->g_display.gd_dwidth, gp->g_display.gd_dheight); 15441480Smckusick if (gp->g_display.gd_colors == 2) 15541480Smckusick printf("monochrome"); 15641480Smckusick else 15741480Smckusick printf("%d color", gp->g_display.gd_colors); 15841480Smckusick printf(" %s display\n", grfdev[gp->g_type].gd_desc); 15941480Smckusick return(1); 16041480Smckusick } 16141480Smckusick 16241480Smckusick grfinit(addr, unit) 16341480Smckusick caddr_t addr; 16441480Smckusick { 16541480Smckusick struct grf_softc *gp = &grf_softc[unit]; 16641480Smckusick struct grfreg *gr; 16741480Smckusick register struct grfdev *gd; 16841480Smckusick 16941480Smckusick gr = (struct grfreg *) addr; 17041480Smckusick if (gr->gr_id != GRFHWID) 17141480Smckusick return(0); 17241480Smckusick for (gd = grfdev; gd < &grfdev[ngrfdev]; gd++) 17341480Smckusick if (gd->gd_hardid == gr->gr_id2) 17441480Smckusick break; 17541480Smckusick if (gd < &grfdev[ngrfdev] && (*gd->gd_init)(gp, addr)) { 17641480Smckusick gp->g_display.gd_id = gd->gd_softid; 17741480Smckusick gp->g_type = gd - grfdev; 17841480Smckusick gp->g_flags = GF_ALIVE; 17941480Smckusick return(1); 18041480Smckusick } 18141480Smckusick return(0); 18241480Smckusick } 18341480Smckusick 18441480Smckusick /*ARGSUSED*/ 18541480Smckusick grfopen(dev, flags) 18641480Smckusick dev_t dev; 18741480Smckusick { 18841480Smckusick int unit = GRFUNIT(dev); 18941480Smckusick register struct grf_softc *gp = &grf_softc[unit]; 19041480Smckusick int error = 0; 19141480Smckusick 19241480Smckusick if (unit >= NGRF || (gp->g_flags & GF_ALIVE) == 0) 19341480Smckusick return(ENXIO); 19441480Smckusick if ((gp->g_flags & (GF_OPEN|GF_EXCLUDE)) == (GF_OPEN|GF_EXCLUDE)) 19541480Smckusick return(EBUSY); 19641480Smckusick #ifdef HPUXCOMPAT 19741480Smckusick /* 19841480Smckusick * XXX: cannot handle both HPUX and BSD processes at the same time 19941480Smckusick */ 20041480Smckusick if (u.u_procp->p_flag & SHPUX) 20141480Smckusick if (gp->g_flags & GF_BSDOPEN) 20241480Smckusick return(EBUSY); 20341480Smckusick else 20441480Smckusick gp->g_flags |= GF_HPUXOPEN; 20541480Smckusick else 20641480Smckusick if (gp->g_flags & GF_HPUXOPEN) 20741480Smckusick return(EBUSY); 20841480Smckusick else 20941480Smckusick gp->g_flags |= GF_BSDOPEN; 21041480Smckusick #endif 21141480Smckusick /* 21241480Smckusick * First open. 21341480Smckusick * XXX: always put in graphics mode. 21441480Smckusick */ 21541480Smckusick error = 0; 21641480Smckusick if ((gp->g_flags & GF_OPEN) == 0) { 21741480Smckusick gp->g_flags |= GF_OPEN; 21841480Smckusick error = grfon(dev); 21941480Smckusick } 22041480Smckusick return(error); 22141480Smckusick } 22241480Smckusick 22341480Smckusick /*ARGSUSED*/ 22441480Smckusick grfclose(dev, flags) 22541480Smckusick dev_t dev; 22641480Smckusick { 22741480Smckusick register struct grf_softc *gp = &grf_softc[GRFUNIT(dev)]; 22841480Smckusick 22941480Smckusick (void) grfoff(dev); 23041480Smckusick (void) grfunlock(gp); 23141480Smckusick gp->g_flags &= GF_ALIVE; 23241480Smckusick return(0); 23341480Smckusick } 23441480Smckusick 23541480Smckusick /*ARGSUSED*/ 23641480Smckusick grfioctl(dev, cmd, data, flag) 23741480Smckusick dev_t dev; 23841480Smckusick caddr_t data; 23941480Smckusick { 24041480Smckusick register struct grf_softc *gp = &grf_softc[GRFUNIT(dev)]; 24141480Smckusick int error; 24241480Smckusick 24341480Smckusick #ifdef HPUXCOMPAT 24441480Smckusick if (u.u_procp->p_flag & SHPUX) 24541480Smckusick return(hpuxgrfioctl(dev, cmd, data, flag)); 24641480Smckusick #endif 24741480Smckusick error = 0; 24841480Smckusick switch (cmd) { 24941480Smckusick 25041480Smckusick /* XXX: compatibility hack */ 25141480Smckusick case OGRFIOCGINFO: 25241480Smckusick bcopy((caddr_t)&gp->g_display, data, sizeof(struct ogrfinfo)); 25341480Smckusick break; 25441480Smckusick 25541480Smckusick case GRFIOCGINFO: 25641480Smckusick bcopy((caddr_t)&gp->g_display, data, sizeof(struct grfinfo)); 25741480Smckusick break; 25841480Smckusick 25941480Smckusick case GRFIOCON: 26041480Smckusick error = grfon(dev); 26141480Smckusick break; 26241480Smckusick 26341480Smckusick case GRFIOCOFF: 26441480Smckusick error = grfoff(dev); 26541480Smckusick break; 26641480Smckusick 26741480Smckusick #ifdef MAPMEM 26841480Smckusick case GRFIOCMAP: 26941480Smckusick error = grfmmap(dev, (caddr_t *)data); 27041480Smckusick break; 27141480Smckusick 27241480Smckusick case GRFIOCUNMAP: 27341480Smckusick error = grfunmmap(dev, *(caddr_t *)data); 27441480Smckusick break; 27541480Smckusick #endif 27641480Smckusick 27741480Smckusick default: 27841480Smckusick error = EINVAL; 27941480Smckusick break; 28041480Smckusick 28141480Smckusick } 28241480Smckusick return(error); 28341480Smckusick } 28441480Smckusick 28541480Smckusick /*ARGSUSED*/ 28641480Smckusick grfselect(dev, rw) 28741480Smckusick dev_t dev; 28841480Smckusick { 28941480Smckusick if (rw == FREAD) 29041480Smckusick return(0); 29141480Smckusick return(1); 29241480Smckusick } 29341480Smckusick 29441480Smckusick grflock(gp, block) 29541480Smckusick register struct grf_softc *gp; 29641480Smckusick int block; 29741480Smckusick { 29843316Smckusick struct proc *p = u.u_procp; /* XXX */ 29942358Smckusick int error; 30042358Smckusick extern char devioc[]; 30142358Smckusick 30241480Smckusick #ifdef DEBUG 30341480Smckusick if (grfdebug & GDB_LOCK) 30441480Smckusick printf("grflock(%d): dev %x flags %x lockpid %x\n", 30543316Smckusick p->p_pid, gp-grf_softc, gp->g_flags, 30641480Smckusick gp->g_lockp ? gp->g_lockp->p_pid : -1); 30741480Smckusick #endif 30841480Smckusick #ifdef HPUXCOMPAT 30941480Smckusick if (gp->g_pid) { 31041480Smckusick #ifdef DEBUG 31141480Smckusick if (grfdebug & GDB_LOCK) 31241480Smckusick printf(" lock[0] %d lockslot %d lock[lockslot] %d\n", 31341480Smckusick gp->g_locks[0], gp->g_lockpslot, 31441480Smckusick gp->g_locks[gp->g_lockpslot]); 31541480Smckusick #endif 31641480Smckusick gp->g_locks[0] = 0; 31741480Smckusick if (gp->g_locks[gp->g_lockpslot] == 0) { 31841480Smckusick gp->g_lockp = NULL; 31941480Smckusick gp->g_lockpslot = 0; 32041480Smckusick } 32141480Smckusick } 32241480Smckusick #endif 32341480Smckusick if (gp->g_lockp) { 32443316Smckusick if (gp->g_lockp == p) 32541480Smckusick return(EBUSY); 32641480Smckusick if (!block) 32741480Smckusick return(EAGAIN); 32841480Smckusick do { 32941480Smckusick gp->g_flags |= GF_WANTED; 33042358Smckusick if (error = tsleep((caddr_t)&gp->g_flags, 33142358Smckusick (PZERO+1) | PCATCH, devioc, 0)) 33242358Smckusick return (error); 33341480Smckusick } while (gp->g_lockp); 33441480Smckusick } 33543316Smckusick gp->g_lockp = p; 33641480Smckusick #ifdef HPUXCOMPAT 33741480Smckusick if (gp->g_pid) { 33841480Smckusick int slot = grffindpid(gp); 33941480Smckusick #ifdef DEBUG 34041480Smckusick if (grfdebug & GDB_LOCK) 34141480Smckusick printf(" slot %d\n", slot); 34241480Smckusick #endif 34341480Smckusick gp->g_lockpslot = gp->g_locks[0] = slot; 34441480Smckusick gp->g_locks[slot] = 1; 34541480Smckusick } 34641480Smckusick #endif 34741480Smckusick return(0); 34841480Smckusick } 34941480Smckusick 35041480Smckusick grfunlock(gp) 35141480Smckusick register struct grf_softc *gp; 35241480Smckusick { 35341480Smckusick #ifdef DEBUG 35441480Smckusick if (grfdebug & GDB_LOCK) 35541480Smckusick printf("grfunlock(%d): dev %x flags %x lockpid %d\n", 35641480Smckusick u.u_procp->p_pid, gp-grf_softc, gp->g_flags, 35741480Smckusick gp->g_lockp ? gp->g_lockp->p_pid : -1); 35841480Smckusick #endif 35941480Smckusick if (gp->g_lockp != u.u_procp) 36041480Smckusick return(EBUSY); 36141480Smckusick #ifdef HPUXCOMPAT 36241480Smckusick if (gp->g_pid) { 36341480Smckusick #ifdef DEBUG 36441480Smckusick if (grfdebug & GDB_LOCK) 36541480Smckusick printf(" lock[0] %d lockslot %d lock[lockslot] %d\n", 36641480Smckusick gp->g_locks[0], gp->g_lockpslot, 36741480Smckusick gp->g_locks[gp->g_lockpslot]); 36841480Smckusick #endif 36941480Smckusick gp->g_locks[gp->g_lockpslot] = gp->g_locks[0] = 0; 37041480Smckusick gp->g_lockpslot = 0; 37141480Smckusick } 37241480Smckusick #endif 37341480Smckusick if (gp->g_flags & GF_WANTED) { 37441480Smckusick wakeup((caddr_t)&gp->g_flags); 37541480Smckusick gp->g_flags &= ~GF_WANTED; 37641480Smckusick } 37741480Smckusick gp->g_lockp = NULL; 37841480Smckusick return(0); 37941480Smckusick } 38041480Smckusick 38141480Smckusick /*ARGSUSED*/ 38241480Smckusick grfmap(dev, off, prot) 38341480Smckusick dev_t dev; 38441480Smckusick { 38541480Smckusick return(grfaddr(&grf_softc[GRFUNIT(dev)], off)); 38641480Smckusick } 38741480Smckusick 38841480Smckusick #ifdef HPUXCOMPAT 38941480Smckusick 39041480Smckusick /*ARGSUSED*/ 39141480Smckusick hpuxgrfioctl(dev, cmd, data, flag) 39241480Smckusick dev_t dev; 39341480Smckusick caddr_t data; 39441480Smckusick { 39541480Smckusick register struct grf_softc *gp = &grf_softc[GRFUNIT(dev)]; 39641480Smckusick int error; 39741480Smckusick 39841480Smckusick error = 0; 39941480Smckusick switch (cmd) { 40041480Smckusick 40141480Smckusick case GCID: 40241480Smckusick *(int *)data = gp->g_display.gd_id; 40341480Smckusick break; 40441480Smckusick 40541480Smckusick case GCON: 40641480Smckusick error = grfon(dev); 40741480Smckusick break; 40841480Smckusick 40941480Smckusick case GCOFF: 41041480Smckusick error = grfoff(dev); 41141480Smckusick break; 41241480Smckusick 41341480Smckusick case GCLOCK: 41441480Smckusick error = grflock(gp, 1); 41541480Smckusick break; 41641480Smckusick 41741480Smckusick case GCUNLOCK: 41841480Smckusick error = grfunlock(gp); 41941480Smckusick break; 42041480Smckusick 42141480Smckusick case GCAON: 42241480Smckusick case GCAOFF: 42341480Smckusick break; 42441480Smckusick 42541480Smckusick /* GCSTATIC is implied by our implementation */ 42641480Smckusick case GCSTATIC_CMAP: 42741480Smckusick case GCVARIABLE_CMAP: 42841480Smckusick break; 42941480Smckusick 43041480Smckusick #ifdef MAPMEM 43141480Smckusick /* map in control regs and frame buffer */ 43241480Smckusick case GCMAP: 43341480Smckusick error = grfmmap(dev, (caddr_t *)data); 43441480Smckusick break; 43541480Smckusick 43641480Smckusick case GCUNMAP: 43741480Smckusick error = grfunmmap(dev, *(caddr_t *)data); 43841480Smckusick /* XXX: HP-UX uses GCUNMAP to get rid of GCSLOT memory */ 43941480Smckusick if (error) 44041480Smckusick error = grflckunmmap(dev, *(caddr_t *)data); 44141480Smckusick break; 44241480Smckusick 44341480Smckusick case GCSLOT: 44441480Smckusick { 44541480Smckusick struct grf_slot *sp = (struct grf_slot *)data; 44641480Smckusick 44741480Smckusick sp->slot = grffindpid(gp); 44841480Smckusick if (sp->slot) 44941480Smckusick error = grflckmmap(dev, (caddr_t *)&sp->addr); 45041480Smckusick else 45141480Smckusick error = EINVAL; /* XXX */ 45241480Smckusick break; 45341480Smckusick } 45441480Smckusick 45541480Smckusick /* 45641480Smckusick * XXX: only used right now to map in rbox control registers 45741480Smckusick * Will be replaced in the future with a real IOMAP interface. 45841480Smckusick */ 45941480Smckusick case IOMAPMAP: 46041480Smckusick error = iommap(dev, (caddr_t *)data); 461*43410Shibler #if 0 462*43410Shibler /* 463*43410Shibler * It may not be worth kludging this (using p_devtmp) to 464*43410Shibler * make this work. It was an undocumented side-effect 465*43410Shibler * in HP-UX that the mapped address was the return value 466*43410Shibler * of the ioctl. The only thing I remember that counted 467*43410Shibler * on this behavior was the rbox X10 server. 468*43410Shibler */ 46941480Smckusick if (!error) 47041480Smckusick u.u_r.r_val1 = *(int *)data; /* XXX: this sux */ 471*43410Shibler #endif 47241480Smckusick break; 47341480Smckusick 47441480Smckusick case IOMAPUNMAP: 47541480Smckusick error = iounmmap(dev, *(caddr_t *)data); 47641480Smckusick break; 47741480Smckusick #endif 47841480Smckusick 47941480Smckusick default: 48041480Smckusick error = EINVAL; 48141480Smckusick break; 48241480Smckusick } 48341480Smckusick return(error); 48441480Smckusick } 48541480Smckusick 48641480Smckusick #endif 48741480Smckusick 48841480Smckusick grfon(dev) 48941480Smckusick dev_t dev; 49041480Smckusick { 49141480Smckusick int unit = GRFUNIT(dev); 49241480Smckusick struct grf_softc *gp = &grf_softc[unit]; 49341480Smckusick 49441480Smckusick /* 49541480Smckusick * XXX: iteoff call relies on devices being in same order 49641480Smckusick * as ITEs and the fact that iteoff only uses the minor part 49741480Smckusick * of the dev arg. 49841480Smckusick */ 49941480Smckusick iteoff(unit, 3); 50041480Smckusick return((*grfdev[gp->g_type].gd_mode) 50141480Smckusick (gp, (dev&GRFOVDEV) ? GM_GRFOVON : GM_GRFON)); 50241480Smckusick } 50341480Smckusick 50441480Smckusick grfoff(dev) 50541480Smckusick dev_t dev; 50641480Smckusick { 50741480Smckusick int unit = GRFUNIT(dev); 50841480Smckusick struct grf_softc *gp = &grf_softc[unit]; 50941480Smckusick int error; 51041480Smckusick 51141480Smckusick #ifdef MAPMEM 51241480Smckusick (void) grfunmmap(dev, (caddr_t)0); 51341480Smckusick #endif 51441480Smckusick error = (*grfdev[gp->g_type].gd_mode) 51541480Smckusick (gp, (dev&GRFOVDEV) ? GM_GRFOVOFF : GM_GRFOFF); 51641480Smckusick /* XXX: see comment for iteoff above */ 51741480Smckusick iteon(unit, 2); 51841480Smckusick return(error); 51941480Smckusick } 52041480Smckusick 52141480Smckusick grfaddr(gp, off) 52241480Smckusick struct grf_softc *gp; 52341480Smckusick register int off; 52441480Smckusick { 52541480Smckusick #ifdef MAPMEM 52641480Smckusick register struct grfinfo *gi = &gp->g_display; 52741480Smckusick 52841480Smckusick /* control registers */ 52941480Smckusick if (off >= 0 && off < gi->gd_regsize) 53041480Smckusick return(((u_int)gi->gd_regaddr + off) >> PGSHIFT); 53141480Smckusick 53241480Smckusick /* frame buffer */ 53341480Smckusick if (off >= gi->gd_regsize && off < gi->gd_regsize+gi->gd_fbsize) { 53441480Smckusick off -= gi->gd_regsize; 53541480Smckusick return(((u_int)gi->gd_fbaddr + off) >> PGSHIFT); 53641480Smckusick } 53741480Smckusick #endif 53841480Smckusick /* bogus */ 53941480Smckusick return(-1); 54041480Smckusick } 54141480Smckusick 54241480Smckusick #ifdef HPUXCOMPAT 54341480Smckusick /* 54441480Smckusick * Convert a BSD style minor devno to HPUX style. 54541480Smckusick * We cannot just create HPUX style nodes as they require 24 bits 54641480Smckusick * of minor device number and we only have 8. 54741480Smckusick * XXX: This may give the wrong result for remote stats of other 54841480Smckusick * machines where device 10 exists. 54941480Smckusick */ 55041480Smckusick grfdevno(dev) 55141480Smckusick dev_t dev; 55241480Smckusick { 55341480Smckusick int unit = GRFUNIT(dev); 55441480Smckusick struct grf_softc *gp = &grf_softc[unit]; 55541480Smckusick int newdev; 55641480Smckusick 55741480Smckusick if (unit >= NGRF || (gp->g_flags&GF_ALIVE) == 0) 55841480Smckusick return(bsdtohpuxdev(dev)); 55941480Smckusick /* magic major number */ 56041480Smckusick newdev = 12 << 24; 56141480Smckusick /* now construct minor number */ 56241480Smckusick #if defined(HP360) || defined(HP370) 56341480Smckusick if (gp->g_display.gd_regaddr == (caddr_t)DIOIIBASE) 56441480Smckusick newdev |= 0x840200; 56541480Smckusick else 56641480Smckusick #endif 56741480Smckusick if (gp->g_display.gd_regaddr != (caddr_t)GRFIADDR) 56841480Smckusick newdev |= ((u_int)gp->g_display.gd_regaddr-EXTIOBASE) | 0x200; 56941480Smckusick if (dev & GRFIMDEV) 57041480Smckusick newdev |= 0x02; 57141480Smckusick else if (dev & GRFOVDEV) 57241480Smckusick newdev |= 0x01; 57341480Smckusick #ifdef DEBUG 57441480Smckusick if (grfdebug & GDB_DEVNO) 57541480Smckusick printf("grfdevno: dev %x newdev %x\n", dev, newdev); 57641480Smckusick #endif 57741480Smckusick return(newdev); 57841480Smckusick } 57941480Smckusick #endif 58041480Smckusick 58141480Smckusick #ifdef MAPMEM 58241480Smckusick grfmapin(mp, off) 58341480Smckusick struct mapmem *mp; 58441480Smckusick { 58541480Smckusick return(grfaddr(&grf_softc[GRFUNIT(mp->mm_id)], off)); 58641480Smckusick } 58741480Smckusick 58841480Smckusick grfmmap(dev, addrp) 58941480Smckusick dev_t dev; 59041480Smckusick caddr_t *addrp; 59141480Smckusick { 59243316Smckusick struct proc *p = u.u_procp; /* XXX */ 59341480Smckusick struct grf_softc *gp = &grf_softc[GRFUNIT(dev)]; 59443316Smckusick struct mapmem *mp; 595*43410Shibler int len, error, grfmapin(); 59641480Smckusick 59741480Smckusick #ifdef DEBUG 59841480Smckusick if (grfdebug & GDB_MMAP) 59943316Smckusick printf("grfmmap(%d): addr %x\n", p->p_pid, *addrp); 60041480Smckusick #endif 60141480Smckusick len = gp->g_display.gd_regsize + gp->g_display.gd_fbsize; 602*43410Shibler error = mmalloc(p, minor(dev), addrp, len, MM_RW|MM_CI|MM_NOCORE, 603*43410Shibler &grfops, &mp); 604*43410Shibler if (error == 0) 605*43410Shibler if (error = mmmapin(p, mp, grfmapin)) 606*43410Shibler (void) mmfree(p, mp); 607*43410Shibler return(error); 60841480Smckusick } 60941480Smckusick 61041480Smckusick grfunmmap(dev, addr) 61141480Smckusick dev_t dev; 61241480Smckusick caddr_t addr; 61341480Smckusick { 61441480Smckusick register struct mapmem *mp, **mpp; 61541480Smckusick int found, unit = minor(dev); 61641480Smckusick 61741480Smckusick #ifdef DEBUG 61841480Smckusick if (grfdebug & GDB_MMAP) 61941480Smckusick printf("grfunmmap(%d): id %d addr %x\n", 62041480Smckusick u.u_procp->p_pid, unit, addr); 62141480Smckusick #endif 62241480Smckusick found = 0; 62341480Smckusick mpp = &u.u_mmap; 62441480Smckusick for (mp = *mpp; mp; mp = *mpp) { 62541480Smckusick if (mp->mm_ops != &grfops || mp->mm_id != unit) { 62641480Smckusick mpp = &mp->mm_next; 62741480Smckusick continue; 62841480Smckusick } 62941480Smckusick if (addr && 63041480Smckusick (addr < mp->mm_uva || addr >= mp->mm_uva+mp->mm_size)) { 63141480Smckusick mpp = &mp->mm_next; 63241480Smckusick continue; 63341480Smckusick } 634*43410Shibler (void) grfexit(mp); 63541480Smckusick found++; 63641480Smckusick } 63741480Smckusick return(found ? 0 : EINVAL); 63841480Smckusick } 63941480Smckusick 64041480Smckusick grfexit(mp) 64141480Smckusick struct mapmem *mp; 64241480Smckusick { 64343316Smckusick struct proc *p = u.u_procp; /* XXX */ 64441480Smckusick struct grf_softc *gp = &grf_softc[GRFUNIT(mp->mm_id)]; 64541480Smckusick 64641480Smckusick #ifdef DEBUG 64741480Smckusick if (grfdebug & GDB_MMAP) 64841480Smckusick printf("grfexit(%d): id %d %x@%x\n", 64943316Smckusick p->p_pid, mp->mm_id, mp->mm_size, mp->mm_uva); 65041480Smckusick #endif 65141480Smckusick (void) grfunlock(gp); 65241480Smckusick #ifdef HPUXCOMPAT 65341480Smckusick grfrmpid(gp); 65441480Smckusick #endif 65543316Smckusick mmmapout(p, mp); 656*43410Shibler return(mmfree(p, mp)); 65741480Smckusick } 65841480Smckusick 65941480Smckusick #ifdef HPUXCOMPAT 66041480Smckusick iommap(dev, addrp) 66141480Smckusick dev_t dev; 66241480Smckusick caddr_t *addrp; 66341480Smckusick { 66443316Smckusick struct proc *p = u.u_procp; /* XXX */ 66541480Smckusick struct grf_softc *gp = &grf_softc[GRFUNIT(dev)]; 66643316Smckusick struct mapmem *mp; 667*43410Shibler int len, error, grfmapin(); 66841480Smckusick 66941480Smckusick #ifdef DEBUG 67041480Smckusick if (grfdebug & (GDB_MMAP|GDB_IOMAP)) 67143316Smckusick printf("iommap(%d): addr %x\n", p->p_pid, *addrp); 67241480Smckusick #endif 67341480Smckusick len = gp->g_display.gd_regsize; 674*43410Shibler error = mmalloc(p, minor(dev), addrp, len, MM_RW|MM_CI|MM_NOCORE, 675*43410Shibler &grfiomops, &mp); 676*43410Shibler if (error == 0) 677*43410Shibler if (error = mmmapin(p, mp, grfmapin)) 678*43410Shibler (void) mmfree(p, mp); 679*43410Shibler return(error); 68041480Smckusick } 68141480Smckusick 68241480Smckusick iounmmap(dev, addr) 68341480Smckusick dev_t dev; 68441480Smckusick caddr_t addr; 68541480Smckusick { 68641480Smckusick struct grf_softc *gp = &grf_softc[GRFUNIT(dev)]; 68741480Smckusick register struct mapmem *mp, **mpp; 68841480Smckusick int found, len, unit = minor(dev); 68941480Smckusick 69041480Smckusick #ifdef DEBUG 69141480Smckusick if (grfdebug & (GDB_MMAP|GDB_IOMAP)) 69241480Smckusick printf("iounmmap(%d): id %d addr %x\n", 69341480Smckusick u.u_procp->p_pid, unit, addr); 69441480Smckusick #endif 69541480Smckusick found = 0; 69641480Smckusick len = gp->g_display.gd_regsize; 69741480Smckusick mpp = &u.u_mmap; 69841480Smckusick for (mp = *mpp; mp; mp = *mpp) { 69941480Smckusick if (mp->mm_ops != &grfiomops || mp->mm_id != unit) { 70041480Smckusick mpp = &mp->mm_next; 70141480Smckusick continue; 70241480Smckusick } 70341480Smckusick if (addr && 70441480Smckusick (addr < mp->mm_uva || addr >= mp->mm_uva+mp->mm_size || 70541480Smckusick len != mp->mm_size)) { 70641480Smckusick mpp = &mp->mm_next; 70741480Smckusick continue; 70841480Smckusick } 709*43410Shibler (void) grfexit(mp); 71041480Smckusick found++; 71141480Smckusick } 71241480Smckusick return(found ? 0 : EINVAL); 71341480Smckusick } 71441480Smckusick 71541480Smckusick /* 71641480Smckusick * Processes involved in framebuffer mapping via GCSLOT are recorded in 71741480Smckusick * an array of pids. The first element is used to record the last slot used 71841480Smckusick * (for faster lookups). The remaining elements record up to GRFMAXLCK-1 71941480Smckusick * process ids. Returns a slot number between 1 and GRFMAXLCK or 0 if no 72041480Smckusick * slot is available. 72141480Smckusick */ 72241480Smckusick grffindpid(gp) 72341480Smckusick struct grf_softc *gp; 72441480Smckusick { 72541480Smckusick register short pid, *sp; 72641480Smckusick register int i, limit; 72741480Smckusick int ni; 72841480Smckusick 72941480Smckusick if (gp->g_pid == NULL) { 73041480Smckusick gp->g_pid = (short *) 73141480Smckusick malloc(GRFMAXLCK * sizeof(short), M_DEVBUF, M_WAITOK); 73241480Smckusick bzero((caddr_t)gp->g_pid, GRFMAXLCK * sizeof(short)); 73341480Smckusick } 73441480Smckusick pid = u.u_procp->p_pid; 73541480Smckusick ni = limit = gp->g_pid[0]; 73641480Smckusick for (i = 1, sp = &gp->g_pid[1]; i <= limit; i++, sp++) { 73741480Smckusick if (*sp == pid) 73841480Smckusick goto done; 73941480Smckusick if (*sp == 0) 74041480Smckusick ni = i; 74141480Smckusick } 74241480Smckusick i = ni; 74341480Smckusick if (i < limit) { 74441480Smckusick gp->g_pid[i] = pid; 74541480Smckusick goto done; 74641480Smckusick } 74741480Smckusick if (++i == GRFMAXLCK) 74841480Smckusick return(0); 74941480Smckusick gp->g_pid[0] = i; 75041480Smckusick gp->g_pid[i] = pid; 75141480Smckusick done: 75241480Smckusick #ifdef DEBUG 75341480Smckusick if (grfdebug & GDB_LOCK) 75441480Smckusick printf("grffindpid(%d): slot %d of %d\n", 75541480Smckusick pid, i, gp->g_pid[0]); 75641480Smckusick #endif 75741480Smckusick return(i); 75841480Smckusick } 75941480Smckusick 76041480Smckusick grfrmpid(gp) 76141480Smckusick struct grf_softc *gp; 76241480Smckusick { 76341480Smckusick register short pid, *sp; 76441480Smckusick register int limit, i; 76541480Smckusick int mi; 76641480Smckusick 76741480Smckusick if (gp->g_pid == NULL || (limit = gp->g_pid[0]) == 0) 76841480Smckusick return; 76941480Smckusick pid = u.u_procp->p_pid; 77041480Smckusick limit = gp->g_pid[0]; 77141480Smckusick mi = 0; 77241480Smckusick for (i = 1, sp = &gp->g_pid[1]; i <= limit; i++, sp++) { 77341480Smckusick if (*sp == pid) 77441480Smckusick *sp = 0; 77541480Smckusick else if (*sp) 77641480Smckusick mi = i; 77741480Smckusick } 77841480Smckusick i = mi; 77941480Smckusick if (i < limit) 78041480Smckusick gp->g_pid[0] = i; 78141480Smckusick #ifdef DEBUG 78241480Smckusick if (grfdebug & GDB_LOCK) 78341480Smckusick printf("grfrmpid(%d): slot %d of %d\n", 78441480Smckusick pid, sp-gp->g_pid, gp->g_pid[0]); 78541480Smckusick #endif 78641480Smckusick } 78741480Smckusick 78841480Smckusick /*ARGSUSED*/ 78941480Smckusick grflckmapin(mp, off) 79041480Smckusick struct mapmem *mp; 79141480Smckusick { 79241480Smckusick u_int pa = kvtop((u_int)grf_softc[GRFUNIT(mp->mm_id)].g_locks); 79341480Smckusick 79441480Smckusick #ifdef DEBUG 79541480Smckusick if (grfdebug & GDB_LOCK) 79641480Smckusick printf("grflckmapin(%d): va %x pa %x\n", u.u_procp->p_pid, 79741480Smckusick grf_softc[GRFUNIT(mp->mm_id)].g_locks, pa); 79841480Smckusick #endif 79941480Smckusick return(pa >> PGSHIFT); 80041480Smckusick } 80141480Smckusick 80241480Smckusick grflckmmap(dev, addrp) 80341480Smckusick dev_t dev; 80441480Smckusick caddr_t *addrp; 80541480Smckusick { 80643316Smckusick struct proc *p = u.u_procp; /* XXX */ 80741480Smckusick struct grf_softc *gp = &grf_softc[GRFUNIT(dev)]; 80843316Smckusick struct mapmem *mp; 809*43410Shibler int error, grflckmapin(); 81041480Smckusick 81141480Smckusick #ifdef DEBUG 81241480Smckusick if (grfdebug & (GDB_MMAP|GDB_LOCK)) 81341480Smckusick printf("grflckmmap(%d): addr %x\n", 81443316Smckusick p->p_pid, *addrp); 81541480Smckusick #endif 81641480Smckusick if (gp->g_locks == NULL) { 81741480Smckusick gp->g_locks = (u_char *) cialloc(NBPG); 81841480Smckusick if (gp->g_locks == NULL) 81941480Smckusick return(ENOMEM); 82041480Smckusick } 821*43410Shibler error = mmalloc(p, minor(dev), addrp, NBPG, MM_RW|MM_CI, 822*43410Shibler &grflckops, &mp); 823*43410Shibler if (error == 0) 824*43410Shibler if (error = mmmapin(p, mp, grflckmapin)) 825*43410Shibler (void) mmfree(p, mp); 826*43410Shibler return(error); 82741480Smckusick } 82841480Smckusick 82941480Smckusick grflckunmmap(dev, addr) 83041480Smckusick dev_t dev; 83141480Smckusick caddr_t addr; 83241480Smckusick { 83341480Smckusick register struct mapmem *mp; 83441480Smckusick int unit = minor(dev); 83541480Smckusick 83641480Smckusick #ifdef DEBUG 83741480Smckusick if (grfdebug & (GDB_MMAP|GDB_LOCK)) 83841480Smckusick printf("grflckunmmap(%d): id %d addr %x\n", 83941480Smckusick u.u_procp->p_pid, unit, addr); 84041480Smckusick #endif 84141480Smckusick for (mp = u.u_mmap; mp; mp = mp->mm_next) 84241480Smckusick if (mp->mm_ops == &grflckops && mp->mm_id == unit && 84341480Smckusick mp->mm_uva == addr) { 844*43410Shibler (void) grfexit(mp); 84541480Smckusick return(0); 84641480Smckusick } 84741480Smckusick return(EINVAL); 84841480Smckusick } 84941480Smckusick #endif /* HPUXCOMPAT */ 85041480Smckusick #endif /* MAPMEM */ 85141480Smckusick #endif /* NGRF > 0 */ 852