#ifndef lint static char sccsid[] = "@(#)cgone.c 1.1 92/07/30 SMI"; #endif /* * Copyright 1983, 1986, 1987 by Sun Microsystems, Inc. */ /* * Sun One Color Graphics Board Driver */ #include "cgone.h" #include "win.h" #include #include #include #include #include #include #include #include #include /* handy register access macro */ #define cg1_reg(fb, r) ((fb)->update[0].regsel.reg[(r)].dat[0]) #define CG1SIZE (sizeof (struct cg1fb)) /* Mainbus device data */ int cgoneprobe(), cgoneintr(); struct mb_device *cgoneinfo[NCGONE]; struct mb_driver cgonedriver = { cgoneprobe, 0, 0, 0, 0, cgoneintr, CG1SIZE, "cgone", cgoneinfo, 0, 0, 0, 0 }; /* driver per-unit data */ struct cg1_softc { struct cg1fb *fb; /* virtual address */ #if NWIN > 0 Pixrect pr; /* kernel pixrect and private data */ struct cg1pr prd; #endif NWIN > 0 } cg1_softc[NCGONE]; /* return structure for FBIOGTYPE ioctl */ static struct fbtype cg1_fbtype = { /* type, height, width, depth, cmsize, size */ FBTYPE_SUN1COLOR, CG1_HEIGHT, CG1_WIDTH, CG1_DEPTH, 1 << CG1_DEPTH, CG1SIZE }; #if NWIN > 0 /* SunWindows specific data */ /* kernel pixrect ops vector */ struct pixrectops cg1_ops = { cg1_rop, cg1_putcolormap, cg1_putattributes, # ifdef _PR_IOCTL_KERNEL_DEFINED 0 # endif }; /* default pixrect and private data */ static Pixrect pr_default = { /* ops, size, depth, data */ &cg1_ops, { CG1_WIDTH, CG1_HEIGHT }, CG1_DEPTH, 0 }; static struct cg1pr prd_default = { /* va, fd, planes, offset */ 0, 0, 255, { 0, 0 } }; #endif NWIN > 0 /*ARGSUSED*/ cgoneprobe(reg, unit) caddr_t reg; int unit; { register struct cg1fb *fb = (struct cg1fb *) reg; register char *xaddr; /* * Probe sequence: * set function to invert * write a pixel * read it back and see if it was inverted */ #define DATA1 0x5C #define DATA2 0x33 xaddr = (char *) cg1_xpipe(fb, 0, 1, 0); if (pokec((char *) &cg1_reg(fb, CG_FUNCREG), ~CG_SRC) || pokec((char *) &cg1_reg(fb, CG_MASKREG), 0) || pokec((char *) cg1_ysrc(fb, 0), 0) || pokec(xaddr, DATA1) || peekc(xaddr) == -1 || pokec(xaddr, DATA2) || peekc(xaddr) != (DATA1 ^ 0xff)) return 0; /* * The bwone frame buffer doesn't indicate that an interrupt * is pending, and the interrupt level is user program changable. * Thus, the kernel never knows what level to expect an * interrupt from and doesn't know if an interrupt is pending. * We add the bwoneintr routine to a list of interrupt handlers * that are called if no one else handles an interrupt. */ add_default_intr(cgoneintr); cg1_softc[unit].fb = fb; return CG1SIZE; #undef DATA1 #undef DATA2 } cgoneopen(dev, flag) dev_t dev; int flag; { return fbopen(dev, flag, NCGONE, cgoneinfo); } /*ARGSUSED*/ cgoneclose(dev, flag) dev_t dev; int flag; { return 0; } cgonemmap(dev, off, prot) dev_t dev; off_t off; int prot; { return fbmmap(dev, off, prot, NCGONE, cgoneinfo, CG1SIZE); } /*ARGSUSED*/ cgoneioctl(dev, cmd, data, flag) dev_t dev; int cmd; caddr_t data; int flag; { register struct cg1_softc *softc = &cg1_softc[minor(dev)]; switch (cmd) { case FBIOGTYPE: * (struct fbtype *) data = cg1_fbtype; break; #if NWIN > 0 case FBIOGPIXRECT: ((struct fbpixrect *) data)->fbpr_pixrect = &softc->pr; /* initialize pixrect */ softc->pr = pr_default; softc->pr.pr_data = (caddr_t) &softc->prd; /* initialize private data */ softc->prd = prd_default; softc->prd.cgpr_va = softc->fb; /* enable video, disable interrupt */ cg1_setcontrol(softc->fb, CG_VIDEOENABLE); break; #endif NWIN > 0 case FBIOSVIDEO: if (* (int *) data & FBVIDEO_ON) cg1_reg(softc->fb, CG_STATUS) |= CG_VIDEOENABLE; else cg1_reg(softc->fb, CG_STATUS) &= ~CG_VIDEOENABLE; break; case FBIOGVIDEO: * (int *) data = cg1_reg(softc->fb, CG_STATUS) & CG_VIDEOENABLE ? FBVIDEO_ON : FBVIDEO_OFF; break; default: return ENOTTY; } return 0; } static cgoneintclear(addr) caddr_t addr; { /* * Turn off interrupts, then return 0 since we have no way of * knowing whether we caused the interrupt. */ cg1_intclear((struct cg1fb *) addr); return 0; } cgoneintr() { return fbintr(NCGONE, cgoneinfo, cgoneintclear); }