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*45750Smckusick * @(#)grf.c 7.5 (Berkeley) 12/05/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 "malloc.h" 3241480Smckusick 3341480Smckusick #include "device.h" 3441480Smckusick #include "grfioctl.h" 3541480Smckusick #include "grfvar.h" 3641480Smckusick 3741480Smckusick #include "machine/cpu.h" 3841480Smckusick 3941480Smckusick #ifdef HPUXCOMPAT 4041480Smckusick #include "../hpux/hpux.h" 4141480Smckusick #endif 4241480Smckusick 43*45750Smckusick #include "../vm/vm_param.h" 44*45750Smckusick #include "../vm/vm_map.h" 45*45750Smckusick #include "../vm/vm_kern.h" 46*45750Smckusick #include "../vm/vm_page.h" 47*45750Smckusick #include "../vm/vm_pager.h" 48*45750Smckusick #include "specdev.h" 49*45750Smckusick #include "vnode.h" 50*45750Smckusick #include "mman.h" 51*45750Smckusick 5241480Smckusick #include "ite.h" 5341480Smckusick #if NITE == 0 5441480Smckusick #define iteon(u,f) 5541480Smckusick #define iteoff(u,f) 5641480Smckusick #endif 5741480Smckusick 5841480Smckusick int grfprobe(); 5941480Smckusick int tc_init(), tc_mode(); 6041480Smckusick int gb_init(), gb_mode(); 6141480Smckusick int rb_init(), rb_mode(); 6241480Smckusick int dv_init(), dv_mode(); 6341480Smckusick 6441480Smckusick struct grfdev grfdev[] = { 6541480Smckusick GID_TOPCAT, GRFBOBCAT, tc_init, tc_mode, 6641480Smckusick "topcat", 6741480Smckusick GID_GATORBOX, GRFGATOR, gb_init, gb_mode, 6841480Smckusick "gatorbox", 6941480Smckusick GID_RENAISSANCE,GRFRBOX, rb_init, rb_mode, 7041480Smckusick "renaissance", 7141480Smckusick GID_LRCATSEYE, GRFCATSEYE, tc_init, tc_mode, 7241480Smckusick "lo-res catseye", 7341480Smckusick GID_HRCCATSEYE, GRFCATSEYE, tc_init, tc_mode, 7441480Smckusick "hi-res catseye", 7541480Smckusick GID_HRMCATSEYE, GRFCATSEYE, tc_init, tc_mode, 7641480Smckusick "hi-res catseye", 7741480Smckusick GID_DAVINCI, GRFDAVINCI, dv_init, dv_mode, 7841480Smckusick "davinci", 7941480Smckusick }; 8041480Smckusick int ngrfdev = sizeof(grfdev) / sizeof(grfdev[0]); 8141480Smckusick 8241480Smckusick struct driver grfdriver = { grfprobe, "grf" }; 8341480Smckusick struct grf_softc grf_softc[NGRF]; 8441480Smckusick 8541480Smckusick #ifdef DEBUG 8641480Smckusick int grfdebug = 0; 8741480Smckusick #define GDB_DEVNO 0x01 8841480Smckusick #define GDB_MMAP 0x02 8941480Smckusick #define GDB_IOMAP 0x04 9041480Smckusick #define GDB_LOCK 0x08 9141480Smckusick #endif 9241480Smckusick 9341480Smckusick /* 9441480Smckusick * XXX: called from ite console init routine. 9541480Smckusick * Does just what configure will do later but without printing anything. 9641480Smckusick */ 9741480Smckusick grfconfig() 9841480Smckusick { 9941480Smckusick register caddr_t addr; 10041480Smckusick register struct hp_hw *hw; 10141480Smckusick register struct hp_device *hd, *nhd; 10241480Smckusick 10341480Smckusick for (hw = sc_table; hw->hw_type; hw++) { 10441480Smckusick if (hw->hw_type != BITMAP) 10541480Smckusick continue; 10641480Smckusick /* 10741480Smckusick * Found one, now match up with a logical unit number 10841480Smckusick */ 10941480Smckusick nhd = NULL; 11041480Smckusick addr = hw->hw_addr; 11141480Smckusick for (hd = hp_dinit; hd->hp_driver; hd++) { 11241480Smckusick if (hd->hp_driver != &grfdriver || hd->hp_alive) 11341480Smckusick continue; 11441480Smckusick /* 11541480Smckusick * Wildcarded. If first, remember as possible match. 11641480Smckusick */ 11741480Smckusick if (hd->hp_addr == NULL) { 11841480Smckusick if (nhd == NULL) 11941480Smckusick nhd = hd; 12041480Smckusick continue; 12141480Smckusick } 12241480Smckusick /* 12341480Smckusick * Not wildcarded. 12441480Smckusick * If exact match done searching, else keep looking. 12541480Smckusick */ 12641480Smckusick if ((caddr_t)sctoaddr(hd->hp_addr) == addr) { 12741480Smckusick nhd = hd; 12841480Smckusick break; 12941480Smckusick } 13041480Smckusick } 13141480Smckusick /* 13241480Smckusick * Found a match, initialize 13341480Smckusick */ 13441480Smckusick if (nhd && grfinit(addr, nhd->hp_unit)) { 13541480Smckusick nhd->hp_addr = addr; 13641480Smckusick } 13741480Smckusick } 13841480Smckusick } 13941480Smckusick 14041480Smckusick /* 14141480Smckusick * Normal init routine called by configure() code 14241480Smckusick */ 14341480Smckusick grfprobe(hd) 14441480Smckusick struct hp_device *hd; 14541480Smckusick { 14641480Smckusick struct grf_softc *gp = &grf_softc[hd->hp_unit]; 14741480Smckusick 14841480Smckusick if ((gp->g_flags & GF_ALIVE) == 0 && 14941480Smckusick !grfinit(hd->hp_addr, hd->hp_unit)) 15041480Smckusick return(0); 15141480Smckusick printf("grf%d: %d x %d ", hd->hp_unit, 15241480Smckusick gp->g_display.gd_dwidth, gp->g_display.gd_dheight); 15341480Smckusick if (gp->g_display.gd_colors == 2) 15441480Smckusick printf("monochrome"); 15541480Smckusick else 15641480Smckusick printf("%d color", gp->g_display.gd_colors); 15741480Smckusick printf(" %s display\n", grfdev[gp->g_type].gd_desc); 15841480Smckusick return(1); 15941480Smckusick } 16041480Smckusick 16141480Smckusick grfinit(addr, unit) 16241480Smckusick caddr_t addr; 16341480Smckusick { 16441480Smckusick struct grf_softc *gp = &grf_softc[unit]; 16541480Smckusick struct grfreg *gr; 16641480Smckusick register struct grfdev *gd; 16741480Smckusick 16841480Smckusick gr = (struct grfreg *) addr; 16941480Smckusick if (gr->gr_id != GRFHWID) 17041480Smckusick return(0); 17141480Smckusick for (gd = grfdev; gd < &grfdev[ngrfdev]; gd++) 17241480Smckusick if (gd->gd_hardid == gr->gr_id2) 17341480Smckusick break; 17441480Smckusick if (gd < &grfdev[ngrfdev] && (*gd->gd_init)(gp, addr)) { 17541480Smckusick gp->g_display.gd_id = gd->gd_softid; 17641480Smckusick gp->g_type = gd - grfdev; 17741480Smckusick gp->g_flags = GF_ALIVE; 17841480Smckusick return(1); 17941480Smckusick } 18041480Smckusick return(0); 18141480Smckusick } 18241480Smckusick 18341480Smckusick /*ARGSUSED*/ 18441480Smckusick grfopen(dev, flags) 18541480Smckusick dev_t dev; 18641480Smckusick { 18741480Smckusick int unit = GRFUNIT(dev); 18841480Smckusick register struct grf_softc *gp = &grf_softc[unit]; 18941480Smckusick int error = 0; 19041480Smckusick 19141480Smckusick if (unit >= NGRF || (gp->g_flags & GF_ALIVE) == 0) 19241480Smckusick return(ENXIO); 19341480Smckusick if ((gp->g_flags & (GF_OPEN|GF_EXCLUDE)) == (GF_OPEN|GF_EXCLUDE)) 19441480Smckusick return(EBUSY); 19541480Smckusick #ifdef HPUXCOMPAT 19641480Smckusick /* 19741480Smckusick * XXX: cannot handle both HPUX and BSD processes at the same time 19841480Smckusick */ 19941480Smckusick if (u.u_procp->p_flag & SHPUX) 20041480Smckusick if (gp->g_flags & GF_BSDOPEN) 20141480Smckusick return(EBUSY); 20241480Smckusick else 20341480Smckusick gp->g_flags |= GF_HPUXOPEN; 20441480Smckusick else 20541480Smckusick if (gp->g_flags & GF_HPUXOPEN) 20641480Smckusick return(EBUSY); 20741480Smckusick else 20841480Smckusick gp->g_flags |= GF_BSDOPEN; 20941480Smckusick #endif 21041480Smckusick /* 21141480Smckusick * First open. 21241480Smckusick * XXX: always put in graphics mode. 21341480Smckusick */ 21441480Smckusick error = 0; 21541480Smckusick if ((gp->g_flags & GF_OPEN) == 0) { 21641480Smckusick gp->g_flags |= GF_OPEN; 21741480Smckusick error = grfon(dev); 21841480Smckusick } 21941480Smckusick return(error); 22041480Smckusick } 22141480Smckusick 22241480Smckusick /*ARGSUSED*/ 22341480Smckusick grfclose(dev, flags) 22441480Smckusick dev_t dev; 22541480Smckusick { 22641480Smckusick register struct grf_softc *gp = &grf_softc[GRFUNIT(dev)]; 22741480Smckusick 22841480Smckusick (void) grfoff(dev); 22941480Smckusick (void) grfunlock(gp); 23041480Smckusick gp->g_flags &= GF_ALIVE; 23141480Smckusick return(0); 23241480Smckusick } 23341480Smckusick 23441480Smckusick /*ARGSUSED*/ 23541480Smckusick grfioctl(dev, cmd, data, flag) 23641480Smckusick dev_t dev; 23741480Smckusick caddr_t data; 23841480Smckusick { 23941480Smckusick register struct grf_softc *gp = &grf_softc[GRFUNIT(dev)]; 24041480Smckusick int error; 24141480Smckusick 24241480Smckusick #ifdef HPUXCOMPAT 24341480Smckusick if (u.u_procp->p_flag & SHPUX) 24441480Smckusick return(hpuxgrfioctl(dev, cmd, data, flag)); 24541480Smckusick #endif 24641480Smckusick error = 0; 24741480Smckusick switch (cmd) { 24841480Smckusick 24941480Smckusick /* XXX: compatibility hack */ 25041480Smckusick case OGRFIOCGINFO: 25141480Smckusick bcopy((caddr_t)&gp->g_display, data, sizeof(struct ogrfinfo)); 25241480Smckusick break; 25341480Smckusick 25441480Smckusick case GRFIOCGINFO: 25541480Smckusick bcopy((caddr_t)&gp->g_display, data, sizeof(struct grfinfo)); 25641480Smckusick break; 25741480Smckusick 25841480Smckusick case GRFIOCON: 25941480Smckusick error = grfon(dev); 26041480Smckusick break; 26141480Smckusick 26241480Smckusick case GRFIOCOFF: 26341480Smckusick error = grfoff(dev); 26441480Smckusick break; 26541480Smckusick 26641480Smckusick case GRFIOCMAP: 26741480Smckusick error = grfmmap(dev, (caddr_t *)data); 26841480Smckusick break; 26941480Smckusick 27041480Smckusick case GRFIOCUNMAP: 27141480Smckusick error = grfunmmap(dev, *(caddr_t *)data); 27241480Smckusick break; 27341480Smckusick 27441480Smckusick default: 27541480Smckusick error = EINVAL; 27641480Smckusick break; 27741480Smckusick 27841480Smckusick } 27941480Smckusick return(error); 28041480Smckusick } 28141480Smckusick 28241480Smckusick /*ARGSUSED*/ 28341480Smckusick grfselect(dev, rw) 28441480Smckusick dev_t dev; 28541480Smckusick { 28641480Smckusick if (rw == FREAD) 28741480Smckusick return(0); 28841480Smckusick return(1); 28941480Smckusick } 29041480Smckusick 29141480Smckusick grflock(gp, block) 29241480Smckusick register struct grf_softc *gp; 29341480Smckusick int block; 29441480Smckusick { 29543316Smckusick struct proc *p = u.u_procp; /* XXX */ 29642358Smckusick int error; 29742358Smckusick extern char devioc[]; 29842358Smckusick 29941480Smckusick #ifdef DEBUG 30041480Smckusick if (grfdebug & GDB_LOCK) 30141480Smckusick printf("grflock(%d): dev %x flags %x lockpid %x\n", 30243316Smckusick p->p_pid, gp-grf_softc, gp->g_flags, 30341480Smckusick gp->g_lockp ? gp->g_lockp->p_pid : -1); 30441480Smckusick #endif 30541480Smckusick #ifdef HPUXCOMPAT 30641480Smckusick if (gp->g_pid) { 30741480Smckusick #ifdef DEBUG 30841480Smckusick if (grfdebug & GDB_LOCK) 30941480Smckusick printf(" lock[0] %d lockslot %d lock[lockslot] %d\n", 31041480Smckusick gp->g_locks[0], gp->g_lockpslot, 31141480Smckusick gp->g_locks[gp->g_lockpslot]); 31241480Smckusick #endif 31341480Smckusick gp->g_locks[0] = 0; 31441480Smckusick if (gp->g_locks[gp->g_lockpslot] == 0) { 31541480Smckusick gp->g_lockp = NULL; 31641480Smckusick gp->g_lockpslot = 0; 31741480Smckusick } 31841480Smckusick } 31941480Smckusick #endif 32041480Smckusick if (gp->g_lockp) { 32143316Smckusick if (gp->g_lockp == p) 32241480Smckusick return(EBUSY); 32341480Smckusick if (!block) 32441480Smckusick return(EAGAIN); 32541480Smckusick do { 32641480Smckusick gp->g_flags |= GF_WANTED; 32742358Smckusick if (error = tsleep((caddr_t)&gp->g_flags, 32842358Smckusick (PZERO+1) | PCATCH, devioc, 0)) 32942358Smckusick return (error); 33041480Smckusick } while (gp->g_lockp); 33141480Smckusick } 33243316Smckusick gp->g_lockp = p; 33341480Smckusick #ifdef HPUXCOMPAT 33441480Smckusick if (gp->g_pid) { 33541480Smckusick int slot = grffindpid(gp); 33641480Smckusick #ifdef DEBUG 33741480Smckusick if (grfdebug & GDB_LOCK) 33841480Smckusick printf(" slot %d\n", slot); 33941480Smckusick #endif 34041480Smckusick gp->g_lockpslot = gp->g_locks[0] = slot; 34141480Smckusick gp->g_locks[slot] = 1; 34241480Smckusick } 34341480Smckusick #endif 34441480Smckusick return(0); 34541480Smckusick } 34641480Smckusick 34741480Smckusick grfunlock(gp) 34841480Smckusick register struct grf_softc *gp; 34941480Smckusick { 35041480Smckusick #ifdef DEBUG 35141480Smckusick if (grfdebug & GDB_LOCK) 35241480Smckusick printf("grfunlock(%d): dev %x flags %x lockpid %d\n", 35341480Smckusick u.u_procp->p_pid, gp-grf_softc, gp->g_flags, 35441480Smckusick gp->g_lockp ? gp->g_lockp->p_pid : -1); 35541480Smckusick #endif 35641480Smckusick if (gp->g_lockp != u.u_procp) 35741480Smckusick return(EBUSY); 35841480Smckusick #ifdef HPUXCOMPAT 35941480Smckusick if (gp->g_pid) { 36041480Smckusick #ifdef DEBUG 36141480Smckusick if (grfdebug & GDB_LOCK) 36241480Smckusick printf(" lock[0] %d lockslot %d lock[lockslot] %d\n", 36341480Smckusick gp->g_locks[0], gp->g_lockpslot, 36441480Smckusick gp->g_locks[gp->g_lockpslot]); 36541480Smckusick #endif 36641480Smckusick gp->g_locks[gp->g_lockpslot] = gp->g_locks[0] = 0; 36741480Smckusick gp->g_lockpslot = 0; 36841480Smckusick } 36941480Smckusick #endif 37041480Smckusick if (gp->g_flags & GF_WANTED) { 37141480Smckusick wakeup((caddr_t)&gp->g_flags); 37241480Smckusick gp->g_flags &= ~GF_WANTED; 37341480Smckusick } 37441480Smckusick gp->g_lockp = NULL; 37541480Smckusick return(0); 37641480Smckusick } 37741480Smckusick 37841480Smckusick /*ARGSUSED*/ 37941480Smckusick grfmap(dev, off, prot) 38041480Smckusick dev_t dev; 38141480Smckusick { 38241480Smckusick return(grfaddr(&grf_softc[GRFUNIT(dev)], off)); 38341480Smckusick } 38441480Smckusick 38541480Smckusick #ifdef HPUXCOMPAT 38641480Smckusick 38741480Smckusick /*ARGSUSED*/ 38841480Smckusick hpuxgrfioctl(dev, cmd, data, flag) 38941480Smckusick dev_t dev; 39041480Smckusick caddr_t data; 39141480Smckusick { 39241480Smckusick register struct grf_softc *gp = &grf_softc[GRFUNIT(dev)]; 39341480Smckusick int error; 39441480Smckusick 39541480Smckusick error = 0; 39641480Smckusick switch (cmd) { 39741480Smckusick 39841480Smckusick case GCID: 39941480Smckusick *(int *)data = gp->g_display.gd_id; 40041480Smckusick break; 40141480Smckusick 40241480Smckusick case GCON: 40341480Smckusick error = grfon(dev); 40441480Smckusick break; 40541480Smckusick 40641480Smckusick case GCOFF: 40741480Smckusick error = grfoff(dev); 40841480Smckusick break; 40941480Smckusick 41041480Smckusick case GCLOCK: 41141480Smckusick error = grflock(gp, 1); 41241480Smckusick break; 41341480Smckusick 41441480Smckusick case GCUNLOCK: 41541480Smckusick error = grfunlock(gp); 41641480Smckusick break; 41741480Smckusick 41841480Smckusick case GCAON: 41941480Smckusick case GCAOFF: 42041480Smckusick break; 42141480Smckusick 42241480Smckusick /* GCSTATIC is implied by our implementation */ 42341480Smckusick case GCSTATIC_CMAP: 42441480Smckusick case GCVARIABLE_CMAP: 42541480Smckusick break; 42641480Smckusick 42741480Smckusick /* map in control regs and frame buffer */ 42841480Smckusick case GCMAP: 42941480Smckusick error = grfmmap(dev, (caddr_t *)data); 43041480Smckusick break; 43141480Smckusick 43241480Smckusick case GCUNMAP: 43341480Smckusick error = grfunmmap(dev, *(caddr_t *)data); 43441480Smckusick /* XXX: HP-UX uses GCUNMAP to get rid of GCSLOT memory */ 43541480Smckusick if (error) 43641480Smckusick error = grflckunmmap(dev, *(caddr_t *)data); 43741480Smckusick break; 43841480Smckusick 43941480Smckusick case GCSLOT: 44041480Smckusick { 44141480Smckusick struct grf_slot *sp = (struct grf_slot *)data; 44241480Smckusick 44341480Smckusick sp->slot = grffindpid(gp); 444*45750Smckusick if (sp->slot) { 44541480Smckusick error = grflckmmap(dev, (caddr_t *)&sp->addr); 446*45750Smckusick if (error && gp->g_pid) { 447*45750Smckusick free((caddr_t)gp->g_pid, M_DEVBUF); 448*45750Smckusick gp->g_pid = NULL; 449*45750Smckusick } 450*45750Smckusick } 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); 46143410Shibler #if 0 46243410Shibler /* 46343410Shibler * It may not be worth kludging this (using p_devtmp) to 46443410Shibler * make this work. It was an undocumented side-effect 46543410Shibler * in HP-UX that the mapped address was the return value 46643410Shibler * of the ioctl. The only thing I remember that counted 46743410Shibler * on this behavior was the rbox X10 server. 46843410Shibler */ 46941480Smckusick if (!error) 47041480Smckusick u.u_r.r_val1 = *(int *)data; /* XXX: this sux */ 47143410Shibler #endif 47241480Smckusick break; 47341480Smckusick 47441480Smckusick case IOMAPUNMAP: 47541480Smckusick error = iounmmap(dev, *(caddr_t *)data); 47641480Smckusick break; 47741480Smckusick 47841480Smckusick default: 47941480Smckusick error = EINVAL; 48041480Smckusick break; 48141480Smckusick } 48241480Smckusick return(error); 48341480Smckusick } 48441480Smckusick 48541480Smckusick #endif 48641480Smckusick 48741480Smckusick grfon(dev) 48841480Smckusick dev_t dev; 48941480Smckusick { 49041480Smckusick int unit = GRFUNIT(dev); 49141480Smckusick struct grf_softc *gp = &grf_softc[unit]; 49241480Smckusick 49341480Smckusick /* 49441480Smckusick * XXX: iteoff call relies on devices being in same order 49541480Smckusick * as ITEs and the fact that iteoff only uses the minor part 49641480Smckusick * of the dev arg. 49741480Smckusick */ 49841480Smckusick iteoff(unit, 3); 49941480Smckusick return((*grfdev[gp->g_type].gd_mode) 50041480Smckusick (gp, (dev&GRFOVDEV) ? GM_GRFOVON : GM_GRFON)); 50141480Smckusick } 50241480Smckusick 50341480Smckusick grfoff(dev) 50441480Smckusick dev_t dev; 50541480Smckusick { 50641480Smckusick int unit = GRFUNIT(dev); 50741480Smckusick struct grf_softc *gp = &grf_softc[unit]; 50841480Smckusick int error; 50941480Smckusick 51041480Smckusick (void) grfunmmap(dev, (caddr_t)0); 51141480Smckusick error = (*grfdev[gp->g_type].gd_mode) 51241480Smckusick (gp, (dev&GRFOVDEV) ? GM_GRFOVOFF : GM_GRFOFF); 51341480Smckusick /* XXX: see comment for iteoff above */ 51441480Smckusick iteon(unit, 2); 51541480Smckusick return(error); 51641480Smckusick } 51741480Smckusick 51841480Smckusick grfaddr(gp, off) 51941480Smckusick struct grf_softc *gp; 52041480Smckusick register int off; 52141480Smckusick { 52241480Smckusick register struct grfinfo *gi = &gp->g_display; 52341480Smckusick 52441480Smckusick /* control registers */ 52541480Smckusick if (off >= 0 && off < gi->gd_regsize) 52641480Smckusick return(((u_int)gi->gd_regaddr + off) >> PGSHIFT); 52741480Smckusick 52841480Smckusick /* frame buffer */ 52941480Smckusick if (off >= gi->gd_regsize && off < gi->gd_regsize+gi->gd_fbsize) { 53041480Smckusick off -= gi->gd_regsize; 53141480Smckusick return(((u_int)gi->gd_fbaddr + off) >> PGSHIFT); 53241480Smckusick } 53341480Smckusick /* bogus */ 53441480Smckusick return(-1); 53541480Smckusick } 53641480Smckusick 53741480Smckusick #ifdef HPUXCOMPAT 53841480Smckusick /* 53941480Smckusick * Convert a BSD style minor devno to HPUX style. 54041480Smckusick * We cannot just create HPUX style nodes as they require 24 bits 54141480Smckusick * of minor device number and we only have 8. 54241480Smckusick * XXX: This may give the wrong result for remote stats of other 54341480Smckusick * machines where device 10 exists. 54441480Smckusick */ 54541480Smckusick grfdevno(dev) 54641480Smckusick dev_t dev; 54741480Smckusick { 54841480Smckusick int unit = GRFUNIT(dev); 54941480Smckusick struct grf_softc *gp = &grf_softc[unit]; 55041480Smckusick int newdev; 55141480Smckusick 55241480Smckusick if (unit >= NGRF || (gp->g_flags&GF_ALIVE) == 0) 55341480Smckusick return(bsdtohpuxdev(dev)); 55441480Smckusick /* magic major number */ 55541480Smckusick newdev = 12 << 24; 55641480Smckusick /* now construct minor number */ 55741480Smckusick if (gp->g_display.gd_regaddr != (caddr_t)GRFIADDR) 55841480Smckusick newdev |= ((u_int)gp->g_display.gd_regaddr-EXTIOBASE) | 0x200; 55941480Smckusick if (dev & GRFIMDEV) 56041480Smckusick newdev |= 0x02; 56141480Smckusick else if (dev & GRFOVDEV) 56241480Smckusick newdev |= 0x01; 56341480Smckusick #ifdef DEBUG 56441480Smckusick if (grfdebug & GDB_DEVNO) 56541480Smckusick printf("grfdevno: dev %x newdev %x\n", dev, newdev); 56641480Smckusick #endif 56741480Smckusick return(newdev); 56841480Smckusick } 56941480Smckusick #endif 57041480Smckusick 57141480Smckusick grfmmap(dev, addrp) 57241480Smckusick dev_t dev; 57341480Smckusick caddr_t *addrp; 57441480Smckusick { 57543316Smckusick struct proc *p = u.u_procp; /* XXX */ 57641480Smckusick struct grf_softc *gp = &grf_softc[GRFUNIT(dev)]; 577*45750Smckusick int len, error; 578*45750Smckusick struct vnode vn; 579*45750Smckusick struct specinfo si; 580*45750Smckusick int flags; 58141480Smckusick 58241480Smckusick #ifdef DEBUG 58341480Smckusick if (grfdebug & GDB_MMAP) 58443316Smckusick printf("grfmmap(%d): addr %x\n", p->p_pid, *addrp); 58541480Smckusick #endif 58641480Smckusick len = gp->g_display.gd_regsize + gp->g_display.gd_fbsize; 587*45750Smckusick flags = MAP_FILE|MAP_SHARED; 588*45750Smckusick if (*addrp) 589*45750Smckusick flags |= MAP_FIXED; 590*45750Smckusick else 591*45750Smckusick *addrp = (caddr_t)0x1000000; /* XXX */ 592*45750Smckusick vn.v_type = VCHR; /* XXX */ 593*45750Smckusick vn.v_specinfo = &si; /* XXX */ 594*45750Smckusick vn.v_rdev = dev; /* XXX */ 595*45750Smckusick error = vm_mmap(u.u_procp->p_map, (vm_offset_t *)addrp, 596*45750Smckusick (vm_size_t)len, VM_PROT_ALL, flags, (caddr_t)&vn, 0); 59743410Shibler return(error); 59841480Smckusick } 59941480Smckusick 60041480Smckusick grfunmmap(dev, addr) 60141480Smckusick dev_t dev; 60241480Smckusick caddr_t addr; 60341480Smckusick { 60443316Smckusick struct proc *p = u.u_procp; /* XXX */ 605*45750Smckusick struct grf_softc *gp = &grf_softc[GRFUNIT(dev)]; 606*45750Smckusick vm_size_t size; 607*45750Smckusick int rv; 60841480Smckusick 60941480Smckusick #ifdef DEBUG 61041480Smckusick if (grfdebug & GDB_MMAP) 611*45750Smckusick printf("grfunmmap(%d): dev %x addr %x\n", p->p_pid, dev, addr); 61241480Smckusick #endif 613*45750Smckusick if (addr == 0) 614*45750Smckusick return(EINVAL); /* XXX: how do we deal with this? */ 615*45750Smckusick size = round_page(gp->g_display.gd_regsize + gp->g_display.gd_fbsize); 616*45750Smckusick rv = vm_deallocate(p->p_map, (vm_offset_t)addr, size); 617*45750Smckusick return(rv == KERN_SUCCESS ? 0 : EINVAL); 61841480Smckusick } 61941480Smckusick 62041480Smckusick #ifdef HPUXCOMPAT 62141480Smckusick iommap(dev, addrp) 62241480Smckusick dev_t dev; 62341480Smckusick caddr_t *addrp; 62441480Smckusick { 62543316Smckusick struct proc *p = u.u_procp; /* XXX */ 62641480Smckusick struct grf_softc *gp = &grf_softc[GRFUNIT(dev)]; 62741480Smckusick 62841480Smckusick #ifdef DEBUG 62941480Smckusick if (grfdebug & (GDB_MMAP|GDB_IOMAP)) 63043316Smckusick printf("iommap(%d): addr %x\n", p->p_pid, *addrp); 63141480Smckusick #endif 632*45750Smckusick return(EINVAL); 63341480Smckusick } 63441480Smckusick 63541480Smckusick iounmmap(dev, addr) 63641480Smckusick dev_t dev; 63741480Smckusick caddr_t addr; 63841480Smckusick { 639*45750Smckusick int unit = minor(dev); 64041480Smckusick 64141480Smckusick #ifdef DEBUG 64241480Smckusick if (grfdebug & (GDB_MMAP|GDB_IOMAP)) 64341480Smckusick printf("iounmmap(%d): id %d addr %x\n", 64441480Smckusick u.u_procp->p_pid, unit, addr); 64541480Smckusick #endif 646*45750Smckusick return(0); 64741480Smckusick } 64841480Smckusick 64941480Smckusick /* 65041480Smckusick * Processes involved in framebuffer mapping via GCSLOT are recorded in 65141480Smckusick * an array of pids. The first element is used to record the last slot used 65241480Smckusick * (for faster lookups). The remaining elements record up to GRFMAXLCK-1 65341480Smckusick * process ids. Returns a slot number between 1 and GRFMAXLCK or 0 if no 65441480Smckusick * slot is available. 65541480Smckusick */ 65641480Smckusick grffindpid(gp) 65741480Smckusick struct grf_softc *gp; 65841480Smckusick { 65941480Smckusick register short pid, *sp; 66041480Smckusick register int i, limit; 66141480Smckusick int ni; 66241480Smckusick 66341480Smckusick if (gp->g_pid == NULL) { 66441480Smckusick gp->g_pid = (short *) 66541480Smckusick malloc(GRFMAXLCK * sizeof(short), M_DEVBUF, M_WAITOK); 66641480Smckusick bzero((caddr_t)gp->g_pid, GRFMAXLCK * sizeof(short)); 66741480Smckusick } 66841480Smckusick pid = u.u_procp->p_pid; 66941480Smckusick ni = limit = gp->g_pid[0]; 67041480Smckusick for (i = 1, sp = &gp->g_pid[1]; i <= limit; i++, sp++) { 67141480Smckusick if (*sp == pid) 67241480Smckusick goto done; 67341480Smckusick if (*sp == 0) 67441480Smckusick ni = i; 67541480Smckusick } 67641480Smckusick i = ni; 67741480Smckusick if (i < limit) { 67841480Smckusick gp->g_pid[i] = pid; 67941480Smckusick goto done; 68041480Smckusick } 68141480Smckusick if (++i == GRFMAXLCK) 68241480Smckusick return(0); 68341480Smckusick gp->g_pid[0] = i; 68441480Smckusick gp->g_pid[i] = pid; 68541480Smckusick done: 68641480Smckusick #ifdef DEBUG 68741480Smckusick if (grfdebug & GDB_LOCK) 68841480Smckusick printf("grffindpid(%d): slot %d of %d\n", 68941480Smckusick pid, i, gp->g_pid[0]); 69041480Smckusick #endif 69141480Smckusick return(i); 69241480Smckusick } 69341480Smckusick 69441480Smckusick grfrmpid(gp) 69541480Smckusick struct grf_softc *gp; 69641480Smckusick { 69741480Smckusick register short pid, *sp; 69841480Smckusick register int limit, i; 69941480Smckusick int mi; 70041480Smckusick 70141480Smckusick if (gp->g_pid == NULL || (limit = gp->g_pid[0]) == 0) 70241480Smckusick return; 70341480Smckusick pid = u.u_procp->p_pid; 70441480Smckusick limit = gp->g_pid[0]; 70541480Smckusick mi = 0; 70641480Smckusick for (i = 1, sp = &gp->g_pid[1]; i <= limit; i++, sp++) { 70741480Smckusick if (*sp == pid) 70841480Smckusick *sp = 0; 70941480Smckusick else if (*sp) 71041480Smckusick mi = i; 71141480Smckusick } 71241480Smckusick i = mi; 71341480Smckusick if (i < limit) 71441480Smckusick gp->g_pid[0] = i; 71541480Smckusick #ifdef DEBUG 71641480Smckusick if (grfdebug & GDB_LOCK) 71741480Smckusick printf("grfrmpid(%d): slot %d of %d\n", 71841480Smckusick pid, sp-gp->g_pid, gp->g_pid[0]); 71941480Smckusick #endif 72041480Smckusick } 72141480Smckusick 72241480Smckusick grflckmmap(dev, addrp) 72341480Smckusick dev_t dev; 72441480Smckusick caddr_t *addrp; 72541480Smckusick { 72643316Smckusick struct proc *p = u.u_procp; /* XXX */ 72741480Smckusick 72841480Smckusick #ifdef DEBUG 72941480Smckusick if (grfdebug & (GDB_MMAP|GDB_LOCK)) 73041480Smckusick printf("grflckmmap(%d): addr %x\n", 73143316Smckusick p->p_pid, *addrp); 73241480Smckusick #endif 733*45750Smckusick return(EINVAL); 73441480Smckusick } 73541480Smckusick 73641480Smckusick grflckunmmap(dev, addr) 73741480Smckusick dev_t dev; 73841480Smckusick caddr_t addr; 73941480Smckusick { 74041480Smckusick int unit = minor(dev); 74141480Smckusick 74241480Smckusick #ifdef DEBUG 74341480Smckusick if (grfdebug & (GDB_MMAP|GDB_LOCK)) 74441480Smckusick printf("grflckunmmap(%d): id %d addr %x\n", 74541480Smckusick u.u_procp->p_pid, unit, addr); 74641480Smckusick #endif 74741480Smckusick return(EINVAL); 74841480Smckusick } 74941480Smckusick #endif /* HPUXCOMPAT */ 750*45750Smckusick 75141480Smckusick #endif /* NGRF > 0 */ 752