831 lines
17 KiB
C
831 lines
17 KiB
C
#if !defined(lint) && !defined(NOID)
|
|
static char sccsid[] = "@(#)cgthree.c 1.1 94/10/31 SMI";
|
|
#endif
|
|
|
|
/*
|
|
* Copyright 1988-1989, Sun Microsystems, Inc.
|
|
*/
|
|
|
|
/*
|
|
* Sbus 8 bit color memory frame buffer driver
|
|
*/
|
|
|
|
#include "win.h"
|
|
|
|
#include <sys/param.h>
|
|
#include <sys/time.h>
|
|
#include <sys/buf.h>
|
|
#include <sys/errno.h>
|
|
#include <sys/ioctl.h>
|
|
#include <sys/map.h>
|
|
#include <sys/proc.h>
|
|
#include <sys/user.h>
|
|
#include <sys/vmmac.h>
|
|
|
|
#include <sun/fbio.h>
|
|
|
|
#include <sundev/mbvar.h>
|
|
#include <sbusdev/memfb.h>
|
|
|
|
#include <machine/mmu.h>
|
|
#include <machine/pte.h>
|
|
|
|
#include <pixrect/pixrect.h>
|
|
#include <pixrect/pr_impl_util.h>
|
|
#include <pixrect/pr_planegroups.h>
|
|
#include <pixrect/memvar.h>
|
|
#include <pixrect/cg3var.h>
|
|
|
|
addr_t kmem_zalloc();
|
|
addr_t map_regs();
|
|
void report_dev();
|
|
|
|
/* configuration options */
|
|
|
|
#ifndef OLDDEVSW
|
|
#define OLDDEVSW 1
|
|
#endif OLDDEVSW
|
|
|
|
#ifndef NOHWINIT
|
|
#define NOHWINIT 1
|
|
#endif NOHWINIT
|
|
|
|
#ifndef CG3DEBUG
|
|
#define CG3DEBUG 0
|
|
#endif CG3DEBUG
|
|
|
|
#if NOHWINIT
|
|
int cg3_hwinit = 1;
|
|
int cg3_type = 0; /* == 2 for small */
|
|
int cg3_on = 1; /* must be 1 to enable cg3 */
|
|
#endif NOHWINIT
|
|
|
|
#if CG3DEBUG
|
|
int cg3_debug = 0;
|
|
#define DEBUGF(level, args) _STMT(if (cg3_debug >= (level)) printf args;)
|
|
#else CG3DEBUG
|
|
#define DEBUGF(level, args) /* nothing */
|
|
#endif CG3DEBUG
|
|
|
|
#define CG3_CMAP_ENTRIES MFB_CMAP_ENTRIES
|
|
|
|
#if OLDDEVSW
|
|
#define STATIC /* nothing */
|
|
#define cg3_open cgthreeopen
|
|
#define cg3_close cgthreeclose
|
|
#define cg3_mmap cgthreemmap
|
|
#define cg3_ioctl cgthreeioctl
|
|
#else OLDDEVSW
|
|
#define STATIC static
|
|
#endif OLDDEVSW
|
|
|
|
/* config info */
|
|
static int cg3_identify();
|
|
static int cg3_attach();
|
|
STATIC int cg3_open();
|
|
STATIC int cg3_close();
|
|
STATIC int cg3_ioctl();
|
|
STATIC int cg3_mmap();
|
|
|
|
struct dev_ops cgthree_ops = {
|
|
0, /* revision */
|
|
cg3_identify,
|
|
cg3_attach,
|
|
cg3_open,
|
|
cg3_close,
|
|
0, 0, 0, 0, 0,
|
|
cg3_ioctl,
|
|
0,
|
|
cg3_mmap,
|
|
};
|
|
|
|
|
|
/* per-unit data */
|
|
struct cg3_softc {
|
|
struct mfb_reg *reg; /* video chip registers */
|
|
#if NWIN > 0
|
|
Pixrect pr; /* kernel pixrect */
|
|
struct mprp_data prd; /* pixrect private data */
|
|
#define _w pr.pr_size.x
|
|
#define _h pr.pr_size.y
|
|
#define _fb prd.mpr.md_image
|
|
#define _linebytes prd.mpr.md_linebytes
|
|
#else NWIN > 0
|
|
int _w, _h; /* resolution */
|
|
#endif NWIN > 0
|
|
int size; /* total size of frame buffer */
|
|
int dummysize; /* total size of overlay plane */
|
|
int basepage; /* page # for base address */
|
|
|
|
u_short cmap_index; /* colormap update index */
|
|
u_short cmap_count; /* colormap update count */
|
|
union { /* shadow color map */
|
|
u_long cmap_long[CG3_CMAP_ENTRIES * 3 / sizeof (u_long)];
|
|
u_char cmap_char[3][CG3_CMAP_ENTRIES];
|
|
} cmap_image;
|
|
#define cmap_rgb cmap_image.cmap_char[0]
|
|
};
|
|
|
|
static int ncg3;
|
|
static struct cg3_softc *cg3_softc;
|
|
|
|
|
|
/* default structure for FBIOGATTR ioctl */
|
|
static struct fbgattr cg3_attr = {
|
|
/* real_type owner */
|
|
FBTYPE_SUN3COLOR, 0,
|
|
/* fbtype: type h w depth cms size */
|
|
{ FBTYPE_SUN3COLOR, 0, 0, 8, 256, 0 },
|
|
/* fbsattr: flags emu_type dev_specific */
|
|
{ 0, FBTYPE_SUN4COLOR, { 0 } },
|
|
/* emu_types */
|
|
{ FBTYPE_SUN3COLOR, FBTYPE_SUN4COLOR, -1, -1}
|
|
};
|
|
|
|
|
|
/*
|
|
* handy macros
|
|
*/
|
|
|
|
#define getsoftc(unit) (&cg3_softc[unit])
|
|
|
|
#define btob(n) ctob(btoc(n)) /* XXX */
|
|
|
|
#define BCOPY(s, d, c) bcopy((caddr_t) (s), (caddr_t) (d), (u_int) (c))
|
|
#define COPYIN(s, d, c) copyin((caddr_t) (s), (caddr_t) (d), (u_int) (c))
|
|
#define COPYOUT(s, d, c) copyout((caddr_t) (s), (caddr_t) (d), (u_int) (c))
|
|
|
|
/* enable/disable interrupt */
|
|
#define cg3_int_enable(softc) mfb_int_enable((softc)->reg)
|
|
#define cg3_int_disable(softc) mfb_int_disable((softc)->reg)
|
|
|
|
/* check if color map update is pending */
|
|
#define cg3_update_pending(softc) ((softc)->cmap_count)
|
|
|
|
/*
|
|
* Compute color map update parameters: starting index and count.
|
|
* If count is already nonzero, adjust values as necessary.
|
|
*/
|
|
/* XXX why don't I just use a tmp var, or function??? */
|
|
#define cg3_update_cmap(softc, index, count) \
|
|
if ((softc)->cmap_count) { \
|
|
if ((index) + (count) > \
|
|
(softc)->cmap_count += (softc)->cmap_index) \
|
|
(softc)->cmap_count = (index) + (count); \
|
|
if ((index) < (softc)->cmap_index) \
|
|
(softc)->cmap_index = (index); \
|
|
(softc)->cmap_count -= (softc)->cmap_index; \
|
|
} \
|
|
else { \
|
|
(softc)->cmap_index = (index); \
|
|
(softc)->cmap_count = (count); \
|
|
} \
|
|
|
|
|
|
/*
|
|
* forward references
|
|
*/
|
|
static cg3_putcolormap();
|
|
static cg3_poll();
|
|
static void cg3_intr();
|
|
static void cg3_reset_cmap();
|
|
static void cg3_cmap_bcopy();
|
|
|
|
#if NWIN > 0
|
|
|
|
/*
|
|
* SunWindows specific stuff
|
|
*/
|
|
|
|
/* kernel pixrect ops vector */
|
|
static struct pixrectops cg3_pr_ops = {
|
|
mem_rop,
|
|
cg3_putcolormap,
|
|
mem_putattributes
|
|
};
|
|
|
|
/* XXX can I share code with ioctl? */
|
|
/* XXX vestigial overlay stuff */
|
|
static
|
|
cg3_putcolormap(pr, index, count, red, green, blue)
|
|
Pixrect *pr;
|
|
int index, count;
|
|
unsigned char *red, *green, *blue;
|
|
{
|
|
register struct cg3_softc *softc = getsoftc(mpr_d(pr)->md_primary);
|
|
register u_int rindex = (u_int) index;
|
|
register u_int rcount = (u_int) count;
|
|
register u_char *map;
|
|
register u_int entries;
|
|
|
|
DEBUGF(5, ("cg3_putcolormap unit=%d index=%d count=%d\n",
|
|
mpr_d(pr)->md_primary, index, count));
|
|
|
|
map = softc->cmap_rgb;
|
|
entries = CG3_CMAP_ENTRIES;
|
|
|
|
/* check arguments */
|
|
if (rindex >= entries ||
|
|
rindex + rcount > entries)
|
|
return (PIX_ERR);
|
|
|
|
if (rcount == 0)
|
|
return (0);
|
|
|
|
/* lock out updates of the hardware colormap */
|
|
if (cg3_update_pending(softc))
|
|
cg3_int_disable(softc);
|
|
|
|
map += rindex * 3;
|
|
cg3_cmap_bcopy(red, map, rcount);
|
|
cg3_cmap_bcopy(green, map + 1, rcount);
|
|
cg3_cmap_bcopy(blue, map + 2, rcount);
|
|
|
|
cg3_update_cmap(softc, rindex, rcount);
|
|
|
|
/* enable interrupt so we can load the hardware colormap */
|
|
cg3_int_enable(softc);
|
|
|
|
return (0);
|
|
}
|
|
|
|
#endif NWIN > 0
|
|
|
|
static
|
|
cg3_identify(name)
|
|
char *name;
|
|
{
|
|
DEBUGF(1, ("cg3_identify(%s)\n", name));
|
|
|
|
#if NOHWINIT
|
|
if (!cg3_on)
|
|
return (0);
|
|
#endif NOHWINIT
|
|
|
|
if (strcmp(name, "cgthree") == 0)
|
|
return (++ncg3);
|
|
else
|
|
return (0);
|
|
}
|
|
|
|
static
|
|
cg3_attach(devi)
|
|
struct dev_info *devi;
|
|
{
|
|
register struct cg3_softc *softc;
|
|
register addr_t reg;
|
|
int w, h, bytes, basepage;
|
|
static int unit=0;
|
|
extern struct dev_info *top_devinfo; /* in autoconf.c */
|
|
|
|
DEBUGF(1, ("cg3_attach ncg3=%d unit=%d\n", ncg3, unit));
|
|
|
|
/* Allocate softc structs on first attach */
|
|
if (!cg3_softc)
|
|
cg3_softc = (struct cg3_softc *)
|
|
kmem_zalloc((u_int) sizeof (struct cg3_softc) * ncg3);
|
|
|
|
softc = getsoftc(unit);
|
|
|
|
/* Grab properties from PROM */
|
|
softc->_w = w = getprop(devi->devi_nodeid, "width", 1152);
|
|
softc->_h = h = getprop(devi->devi_nodeid, "height", 900);
|
|
#if NOHWINIT
|
|
/* if properties are missing initialize the hardware */
|
|
if (getproplen(devi->devi_nodeid, "width") != sizeof (int)) {
|
|
if (!cg3_probe(devi, softc))
|
|
return (-1);
|
|
}
|
|
#endif NOHWINIT
|
|
bytes = getprop(devi->devi_nodeid, "linebytes", mpr_linebytes(w, 8));
|
|
#if NWIN > 0
|
|
softc->_linebytes = bytes;
|
|
#endif NWIN > 0
|
|
|
|
/* Compute size of color frame buffer */
|
|
softc->size = bytes = ptob(btopr(bytes * h));
|
|
|
|
/* Compute size of dummy overlay/enable planes */
|
|
softc->dummysize = ptob(btopr(mpr_linebytes(w, 1) * h)) * 2;
|
|
|
|
#if NWIN > 0
|
|
/* only use address property if we are console fb */
|
|
if (reg = (addr_t) getprop(devi->devi_nodeid, "address", 0)) {
|
|
int fbid = getprop(top_devinfo->devi_nodeid, "fb", -1);
|
|
if (fbid == devi->devi_nodeid) {
|
|
softc->_fb = (MPR_T *) reg;
|
|
bytes = 0;
|
|
DEBUGF(2, ("cg3 mapped by PROM\n"));
|
|
}
|
|
}
|
|
#else NWIN > 0
|
|
bytes = 0;
|
|
#endif NWIN > 0
|
|
|
|
/*
|
|
* Allocate virtual space for registers and maybe frame buffer.
|
|
* Map registers.
|
|
*/
|
|
if (!(reg = map_regs(devi->devi_reg[0].reg_addr + MFB_OFF_REG,
|
|
(u_int) bytes + NBPG,
|
|
devi->devi_reg[0].reg_bustype)))
|
|
return (-1);
|
|
|
|
softc->reg = (struct mfb_reg *) reg;
|
|
|
|
/* save base page # for registers */
|
|
softc->basepage = basepage = fbgetpage(reg);
|
|
|
|
DEBUGF(1, ("cg3_attach reg=0x%x/0x%x (0x%x)\n",
|
|
(u_int) reg,
|
|
basepage << PGSHIFT,
|
|
basepage));
|
|
|
|
#if NWIN > 0
|
|
/* map frame buffer if necessary */
|
|
if (bytes) {
|
|
fbmapin(reg + NBPG,
|
|
(int) (basepage + btop(MFB_OFF_FB - MFB_OFF_REG)),
|
|
bytes);
|
|
softc->_fb = (MPR_T *) (reg + NBPG);
|
|
}
|
|
|
|
DEBUGF(1, ("cg3_attach fb=0x%x/0x%x (0x%x)\n",
|
|
(u_int) softc->_fb,
|
|
fbgetpage((addr_t) softc->_fb) << PGSHIFT,
|
|
fbgetpage((addr_t) softc->_fb)));
|
|
#endif NWIN > 0
|
|
|
|
/* save unit number */
|
|
devi->devi_unit = unit;
|
|
|
|
/* attach interrupt */
|
|
addintr(devi->devi_intr[0].int_pri, cg3_poll, devi->devi_name, unit);
|
|
|
|
/* save back pointer to softc */
|
|
devi->devi_data = (addr_t) softc;
|
|
|
|
/*
|
|
* Initialize hardware colormap and software colormap images.
|
|
* It might make sense to read the hardware colormap here.
|
|
*/
|
|
cg3_reset_cmap(softc->cmap_rgb, CG3_CMAP_ENTRIES);
|
|
|
|
/* XXX wasteful macro */
|
|
cg3_update_cmap(softc, _ZERO_, CG3_CMAP_ENTRIES);
|
|
|
|
/* prepare for next attach */
|
|
unit++;
|
|
|
|
report_dev(devi);
|
|
|
|
return (0);
|
|
}
|
|
|
|
STATIC
|
|
cg3_open(dev, flag)
|
|
dev_t dev;
|
|
int flag;
|
|
{
|
|
DEBUGF(2, ("cg3_open(%d)\n", minor(dev)));
|
|
|
|
return (fbopen(dev, flag, ncg3));
|
|
}
|
|
|
|
/*ARGSUSED*/
|
|
STATIC
|
|
cg3_close(dev, flag)
|
|
dev_t dev;
|
|
int flag;
|
|
{
|
|
DEBUGF(2, ("cg3_close(%d)\n", minor(dev)));
|
|
|
|
/* disable cursor compare */
|
|
getsoftc(minor(dev))->reg->control &= ~MFB_CR_CURSOR;
|
|
|
|
return (0);
|
|
}
|
|
|
|
/*ARGSUSED*/
|
|
STATIC
|
|
cg3_mmap(dev, off, prot)
|
|
dev_t dev;
|
|
register off_t off;
|
|
int prot;
|
|
{
|
|
register struct cg3_softc *softc = getsoftc(minor(dev));
|
|
|
|
DEBUGF(off ? 9 : 1, ("cg3_mmap(%d, 0x%x)\n", minor(dev), (u_int) off));
|
|
|
|
if (off == MFB_REG_MMAP_OFFSET && suser())
|
|
off = 0;
|
|
else if (off >= CG3_MMAP_OFFSET) {
|
|
if ((off -= CG3_MMAP_OFFSET) >= softc->size)
|
|
return (-1);
|
|
off += MFB_OFF_FB - MFB_OFF_REG;
|
|
} else if ((u_int) off < softc->dummysize)
|
|
off = MFB_OFF_DUMMY - MFB_OFF_REG;
|
|
else if ((u_int) (off -= softc->dummysize) < softc->size)
|
|
off += MFB_OFF_FB - MFB_OFF_REG;
|
|
else
|
|
return (-1);
|
|
|
|
DEBUGF(off != MFB_OFF_FB - MFB_OFF_REG ? 9 : 1,
|
|
("cg3_mmap returning 0x%x (0x%x)\n",
|
|
ptob(softc->basepage) + off,
|
|
softc->basepage + btop(off)));
|
|
|
|
return (softc->basepage + btop(off));
|
|
}
|
|
|
|
/*ARGSUSED*/
|
|
STATIC
|
|
cg3_ioctl(dev, cmd, data, flag)
|
|
dev_t dev;
|
|
int cmd;
|
|
caddr_t data;
|
|
int flag;
|
|
{
|
|
register struct cg3_softc *softc = getsoftc(minor(dev));
|
|
|
|
DEBUGF(2, ("cg3_ioctl(%d, 0x%x)\n", minor(dev), cmd));
|
|
|
|
switch (cmd) {
|
|
|
|
case FBIOPUTCMAP:
|
|
case FBIOGETCMAP: {
|
|
register struct fbcmap *cmap = (struct fbcmap *) data;
|
|
register u_int index = (u_int) cmap->index;
|
|
register u_int count = (u_int) cmap->count;
|
|
register u_char *map;
|
|
register u_int entries;
|
|
static u_char cmbuf[CG3_CMAP_ENTRIES];
|
|
|
|
switch (PIX_ATTRGROUP(index)) {
|
|
case 0:
|
|
case PIXPG_8BIT_COLOR:
|
|
map = softc->cmap_rgb;
|
|
entries = CG3_CMAP_ENTRIES;
|
|
break;
|
|
default:
|
|
return (EINVAL);
|
|
}
|
|
|
|
if ((index &= PIX_ALL_PLANES) >= entries ||
|
|
index + count > entries)
|
|
return (EINVAL);
|
|
|
|
if (count == 0)
|
|
return (0);
|
|
|
|
if (cmd == FBIOPUTCMAP) {
|
|
register int error;
|
|
|
|
DEBUGF(2, ("FBIOPUTCMAP\n"));
|
|
if (cg3_update_pending(softc))
|
|
cg3_int_disable(softc);
|
|
|
|
map += index * 3;
|
|
|
|
if (error = COPYIN(cmap->red, cmbuf, count))
|
|
break;
|
|
cg3_cmap_bcopy(cmbuf, map++, count);
|
|
|
|
if (error = COPYIN(cmap->green, cmbuf, count))
|
|
break;
|
|
cg3_cmap_bcopy(cmbuf, map++, count);
|
|
|
|
if (error = COPYIN(cmap->blue, cmbuf, count))
|
|
break;
|
|
cg3_cmap_bcopy(cmbuf, map, count);
|
|
|
|
if (error) {
|
|
if (cg3_update_pending(softc))
|
|
cg3_int_enable(softc);
|
|
return (EFAULT);
|
|
}
|
|
|
|
cg3_update_cmap(softc, index, count);
|
|
cg3_int_enable(softc);
|
|
} else {
|
|
/* FBIOGETCMAP */
|
|
DEBUGF(2, ("FBIOGETCMAP\n"));
|
|
map += index * 3;
|
|
cg3_cmap_bcopy(cmbuf, map++, -count);
|
|
if (COPYOUT(cmbuf, cmap->red, count))
|
|
return (EFAULT);
|
|
|
|
cg3_cmap_bcopy(cmbuf, map++, -count);
|
|
if (COPYOUT(cmbuf, cmap->green, count))
|
|
return (EFAULT);
|
|
|
|
cg3_cmap_bcopy(cmbuf, map, -count);
|
|
if (COPYOUT(cmbuf, cmap->blue, count))
|
|
return (EFAULT);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case FBIOGATTR: {
|
|
register struct fbgattr *attr = (struct fbgattr *) data;
|
|
|
|
DEBUGF(2, ("FBIOGATTR\n"));
|
|
*attr = cg3_attr;
|
|
data = (caddr_t) &attr->fbtype;
|
|
}
|
|
/* fall through */
|
|
|
|
case FBIOGTYPE: {
|
|
register struct fbtype *fb = (struct fbtype *) data;
|
|
|
|
if (cmd == FBIOGTYPE) {
|
|
DEBUGF(2, ("FBIOGTYPE\n"));
|
|
*fb = cg3_attr.fbtype;
|
|
fb->fb_type = FBTYPE_SUN4COLOR;
|
|
}
|
|
fb->fb_width = softc->_w;
|
|
fb->fb_height = softc->_h;
|
|
/* XXX not quite like a cg4 */
|
|
fb->fb_size = softc->size;
|
|
}
|
|
break;
|
|
|
|
#if NWIN > 0
|
|
|
|
case FBIOGPIXRECT:
|
|
((struct fbpixrect *) data)->fbpr_pixrect = &softc->pr;
|
|
|
|
DEBUGF(2, ("FBIOGPIXRECT\n"));
|
|
/* initialize pixrect and private data */
|
|
softc->pr.pr_ops = &cg3_pr_ops;
|
|
/* pr_size set in attach */
|
|
softc->pr.pr_depth = 8;
|
|
softc->pr.pr_data = (caddr_t) &softc->prd;
|
|
|
|
/* md_linebytes, md_image set in attach */
|
|
/* md_offset already zero */
|
|
softc->prd.mpr.md_primary = minor(dev);
|
|
softc->prd.mpr.md_flags = MP_DISPLAY | MP_PLANEMASK;
|
|
softc->prd.planes = 255;
|
|
|
|
/* enable video */
|
|
mfb_set_video(softc->reg, _ONE_);
|
|
|
|
break;
|
|
|
|
#endif NWIN > 0
|
|
|
|
case FBIOSVIDEO:
|
|
DEBUGF(2, ("FBIOSVIDEO\n"));
|
|
mfb_set_video(softc->reg, * (int *) data & FBVIDEO_ON);
|
|
break;
|
|
|
|
case FBIOGVIDEO:
|
|
DEBUGF(2, ("FBIOGVIDEO\n"));
|
|
* (int *) data =
|
|
mfb_get_video(softc->reg) ? FBVIDEO_ON : FBVIDEO_OFF;
|
|
break;
|
|
|
|
default:
|
|
return (ENOTTY);
|
|
|
|
} /* switch (cmd) */
|
|
|
|
return (0);
|
|
}
|
|
|
|
static
|
|
cg3_poll()
|
|
{
|
|
register int i, serviced = 0;
|
|
register struct cg3_softc *softc;
|
|
|
|
/*
|
|
* Look for any frame buffers that were expecting an interrupt.
|
|
*/
|
|
|
|
DEBUGF(7, ("cg3_poll\n"));
|
|
for (softc = cg3_softc, i = ncg3; --i >= 0; softc++)
|
|
if (mfb_int_pending(softc->reg)) {
|
|
if (cg3_update_pending(softc))
|
|
cg3_intr(softc);
|
|
else
|
|
/* XXX catch stray interrupts? */
|
|
cg3_int_disable(softc);
|
|
serviced++;
|
|
}
|
|
|
|
return (serviced);
|
|
}
|
|
|
|
static void
|
|
cg3_intr(softc)
|
|
register struct cg3_softc *softc;
|
|
{
|
|
register struct mfb_cmap *cmap = &softc->reg->cmap;
|
|
register LOOP_T index = softc->cmap_index;
|
|
register LOOP_T count = softc->cmap_count;
|
|
register u_long *in = &softc->cmap_image.cmap_long[0];
|
|
register u_long *out = (u_long *) &cmap->cmap;
|
|
|
|
DEBUGF(7, ("cg3_intr(%d)\n", softc - cg3_softc));
|
|
|
|
/* count multiples of 4 RGB entries */
|
|
count = (count + (index & 3) + 3) >> 2;
|
|
|
|
/* round index to 4 entry boundary */
|
|
index &= ~3;
|
|
|
|
cmap->addr = index;
|
|
PTR_INCR(u_long *, in, index * 3);
|
|
|
|
/* copy 12 bytes (4 RGB entries) per loop iteration */
|
|
PR_LOOPV(count,
|
|
*out = in[0];
|
|
*out = in[1];
|
|
*out = in[2];
|
|
in += 3);
|
|
|
|
softc->cmap_count = 0;
|
|
cg3_int_disable(softc);
|
|
}
|
|
|
|
/*
|
|
* Initialize a colormap: background = white, all others = black
|
|
*/
|
|
static void
|
|
cg3_reset_cmap(cmap, entries)
|
|
register u_char *cmap;
|
|
register u_int entries;
|
|
{
|
|
bzero((char *) cmap, entries * 3);
|
|
cmap[0] = 255;
|
|
cmap[1] = 255;
|
|
cmap[2] = 255;
|
|
}
|
|
|
|
/*
|
|
* Copy colormap entries between red, green, or blue array and
|
|
* interspersed rgb array.
|
|
*
|
|
* count > 0 : copy count bytes from buf to rgb
|
|
* count < 0 : copy -count bytes from rgb to buf
|
|
*/
|
|
static void
|
|
cg3_cmap_bcopy(bufp, rgb, count)
|
|
register u_char *bufp, *rgb;
|
|
u_int count;
|
|
{
|
|
register LOOP_T rcount = count;
|
|
|
|
if (--rcount >= 0)
|
|
PR_LOOPVP(rcount,
|
|
*rgb = *bufp++;
|
|
rgb += 3);
|
|
else {
|
|
rcount = -rcount - 2;
|
|
PR_LOOPVP(rcount,
|
|
*bufp++ = *rgb;
|
|
rgb += 3);
|
|
}
|
|
}
|
|
|
|
#if NOHWINIT
|
|
static int
|
|
cg3_probe(devi, softc)
|
|
struct dev_info *devi;
|
|
struct cg3_softc *softc;
|
|
{
|
|
struct mfb_reg *mfb;
|
|
int stat, monitor_type, retval = 0;
|
|
void unmap_regs();
|
|
|
|
if (!(mfb = (struct mfb_reg *)
|
|
map_regs(devi->devi_reg[0].reg_addr + MFB_OFF_REG,
|
|
(u_int) NBPG,
|
|
devi->devi_reg[0].reg_bustype)))
|
|
goto bad;
|
|
|
|
if ((stat = peekc((char *)&mfb->status)) == -1)
|
|
goto bad;
|
|
|
|
/* New sense codes for CG3 FB 501-1718 (prom 1.4) */
|
|
#define MFB_SR_1152_900_76HZ_A 0x40 /* 76Hz monitor sense codes */
|
|
#define MFB_SR_1152_900_76HZ_B 0x60
|
|
|
|
monitor_type = stat & MFB_SR_RES_MASK;
|
|
|
|
switch (stat & MFB_SR_ID_MASK) {
|
|
case MFB_SR_ID_COLOR:
|
|
if ((monitor_type == MFB_SR_1152_900_76HZ_A) ||
|
|
(monitor_type == MFB_SR_1152_900_76HZ_B))
|
|
cg3_type = 1;
|
|
break;
|
|
default:
|
|
DEBUGF(1, ("cg3_hwinit bad type SR=0x%x\n", (u_int) stat));
|
|
goto bad;
|
|
}
|
|
|
|
if (cg3_type == 2) {
|
|
softc->_w = 640;
|
|
softc->_h = 480;
|
|
}
|
|
|
|
if (cg3_hwinit)
|
|
cg3_init(mfb);
|
|
|
|
DEBUGF(1, ("cg3_hwinit type=%d (%d,%d)\n",
|
|
cg3_type, softc->_w, softc->_h));
|
|
|
|
retval = 1;
|
|
bad:
|
|
if (!retval) {
|
|
DEBUGF(2, ("cg3_probe failed\n"));
|
|
}
|
|
unmap_regs((addr_t) mfb, (u_int) NBPG);
|
|
return (retval);
|
|
}
|
|
|
|
/* 66 Hz */
|
|
char cg3_mfbval0[] = {
|
|
0x14, 0xbb,
|
|
0x15, 0x2b,
|
|
0x16, 0x04,
|
|
0x17, 0x14,
|
|
0x18, 0xae,
|
|
0x19, 0x03,
|
|
0x1a, 0xa8,
|
|
0x1b, 0x24,
|
|
0x1c, 0x01,
|
|
0x1d, 0x05,
|
|
0x1e, 0xff,
|
|
0x1f, 0x01,
|
|
0x10, 0x20,
|
|
0
|
|
};
|
|
/* 76 Hz */
|
|
char cg3_mfbval1[] = {
|
|
0x14, 0xb7,
|
|
0x15, 0x27,
|
|
0x16, 0x03,
|
|
0x17, 0x0f,
|
|
0x18, 0xae,
|
|
0x19, 0x03,
|
|
0x1a, 0xae,
|
|
0x1b, 0x2a,
|
|
0x1c, 0x01,
|
|
0x1d, 0x09,
|
|
0x1e, 0xff,
|
|
0x1f, 0x01,
|
|
0x10, 0x24,
|
|
0
|
|
};
|
|
char cg3_mfbval2[] = {
|
|
0x14, 0x70,
|
|
0x15, 0x20,
|
|
0x16, 0x08,
|
|
0x17, 0x10,
|
|
0x18, 0x06,
|
|
0x19, 0x02,
|
|
0x1a, 0x31,
|
|
0x1b, 0x51,
|
|
0x1c, 0x06,
|
|
0x1d, 0x0c,
|
|
0x1e, 0xff,
|
|
0x1f, 0x01,
|
|
0x10, 0x22,
|
|
0
|
|
};
|
|
static char *mfbvals[] = {
|
|
cg3_mfbval0,
|
|
cg3_mfbval1,
|
|
cg3_mfbval2,
|
|
};
|
|
|
|
static
|
|
cg3_init(mfb)
|
|
struct mfb_reg *mfb;
|
|
{
|
|
static char dacval[] = {
|
|
4, 0xff,
|
|
5, 0,
|
|
6, 0x70,
|
|
7, 0,
|
|
0
|
|
};
|
|
|
|
register char *p;
|
|
|
|
/* initialize video chip */
|
|
for (p = mfbvals[cg3_type]; *p; p += 2)
|
|
((char *) mfb)[p[0]] = p[1];
|
|
|
|
/* initialize DAC */
|
|
for (p = dacval; *p; p += 2) {
|
|
mfb->cmap.addr = p[0];
|
|
mfb->cmap.ctrl = p[1];
|
|
}
|
|
|
|
}
|
|
#endif NOHWINIT
|