PR/32552: Antonio Bravo: cgfourteen 24-bit support

Original code from der Mouse, posted to the mailing lists by Jakob Menzi.
This commit is contained in:
christos 2006-01-17 04:22:08 +00:00
parent 589b108660
commit d07104a9ce
3 changed files with 190 additions and 329 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: cgfourteen.c,v 1.41 2005/12/11 12:19:05 christos Exp $ */ /* $NetBSD: cgfourteen.c,v 1.42 2006/01/17 04:22:08 christos Exp $ */
/* /*
* Copyright (c) 1996 * Copyright (c) 1996
@ -66,19 +66,14 @@
* enabled by allowing any user to map the control registers for the * enabled by allowing any user to map the control registers for the
* cg14 into their space. * cg14 into their space.
*/ */
#undef CG14_MAP_REGS #define CG14_MAP_REGS
/* /*
* The following enables 24-bit operation: when opened, the framebuffer * The following enables 24-bit operation: when opened, the framebuffer
* will switch to 24-bit mode (actually 32-bit mode), and provide a * will switch to 24-bit mode (actually 32-bit mode), and provide a
* simple cg8 emulation. * simple cg8 emulation.
*
* XXX Note that the code enabled by this define is currently untested/broken.
*/ */
#undef CG14_CG8 #define CG14_CG8
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: cgfourteen.c,v 1.41 2005/12/11 12:19:05 christos Exp $");
#include <sys/param.h> #include <sys/param.h>
#include <sys/systm.h> #include <sys/systm.h>
@ -92,13 +87,12 @@ __KERNEL_RCSID(0, "$NetBSD: cgfourteen.c,v 1.41 2005/12/11 12:19:05 christos Exp
#include <uvm/uvm_extern.h> #include <uvm/uvm_extern.h>
#include <machine/bus.h>
#include <machine/autoconf.h>
#include <dev/sbus/sbusvar.h>
#include <dev/sun/fbio.h> #include <dev/sun/fbio.h>
#include <machine/autoconf.h>
#include <machine/pmap.h>
#include <dev/sun/fbvar.h> #include <dev/sun/fbvar.h>
#include <machine/cpu.h>
#include <dev/sbus/sbusvar.h>
#include <sparc/dev/cgfourteenreg.h> #include <sparc/dev/cgfourteenreg.h>
#include <sparc/dev/cgfourteenvar.h> #include <sparc/dev/cgfourteenvar.h>
@ -110,25 +104,28 @@ static void cgfourteenunblank(struct device *);
CFATTACH_DECL(cgfourteen, sizeof(struct cgfourteen_softc), CFATTACH_DECL(cgfourteen, sizeof(struct cgfourteen_softc),
cgfourteenmatch, cgfourteenattach, NULL, NULL); cgfourteenmatch, cgfourteenattach, NULL, NULL);
extern struct cfdriver cgfourteen_cd; extern struct cfdriver cgfourteen_cd;
dev_type_open(cgfourteenopen); dev_type_open(cgfourteenopen);
dev_type_close(cgfourteenclose); dev_type_close(cgfourteenclose);
dev_type_ioctl(cgfourteenioctl); dev_type_ioctl(cgfourteenioctl);
dev_type_mmap(cgfourteenmmap); dev_type_mmap(cgfourteenmmap);
dev_type_poll(cgfourteenpoll);
const struct cdevsw cgfourteen_cdevsw = { const struct cdevsw cgfourteen_cdevsw = {
cgfourteenopen, cgfourteenclose, noread, nowrite, cgfourteenioctl, cgfourteenopen, cgfourteenclose, noread, nowrite, cgfourteenioctl,
nostop, notty, nopoll, cgfourteenmmap, nokqfilter, nostop, notty, cgfourteenpoll, cgfourteenmmap, nokqfilter,
}; };
/* frame buffer generic driver */ /* frame buffer generic driver */
static struct fbdriver cgfourteenfbdriver = { static struct fbdriver cgfourteenfbdriver = {
cgfourteenunblank, cgfourteenopen, cgfourteenclose, cgfourteenioctl, cgfourteenunblank, cgfourteenopen, cgfourteenclose, cgfourteenioctl,
nopoll, cgfourteenmmap, nokqfilter cgfourteenpoll, cgfourteenmmap, nokqfilter
}; };
extern struct tty *fbconstty;
static void cg14_set_video(struct cgfourteen_softc *, int); static void cg14_set_video(struct cgfourteen_softc *, int);
static int cg14_get_video(struct cgfourteen_softc *); static int cg14_get_video(struct cgfourteen_softc *);
static int cg14_get_cmap(struct fbcmap *, union cg14cmap *, int); static int cg14_get_cmap(struct fbcmap *, union cg14cmap *, int);
@ -136,24 +133,11 @@ static int cg14_put_cmap(struct fbcmap *, union cg14cmap *, int);
static void cg14_load_hwcmap(struct cgfourteen_softc *, int, int); static void cg14_load_hwcmap(struct cgfourteen_softc *, int, int);
static void cg14_init(struct cgfourteen_softc *); static void cg14_init(struct cgfourteen_softc *);
static void cg14_reset(struct cgfourteen_softc *); static void cg14_reset(struct cgfourteen_softc *);
static void cg14_loadomap(struct cgfourteen_softc *); /* cursor overlay */
static void cg14_setcursor(struct cgfourteen_softc *); /* set position */
static void cg14_loadcursor(struct cgfourteen_softc *); /* set shape */
/*
* We map the display memory with an offset of 256K when emulating the cg3 or
* cg8; the cg3 uses this offset for compatibility with the cg4, and both the
* cg4 and cg8 have a mono overlay plane and an overlay enable plane in the
* first 256K. Mapping at an offset of 0x04000000 causes only the color
* frame buffer to be mapped, without the overlay planes.
*/
#define START (128*1024 + 128*1024)
#define NOOVERLAY (0x04000000)
/* /*
* Match a cgfourteen. * Match a cgfourteen.
*/ */
static int int
cgfourteenmatch(struct device *parent, struct cfdata *cf, void *aux) cgfourteenmatch(struct device *parent, struct cfdata *cf, void *aux)
{ {
union obio_attach_args *uoba = aux; union obio_attach_args *uoba = aux;
@ -173,10 +157,28 @@ cgfourteenmatch(struct device *parent, struct cfdata *cf, void *aux)
return (strcmp(cf->cf_name, sa->sa_name) == 0); return (strcmp(cf->cf_name, sa->sa_name) == 0);
} }
/*
* Set COLOUR_OFFSET to the offset of the video RAM. This is to provide
* space for faked overlay junk for the cg8 emulation.
*
* As it happens, this value is correct for both cg3 and cg8 emulation!
*/
#define COLOUR_OFFSET (256*1024)
static void cg14_set_rcons_luts(struct cgfourteen_softc *sc)
{
int i;
for (i=0;i<CG14_CLUT_SIZE;i++) sc->sc_xlut->xlut_lut[i] = 0x22;
for (i=0;i<CG14_CLUT_SIZE;i++) sc->sc_clut2->clut_lut[i] = 0x00ffffff;
sc->sc_clut2->clut_lut[0] = 0x00ffffff;
sc->sc_clut2->clut_lut[255] = 0;
}
/* /*
* Attach a display. We need to notice if it is the console, too. * Attach a display. We need to notice if it is the console, too.
*/ */
static void void
cgfourteenattach(struct device *parent, struct device *self, void *aux) cgfourteenattach(struct device *parent, struct device *self, void *aux)
{ {
union obio_attach_args *uoba = aux; union obio_attach_args *uoba = aux;
@ -204,29 +206,16 @@ cgfourteenattach(struct device *parent, struct device *self, void *aux)
#ifdef CG14_CG8 #ifdef CG14_CG8
fb->fb_type.fb_type = FBTYPE_MEMCOLOR; fb->fb_type.fb_type = FBTYPE_MEMCOLOR;
fb->fb_type.fb_depth = 32; fb->fb_type.fb_depth = 32;
fb_setsize_obp(fb, sc->sc_fb.fb_type.fb_depth, 1152, 900, node);
ramsize = roundup(fb->fb_type.fb_height * 1152 * 4, NBPG);
#else #else
fb->fb_type.fb_type = FBTYPE_SUN3COLOR; fb->fb_type.fb_type = FBTYPE_SUN3COLOR;
fb->fb_type.fb_depth = 8; fb->fb_type.fb_depth = 8;
#endif
fb_setsize_obp(fb, sc->sc_fb.fb_type.fb_depth, 1152, 900, node); fb_setsize_obp(fb, sc->sc_fb.fb_type.fb_depth, 1152, 900, node);
#ifdef CG14_CG8 ramsize = roundup(fb->fb_type.fb_height * fb->fb_linebytes, NBPG);
/*
* fb_setsize_obp set fb->fb_linebytes based on the current
* depth reported by obp, but that defaults to 8 bits (as
* reported by getpropint(). Update the value to reflect
* the depth that will be used after open.
* The display memory size returned by the cg8 driver includes
* the space used by the overlay planes, but the size returned
* by the cg3 driver does not; emulate the other drivers.
*/
fb->fb_linebytes = (fb->fb_type.fb_width * fb->fb_type.fb_depth) / 8;
ramsize = roundup(START + (fb->fb_type.fb_height * fb->fb_linebytes),
PAGE_SIZE);
#else
ramsize = roundup(fb->fb_type.fb_height * fb->fb_linebytes, PAGE_SIZE);
#endif #endif
fb->fb_type.fb_cmsize = CG14_CLUT_SIZE; fb->fb_type.fb_cmsize = CG14_CLUT_SIZE;
fb->fb_type.fb_size = ramsize; fb->fb_type.fb_size = ramsize + COLOUR_OFFSET;
if (sa->sa_nreg < 2) { if (sa->sa_nreg < 2) {
printf("%s: only %d register sets\n", printf("%s: only %d register sets\n",
@ -234,7 +223,7 @@ cgfourteenattach(struct device *parent, struct device *self, void *aux)
return; return;
} }
bcopy(sa->sa_reg, sc->sc_physadr, bcopy(sa->sa_reg, sc->sc_physadr,
sa->sa_nreg * sizeof(struct openprom_addr)); sa->sa_nreg * sizeof(struct sbus_reg));
/* /*
* Now map in the 8 useful pages of registers * Now map in the 8 useful pages of registers
@ -245,9 +234,11 @@ cgfourteenattach(struct device *parent, struct device *self, void *aux)
#endif #endif
sa->sa_size = 0x10000; sa->sa_size = 0x10000;
} }
if (sbus_bus_map(sa->sa_bustag, if (sbus_bus_map(sa->sa_bustag, sa->sa_slot,
sa->sa_slot, sa->sa_offset, sa->sa_size, sa->sa_offset,
BUS_SPACE_MAP_LINEAR, &bh) != 0) { sa->sa_size,
BUS_SPACE_MAP_LINEAR,
&bh) != 0) {
printf("%s: cannot map control registers\n", self->dv_xname); printf("%s: cannot map control registers\n", self->dv_xname);
return; return;
} }
@ -272,7 +263,7 @@ cgfourteenattach(struct device *parent, struct device *self, void *aux)
fb->fb_type.fb_width, fb->fb_type.fb_height); fb->fb_type.fb_width, fb->fb_type.fb_height);
#endif #endif
/* /*
* Enable the video, but don't change the pixel depth. * Enable the video.
*/ */
cg14_set_video(sc, 1); cg14_set_video(sc, 1);
@ -284,19 +275,32 @@ cgfourteenattach(struct device *parent, struct device *self, void *aux)
sc->sc_cmap.cm_chip[i] = lut[i]; sc->sc_cmap.cm_chip[i] = lut[i];
/* See if we're the console */ /* See if we're the console */
isconsole = fb_is_console(node); isconsole = fb_is_console(node);
if (isconsole) { if (isconsole) {
printf(" (console)\n"); printf(" (console)\n");
#ifdef notdef
/*
* We don't use the raster console since the cg14 is
* fast enough already.
*/
#ifdef RASTERCONSOLE #ifdef RASTERCONSOLE
fbrcons_init(fb); /* *sbus*_bus_map? but that's how we map the regs... */
if (sbus_bus_map( sc->sc_bustag,
sc->sc_physadr[CG14_PXL_IDX].sbr_slot,
sc->sc_physadr[CG14_PXL_IDX].sbr_offset+0x03800000,
1152*900, BUS_SPACE_MAP_LINEAR,
&bh) != 0) {
printf("%s: cannot map pixels\n",&sc->sc_dev.dv_xname[0]);
} else {
sc->sc_rcfb = sc->sc_fb;
sc->sc_rcfb.fb_type.fb_type = FBTYPE_SUN3COLOR;
sc->sc_rcfb.fb_type.fb_depth = 8;
sc->sc_rcfb.fb_linebytes = 1152;
sc->sc_rcfb.fb_type.fb_size = roundup(1152*900,NBPG);
sc->sc_rcfb.fb_pixels = (void *)bh;
printf("vram at %p\n",(void *)bh);
for (i=0;i<1152*900;i++) ((unsigned char *)bh)[i] = 0;
fbrcons_init(&sc->sc_rcfb);
cg14_set_rcons_luts(sc);
sc->sc_ctl->ctl_mctl = CG14_MCTL_ENABLEVID | CG14_MCTL_PIXMODE_32 | CG14_MCTL_POWERCTL;
}
#endif #endif
#endif /* notdef */
} else } else
printf("\n"); printf("\n");
@ -315,14 +319,16 @@ static int cg14_opens = 0;
int int
cgfourteenopen(dev_t dev, int flags, int mode, struct lwp *l) cgfourteenopen(dev_t dev, int flags, int mode, struct lwp *l)
{ {
struct cgfourteen_softc *sc = cgfourteen_cd.cd_devs[minor(dev)]; struct cgfourteen_softc *sc;
int unit = minor(dev); int unit;
int s, oldopens; int s, oldopens;
if (unit >= cgfourteen_cd.cd_ndevs || unit = minor(dev);
cgfourteen_cd.cd_devs[unit] == NULL) if (unit >= cgfourteen_cd.cd_ndevs)
return (ENXIO); return(ENXIO);
sc = cgfourteen_cd.cd_devs[minor(dev)];
if (sc == NULL)
return(ENXIO);
s = splhigh(); s = splhigh();
oldopens = cg14_opens++; oldopens = cg14_opens++;
splx(s); splx(s);
@ -360,10 +366,7 @@ cgfourteenioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct lwp *l)
{ {
struct cgfourteen_softc *sc = cgfourteen_cd.cd_devs[minor(dev)]; struct cgfourteen_softc *sc = cgfourteen_cd.cd_devs[minor(dev)];
struct fbgattr *fba; struct fbgattr *fba;
union cg14cursor_cmap tcm; int error;
int v, error;
u_int count;
u_int eplane[32], cplane[32];
switch (cmd) { switch (cmd) {
@ -384,7 +387,7 @@ cgfourteenioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct lwp *l)
break; break;
case FBIOGETCMAP: case FBIOGETCMAP:
return (cg14_get_cmap((struct fbcmap *)data, &sc->sc_cmap, return(cg14_get_cmap((struct fbcmap *)data, &sc->sc_cmap,
CG14_CLUT_SIZE)); CG14_CLUT_SIZE));
case FBIOPUTCMAP: case FBIOPUTCMAP:
@ -410,112 +413,6 @@ cgfourteenioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct lwp *l)
cg14_set_video(sc, *(int *)data); cg14_set_video(sc, *(int *)data);
break; break;
/* these are for both FBIOSCURSOR and FBIOGCURSOR */
#define p ((struct fbcursor *)data)
#define cc (&sc->sc_cursor)
case FBIOGCURSOR:
/* do not quite want everything here... */
p->set = FB_CUR_SETALL; /* close enough, anyway */
p->enable = cc->cc_enable;
p->pos = cc->cc_pos;
p->hot = cc->cc_hot;
p->size = cc->cc_size;
/* begin ugh ... can we lose some of this crap?? */
if (p->image != NULL) {
count = cc->cc_size.y * 32 / NBBY;
error = copyout(cc->cc_cplane, p->image, count);
if (error)
return (error);
error = copyout(cc->cc_eplane, p->mask, count);
if (error)
return (error);
}
if (p->cmap.red != NULL) {
error = cg14_get_cmap(&p->cmap,
(union cg14cmap *)&cc->cc_color, 2);
if (error)
return (error);
} else {
p->cmap.index = 0;
p->cmap.count = 2;
}
/* end ugh */
break;
case FBIOSCURSOR:
/*
* For setcmap and setshape, verify parameters, so that
* we do not get halfway through an update and then crap
* out with the software state screwed up.
*/
v = p->set;
if (v & FB_CUR_SETCMAP) {
/*
* This use of a temporary copy of the cursor
* colormap is not terribly efficient, but these
* copies are small (8 bytes)...
*/
tcm = cc->cc_color;
error = cg14_put_cmap(&p->cmap, (union cg14cmap *)&tcm,
2);
if (error)
return (error);
}
if (v & FB_CUR_SETSHAPE) {
if ((u_int)p->size.x > 32 || (u_int)p->size.y > 32)
return (EINVAL);
count = p->size.y * 32 / NBBY;
error = copyin(p->mask, eplane, count);
if (error)
return error;
error = copyin(p->image, cplane, count);
if (error)
return error;
}
/* parameters are OK; do it */
if (v & (FB_CUR_SETCUR | FB_CUR_SETPOS | FB_CUR_SETHOT)) {
if (v & FB_CUR_SETCUR)
cc->cc_enable = p->enable;
if (v & FB_CUR_SETPOS)
cc->cc_pos = p->pos;
if (v & FB_CUR_SETHOT)
cc->cc_hot = p->hot;
cg14_setcursor(sc);
}
if (v & FB_CUR_SETCMAP) {
cc->cc_color = tcm;
cg14_loadomap(sc); /* XXX defer to vertical retrace */
}
if (v & FB_CUR_SETSHAPE) {
cc->cc_size = p->size;
count = p->size.y * 32 / NBBY;
memset(cc->cc_eplane, 0, sizeof cc->cc_eplane);
memcpy(cc->cc_eplane, eplane, count);
memset(cc->cc_cplane, 0, sizeof cc->cc_cplane);
memcpy(cc->cc_cplane, cplane, count);
cg14_loadcursor(sc);
}
break;
#undef cc
#undef p
case FBIOGCURPOS:
*(struct fbcurpos *)data = sc->sc_cursor.cc_pos;
break;
case FBIOSCURPOS:
sc->sc_cursor.cc_pos = *(struct fbcurpos *)data;
cg14_setcursor(sc);
break;
case FBIOGCURMAX:
/* max cursor size is 32x32 */
((struct fbcurpos *)data)->x = 32;
((struct fbcurpos *)data)->y = 32;
break;
default: default:
return (ENOTTY); return (ENOTTY);
} }
@ -536,17 +433,27 @@ cgfourteenunblank(struct device *dev)
* Return the address that would map the given device at the given * Return the address that would map the given device at the given
* offset, allowing for the given protection, or return -1 for error. * offset, allowing for the given protection, or return -1 for error.
* *
* The cg14 frame buffer can be mapped in either 8-bit or 32-bit mode * Since we're pretending to be a cg8, we put the main video RAM at the
* starting at the address stored in the PROM. In 8-bit mode, the X * same place the cg8 does, at offset 256k. The cg8 has an enable
* channel is not present, and can be ignored. In 32-bit mode, mapping * plane in the 256k space; our "enable" plane works differently. We
* at 0K delivers a 32-bpp buffer where the upper 8 bits select the X * can't emulate the enable plane very well, but all X uses it for is
* channel information. We hardwire the Xlut to all zeroes to insure * to clear it at startup - so we map the first page of video RAM over
* that, regardless of this value, direct 24-bit color access will be * and over to fill that 256k space. We also map some other views of
* used. * the video RAM space.
* *
* Alternatively, mapping the frame buffer at an offset of 16M seems to * Our memory map thus looks like
* tell the chip to ignore the X channel. XXX where does it get the X value *
* to use? * mmap range space base offset
* 00000000-00040000 vram 0 (multi-mapped - see above)
* 00040000-00434800 vram 00000000
* 01000000-01400000 vram 01000000
* 02000000-02200000 vram 02000000
* 02800000-02a00000 vram 02800000
* 03000000-03100000 vram 03000000
* 03400000-03500000 vram 03400000
* 03800000-03900000 vram 03800000
* 03c00000-03d00000 vram 03c00000
* 10000000-10010000 regs 00000000 (only if CG14_MAP_REGS)
*/ */
paddr_t paddr_t
cgfourteenmmap(dev_t dev, off_t off, int prot) cgfourteenmmap(dev_t dev, off_t off, int prot)
@ -559,50 +466,52 @@ cgfourteenmmap(dev_t dev, off_t off, int prot)
if (off < 0) if (off < 0)
return (-1); return (-1);
#if defined(DEBUG) && defined(CG14_MAP_REGS) /* XXX: security hole */ #if defined(CG14_MAP_REGS) /* XXX: security hole */
/* /*
* Map the control registers into user space. Should only be * Map the control registers into user space. Should only be
* used for debugging! * used for debugging!
*/ */
if ((u_int)off >= 0x10000000 && (u_int)off < 0x10000000 + 16*4096) { if ((u_int)off >= 0x10000000 && (u_int)off < 0x10000000 + 16*4096) {
off -= 0x10000000; off -= 0x10000000;
if (bus_space_mmap(sc->sc_bustag, return (bus_space_mmap(sc->sc_bustag,
BUS_ADDR(sc->sc_physadr[CG14_CTL_IDX].sbr_slot, BUS_ADDR(sc->sc_physadr[CG14_CTL_IDX].sbr_slot,
sc->sc_physadr[CG14_CTL_IDX].sbr_offset), sc->sc_physadr[CG14_CTL_IDX].sbr_offset),
off, prot, BUS_SPACE_MAP_LINEAR)); off, prot, BUS_SPACE_MAP_LINEAR));
} }
#endif #endif
if ((u_int)off >= NOOVERLAY) if (off < COLOUR_OFFSET)
off -= NOOVERLAY;
else if ((u_int)off >= START)
off -= START;
else
off = 0; off = 0;
else if (off < COLOUR_OFFSET+(1152*900*4))
/* off -= COLOUR_OFFSET;
* fb_size includes the overlay space only for the CG8. else {
*/ switch (off >> 20) {
#ifdef CG14_CG8 case 0x010: case 0x011: case 0x012: case 0x013:
if (off >= sc->sc_fb.fb_type.fb_size - START) case 0x020: case 0x021:
#else case 0x028: case 0x029:
if (off >= sc->sc_fb.fb_type.fb_size) case 0x030:
#endif case 0x034:
{ case 0x038:
#ifdef DEBUG case 0x03c:
printf("\nmmap request out of bounds: request 0x%x, " break;
"bound 0x%x\n", (unsigned) off, default:
(unsigned)sc->sc_fb.fb_type.fb_size); return(-1);
#endif }
return (-1);
} }
return (bus_space_mmap(sc->sc_bustag, return (bus_space_mmap(sc->sc_bustag,
BUS_ADDR(sc->sc_physadr[CG14_PXL_IDX].oa_space, BUS_ADDR(sc->sc_physadr[CG14_PXL_IDX].sbr_slot,
sc->sc_physadr[CG14_PXL_IDX].oa_base), sc->sc_physadr[CG14_PXL_IDX].sbr_offset),
off, prot, BUS_SPACE_MAP_LINEAR)); off, prot, BUS_SPACE_MAP_LINEAR));
} }
int
cgfourteenpoll(dev_t dev, int events, struct lwp *l)
{
return (seltrue(dev, events, l));
}
/* /*
* Miscellaneous helper functions * Miscellaneous helper functions
*/ */
@ -611,8 +520,8 @@ cgfourteenmmap(dev_t dev, off_t off, int prot)
static void static void
cg14_init(struct cgfourteen_softc *sc) cg14_init(struct cgfourteen_softc *sc)
{ {
volatile uint32_t *clut; u_int32_t *clut;
volatile uint8_t *xlut; u_int8_t *xlut;
int i; int i;
/* /*
@ -626,8 +535,8 @@ cg14_init(struct cgfourteen_softc *sc)
sc->sc_savectl = sc->sc_ctl->ctl_mctl; sc->sc_savectl = sc->sc_ctl->ctl_mctl;
sc->sc_savehwc = sc->sc_hwc->curs_ctl; sc->sc_savehwc = sc->sc_hwc->curs_ctl;
clut = sc->sc_clut1->clut_lut; clut = (u_int32_t *) sc->sc_clut1->clut_lut;
xlut = sc->sc_xlut->xlut_lut; xlut = (u_int8_t *) sc->sc_xlut->xlut_lut;
for (i = 0; i < CG14_CLUT_SIZE; i++) { for (i = 0; i < CG14_CLUT_SIZE; i++) {
sc->sc_saveclut.cm_chip[i] = clut[i]; sc->sc_saveclut.cm_chip[i] = clut[i];
sc->sc_savexlut[i] = xlut[i]; sc->sc_savexlut[i] = xlut[i];
@ -643,7 +552,8 @@ cg14_init(struct cgfourteen_softc *sc)
/* /*
* Zero the xlut to enable direct-color mode * Zero the xlut to enable direct-color mode
*/ */
memset(sc->sc_xlut, 0, CG14_CLUT_SIZE); for (i = 0; i < CG14_CLUT_SIZE; i++)
sc->sc_xlut->xlut_lut[i] = 0;
#else #else
/* /*
* Enable the video and put it in 8 bit mode * Enable the video and put it in 8 bit mode
@ -653,8 +563,8 @@ cg14_init(struct cgfourteen_softc *sc)
#endif #endif
} }
/* Restore the state saved on cg14_init */
static void static void
/* Restore the state saved on cg14_init */
cg14_reset(struct cgfourteen_softc *sc) cg14_reset(struct cgfourteen_softc *sc)
{ {
volatile uint32_t *clut; volatile uint32_t *clut;
@ -690,7 +600,6 @@ cg14_reset(struct cgfourteen_softc *sc)
static void static void
cg14_set_video(struct cgfourteen_softc *sc, int enable) cg14_set_video(struct cgfourteen_softc *sc, int enable)
{ {
/* /*
* We can only use DPMS to power down the display if the chip revision * We can only use DPMS to power down the display if the chip revision
* is greater than 0. * is greater than 0.
@ -714,7 +623,6 @@ cg14_set_video(struct cgfourteen_softc *sc, int enable)
static int static int
cg14_get_video(struct cgfourteen_softc *sc) cg14_get_video(struct cgfourteen_softc *sc)
{ {
return ((sc->sc_ctl->ctl_mctl & CG14_MCTL_ENABLEVID) != 0); return ((sc->sc_ctl->ctl_mctl & CG14_MCTL_ENABLEVID) != 0);
} }
@ -722,64 +630,63 @@ cg14_get_video(struct cgfourteen_softc *sc)
static int static int
cg14_get_cmap(struct fbcmap *p, union cg14cmap *cm, int cmsize) cg14_get_cmap(struct fbcmap *p, union cg14cmap *cm, int cmsize)
{ {
u_int i, start, count; u_int i, start, count;
u_char *cp; u_char *cp;
int error; int error;
start = p->index; start = p->index;
count = p->count; count = p->count;
if (start >= cmsize || count > cmsize - start) if (start >= cmsize || count > cmsize - start)
return (EINVAL); return (EINVAL);
for (cp = &cm->cm_map[start][0], i = 0; i < count; cp += 4, i++) { for (cp = &cm->cm_map[start][0], i = 0; i < count; cp += 4, i++) {
error = copyout(&cp[3], &p->red[i], 1); error = copyout(&cp[3], &p->red[i], 1);
if (error) if (error)
return error; return error;
error = copyout(&cp[2], &p->green[i], 1); error = copyout(&cp[2], &p->green[i], 1);
if (error) if (error)
return error; return error;
error = copyout(&cp[1], &p->blue[i], 1); error = copyout(&cp[1], &p->blue[i], 1);
if (error) if (error)
return error; return error;
} }
return (0); return (0);
} }
/* Write the software shadow colormap */ /* Write the software shadow colormap */
static int static int
cg14_put_cmap(struct fbcmap *p, union cg14cmap *cm, int cmsize) cg14_put_cmap(struct fbcmap *p, union cg14cmap *cm, int cmsize)
{ {
u_int i, start, count; u_int i, start, count;
u_char *cp; u_char *cp;
u_char cmap[256][4]; u_char cmap[256][4];
int error; int error;
start = p->index; start = p->index;
count = p->count; count = p->count;
if (start >= cmsize || count > cmsize - start) if (start >= cmsize || count > cmsize - start)
return (EINVAL); return (EINVAL);
memcpy(&cmap, &cm->cm_map, sizeof cmap); memcpy(&cmap, &cm->cm_map, sizeof cmap);
for (cp = &cmap[start][0], i = 0; i < count; cp += 4, i++) { for (cp = &cmap[start][0], i = 0; i < count; cp += 4, i++) {
error = copyin(&p->red[i], &cp[3], 1); error = copyin(&p->red[i], &cp[3], 1);
if (error) if (error)
return error; return error;
error = copyin(&p->green[i], &cp[2], 1); error = copyin(&p->green[i], &cp[2], 1);
if (error) if (error)
return error; return error;
error = copyin(&p->blue[i], &cp[1], 1); error = copyin(&p->blue[i], &cp[1], 1);
if (error) if (error)
return error; return error;
cp[0] = 0; /* no alpha channel */ cp[0] = 0; /* no alpha channel */
} }
memcpy(&cm->cm_map, &cmap, sizeof cmap); memcpy(&cm->cm_map, &cmap, sizeof cmap);
return (0); return (0);
} }
static void static void
cg14_load_hwcmap(struct cgfourteen_softc *sc, int start, int ncolors) cg14_load_hwcmap(struct cgfourteen_softc *sc, int start, int ncolors)
{ {
/* XXX switch to auto-increment, and on retrace intr */ /* XXX switch to auto-increment, and on retrace intr */
/* Setup pointers to source and dest */ /* Setup pointers to source and dest */
@ -790,56 +697,3 @@ cg14_load_hwcmap(struct cgfourteen_softc *sc, int start, int ncolors)
while (--ncolors >= 0) while (--ncolors >= 0)
*lutp++ = *colp++; *lutp++ = *colp++;
} }
/*
* Load the cursor (overlay `foreground' and `background') colors.
*/
static void
cg14_setcursor(struct cgfourteen_softc *sc)
{
/* we need to subtract the hot-spot value here */
#define COORD(f) (sc->sc_cursor.cc_pos.f - sc->sc_cursor.cc_hot.f)
sc->sc_hwc->curs_ctl = (sc->sc_cursor.cc_enable ? CG14_CURS_ENABLE : 0);
sc->sc_hwc->curs_x = COORD(x);
sc->sc_hwc->curs_y = COORD(y);
#undef COORD
}
static void
cg14_loadcursor(struct cgfourteen_softc *sc)
{
volatile struct cg14curs *hwc;
u_int edgemask, m;
int i;
/*
* Keep the top size.x bits. Here we *throw out* the top
* size.x bits from an all-one-bits word, introducing zeros in
* the top size.x bits, then invert all the bits to get what
* we really wanted as our mask. But this fails if size.x is
* 32---a sparc uses only the low 5 bits of the shift count---
* so we have to special case that.
*/
edgemask = ~0;
if (sc->sc_cursor.cc_size.x < 32)
edgemask = ~(edgemask >> sc->sc_cursor.cc_size.x);
hwc = sc->sc_hwc;
for (i = 0; i < 32; i++) {
m = sc->sc_cursor.cc_eplane[i] & edgemask;
hwc->curs_plane0[i] = m;
hwc->curs_plane1[i] = m & sc->sc_cursor.cc_cplane[i];
}
}
static void
cg14_loadomap(struct cgfourteen_softc *sc)
{
/* set background color */
sc->sc_hwc->curs_color1 = sc->sc_cursor.cc_color.cm_chip[0];
/* set foreground color */
sc->sc_hwc->curs_color2 = sc->sc_cursor.cc_color.cm_chip[1];
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: cgfourteenreg.h,v 1.2 2005/11/16 00:49:03 uwe Exp $ */ /* $NetBSD: cgfourteenreg.h,v 1.3 2006/01/17 04:22:09 christos Exp $ */
/* /*
* Copyright (c) 1996 * Copyright (c) 1996

View File

@ -1,4 +1,4 @@
/* $NetBSD: cgfourteenvar.h,v 1.5 2005/11/16 00:49:03 uwe Exp $ */ /* $NetBSD: cgfourteenvar.h,v 1.6 2006/01/17 04:22:09 christos Exp $ */
/* /*
* Copyright (c) 1996 * Copyright (c) 1996
@ -32,7 +32,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
*/ */
struct sbus_reg {
uint32_t sbr_slot;
uint32_t sbr_offset;
uint32_t sbr_size;
};
/* /*
* Layout of cg14 hardware colormap * Layout of cg14 hardware colormap
*/ */
@ -57,8 +61,8 @@ struct cg14_cursor { /* cg14 hardware cursor status */
struct fbcurpos cc_pos; /* position */ struct fbcurpos cc_pos; /* position */
struct fbcurpos cc_hot; /* hot-spot */ struct fbcurpos cc_hot; /* hot-spot */
struct fbcurpos cc_size; /* size of mask & image fields */ struct fbcurpos cc_size; /* size of mask & image fields */
u_int cc_eplane[32]; /* enable plane */ uint cc_eplane[32]; /* enable plane */
u_int cc_cplane[32]; /* color plane */ uint cc_cplane[32]; /* color plane */
union cg14cursor_cmap cc_color; /* cursor colormap */ union cg14cursor_cmap cc_color; /* cursor colormap */
}; };
@ -68,17 +72,20 @@ struct cg14_cursor { /* cg14 hardware cursor status */
struct cgfourteen_softc { struct cgfourteen_softc {
struct device sc_dev; /* base device */ struct device sc_dev; /* base device */
struct fbdevice sc_fb; /* frame buffer device */ struct fbdevice sc_fb; /* frame buffer device */
#ifdef RASTERCONSOLE
struct fbdevice sc_rcfb; /* sc_fb variant for rcons */
#endif
bus_space_tag_t sc_bustag; bus_space_tag_t sc_bustag;
struct openprom_addr sc_physadr[2]; /* phys addrs of h/w */ struct sbus_reg sc_physadr[2]; /* phys addrs of h/w */
#define CG14_CTL_IDX 0 #define CG14_CTL_IDX 0
#define CG14_PXL_IDX 1 #define CG14_PXL_IDX 1
union cg14cmap sc_cmap; /* current colormap */ union cg14cmap sc_cmap; /* current colormap */
struct cg14_cursor sc_cursor; /* Hardware cursor state */ struct cg14_cursor sc_cursor; /* Hardware cursor state */
union cg14cmap sc_saveclut; /* a place to stash PROM state */ union cg14cmap sc_saveclut; /* a place to stash PROM state */
uint8_t sc_savexlut[256]; uint8_t sc_savexlut[256];
uint8_t sc_savectl; uint8_t sc_savectl;
uint8_t sc_savehwc; uint8_t sc_savehwc;
struct cg14ctl *sc_ctl; /* various registers */ struct cg14ctl *sc_ctl; /* various registers */
struct cg14curs *sc_hwc; struct cg14curs *sc_hwc;
@ -87,5 +94,5 @@ struct cgfourteen_softc {
struct cg14clut *sc_clut1; struct cg14clut *sc_clut1;
struct cg14clut *sc_clut2; struct cg14clut *sc_clut2;
struct cg14clut *sc_clut3; struct cg14clut *sc_clut3;
u_int *sc_clutincr; uint *sc_clutincr;
}; };