* Copyright (c) 1992 The Regents of the University of California.
* This software was developed by the Computer Systems Engineering group
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
* contributed to Berkeley.
* All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Lawrence Berkeley Laboratories.
* %sccs.include.redist.c%
* @(#)cgthree.c 7.2 (Berkeley) %G%
* from: $Header: cgthree.c,v 1.5 92/06/17 06:59:31 torek Exp $
* color display (cgthree) driver.
* Does not handle interrupts, even though they can occur.
#include "machine/autoconf.h"
#include "machine/pmap.h"
#include "machine/fbvar.h"
u_char cm_map
[256][3]; /* 256 R/G/B entries */
u_int cm_chip
[256 * 3 / 4]; /* the way the chip gets loaded */
/* per-display variables */
struct device sc_dev
; /* base device */
struct sbusdev sc_sd
; /* sbus device */
struct fbdevice sc_fb
; /* frame buffer device */
volatile struct cgthreereg
*sc_reg
;/* control registers */
caddr_t sc_phys
; /* display RAM (phys addr) */
int sc_blanked
; /* true if blanked */
union colormap sc_cmap
; /* current color map */
/* autoconfiguration driver */
static void cgthreeattach(struct device
*, struct device
*, void *);
struct cfdriver cgthreecd
=
{ NULL
, "cgthree", matchbyname
, cgthreeattach
,
DV_DULL
, sizeof(struct cgthree_softc
) };
* XXX we do not handle frame buffer interrupts (do not know how) ... we
* need these to do color map loading at vertical retrace time!
/* frame buffer generic driver */
static void cgthreeunblank(struct device
*);
static struct fbdriver cgthreefbdriver
= { cgthreeunblank
};
extern struct tty
*fbconstty
;
static int cgthree_cnputc();
static struct cgthree_softc
*bwcons
;
#define CGTHREE_MAJOR 55 /* XXX */
* Attach a display. We need to notice if it is the console, too.
cgthreeattach(parent
, self
, args
)
struct device
*parent
, *self
;
register struct cgthree_softc
*sc
= (struct cgthree_softc
*)self
;
register struct sbus_attach_args
*sa
= args
;
register int node
= sa
->sa_ra
.ra_node
, ramsize
, i
;
register volatile struct cgthreereg
*cg3
;
register struct cgthree_all
*p
;
sc
->sc_fb
.fb_major
= CGTHREE_MAJOR
; /* XXX to be removed */
sc
->sc_fb
.fb_driver
= &cgthreefbdriver
;
sc
->sc_fb
.fb_device
= &sc
->sc_dev
;
* The defaults below match my screen, but are not guaranteed
* to be correct as defaults go...
sc
->sc_fb
.fb_type
.fb_type
= FBTYPE_SUN3COLOR
;
sc
->sc_fb
.fb_type
.fb_width
= getpropint(node
, "width", 1152);
sc
->sc_fb
.fb_type
.fb_height
= getpropint(node
, "height", 900);
sc
->sc_fb
.fb_linebytes
= getpropint(node
, "linebytes", 1152);
ramsize
= sc
->sc_fb
.fb_type
.fb_height
* sc
->sc_fb
.fb_linebytes
;
sc
->sc_fb
.fb_type
.fb_depth
= 8;
sc
->sc_fb
.fb_type
.fb_cmsize
= 256;
sc
->sc_fb
.fb_type
.fb_size
= ramsize
;
printf(": %s, %d x %d", getpropstring(node
, "model"),
sc
->sc_fb
.fb_type
.fb_width
, sc
->sc_fb
.fb_type
.fb_height
);
* When the ROM has mapped in a cgthree display, the address
* maps only the video RAM, so in any case we have to map the
* registers ourselves. We only need the video RAM if we are
* going to print characters via rconsole.
isconsole
= node
== fbnode
&& fbconstty
!= NULL
;
p
= (struct cgthree_all
*)sa
->sa_ra
.ra_paddr
;
if ((sc
->sc_fb
.fb_pixels
= sa
->sa_ra
.ra_vaddr
) == NULL
&& isconsole
) {
/* this probably cannot happen, but what the heck */
sc
->sc_fb
.fb_pixels
= mapiodev(p
->ba_ram
, ramsize
);
sc
->sc_reg
= cg3
= (volatile struct cgthreereg
*)
mapiodev((caddr_t
)&p
->ba_reg
, sizeof(p
->ba_reg
));
/* grab initial (current) color map, then set video */
for (i
= 0; i
< 256 * 3 / 4; i
++)
sc
->sc_cmap
.cm_chip
[i
] = cg3
->cg3_cmap
;
cgthreeunblank(&sc
->sc_dev
);
sbus_establish(&sc
->sc_sd
, &sc
->sc_dev
);
cgthreeopen(dev
, flags
, mode
, p
)
if (unit
>= cgthreecd
.cd_ndevs
|| cgthreecd
.cd_devs
[unit
] == NULL
)
cgthreeclose(dev
, flags
, mode
, p
)
cgthreeioctl(dev
, cmd
, data
, flags
, p
)
register struct cgthree_softc
*sc
= cgthreecd
.cd_devs
[minor(dev
)];
register struct fbgattr
*fba
;
*(struct fbtype
*)data
= sc
->sc_fb
.fb_type
;
fba
= (struct fbgattr
*)data
;
fba
->real_type
= sc
->sc_fb
.fb_type
.fb_type
;
fba
->owner
= 0; /* XXX ??? */
fba
->fbtype
= sc
->sc_fb
.fb_type
;
fba
->sattr
.emu_type
= sc
->sc_fb
.fb_type
.fb_type
;
fba
->sattr
.dev_specific
[0] = -1;
fba
->emu_types
[0] = sc
->sc_fb
.fb_type
.fb_type
;
register struct fbcmap
*p
= (struct fbcmap
*)data
;
register int i
, color
, count
, error
;
/* get color map from software copy */
if ((unsigned)(color
= p
->index
) >= 256 ||
(unsigned)(count
= p
->count
) > 256 - color
)
if (!useracc(p
->red
, count
, B_WRITE
) ||
!useracc(p
->green
, count
, B_WRITE
) ||
!useracc(p
->blue
, count
, B_WRITE
))
cp
= &sc
->sc_cmap
.cm_map
[color
][0];
for (i
= 0; i
< count
; cp
+= 3, i
++) {
register struct fbcmap
*p
= (struct fbcmap
*)data
;
register int i
, color
, count
, error
;
/* update software copy */
if ((unsigned)(color
= p
->index
) >= 256 ||
(unsigned)(count
= p
->count
) > 256 - color
)
if (!useracc(p
->red
, count
, B_READ
) ||
!useracc(p
->green
, count
, B_READ
) ||
!useracc(p
->blue
, count
, B_READ
))
cp
= &sc
->sc_cmap
.cm_map
[color
][0];
for (i
= 0; i
< count
; cp
+= 3, i
++) {
/* then blast them into the chip */
/* XXX should use retrace interrupt */
#define D4M3(x) ((((x) >> 2) << 1) + ((x) >> 2)) /* (x / 4) * 3 */
#define D4M4(x) ((x) & ~3) /* (x / 4) * 4 */
ip
= &sc
->sc_cmap
.cm_chip
[D4M3(color
)];
count
= D4M3(color
+ count
- 1) - D4M3(color
) + 3;
sc
->sc_reg
->cg3_addr
= D4M4(color
);
sc
->sc_reg
->cg3_cmap
= *ip
++;
*(int *)data
= sc
->sc_blanked
;
cgthreeunblank(&sc
->sc_dev
);
register volatile struct cgthreereg
*cg3
= sc
->sc_reg
;
cg3
->cg3_addr
= 0x06; /* command reg */
cg3
->cg3_ctrl
= 0x70; /* overlay plane */
cg3
->cg3_addr
= 0x04; /* read mask */
cg3
->cg3_ctrl
= 0x00; /* color planes */
/* set color 0 to black; scribble on R of color 1 */
struct cgthree_softc
*sc
= (struct cgthree_softc
*)dev
;
register volatile struct cgthreereg
*cg3
= sc
->sc_reg
;
cg3
->cg3_addr
= 0x06; /* command reg */
cg3
->cg3_ctrl
= 0x73; /* overlay plane */
cg3
->cg3_addr
= 0x04; /* read mask */
cg3
->cg3_ctrl
= 0xff; /* color planes */
/* restore color 0 and R of color 1 */
cg3
->cg3_cmap
= sc
->sc_cmap
.cm_chip
[0];
* Return the address that would map the given device at the given
* offset, allowing for the given protection, or return -1 for error.
* The cg3 is mapped starting at 256KB, for pseudo-compatibility with
* the cg4 (which had an overlay plane in the first 128K and an enable
* plane in the next 128K). X11 uses only 256k+ region but tries to
* map the whole thing, so we repeatedly map the first 256K to the
* first page of the color screen. If someone tries to use the overlay
* and enable regions, they will get a surprise....
cgthreemap(dev
, off
, prot
)
register struct cgthree_softc
*sc
= cgthreecd
.cd_devs
[minor(dev
)];
#define START (128*1024 + 128*1024)
if ((unsigned)off
< START
)
if ((unsigned)off
>= sc
->sc_fb
.fb_type
.fb_size
)
* I turned on PMAP_NC here to disable the cache as I was
* getting horribly broken behaviour with it on.
return ((int)sc
->sc_phys
+ off
+ PMAP_OBIO
+ PMAP_NC
);