Files
Arquivotheca.SunOS-4.1.4/sys/sbusdev/bwtwo.c
seta75D ff309bfe1c Init
2021-10-11 18:37:13 -03:00

535 lines
9.8 KiB
C

#if !defined(lint) && !defined(NOID)
static char sccsid[] = "@(#)bwtwo.c 1.1 94/10/31 SMI";
#endif
/*
* Copyright 1988-1989, Sun Microsystems, Inc.
*/
/*
* Sbus monochrome 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/memvar.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 BW2DEBUG
#define BW2DEBUG 0
#endif BW2DEBUG
#if NOHWINIT
int bw2_hwinit = 1;
int bw2_type = 1;
int bw2_on = 1; /* must be 1 to enable bw2 */
#endif NOHWINIT
#if BW2DEBUG
int bw2_debug = 0;
#define DEBUGF(level, args) _STMT(if (bw2_debug >= (level)) printf args; )
#else BW2DEBUG
#define DEBUGF(level, args) /* nothing */
#endif BW2DEBUG
#if OLDDEVSW
#define STATIC /* nothing */
#define bw2_open bwtwoopen
#define bw2_close bwtwoclose
#define bw2_mmap bwtwommap
#define bw2_ioctl bwtwoioctl
#else OLDDEVSW
#define STATIC static
#endif OLDDEVSW
/* config info */
static int bw2_identify();
static int bw2_attach();
STATIC int bw2_open();
STATIC int bw2_close();
STATIC int bw2_ioctl();
STATIC int bw2_mmap();
struct dev_ops bwtwo_ops = {
0, /* revision */
bw2_identify,
bw2_attach,
bw2_open,
bw2_close,
0, 0, 0, 0, 0,
bw2_ioctl,
0,
bw2_mmap,
};
/* per-unit data */
struct bw2_softc {
struct mfb_reg *reg; /* video chip registers */
#if NWIN > 0
Pixrect pr; /* kernel pixrect */
struct mpr_data prd; /* pixrect private data */
#define _w pr.pr_size.x
#define _h pr.pr_size.y
#define _fb prd.md_image
#define _linebytes prd.md_linebytes
#else NWIN > 0
int _w, _h; /* resolution */
#endif NWIN > 0
int size; /* total size of frame buffer */
int basepage; /* page # for base address */
};
static int nbw2;
static struct bw2_softc *bw2_softc;
/*
* handy macros
*/
#define getsoftc(unit) (&bw2_softc[unit])
static
bw2_identify(name)
char *name;
{
DEBUGF(1, ("bw2_identify(%s)\n", name));
#if NOHWINIT
if (!bw2_on)
return (0);
#endif NOHWINIT
if (strcmp(name, "bwtwo") == 0)
return (++nbw2);
else
return (0);
}
static
bw2_attach(devi)
struct dev_info *devi;
{
register struct bw2_softc *softc;
register addr_t reg;
int nodeid, bytes, basepage;
static int unit;
extern struct dev_info *top_devinfo; /* in autoconf.c */
DEBUGF(1, ("bw2_attach nbw2=%d unit=%d\n", nbw2, unit));
/* Allocate softc structs on first attach */
if (!bw2_softc)
bw2_softc = (struct bw2_softc *)
kmem_zalloc((u_int) sizeof (struct bw2_softc) * nbw2);
softc = getsoftc(unit);
/* Grab properties from PROM */
nodeid = devi->devi_nodeid;
softc->_w = getprop(nodeid, "width", 1152);
softc->_h = getprop(nodeid, "height", 900);
#if NOHWINIT
/* if properties are missing initialize the hardware */
if (getproplen(nodeid, "width") != sizeof (int)) {
if (!bw2_probe(devi, softc))
return (-1);
}
#endif NOHWINIT
bytes = getprop(nodeid, "linebytes", mpr_linebytes(softc->_w, 1));
#if NWIN > 0
softc->_linebytes = bytes;
#endif NWIN > 0
/* Compute size of frame buffer */
softc->size = bytes = ptob(btopr(bytes * softc->_h));
#if NWIN > 0
/* only use address property if we are console fb */
if (reg = (addr_t) getprop(nodeid, "address", 0)) {
int fbid = getprop(top_devinfo->devi_nodeid, "fb", -1);
if (fbid == nodeid) {
softc->_fb = (MPR_T *) reg;
bytes = 0;
DEBUGF(2, ("bw2 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, ("bw2_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, ("bw2_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;
/* save back pointer to softc */
devi->devi_data = (addr_t) softc;
/* prepare for next attach */
unit++;
report_dev(devi);
return (0);
}
STATIC
bw2_open(dev, flag)
dev_t dev;
int flag;
{
DEBUGF(2, ("bw2_open(%d)\n", minor(dev)));
return (fbopen(dev, flag, nbw2));
}
/*ARGSUSED*/
STATIC
bw2_close(dev, flag)
dev_t dev;
int flag;
{
DEBUGF(2, ("bw2_close(%d)\n", minor(dev)));
/* disable cursor compare */
getsoftc(minor(dev))->reg->control &= ~MFB_CR_CURSOR;
return (0);
}
/*ARGSUSED*/
STATIC
bw2_mmap(dev, off, prot)
dev_t dev;
register off_t off;
int prot;
{
register struct bw2_softc *softc = getsoftc(minor(dev));
DEBUGF(off ? 9 : 1, ("bw2_mmap(%d, 0x%x)\n", minor(dev), (u_int) off));
if (off == MFB_REG_MMAP_OFFSET && suser())
off = 0;
else if ((u_int) off < softc->size)
off += MFB_OFF_FB - MFB_OFF_REG;
else
return (-1);
DEBUGF(off != MFB_OFF_FB - MFB_OFF_REG ? 9 : 1,
("bw2_mmap returning 0x%x (0x%x)\n",
ptob(softc->basepage) + off,
softc->basepage + btop(off)));
return (softc->basepage + btop(off));
}
/*ARGSUSED*/
STATIC
bw2_ioctl(dev, cmd, data, flag)
dev_t dev;
int cmd;
caddr_t data;
int flag;
{
register struct bw2_softc *softc = getsoftc(minor(dev));
DEBUGF(2, ("bw2_ioctl(%d, 0x%x)\n", minor(dev), cmd));
switch (cmd) {
case FBIOGTYPE: {
register struct fbtype *fb = (struct fbtype *) data;
DEBUGF(2, ("FBIOGTYPE\n"));
fb->fb_type = FBTYPE_SUN2BW;
fb->fb_height = softc->_h;
fb->fb_width = softc->_w;
fb->fb_depth = 1;
fb->fb_cmsize = 2;
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 = &mem_ops;
/* pr_size set in attach */
softc->pr.pr_depth = 1;
softc->pr.pr_data = (caddr_t) &softc->prd;
/* md_linebytes, md_image set in attach */
/* md_offset already zero */
softc->prd.md_primary = minor(dev);
softc->prd.md_flags = MP_DISPLAY;
/* 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);
}
return (0);
}
#if NOHWINIT
static int
bw2_probe(devi, softc)
struct dev_info *devi;
struct bw2_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 only for BW2 FB 501-1561 (prom 1.5) */
#define MFB_SR_1152_900_76HZ_A 0x40 /* 76Hz monitor sense codes */
#define MFB_SR_1152_900_76HZ_B 0x60
#define MFB_SR_ID_MSYNC 0x04 /* SR id of 501-1561 BW2 */
monitor_type = stat & MFB_SR_RES_MASK;
switch (stat & MFB_SR_ID_MASK) {
case MFB_SR_ID_MONO_ECL:
if (monitor_type == MFB_SR_1600_1280)
bw2_type = 0;
else
bw2_type = 1;
break;
case MFB_SR_ID_MONO:
bw2_type = 2;
break;
case MFB_SR_ID_MSYNC:
if ((monitor_type == MFB_SR_1152_900_76HZ_A) ||
(monitor_type == MFB_SR_1152_900_76HZ_B))
bw2_type = 4;
else
bw2_type = 3;
break;
default:
DEBUGF(1, ("bw2_hwinit bad type SR=0x%x\n", (u_int) stat));
goto bad;
}
if (bw2_type == 0) {
softc->_w = 1600;
softc->_h = 1280;
}
if (bw2_hwinit)
bw2_init(mfb);
DEBUGF(1, ("bw2_hwinit type=%d (%d,%d)\n",
bw2_type, softc->_w, softc->_h));
retval = 1;
bad:
if (!retval) {
DEBUGF(2, ("bw2_probe failed\n"));
}
unmap_regs((addr_t) mfb, (u_int) NBPG);
return (retval);
}
/* high-res ECL */
char bw2_mfbval0[] = {
0x14, 0x8b,
0x15, 0x28,
0x16, 0x03,
0x17, 0x13,
0x18, 0x7b,
0x19, 0x05,
0x1a, 0x34,
0x1b, 0x2e,
0x1c, 0x00,
0x1d, 0x0a,
0x1e, 0xff,
0x1f, 0x01,
0x10, 0x21,
0
};
/* low-res ECL */
char bw2_mfbval1[] = {
0x14, 0x65,
0x15, 0x1e,
0x16, 0x04,
0x17, 0x0c,
0x18, 0x5e,
0x19, 0x03,
0x1a, 0xa7, /* increase for > 900 lines */
0x1b, 0x23,
0x1c, 0x00,
0x1d, 0x08,
0x1e, 0xff,
0x1f, 0x01,
0x10, 0x20,
0
};
/* low-res analog */
char bw2_mfbval2[] = {
0x14, 0xbb,
0x15, 0x2b,
0x16, 0x03,
0x17, 0x13,
0x18, 0xb0,
0x19, 0x03,
0x1a, 0xa6,
0x1b, 0x22,
0x1c, 0x01,
0x1d, 0x05,
0x1e, 0xff,
0x1f, 0x01,
0x10, 0x20,
0
};
/* BW2 FB 501-1561 (prom 1.5) 66 Hz */
char bw2_mfbval3[] = {
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
};
/* BW2 FB 501-1561 (prom 1.5) 76 Hz */
char bw2_mfbval4[] = {
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
};
static char *mfbvals[] = {
bw2_mfbval0,
bw2_mfbval1,
bw2_mfbval2,
bw2_mfbval3,
bw2_mfbval4,
};
static
bw2_init(mfb)
struct mfb_reg *mfb;
{
register char *p;
/* initialize video chip */
for (p = mfbvals[bw2_type]; *p; p += 2)
((char *) mfb)[p[0]] = p[1];
}
#endif NOHWINIT