Change pmax framebuffer drivers to use Ted Lemon's port of the

NetBSD/sparc rcons glass-tty console pseudo-device driver, via
the "fb" generic-framebuffer pseudo-device driver.

Individual framebuffer device drivers are now autoconfig glue,
and initialization code for a set of vdac/ramdac-level methods,
called "fbdriver", that's used by all the pmax device drivers.
All the handlers for user-level requests (open/ioctl/read/write/close)
are moved into the fb pseudo-device driver, which uses the
the "fbdriver" methods to work on any given pmax hardware driver.
Framebuffers  supported are: sfb cfb mfb xcfb pm.

Move the qvss (pm) -style mmap()ed device interface, kernel tracking
of mouse button/movement events, and placing mouse/keyboard
events in an mmap()ed ring buffer, out of the framebuffer device
drivers and into separate source files. The fb pseudo-device driver
uses the qvss-compatible interface, since that's what the (R5) X
server uses.
This commit is contained in:
jonathan 1995-09-11 07:45:36 +00:00
parent ef09db9674
commit 1d976e39b9
11 changed files with 2418 additions and 4391 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,204 @@
/*ARGSUSED*/
fbopen(dev, flag)
dev_t dev;
int flag;
{
register struct fbinfo *fi;
int s;
#ifdef fpinitialized
if (!fp->initialized)
return (ENXIO);
#endif
if (minor(dev) >= fbcd.cd_ndevs ||
(fi = fbcd.cd_devs[minor(dev)]) == NULL)
return(ENXIO);
if (fi->fi_open)
return (EBUSY);
fi->fi_open = 1;
(*fi->fi_driver->fbd_initcmap)(fi);
/*
* Set up event queue for later
*/
pmEventQueueInit(&fi->fi_fbu->scrInfo.qe);
genConfigMouse();
return (0);
}
/*ARGSUSED*/
fbclose(dev, flag)
dev_t dev;
int flag;
{
register struct fbinfo *fi;
register struct pmax_fbtty *fbtty;
int pixelsize;
int s;
if (minor(dev) >= fbcd.cd_ndevs ||
(fi = fbcd.cd_devs[minor(dev)]) == NULL)
return(EBADF);
if (!fi->fi_open)
return (EBADF);
fbtty = fi->fi_glasstty;
fi->fi_open = 0;
(*fi->fi_driver->fbd_initcmap)(fi);
genDeconfigMouse();
fbScreenInit(fi);
bzero((caddr_t)fi->fi_pixels, fi->fi_pixelsize);
(*fi->fi_driver->fbd_poscursor)
(fi, fbtty->col * 8, fbtty->row * 15);
return (0);
}
/*ARGSUSED*/
fbioctl(dev, cmd, data, flag, p)
dev_t dev;
caddr_t data;
struct proc *p;
{
register struct fbinfo *fi;
register struct pmax_fbtty *fbtty;
int s;
if (minor(dev) >= fbcd.cd_ndevs ||
(fi = fbcd.cd_devs[minor(dev)]) == NULL)
return(EBADF);
fbtty = fi->fi_glasstty;
switch (cmd) {
case QIOCGINFO:
return (fbmmap_fb(fi, dev, data, p));
case QIOCPMSTATE:
/*
* Set mouse state.
*/
fi->fi_fbu->scrInfo.mouse = *(pmCursor *)data;
(*fi->fi_driver->fbd_poscursor)
(fi, fi->fi_fbu->scrInfo.mouse.x,
fi->fi_fbu->scrInfo.mouse.y);
break;
case QIOCINIT:
/*
* Initialize the screen.
*/
fbScreenInit(fi);
break;
case QIOCKPCMD:
{
pmKpCmd *kpCmdPtr;
unsigned char *cp;
kpCmdPtr = (pmKpCmd *)data;
if (kpCmdPtr->nbytes == 0)
kpCmdPtr->cmd |= 0x80;
if (!fi->fi_open)
kpCmdPtr->cmd |= 1;
(*fbtty->KBDPutc)(fbtty->kbddev, (int)kpCmdPtr->cmd);
cp = &kpCmdPtr->par[0];
for (; kpCmdPtr->nbytes > 0; cp++, kpCmdPtr->nbytes--) {
if (kpCmdPtr->nbytes == 1)
*cp |= 0x80;
(*fbtty->KBDPutc)(fbtty->kbddev, (int)*cp);
}
break;
}
case QIOCADDR:
*(PM_Info **)data = &fi->fi_fbu->scrInfo;
break;
case QIOWCURSOR:
(*fi->fi_driver->fbd_loadcursor)
(fi, (unsigned short *)data);
break;
case QIOWCURSORCOLOR:
(*fi->fi_driver->fbd_cursorcolor)(fi, (unsigned int *)data);
break;
case QIOSETCMAP:
(*fi->fi_driver->fbd_putcmap)
(fi,
(char *)&((ColorMap *)data)->Entry,
((ColorMap *)data)->index, 1);
break;
case QIOKERNLOOP:
genConfigMouse();
break;
case QIOKERNUNLOOP:
genDeconfigMouse();
break;
case QIOVIDEOON:
(*fi->fi_driver->fbd_unblank) (fi);
break;
case QIOVIDEOOFF:
(*fi->fi_driver->fbd_blank) (fi);
break;
default:
printf("fb%d: Unknown ioctl command %x\n", minor(dev), cmd);
return (EINVAL);
}
return (0);
}
fbselect(dev, flag, p)
dev_t dev;
int flag;
struct proc *p;
{
struct fbinfo *fi = fbcd.cd_devs[minor(dev)];
switch (flag) {
case FREAD:
if (fi->fi_fbu->scrInfo.qe.eHead !=
fi->fi_fbu->scrInfo.qe.eTail)
return (1);
selrecord(p, &fi->fi_selp);
break;
}
return (0);
}
/*
* Return the physical page number that corresponds to byte offset 'off'.
*/
/*ARGSUSED*/
fbmmap(dev, off, prot)
dev_t dev;
{
int len;
register struct fbinfo *fi;
if (minor(dev) >= fbcd.cd_ndevs ||
(fi = fbcd.cd_devs[minor(dev)]) == NULL)
return(-1);
len = pmax_round_page(((vm_offset_t)fi->fi_fbu & PGOFSET)
+ sizeof(*fi->fi_fbu));
if (off < len)
return pmax_btop(MACH_CACHED_TO_PHYS(fi->fi_fbu) + off);
off -= len;
if (off >= fi->fi_type.fb_size)
return (-1);
return pmax_btop(MACH_UNCACHED_TO_PHYS(fi->fi_pixels) + off);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
/* $NetBSD: pm.c,v 1.6 1995/08/10 04:21:44 jonathan Exp $ */
/* $NetBSD: pm.c,v 1.7 1995/09/11 07:45:43 jonathan Exp $ */
/*-
* Copyright (c) 1992, 1993
@ -56,6 +56,7 @@
*/
#include <fb.h>
#include <pm.h>
#include <dc.h>
#if NPM > 0
@ -81,42 +82,77 @@ pm needs dc device
#include <machine/dc7085cons.h>
#include <machine/pmioctl.h>
#include <machine/fbio.h>
#include <machine/fbvar.h>
#include <pmax/pmax/kn01.h>
#include <pmax/pmax/pmaxtype.h>
#include <pmax/pmax/cons.h>
#include <pmax/dev/device.h>
#include <pmax/dev/pmreg.h>
#include <pmax/dev/fbreg.h>
#include <pmax/dev/pmreg.h>
#include <pmax/dev/bt478.h>
/*
* These need to be mapped into user space.
*/
struct fbuaccess pmu;
struct pmax_fb pmfb;
static u_short curReg; /* copy of PCCRegs.cmdr since it's read only */
/*
* rcons methods and globals.
*/
struct pmax_fbtty pmfb;
struct fbinfo pmfi; /*XXX*/
/*
* Forward references.
*/
static void pmScreenInit __P(());
static void pmLoadCursor __P((u_short *ptr));
extern void pmScreenInit __P((struct fbinfo *fi));
static void pmLoadCursor __P((struct fbinfo *fi, u_short *ptr));
void pmPosCursor __P((struct fbinfo *fi, int x, int y));
#ifdef notyet /* these should be removed */
static void pmRestoreCursorColor __P(());
static void pmCursorColor __P((u_int *color));
void pmPosCursor __P((int x, int y));
static void pmInitColorMap __P(());
static void pmLoadColorMap __P ((ColorMap *ptr));
#endif
void bt478CursorColor __P((struct fbinfo *fi, u_int *color));
void bt478InitColorMap __P((struct fbinfo *fi));
static void pmLoadColorMap __P ((ColorMap *ptr)); /*XXX*/
int pminit __P((struct fbinfo *fi, int unit, int silent));
static int pm_video_on __P ((struct fbinfo *));
static int pm_video_off __P ((struct fbinfo *));
int bt478LoadColorMap __P ((struct fbinfo *, caddr_t, int, int));
int bt478GetColorMap __P ((struct fbinfo *, caddr_t, int, int));
#if 0
static void pmVDACInit();
void pmKbdEvent(), pmMouseEvent(), pmMouseButtons();
#endif
/* pm framebuffers are only found in {dec,vax}station 3100s with dc7085s */
extern void dcPutc();
extern void (*dcDivertXInput)();
extern void (*dcMouseEvent)();
extern void (*dcMouseButtons)();
extern int pmax_boardtype;
extern u_short defCursor[32];
extern struct consdev cn_tab;
void genConfigMouse(), genDeconfigMouse();
void genKbdEvent(), genMouseEvent(), genMouseButtons();
extern void pmEventQueueInit __P((pmEventQueue *qe));
#define CMAP_BITS (3 * 256) /* 256 entries, 3 bytes per. */
static u_char cmap_bits [NPM * CMAP_BITS]; /* One colormap per pm... */
/*
* Autoconfiguration data for config.new.
@ -131,6 +167,19 @@ struct cfdriver pmcd = {
NULL, "pm", pmmatch, pmattach, DV_DULL, sizeof(struct device), 0
};
/* new-style raster-cons "driver" methods */
struct fbdriver pm_driver = {
pm_video_on,
pm_video_off,
bt478InitColorMap,
bt478GetColorMap,
bt478LoadColorMap,
pmPosCursor,
pmLoadCursor,
bt478CursorColor,
};
int
pmmatch(parent, match, aux)
struct device *parent;
@ -140,11 +189,16 @@ pmmatch(parent, match, aux)
struct cfdata *cf = match;
struct confargs *ca = aux;
static int npms = 1;
caddr_t pmaddr = BUS_CVTADDR(ca);
/* make sure that we're looking for this type of device. */
if (!BUS_MATCHNAME(ca, "pm"))
return (0);
if (badaddr(pmaddr, 4))
return (0);
#ifdef notyet
/* if it can't have the one mentioned, reject it */
if (cf->cf_unit >= npms)
@ -160,8 +214,9 @@ pmattach(parent, self, aux)
void *aux;
{
struct confargs *ca = aux;
caddr_t pmaddr = BUS_CVTADDR(ca);
if (!pminit(BUS_CVTADDR(ca)))
if (!pminit(&pmfi, 0, 0))
return;
/* no interrupts for PM */
@ -169,232 +224,73 @@ pmattach(parent, self, aux)
return;
}
/*ARGSUSED*/
pmopen(dev, flag)
dev_t dev;
int flag;
{
register struct pmax_fb *fp = &pmfb;
int s;
if (!fp->initialized)
return (ENXIO);
if (fp->GraphicsOpen)
return (EBUSY);
fp->GraphicsOpen = 1;
if (!fp->isMono)
pmInitColorMap();
/*
* Set up event queue for later
*/
fp->fbu->scrInfo.qe.eSize = PM_MAXEVQ;
fp->fbu->scrInfo.qe.eHead = fp->fbu->scrInfo.qe.eTail = 0;
fp->fbu->scrInfo.qe.tcSize = MOTION_BUFFER_SIZE;
fp->fbu->scrInfo.qe.tcNext = 0;
fp->fbu->scrInfo.qe.timestamp_ms = TO_MS(time);
s = spltty();
dcDivertXInput = pmKbdEvent;
dcMouseEvent = pmMouseEvent;
dcMouseButtons = pmMouseButtons;
splx(s);
return (0);
}
/*ARGSUSED*/
pmclose(dev, flag)
dev_t dev;
int flag;
{
register struct pmax_fb *fp = &pmfb;
int s;
if (!fp->GraphicsOpen)
return (EBADF);
fp->GraphicsOpen = 0;
if (!fp->isMono)
pmInitColorMap();
s = spltty();
dcDivertXInput = (void (*)())0;
dcMouseEvent = (void (*)())0;
dcMouseButtons = (void (*)())0;
splx(s);
pmScreenInit();
bzero((caddr_t)fp->fr_addr,
(fp->isMono ? 1024 / 8 : 1024) * 864);
pmPosCursor(fp->col * 8, fp->row * 15);
return (0);
}
/*ARGSUSED*/
pmioctl(dev, cmd, data, flag, p)
dev_t dev;
caddr_t data;
struct proc *p;
{
register PCCRegs *pcc = (PCCRegs *)MACH_PHYS_TO_UNCACHED(KN01_SYS_PCC);
register struct pmax_fb *fp = &pmfb;
int s;
switch (cmd) {
case QIOCGINFO:
return (fbmmap(fp, dev, data, p));
case QIOCPMSTATE:
/*
* Set mouse state.
*/
fp->fbu->scrInfo.mouse = *(pmCursor *)data;
pmPosCursor(fp->fbu->scrInfo.mouse.x, fp->fbu->scrInfo.mouse.y);
break;
case QIOCINIT:
/*
* Initialize the screen.
*/
pmScreenInit();
break;
case QIOCKPCMD:
{
pmKpCmd *kpCmdPtr;
unsigned char *cp;
kpCmdPtr = (pmKpCmd *)data;
if (kpCmdPtr->nbytes == 0)
kpCmdPtr->cmd |= 0x80;
if (!fp->GraphicsOpen)
kpCmdPtr->cmd |= 1;
(*fp->KBDPutc)(fp->kbddev, (int)kpCmdPtr->cmd);
cp = &kpCmdPtr->par[0];
for (; kpCmdPtr->nbytes > 0; cp++, kpCmdPtr->nbytes--) {
if (kpCmdPtr->nbytes == 1)
*cp |= 0x80;
(*fp->KBDPutc)(fp->kbddev, (int)*cp);
}
break;
}
case QIOCADDR:
*(PM_Info **)data = &fp->fbu->scrInfo;
break;
case QIOWCURSOR:
pmLoadCursor((unsigned short *)data);
break;
case QIOWCURSORCOLOR:
pmCursorColor((unsigned int *)data);
break;
case QIOSETCMAP:
pmLoadColorMap((ColorMap *)data);
break;
case QIOKERNLOOP:
s = spltty();
dcDivertXInput = pmKbdEvent;
dcMouseEvent = pmMouseEvent;
dcMouseButtons = pmMouseButtons;
splx(s);
break;
case QIOKERNUNLOOP:
s = spltty();
dcDivertXInput = (void (*)())0;
dcMouseEvent = (void (*)())0;
dcMouseButtons = (void (*)())0;
splx(s);
break;
case QIOVIDEOON:
if (!fp->isMono)
pmRestoreCursorColor();
curReg |= PCC_ENPA;
curReg &= ~PCC_FOPB;
pcc->cmdr = curReg;
break;
case QIOVIDEOOFF:
if (!fp->isMono)
pmVDACInit();
curReg |= PCC_FOPB;
curReg &= ~PCC_ENPA;
pcc->cmdr = curReg;
break;
default:
printf("pm0: Unknown ioctl command %x\n", cmd);
return (EINVAL);
}
return (0);
}
/*
* Return the physical page number that corresponds to byte offset 'off'.
*/
/*ARGSUSED*/
pmmmap(dev, off, prot)
dev_t dev;
{
int len;
len = pmax_round_page(((vm_offset_t)&pmu & PGOFSET) + sizeof(pmu));
if (off < len)
return pmax_btop(MACH_CACHED_TO_PHYS(&pmu) + off);
off -= len;
if (off >= pmfb.fr_size)
return (-1);
return pmax_btop(MACH_UNCACHED_TO_PHYS(pmfb.fr_addr) + off);
}
pmselect(dev, flag, p)
dev_t dev;
int flag;
struct proc *p;
{
struct pmax_fb *fp = &pmfb;
switch (flag) {
case FREAD:
if (fp->fbu->scrInfo.qe.eHead != fp->fbu->scrInfo.qe.eTail)
return (1);
selrecord(p, &fp->selp);
break;
}
return (0);
}
static u_char bg_RGB[3]; /* background color for the cursor */
static u_char fg_RGB[3]; /* foreground color for the cursor */
/*
* Test to see if device is present.
* Return true if found and initialized ok.
*/
pminit()
pminit(fi, unit, silent)
struct fbinfo *fi;
int unit;
int silent;
{
register PCCRegs *pcc = (PCCRegs *)MACH_PHYS_TO_UNCACHED(KN01_SYS_PCC);
register struct pmax_fb *fp = &pmfb;
fp->isMono = *(volatile u_short *)MACH_PHYS_TO_UNCACHED(KN01_SYS_CSR) &
KN01_CSR_MONO;
fp->fr_addr = (char *)MACH_PHYS_TO_UNCACHED(KN01_PHYS_FBUF_START);
fp->fr_size = fp->isMono ? 0x40000 : 0x100000;
/* Set address of frame buffer... */
fi->fi_pixels = (caddr_t)MACH_PHYS_TO_UNCACHED(KN01_PHYS_FBUF_START);
/* Fill in the stuff that differs from monochrome to color. */
if (*(volatile u_short *)MACH_PHYS_TO_UNCACHED(KN01_SYS_CSR) &
KN01_CSR_MONO) {
/* check for no frame buffer */
if (badaddr((char *)fi->fi_pixels, 4))
return (0);
fi->fi_type.fb_depth = 1;
fi->fi_type.fb_cmsize = 0;
fi->fi_type.fb_boardtype = PMAX_FBTYPE_PM_MONO;
fi->fi_type.fb_size = 0x40000;
fi->fi_linebytes = 256;
} else {
fi->fi_type.fb_depth = 8;
fi->fi_type.fb_cmsize = 256;
fi->fi_type.fb_boardtype = PMAX_FBTYPE_PM_COLOR;
fi->fi_type.fb_size = 0x100000;
fi->fi_linebytes = 1024;
}
/* Fill in main frame buffer info struct. */
fi->fi_pixelsize =
((fi->fi_type.fb_depth == 1) ? 1024 / 8 : 1024) * 864;
fi->fi_unit = unit;
fi->fi_base = (caddr_t)pcc;
fi->fi_vdac = (caddr_t)MACH_PHYS_TO_UNCACHED(KN01_SYS_VDAC);
fi->fi_blanked = 0;
fi->fi_cmap_bits = (caddr_t)&cmap_bits [CMAP_BITS * unit];
fi->fi_type.fb_width = 1024;
fi->fi_type.fb_height = 864;
/*
* compatibility glue
*/
fi->fi_glasstty = &pmfb;
/*
* Must be in Uncached space since the fbuaccess structure is
* mapped into the user's address space uncached.
*/
fp->fbu = (struct fbuaccess *)
fi->fi_fbu = (struct fbuaccess *)
MACH_PHYS_TO_UNCACHED(MACH_CACHED_TO_PHYS(&pmu));
fp->posCursor = pmPosCursor;
fp->KBDPutc = dcPutc;
fp->kbddev = makedev(DCDEV, DCKBD_PORT);
if (fp->isMono) {
fi->fi_glasstty->KBDPutc = dcPutc;
fi->fi_glasstty->kbddev = makedev(DCDEV, DCKBD_PORT);
if (fi->fi_type.fb_depth == 1) {
/* check for no frame buffer */
if (badaddr((char *)fp->fr_addr, 4))
if (badaddr((char *)fi->fi_pixels, 4))
return (0);
}
@ -408,74 +304,47 @@ pminit()
*/
pcc->cmdr = curReg = PCC_ENPA | PCC_ENPB;
/*
* Initialize screen info.
*/
fp->fbu->scrInfo.max_row = 56;
fp->fbu->scrInfo.max_col = 80;
fp->fbu->scrInfo.max_x = 1024;
fp->fbu->scrInfo.max_y = 864;
fp->fbu->scrInfo.max_cur_x = 1023;
fp->fbu->scrInfo.max_cur_y = 863;
fp->fbu->scrInfo.version = 11;
fp->fbu->scrInfo.mthreshold = 4;
fp->fbu->scrInfo.mscale = 2;
fp->fbu->scrInfo.min_cur_x = -15;
fp->fbu->scrInfo.min_cur_y = -15;
fp->fbu->scrInfo.qe.timestamp_ms = TO_MS(time);
fp->fbu->scrInfo.qe.eSize = PM_MAXEVQ;
fp->fbu->scrInfo.qe.eHead = fp->fbu->scrInfo.qe.eTail = 0;
fp->fbu->scrInfo.qe.tcSize = MOTION_BUFFER_SIZE;
fp->fbu->scrInfo.qe.tcNext = 0;
/*
* Initialize the color map, the screen, and the mouse.
*/
pmInitColorMap();
pmScreenInit();
fbScroll(fp);
bt478init(&pmfi);
/*
* Initialize old-style pmax screen info.
*/
fi->fi_fbu->scrInfo.max_row = 56;
fi->fi_fbu->scrInfo.max_col = 80;
init_pmaxfbu(fi);
/* These are non-zero on the kn01 framebuffer. Why? */
fi->fi_fbu->scrInfo.min_cur_x = -15;
fi->fi_fbu->scrInfo.min_cur_y = -15;
#ifdef notanymore
bt478InitColorMap(&pmfi); /* done inside bt478init() */
#endif
/*
* Connect to the raster-console pseudo-driver.
*/
fi->fi_glasstty = &pmfb; /*XXX*/
fbconnect((fi->fi_type.fb_depth == 1) ? "KN01 mfb" : "KN01 cfb",
fi, silent);
#ifdef fpinitialized
fp->initialized = 1;
if (cn_tab.cn_fb == (struct pmax_fb *)0)
cn_tab.cn_fb = fp;
#endif
return (1);
}
/*
* ----------------------------------------------------------------------------
*
* pmScreenInit --
*
* Initialize the screen.
*
* Results:
* None.
*
* Side effects:
* The screen is initialized.
*
* ----------------------------------------------------------------------------
*/
static void
pmScreenInit()
{
register struct pmax_fb *fp = &pmfb;
/*
* Home the cursor.
* We want an LSI terminal emulation. We want the graphics
* terminal to scroll from the bottom. So start at the bottom.
*/
fp->row = 55;
fp->col = 0;
/*
* Load the cursor with the default values
*
*/
pmLoadCursor(defCursor);
}
static u_char bg_RGB[3]; /* background color for the cursor */
static u_char fg_RGB[3]; /* foreground color for the cursor */
/*
* ----------------------------------------------------------------------------
*
@ -492,7 +361,8 @@ pmScreenInit()
* ----------------------------------------------------------------------------
*/
static void
pmLoadCursor(cur)
pmLoadCursor(fi, cur)
struct fbinfo *fi;
unsigned short *cur;
{
register PCCRegs *pcc = (PCCRegs *)MACH_PHYS_TO_UNCACHED(KN01_SYS_PCC);
@ -508,6 +378,7 @@ pmLoadCursor(cur)
pcc->cmdr = curReg;
}
#if 0
/*
* ----------------------------------------------------------------------------
*
@ -524,7 +395,8 @@ pmLoadCursor(cur)
* ----------------------------------------------------------------------------
*/
static void
pmRestoreCursorColor()
pmRestoreCursorColor(fi)
struct fbinfo *fi;
{
register VDACRegs *vdac = (VDACRegs *)MACH_PHYS_TO_UNCACHED(KN01_SYS_VDAC);
register int i;
@ -603,13 +475,12 @@ static void
pmInitColorMap()
{
register VDACRegs *vdac = (VDACRegs *)MACH_PHYS_TO_UNCACHED(KN01_SYS_VDAC);
struct pmax_fb *fp = &pmfb;
register int i;
*(volatile char *)MACH_PHYS_TO_UNCACHED(KN01_PHYS_COLMASK_START) = 0xff;
MachEmptyWriteBuffer();
if (fp->isMono) {
if (fi->fi_type.fb_depth == 1) {
vdac->mapWA = 0; MachEmptyWriteBuffer();
for (i = 0; i < 256; i++) {
vdac->map = (i < 128) ? 0x00 : 0xff;
@ -639,43 +510,10 @@ pmInitColorMap()
pmRestoreCursorColor();
}
/*
* ----------------------------------------------------------------------------
*
* pmVDACInit --
*
* Initialize the VDAC.
*
* Results:
* None.
*
* Side effects:
* None.
*
* ----------------------------------------------------------------------------
*/
static void
pmVDACInit()
{
register VDACRegs *vdac = (VDACRegs *)MACH_PHYS_TO_UNCACHED(KN01_SYS_VDAC);
/*
*
* Initialize the VDAC
*/
vdac->overWA = 0x04; MachEmptyWriteBuffer();
vdac->over = 0x00; MachEmptyWriteBuffer();
vdac->over = 0x00; MachEmptyWriteBuffer();
vdac->over = 0x00; MachEmptyWriteBuffer();
vdac->overWA = 0x08; MachEmptyWriteBuffer();
vdac->over = 0x00; MachEmptyWriteBuffer();
vdac->over = 0x00; MachEmptyWriteBuffer();
vdac->over = 0x7f; MachEmptyWriteBuffer();
vdac->overWA = 0x0c; MachEmptyWriteBuffer();
vdac->over = 0xff; MachEmptyWriteBuffer();
vdac->over = 0xff; MachEmptyWriteBuffer();
vdac->over = 0xff; MachEmptyWriteBuffer();
}
#endif /* 0 */
/* should zap pmloadcolormap too, but i haven't fixed the callers yet */
/*
* ----------------------------------------------------------------------------
@ -707,6 +545,8 @@ pmLoadColorMap(ptr)
vdac->map = ptr->Entry.blue; MachEmptyWriteBuffer();
}
/*
*----------------------------------------------------------------------
*
@ -723,44 +563,55 @@ pmLoadColorMap(ptr)
*----------------------------------------------------------------------
*/
void
pmPosCursor(x, y)
pmPosCursor(fi, x, y)
register struct fbinfo *fi;
register int x, y;
{
register PCCRegs *pcc = (PCCRegs *)MACH_PHYS_TO_UNCACHED(KN01_SYS_PCC);
register struct pmax_fb *fp = &pmfb;
if (y < fp->fbu->scrInfo.min_cur_y || y > fp->fbu->scrInfo.max_cur_y)
y = fp->fbu->scrInfo.max_cur_y;
if (x < fp->fbu->scrInfo.min_cur_x || x > fp->fbu->scrInfo.max_cur_x)
x = fp->fbu->scrInfo.max_cur_x;
fp->fbu->scrInfo.cursor.x = x; /* keep track of real cursor */
fp->fbu->scrInfo.cursor.y = y; /* position, indep. of mouse */
if (y < fi->fi_fbu->scrInfo.min_cur_y ||
y > fi->fi_fbu->scrInfo.max_cur_y)
y = fi->fi_fbu->scrInfo.max_cur_y;
if (x < fi->fi_fbu->scrInfo.min_cur_x ||
x > fi->fi_fbu->scrInfo.max_cur_x)
x = fi->fi_fbu->scrInfo.max_cur_x;
fi->fi_fbu->scrInfo.cursor.x = x; /* keep track of real cursor */
fi->fi_fbu->scrInfo.cursor.y = y; /* position, indep. of mouse */
pcc->xpos = PCC_X_OFFSET + x;
pcc->ypos = PCC_Y_OFFSET + y;
}
/*
* pm keyboard and mouse input. Just punt to the generic ones in fb.c
*/
void
pmKbdEvent(ch)
int ch;
/* enable the video display. */
static int pm_video_on (fi)
struct fbinfo *fi;
{
fbKbdEvent(ch, &pmfb);
register PCCRegs *pcc = (PCCRegs *)fi -> fi_base;
if (!fi -> fi_blanked)
return 0;
pcc -> cmdr = curReg & ~(PCC_FOPA | PCC_FOPB);
bt478RestoreCursorColor (fi);
fi -> fi_blanked = 0;
return 0;
}
void
pmMouseEvent(newRepPtr)
MouseReport *newRepPtr;
/* disable the video display. */
static int pm_video_off (fi)
struct fbinfo *fi;
{
fbMouseEvent(newRepPtr, &pmfb);
register PCCRegs *pcc = (PCCRegs *)fi -> fi_base;
if (fi -> fi_blanked)
return 0;
bt478BlankCursor (fi);
pcc -> cmdr = curReg | PCC_FOPA | PCC_FOPB;
fi -> fi_blanked = 1;
return 0;
}
void
pmMouseButtons(newRepPtr)
MouseReport *newRepPtr;
{
fbMouseButtons(newRepPtr, &pmfb);
}
#endif /* NDC */
#endif /* NPM */

View File

@ -1,4 +1,4 @@
/* $NetBSD: promio.c,v 1.1 1995/04/11 10:08:42 mellon Exp $ */
/* $NetBSD: promio.c,v 1.2 1995/09/11 07:45:50 jonathan Exp $ */
/*
* Copyright (c) 1988 University of Utah.
@ -43,6 +43,8 @@
*/
#include <sys/param.h>
#include <sys/device.h>
#include <dev/cons.h>
#include <sys/proc.h>
#include <sys/systm.h>
#include <sys/buf.h>
@ -53,7 +55,6 @@
#include <pmax/stand/dec_prom.h>
#include <pmax/dev/device.h>
#include <pmax/dev/sccreg.h>
#include <pmax/pmax/kn01.h>
#include <pmax/pmax/kn02.h>
@ -63,18 +64,20 @@
#include <pmax/pmax/asic.h>
#include <pmax/pmax/turbochannel.h>
#include <pmax/pmax/pmaxtype.h>
/* #include <pmax/pmax/cons.h> */
#include <dev/cons.h>
#include <machine/machConst.h>
#include <machine/pmioctl.h>
#include <pmax/dev/fbreg.h>
#include <sys/device.h>
#include <machine/fbio.h>
#include <sparc/rcons/raster.h>
#include <machine/fbvar.h>
#include <pmax/dev/fbreg.h>
#include <machine/autoconf.h>
#include <pmax/tc/tc.h>
#include <pm.h>
#include <cfb.h>
#include <mfb.h>
@ -87,6 +90,7 @@
#include <asc.h>
#if NDC > 0
#include <machine/dc7085cons.h>
extern int dcGetc(), dcparam();
extern void dcPutc();
#endif
@ -101,6 +105,8 @@ static int romgetc __P ((dev_t));
static void romputc __P ((dev_t, int));
static void rompollc __P((dev_t, int));
extern int LKgetc __P((dev_t dev)); /* should be in header file, but which one? */
int pmax_boardtype; /* Mother board type */
/*
@ -109,6 +115,7 @@ int pmax_boardtype; /* Mother board type */
#define DTOPDEV 15
#define DCDEV 16
#define SCCDEV 17
#define RCONSDEV 85
/*
* Console I/O is redirected to the appropriate device, either a screen and
@ -116,6 +123,7 @@ int pmax_boardtype; /* Mother board type */
*/
extern struct consdev *cn_tab; /* Console I/O table... */
extern void rcons_vputc __P((dev_t, int)); /* XXX */
struct consdev cd = {
(void (*)(struct consdev *))0, /* probe */
@ -127,19 +135,42 @@ struct consdev cd = {
CN_DEAD,
};
/* should be locals of consinit, but that's split in two til
* new-style config of decstations is finished
*/
/*
* Forward declarations
*/
int consprobetc __P((int prom_slot));
int consprobeslot __P((caddr_t name, void *addr));
void consinit __P((void));
void xconsinit __P((void));
extern struct tc_cpu_desc * cpu_tcdesc __P ((int cputype));
int kbd;
int pending_remcons = 0;
/*
* Console initialization: called early on from main,
* before vm init or startup. Do enough configuration
* to choose and initialize a console.
*/
void
consinit()
{
register int kbd, crt;
int crt;
register char *oscon;
int screen = 0;
extern void (*v_putc) __P ((dev_t, int));
cn_tab = &cd;
(*callv -> _printf)("consinit\n");
/*
* First get the "osconsole" environment variable.
@ -148,9 +179,11 @@ consinit()
crt = kbd = -1;
if (oscon && *oscon >= '0' && *oscon <= '9') {
kbd = *oscon - '0';
/*cn_tab.cn_pri = CN_DEAD;*/
screen = 0;
while (*++oscon) {
if (*oscon == ',')
/*cn_tab.cn_pri = CN_INTERNAL;*/
screen = 1;
else if (screen &&
*oscon >= '0' && *oscon <= '9') {
@ -160,6 +193,12 @@ consinit()
}
}
}
/* we can't do anything until auto-configuration
* has run, and that requires kmalloc(), which
* hasn't been initialized yet. Just keep using
* whatever the PROM vector gave us.
*/
if (pmax_boardtype == DS_PMAX && kbd == 1)
screen = 1;
/*
@ -167,6 +206,7 @@ consinit()
* osconsole to '1' like the PMAX.
*/
if (pmax_boardtype == DS_3MAX && crt == -1 && kbd == 1) {
/* Try to use pmax onboard framebuffer */
screen = 1;
crt = 0;
kbd = 7;
@ -182,7 +222,8 @@ consinit()
#if NDC > 0 && NPM > 0
if (pminit()) {
cd.cn_dev = makedev(DCDEV, DCKBD_PORT);
cd.cn_getc = dcGetc;
cd.cn_getc = LKgetc;
lk_divert(dcGetc);
cd.cn_pri = CN_INTERNAL;
return;
}
@ -209,7 +250,8 @@ consinit()
#if NDC > 0
if (kbd == 7) {
cd.cn_dev = makedev(DCDEV, DCKBD_PORT);
cd.cn_getc = dcGetc;
cd.cn_getc = LKgetc;
lk_divert(dcGetc);
} else
#endif /* NDC */
goto remcons;
@ -220,7 +262,8 @@ consinit()
#if NSCC > 0
if (kbd == 3) {
cd.cn_dev = makedev(SCCDEV, SCCKBD_PORT);
cd.cn_getc = sccGetc;
lk_divert(sccGetc);
cd.cn_getc = LKgetc;
} else
#endif /* NSCC */
goto remcons;
@ -230,40 +273,52 @@ consinit()
goto remcons;
};
/*
* Check for a suitable turbochannel frame buffer.
*/
if (tc_slot_info[crt].driver_name) {
#if NMFB > 0
if (strcmp(tc_slot_info[crt].driver_name, "mfb") == 0 &&
mfbinit(tc_slot_info[crt].k1seg_address)) {
if (consprobetc(crt)) {
cd.cn_pri = CN_NORMAL;
#ifdef RCONS_HACK
/* FIXME */ cd.cn_putc = v_putc;
/* FIXME */ cd.cn_dev = makedev (RCONSDEV, 0);
#endif /* RCONS_HACK */
cd.cn_putc = rcons_vputc; /*XXX*/
return;
}
#endif /* NMFB */
#if NSFB > 0
if (strcmp(tc_slot_info[crt].driver_name, "sfb") == 0 &&
sfbinit(tc_slot_info[crt].k1seg_address, 0)) {
cd.cn_pri = CN_NORMAL;
return;
}
#endif /* NSFB */
#if NCFB > 0
if (strcmp(tc_slot_info[crt].driver_name, "cfb") == 0 &&
cfbinit(tc_slot_info[crt].k1seg_address)) {
cd.cn_pri = CN_NORMAL;
return;
}
#endif /* NCFB */
printf("crt: %s not supported as console device\n",
tc_slot_info[crt].driver_name);
} else
printf("No crt console device in slot %d\n", crt);
}
remcons:
/*
* Configure a serial port as a remote console.
*/
/* XXX serial drivers need to be rewritten to handle
* init this early. Defer switching to non-PROM
* driver until later.
*/
pending_remcons = 1;
printf("Using PROM serial output until serial drivers initialized\n");
/* We never cahnged output; go back to using PROM input */
cd.cn_dev = makedev (0, 0);
cd.cn_getc = /*(int (*)(dev_t)) */ romgetc;
}
/*
* Configure a serial port as a remote console.
*/
void
xconsinit()
{
if (!pending_remcons)
return;
pending_remcons = 0;
switch (pmax_boardtype) {
case DS_PMAX:
#if NDC > 0
@ -309,6 +364,91 @@ remcons:
printf("Can't configure console!\n");
}
/*
* Probe for a framebuffer option card. Configure the first one
* found as a console.
*/
int
consprobetc(prom_slot)
int prom_slot;
{
void *slotaddr;
int slot;
struct tc_cpu_desc * sc_desc = cpu_tcdesc(pmax_boardtype);
char namebuf[20];
if (sc_desc == NULL)
return;
/*printf("Looking for fb console in slot %d", slot);*/
/*
* Try to configure each turbochannel (or CPU-internal) device.
* Knows about gross internals of TurboChannel bus autoconfig
* descriptor, which needs to be fixed badly.
*/
for (slot = 0; slot < sc_desc->tcd_ndevs; slot++) {
slotaddr = (void *)sc_desc->tcd_slots[slot].tsd_dense;
/*printf("probing slot %d at 0x%x\n", slot, slotaddr);*/
if (tc_checkdevmem(slotaddr) == 0)
continue;
if (tc_checkslot(slotaddr, namebuf) == 0)
continue;
if (consprobeslot(namebuf, slotaddr))
return (1);
}
return (0);
}
/*
* Try and configure one slot as framebuffer console.
* Accept only the framebuffers configured in.
*/
int
consprobeslot(name, addr)
char *name;
void * addr;
{
/*printf(", trying to init a \"%s\"", name);*/
#define DRIVER_FOR_SLOT(slotname, drivername) \
(strcmp (slotname, drivername) == 0)
#if NMFB > 0
if (DRIVER_FOR_SLOT(name, "PMAG-AA ") &&
mfbinit(addr, 0, 1)) {
cd.cn_pri = CN_NORMAL;
return (1);
}
#endif /* NMFB */
#if NSFB > 0
if (DRIVER_FOR_SLOT(name, "PMAGB-BA") &&
sfbinit(addr, 0, 1)) {
cd.cn_pri = CN_NORMAL;
return (1);
}
#endif /* NSFB */
#if NCFB > 0
/*"cfb"*/
if (DRIVER_FOR_SLOT(name, "PMAG-BA ") &&
cfbinit(NULL, addr, 0, 1)) {
cd.cn_pri = CN_NORMAL;
return (1);
}
#endif /* NCFB */
return (0);
}
/*
* Get character from ROM console.
*/
@ -342,3 +482,33 @@ static void rompollc (dev, c)
return;
}
extern struct tty *constty; /* virtual console output device */
extern struct consdev *cn_tab; /* physical console device info */
extern struct vnode *cn_devvp; /* vnode for underlying device. */
/*ARGSUSED*/
int
pmax_cnselect(dev, rw, p)
dev_t dev;
int rw;
struct proc *p;
{
/*
* Redirect the ioctl, if that's appropriate.
* I don't want to think of the possible side effects
* of console redirection here.
*/
if (constty != NULL && (cn_tab == NULL || cn_tab->cn_pri != CN_REMOTE))
dev = constty->t_dev;
else if (cn_tab == NULL)
return ENXIO;
else
dev = cn_tab->cn_dev;
#ifdef RCONS
if (cn_tab -> cn_dev == makedev (85, 0))
return rconsselect (cn_tab -> cn_dev, rw, p);
#endif
return (ttselect(cn_tab->cn_dev, rw, p));
}

View File

@ -0,0 +1,632 @@
/* $NetBSD: qvss_compat.c,v 1.1 1995/09/11 07:45:47 jonathan Exp $ */
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Ralph Campbell and Rick Macklem.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. 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, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)fb.c 8.1 (Berkeley) 6/10/93
*/
/*
* devGraphics.c --
*
* This file contains machine-dependent routines for the graphics device.
*
* Copyright (C) 1989 Digital Equipment Corporation.
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appears in all copies.
* Digital Equipment Corporation makes no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*
* from: Header: /sprite/src/kernel/dev/ds3100.md/RCS/devGraphics.c,
* v 9.2 90/02/13 22:16:24 shirriff Exp SPRITE (DECWRL)";
*/
/*
* This file has all the routines common to the various frame buffer drivers
* including a generic ioctl routine. The pmax_fb structure is passed into the
* routines and has device specifics stored in it.
* The LK201 keycode mapping routine is also here along with initialization
* functions for the keyboard and mouse.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/kernel.h>
#include <sys/proc.h>
#include <sys/mman.h>
#include <sys/vnode.h>
#include <vm/vm.h>
#include <miscfs/specfs/specdev.h>
#include <machine/pmioctl.h>
#include <machine/fbio.h>
#include <machine/fbvar.h>
#include <pmax/dev/fbreg.h>
#include <pmax/dev/lk201.h>
/*#include <pmax/stand/dec_prom.h>*/
#include <pmax/pmax/cons.h>
#include <pmax/pmax/pmaxtype.h>
#include <dc.h>
#include <scc.h>
#include <dtop.h>
/*
* Forward / extern references.
*/
extern void pmEventQueueInit __P((pmEventQueue *qe));
void fbKbdEvent(), fbMouseEvent(), fbMouseButtons(), fbScroll();
extern int pmax_boardtype;
#if NDC > 0
extern void (*dcDivertXInput)();
extern void (*dcMouseEvent)();
extern void (*dcMouseButtons)();
#endif
#if NSCC > 0
extern void (*sccDivertXInput)();
extern void (*sccMouseEvent)();
extern void (*sccMouseButtons)();
#endif
#if NDTOP > 0
extern void (*dtopDivertXInput)();
extern void (*dtopMouseEvent)();
extern void (*dtopMouseButtons)();
#endif
#if 0 /*XXX*/
#if NDC > 0
#include <machine/dc7085cons.h>
extern int dcGetc(), dcparam();
extern void dcPutc();
#endif
#if NDTOP > 0
#include <pmax/dev/dtopreg.h>
extern void dtopKBDPutc();
#endif
#if NSCC > 0
#include <pmax/dev/sccreg.h>
extern int sccGetc(), sccparam();
extern void sccPutc();
#endif
#endif /* 0 */
extern struct fbinfo *firstfi;
/*
* Initialize the old-style pmax framebuffer structure from a new-style
* rcons structure. Can die when all the old style pmax_fb structures
* are gone. Note that the QVSS/pm mapped event buffer includes the
* fbu field initialized below.
*/
init_pmaxfbu(fi)
struct fbinfo *fi;
{
int tty_rows, tty_cols; /* rows, cols for glass-tty mode */
register struct fbuaccess *fbu = NULL;
if (fi == NULL || fi->fi_fbu == NULL)
panic("init_pmaxfb: given null pointer to framebuffer\n");
/* XXX don't rely on there being a pmax_fb struct */
fbu = fi->fi_fbu;
/* fb dimensions */
fbu->scrInfo.max_x = fi->fi_type.fb_width;
fbu->scrInfo.max_y = fi->fi_type.fb_height;
fbu->scrInfo.max_cur_x = fbu->scrInfo.max_x - 1;
fbu->scrInfo.max_cur_y = fbu->scrInfo.max_y - 1;
/* these have the same initial value on qvss-style framebuffers */
fbu->scrInfo.version = 11;
fbu->scrInfo.mthreshold = 4;
fbu->scrInfo.mscale = 2;
/* this is not always right (pm on kn01) but it's a common case */
fbu->scrInfo.min_cur_x = 0;
fbu->scrInfo.min_cur_y = 0;
/*
* Compute glass-tty dimensions. These don't belong here
* anymore, but the Ultrix and 4.3+ bsd drivers put them
* in the event structure mapped into user address space.
*/
tty_cols = 80;
/* A guess, but correct for 1024x864, 1024x768 and 1280x1024 */
tty_rows = (fi->fi_type.fb_height / 15) - 1;
if (tty_rows != fbu->scrInfo.max_row ||
tty_cols != fbu->scrInfo.max_col)
printf("framebuffer init: size mismatch",
"given %dx%d, compute %dx%x\n",
fbu->scrInfo.max_row, fbu->scrInfo.max_col,
tty_rows, tty_cols);
pmEventQueueInit(&fi->fi_fbu->scrInfo.qe);
}
/*
* Initialize the qvss-style ringbuffer of mouse button/move
* events to be empty. Called both when initializing the
* console softc and on each new open of that device.
*/
void
pmEventQueueInit(qe)
pmEventQueue *qe;
{
qe->timestamp_ms = TO_MS(time);
qe->eSize = PM_MAXEVQ;
qe->eHead = qe->eTail = 0;
qe->tcSize = MOTION_BUFFER_SIZE;
qe->tcNext = 0;
}
/*
*----------------------------------------------------------------------
*
* fbKbdEvent --
*
* Process a received character.
*
* Results:
* None.
*
* Side effects:
* Events added to the queue.
*
*----------------------------------------------------------------------
*/
void
fbKbdEvent(ch, fi)
int ch;
register struct fbinfo *fi;
{
register pmEvent *eventPtr;
int i;
register struct fbuaccess *fbu = NULL;
if (!fi->fi_open)
return;
fbu = fi->fi_fbu;
/*
* See if there is room in the queue.
*/
i = PM_EVROUND(fbu->scrInfo.qe.eTail + 1);
if (i == fbu->scrInfo.qe.eHead)
return;
/*
* Add the event to the queue.
*/
eventPtr = &fbu->events[fbu->scrInfo.qe.eTail];
eventPtr->type = BUTTON_RAW_TYPE;
eventPtr->device = KEYBOARD_DEVICE;
eventPtr->x = fbu->scrInfo.mouse.x;
eventPtr->y = fbu->scrInfo.mouse.y;
eventPtr->time = TO_MS(time);
eventPtr->key = ch;
fbu->scrInfo.qe.eTail = i;
selwakeup(&fi->fi_selp);
}
/*
*----------------------------------------------------------------------
*
* fbMouseEvent --
*
* Process a mouse event.
*
* Results:
* None.
*
* Side effects:
* An event is added to the event queue.
*
*----------------------------------------------------------------------
*/
void
fbMouseEvent(newRepPtr, fi)
register MouseReport *newRepPtr;
register struct fbinfo *fi;
{
unsigned milliSec;
int i;
pmEvent *eventPtr;
register struct fbuaccess *fbu = NULL;
if (!fi->fi_open)
return;
fbu = fi->fi_fbu;
milliSec = TO_MS(time);
/*
* Check to see if we have to accelerate the mouse
*/
if (fbu->scrInfo.mscale >= 0) {
if (newRepPtr->dx >= fbu->scrInfo.mthreshold) {
newRepPtr->dx +=
(newRepPtr->dx - fbu->scrInfo.mthreshold) *
fbu->scrInfo.mscale;
}
if (newRepPtr->dy >= fbu->scrInfo.mthreshold) {
newRepPtr->dy +=
(newRepPtr->dy - fbu->scrInfo.mthreshold) *
fbu->scrInfo.mscale;
}
}
/*
* Update mouse position
*/
if (newRepPtr->state & MOUSE_X_SIGN) {
fbu->scrInfo.mouse.x += newRepPtr->dx;
if (fbu->scrInfo.mouse.x > fbu->scrInfo.max_cur_x)
fbu->scrInfo.mouse.x = fbu->scrInfo.max_cur_x;
} else {
fbu->scrInfo.mouse.x -= newRepPtr->dx;
if (fbu->scrInfo.mouse.x < fbu->scrInfo.min_cur_x)
fbu->scrInfo.mouse.x = fbu->scrInfo.min_cur_x;
}
if (newRepPtr->state & MOUSE_Y_SIGN) {
fbu->scrInfo.mouse.y -= newRepPtr->dy;
if (fbu->scrInfo.mouse.y < fbu->scrInfo.min_cur_y)
fbu->scrInfo.mouse.y = fbu->scrInfo.min_cur_y;
} else {
fbu->scrInfo.mouse.y += newRepPtr->dy;
if (fbu->scrInfo.mouse.y > fbu->scrInfo.max_cur_y)
fbu->scrInfo.mouse.y = fbu->scrInfo.max_cur_y;
}
/*
* Move the hardware cursor.
*/
(*fi->fi_driver->fbd_poscursor)
(fi, fbu->scrInfo.mouse.x, fbu->scrInfo.mouse.y);
/*
* Store the motion event in the motion buffer.
*/
fbu->tcs[fbu->scrInfo.qe.tcNext].time = milliSec;
fbu->tcs[fbu->scrInfo.qe.tcNext].x = fbu->scrInfo.mouse.x;
fbu->tcs[fbu->scrInfo.qe.tcNext].y = fbu->scrInfo.mouse.y;
if (++fbu->scrInfo.qe.tcNext >= MOTION_BUFFER_SIZE)
fbu->scrInfo.qe.tcNext = 0;
if (fbu->scrInfo.mouse.y < fbu->scrInfo.mbox.bottom &&
fbu->scrInfo.mouse.y >= fbu->scrInfo.mbox.top &&
fbu->scrInfo.mouse.x < fbu->scrInfo.mbox.right &&
fbu->scrInfo.mouse.x >= fbu->scrInfo.mbox.left)
return;
fbu->scrInfo.mbox.bottom = 0;
if (PM_EVROUND(fbu->scrInfo.qe.eTail + 1) == fbu->scrInfo.qe.eHead)
return;
i = PM_EVROUND(fbu->scrInfo.qe.eTail - 1);
if ((fbu->scrInfo.qe.eTail != fbu->scrInfo.qe.eHead) &&
(i != fbu->scrInfo.qe.eHead)) {
pmEvent *eventPtr;
eventPtr = &fbu->events[i];
if (eventPtr->type == MOTION_TYPE) {
eventPtr->x = fbu->scrInfo.mouse.x;
eventPtr->y = fbu->scrInfo.mouse.y;
eventPtr->time = milliSec;
eventPtr->device = MOUSE_DEVICE;
return;
}
}
/*
* Put event into queue and wakeup any waiters.
*/
eventPtr = &fbu->events[fbu->scrInfo.qe.eTail];
eventPtr->type = MOTION_TYPE;
eventPtr->time = milliSec;
eventPtr->x = fbu->scrInfo.mouse.x;
eventPtr->y = fbu->scrInfo.mouse.y;
eventPtr->device = MOUSE_DEVICE;
fbu->scrInfo.qe.eTail = PM_EVROUND(fbu->scrInfo.qe.eTail + 1);
selwakeup(&fi->fi_selp);
}
/*
*----------------------------------------------------------------------
*
* fbMouseButtons --
*
* Process mouse buttons.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
void
fbMouseButtons(newRepPtr, fi)
MouseReport *newRepPtr;
register struct fbinfo *fi;
{
static char temp, oldSwitch, newSwitch;
int i, j;
pmEvent *eventPtr;
static MouseReport lastRep;
register struct fbuaccess *fbu = NULL;
if (!fi->fi_open)
return;
fbu = fi->fi_fbu;
newSwitch = newRepPtr->state & 0x07;
oldSwitch = lastRep.state & 0x07;
temp = oldSwitch ^ newSwitch;
if (temp == 0)
return;
for (j = 1; j < 8; j <<= 1) {
if ((j & temp) == 0)
continue;
/*
* Check for room in the queue
*/
i = PM_EVROUND(fbu->scrInfo.qe.eTail+1);
if (i == fbu->scrInfo.qe.eHead)
return;
/*
* Put event into queue.
*/
eventPtr = &fbu->events[fbu->scrInfo.qe.eTail];
switch (j) {
case RIGHT_BUTTON:
eventPtr->key = EVENT_RIGHT_BUTTON;
break;
case MIDDLE_BUTTON:
eventPtr->key = EVENT_MIDDLE_BUTTON;
break;
case LEFT_BUTTON:
eventPtr->key = EVENT_LEFT_BUTTON;
}
if (newSwitch & j)
eventPtr->type = BUTTON_DOWN_TYPE;
else
eventPtr->type = BUTTON_UP_TYPE;
eventPtr->device = MOUSE_DEVICE;
eventPtr->time = TO_MS(time);
eventPtr->x = fbu->scrInfo.mouse.x;
eventPtr->y = fbu->scrInfo.mouse.y;
fbu->scrInfo.qe.eTail = i;
}
selwakeup(&fi->fi_selp);
lastRep = *newRepPtr;
fbu->scrInfo.mswitches = newSwitch;
}
/*
* Use vm_mmap() to map the frame buffer and shared data into the user's
* address space.
* Return errno if there was an error.
*/
fbmmap_fb(fi, dev, data, p)
struct fbinfo *fi;
dev_t dev;
caddr_t data;
struct proc *p;
{
int error;
vm_offset_t addr;
vm_size_t len;
struct vnode vn;
struct specinfo si;
struct fbuaccess *fbp;
register struct fbuaccess *fbu = fi->fi_fbu;
len = pmax_round_page(((vm_offset_t)fbu & PGOFSET) +
sizeof(struct fbuaccess)) +
pmax_round_page(fi->fi_type.fb_size);
addr = (vm_offset_t)0x20000000; /* XXX */
vn.v_type = VCHR; /* XXX */
vn.v_specinfo = &si; /* XXX */
vn.v_rdev = dev; /* XXX */
/*
* Map the all the data the user needs access to into
* user space.
*/
error = vm_mmap(&p->p_vmspace->vm_map, &addr, len,
VM_PROT_ALL, VM_PROT_ALL, MAP_SHARED, (caddr_t)&vn,
(vm_offset_t)0);
if (error)
return (error);
fbp = (struct fbuaccess *)(addr + ((vm_offset_t)fbu & PGOFSET));
*(PM_Info **)data = &fbp->scrInfo;
fbu->scrInfo.qe.events = fbp->events;
fbu->scrInfo.qe.tcs = fbp->tcs;
fbu->scrInfo.planemask = (char *)0;
/*
* Map the frame buffer into the user's address space.
*/
fbu->scrInfo.bitmap = (char *)pmax_round_page(fbp + 1);
return (0);
}
/*
* Generic functions for keyboard and mouse input.
* Just use the "generic" qvss/pm-compatible functions above, but pass them
* the soft state for the first framebuffer found on this system.
* We don't support more than one mouse, even for multiple
* framebuffers, so this should be adequate.
* It also relieves each fb driver from having to provide its own
* version of these functions.
*
* TODO: change the callers of these to pass a pointer to the struct fbinfo,
* thus finessing the problem.
*/
void
genKbdEvent(ch)
int ch;
{
fbKbdEvent(ch, firstfi);
}
void
genMouseEvent(newRepPtr)
MouseReport *newRepPtr;
{
fbMouseEvent(newRepPtr, firstfi);
}
void
genMouseButtons(newRepPtr)
MouseReport *newRepPtr;
{
fbMouseButtons(newRepPtr, firstfi);
}
/*
* Configure the mouse and keyboard based on machine type
*/
void
genConfigMouse()
{
int s;
s = spltty();
switch (pmax_boardtype) {
#if NDC > 0
case DS_3MAX:
case DS_PMAX:
dcDivertXInput = genKbdEvent;
dcMouseEvent = genMouseEvent;
dcMouseButtons = genMouseButtons;
break;
#endif
#if NSCC > 1
case DS_3MIN:
case DS_3MAXPLUS:
sccDivertXInput = genKbdEvent;
sccMouseEvent = genMouseEvent;
sccMouseButtons = genMouseButtons;
break;
#endif
#if NDTOP > 0
case DS_MAXINE:
dtopDivertXInput = genKbdEvent;
dtopMouseEvent = genMouseEvent;
dtopMouseButtons = genMouseButtons;
break;
#endif
default:
printf("Can't configure mouse/keyboard\n");
};
splx(s);
}
/*
* and deconfigure them
*/
void
genDeconfigMouse()
{
int s;
s = spltty();
switch (pmax_boardtype) {
#if NDC > 0
case DS_3MAX:
case DS_PMAX:
dcDivertXInput = (void (*)())0;
dcMouseEvent = (void (*)())0;
dcMouseButtons = (void (*)())0;
break;
#endif
#if NSCC > 1
case DS_3MIN:
case DS_3MAXPLUS:
sccDivertXInput = (void (*)())0;
sccMouseEvent = (void (*)())0;
sccMouseButtons = (void (*)())0;
break;
#endif
#if NDTOP > 0
case DS_MAXINE:
dtopDivertXInput = (void (*)())0;
dtopMouseEvent = (void (*)())0;
dtopMouseButtons = (void (*)())0;
break;
#endif
default:
printf("Can't deconfigure mouse/keyboard\n");
};
}
/*
* And a mouse-report handler for redirected mouse input.
*/
#include "dec_mouse.c"

View File

@ -1,13 +1,11 @@
/* $NetBSD: rcons.c,v 1.2 1995/04/21 01:24:33 mellon Exp $ */
/* $NetBSD: rcons.c,v 1.3 1995/09/11 07:45:48 jonathan Exp $ */
/*
* Copyright (c) 1988 University of Utah.
* Copyright (c) 1992, 1993
* Copyright (c) 1995
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* the Systems Programming Group of the University of Utah Computer
* Science Department and Ralph Campbell.
* Ted Lemon.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@ -37,11 +35,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* from: Utah Hdr: cons.c 1.1 90/07/09
*
* @(#)cons.c 8.2 (Berkeley) 1/11/94
*/
#include <rcons.h>
#if NRCONS > 0
#include <sys/param.h>
#include <sys/proc.h>
#include <sys/systm.h>
@ -49,11 +47,12 @@
#include <sys/ioctl.h>
#include <sys/tty.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/conf.h>
#include <sys/vnode.h>
#include <pmax/stand/dec_prom.h>
#include <pmax/dev/device.h>
#include <pmax/dev/sccreg.h>
#include <pmax/pmax/kn01.h>
#include <pmax/pmax/kn02.h>
@ -65,16 +64,15 @@
#include <pmax/pmax/pmaxtype.h>
#include <dev/cons.h>
#include <machine/machConst.h>
#include <machine/pmioctl.h>
#include <pmax/dev/fbreg.h>
#include <sys/device.h>
#include <machine/fbio.h>
#include <sparc/rcons/raster.h>
#include <machine/fbvar.h>
#include <rcons.h>
#include <machine/machConst.h>
#include <machine/pmioctl.h>
#include <pmax/dev/fbreg.h>
/*
* Console I/O is redirected to the appropriate device, either a screen and
@ -86,6 +84,11 @@ struct tty *fbconstty; /* Frame buffer console tty... */
struct tty rcons_tty [NRCONS]; /* Console tty struct... */
extern struct consdev *cn_tab; /* Console I/O table... */
struct vnode *cn_in_devvp; /* vnode for underlying input device. */
dev_t cn_in_dev = NODEV; /* console input device. */
char rcons_maxcols [20];
/* rcons_connect is called by fbconnect when the first frame buffer is
attached. That frame buffer will always be the console frame buffer. */
@ -94,7 +97,11 @@ rcons_connect (info)
{
static struct fbdevice fb;
static int row, col;
extern int (*v_putc)(int);
/* If we're running a serial console, don't set up a raster console
even if there's a device that can support it. */
if (cn_tab -> cn_pri == CN_REMOTE)
return;
fbconstty = &rcons_tty [0];
fbconstty->t_dev = makedev(85, 0); /* /dev/console */
@ -112,24 +119,52 @@ rcons_connect (info)
fb.fb_p0 = 0;
fb.fb_p1 = 0;
row = 0; col = 0;
fb.fb_row = &row;
fb.fb_col = &col;
fb.fb_maxrow = 80;
fb.fb_maxcol = 34;
#define HW_FONT_WIDTH 8
#define HW_FONT_HEIGHT 15
sprintf (rcons_maxcols, "%d", fb.fb_type.fb_height / HW_FONT_HEIGHT);
row = (fb.fb_type.fb_height / HW_FONT_HEIGHT) - 1;
col = 0;
rcons_init (&fb);
cn_tab -> cn_putc = v_putc;
cn_tab -> cn_dev = makedev (85, 0);
/* constty = fbconstty; */
fb.fb_xorigin = 0;
fb.fb_yorigin = 0;
}
/* ARGSUSED */
rconsattach (n)
int n;
{
printf ("rcons%d\n", n);
register struct tty *tp = &rcons_tty [0];
int status;
/* Set up the tty queues now... */
clalloc(&tp->t_rawq, 1024, 1);
clalloc(&tp->t_canq, 1024, 1);
/* output queue doesn't need quoting */
clalloc(&tp->t_outq, 1024, 0);
#ifdef DEBUG
printf("rconsattach: %d raster consoles\n", n);
#endif
/* Try to set up the input device... */
if (cn_in_dev != NODEV && cn_in_devvp == NULLVP) {
/* try to get a reference on its vnode, but fail silently */
cdevvp(cn_in_dev, &cn_in_devvp);
status = ((*cdevsw[major(cn_in_dev)].d_open)
(cn_in_dev, O_NONBLOCK, S_IFCHR, curproc)); /* XXX */
if (status)
printf ("rconsattach: input device open failed: %d\n",
status);
}
/* Now the input side has been opened cleanly, we can dispense
* with any special-case console input hacks, and point the
* console device at rcons.
*/
/* FIXME */ cn_tab->cn_dev = makedev (/*RCONSDEV*/85, 0);
}
/* ARGSUSED */
@ -140,14 +175,7 @@ rconsopen(dev, flag, mode, p)
{
register struct tty *tp = &rcons_tty [0];
static int firstopen = 1;
if(firstopen) {
clalloc(&tp->t_rawq, 1024, 1);
clalloc(&tp->t_canq, 1024, 1);
/* output queue doesn't need quoting */
clalloc(&tp->t_outq, 1024, 0);
firstopen = 0;
}
int status;
if ((tp->t_state & TS_ISOPEN) == 0) {
/*
@ -163,7 +191,9 @@ rconsopen(dev, flag, mode, p)
ttsetwater(tp);
} else if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0)
return (EBUSY);
return ((*linesw[tp->t_line].l_open)(dev, tp));
status = (*linesw[tp->t_line].l_open)(dev, tp);
return status;
}
/* ARGSUSED */
@ -173,9 +203,11 @@ rconsclose(dev, flag, mode, p)
struct proc *p;
{
register struct tty *tp = &rcons_tty [0];
struct vnode *vp;
(*linesw[tp->t_line].l_close)(tp, flag);
ttyclose(tp);
return (0);
}
@ -228,7 +260,7 @@ rconsioctl(dev, cmd, data, flag, p)
return (ENOTTY);
}
/*ARGSUSED*/
/* ARGSUSED */
rconsstop (tp, rw)
struct tty *tp;
int rw;
@ -261,3 +293,22 @@ rconsstrategy(bp)
struct buf *bp;
{
}
/* Called by real input device when there is input for rcons. Passes
input through line discpline interrupt routine... */
rcons_input (dev, ic)
dev_t dev;
int ic;
{
struct tty *tp;
int unit = minor (dev);
if (unit > NRCONS)
return;
tp = &rcons_tty [unit];
if (!(tp -> t_state & TS_ISOPEN)) {
return;
}
(*linesw [tp -> t_line].l_rint)(ic, tp);
}
#endif /* NRCONS > 0 */

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
/* $NetBSD: xcfb.c,v 1.6 1995/08/10 04:21:35 jonathan Exp $ */
/* $NetBSD: xcfb.c,v 1.7 1995/09/11 07:45:42 jonathan Exp $ */
/*-
* Copyright (c) 1992, 1993
@ -80,6 +80,8 @@
* v 9.2 90/02/13 22:16:24 shirriff Exp SPRITE (DECWRL)";
*/
#include <fb.h>
#include <xcfb.h>
#include <dtop.h>
#if NXCFB > 0
@ -103,45 +105,67 @@ xcfb needs dtop device
#include <machine/machConst.h>
#include <machine/pmioctl.h>
#include <pmax/pmax/maxine.h>
#include <machine/fbio.h>
#include <machine/fbvar.h>
#include <pmax/pmax/cons.h>
#include <pmax/dev/xcfbreg.h>
#include <pmax/dev/ims332.h>
#include <pmax/pmax/maxine.h>
#include <pmax/pmax/pmaxtype.h>
#include <pmax/dev/device.h>
#include <pmax/dev/xcfbreg.h>
#include <pmax/dev/dtopreg.h>
#include <pmax/dev/fbreg.h>
/*
* These need to be mapped into user space.
*/
struct fbuaccess xcfbu;
struct pmax_fb xcfbfb;
/*
* rcons methods and globals.
*/
struct pmax_fbtty xcfbfb;
struct fbinfo xcfbfi; /*XXX*/
extern struct cfdriver cfb;
#define CMAP_BITS (3 * 256) /* 256 entries, 3 bytes per. */
static u_char cmap_bits [NXCFB * CMAP_BITS]; /* One colormap per cfb... */
#define XCFB_FB_SIZE 0x100000 /* size of raster (mapped into userspace) */
struct fbdriver xcfb_driver = {
ims332_video_on,
ims332_video_off,
ims332InitColorMap,
ims332GetColorMap,
ims332LoadColorMap,
ims332PosCursor,
ims332LoadCursor,
ims332CursorColor
};
/*
* Forward references.
*/
static void xcfbScreenInit __P(());
static void xcfbLoadCursor __P((u_short *ptr));
static void xcfbRestoreCursorColor __P(());
static void xcfbCursorColor __P((u_int *color));
void xcfbPosCursor __P((int x, int y));
static void xcfbInitColorMap __P(());
static void xcfbLoadColorMap __P ((ColorMap *ptr));
static u_int ims332_read_register();
static void ims332_write_register();
static void ims332_load_colormap_entry();
static void ims332_video_off();
static void ims332_video_on();
extern void fbScreenInit __P((struct fbinfo *fi));
void genKbdEvent(), genMouseEvent(), genMouseButtons();
void xcfbKbdEvent(), xcfbMouseEvent(), xcfbMouseButtons();
extern void dtopKBDPutc();
extern void (*dtopDivertXInput)();
extern void (*dtopMouseEvent)();
extern void (*dtopMouseButtons)();
extern int pmax_boardtype;
extern u_short defCursor[32];
extern struct consdev cn_tab;
/*
@ -187,606 +211,103 @@ xcfbattach(parent, self, aux)
{
struct confargs *ca = aux;
if (!xcfbinit(BUS_CVTADDR(ca)))
if (!xcfbinit(BUS_CVTADDR(ca), self->dv_unit, 0));
return;
/* mark slot as potential console */
framebuffer_in_slot(ca->ca_slotpri);
/* no interrupts for XCFB */
/*BUS_INTR_ESTABLISH(ca, sccintr, self->dv_unit);*/
/*BUS_INTR_ESTABLISH(ca, xcfbintr, self->dv_unit);*/
printf("\n");
}
/*ARGSUSED*/
xcfbopen(dev, flag)
dev_t dev;
int flag;
{
register struct pmax_fb *fp = &xcfbfb;
int s;
if (!fp->initialized)
return (ENXIO);
if (fp->GraphicsOpen)
return (EBUSY);
fp->GraphicsOpen = 1;
xcfbInitColorMap();
/*
* Set up event queue for later
*/
fp->fbu->scrInfo.qe.eSize = PM_MAXEVQ;
fp->fbu->scrInfo.qe.eHead = fp->fbu->scrInfo.qe.eTail = 0;
fp->fbu->scrInfo.qe.tcSize = MOTION_BUFFER_SIZE;
fp->fbu->scrInfo.qe.tcNext = 0;
fp->fbu->scrInfo.qe.timestamp_ms = TO_MS(time);
s = spltty();
dtopDivertXInput = xcfbKbdEvent;
dtopMouseEvent = xcfbMouseEvent;
dtopMouseButtons = xcfbMouseButtons;
splx(s);
return (0);
}
/*ARGSUSED*/
xcfbclose(dev, flag)
dev_t dev;
int flag;
{
register struct pmax_fb *fp = &xcfbfb;
int s;
if (!fp->GraphicsOpen)
return (EBADF);
fp->GraphicsOpen = 0;
xcfbInitColorMap();
s = spltty();
dtopDivertXInput = (void (*)())0;
dtopMouseEvent = (void (*)())0;
dtopMouseButtons = (void (*)())0;
splx(s);
xcfbScreenInit();
bzero((caddr_t)fp->fr_addr, 1024 * 768);
xcfbPosCursor(fp->col * 8, fp->row * 15);
return (0);
}
/*ARGSUSED*/
xcfbioctl(dev, cmd, data, flag, p)
dev_t dev;
caddr_t data;
struct proc *p;
{
register struct pmax_fb *fp = &xcfbfb;
int s;
switch (cmd) {
case QIOCGINFO:
return (fbmmap(fp, dev, data, p));
case QIOCPMSTATE:
/*
* Set mouse state.
*/
fp->fbu->scrInfo.mouse = *(pmCursor *)data;
xcfbPosCursor(fp->fbu->scrInfo.mouse.x, fp->fbu->scrInfo.mouse.y);
break;
case QIOCINIT:
/*
* Initialize the screen.
*/
xcfbScreenInit();
break;
case QIOCKPCMD:
{
pmKpCmd *kpCmdPtr;
unsigned char *cp;
kpCmdPtr = (pmKpCmd *)data;
if (kpCmdPtr->nbytes == 0)
kpCmdPtr->cmd |= 0x80;
if (!fp->GraphicsOpen)
kpCmdPtr->cmd |= 1;
(*fp->KBDPutc)(fp->kbddev, (int)kpCmdPtr->cmd);
cp = &kpCmdPtr->par[0];
for (; kpCmdPtr->nbytes > 0; cp++, kpCmdPtr->nbytes--) {
if (kpCmdPtr->nbytes == 1)
*cp |= 0x80;
(*fp->KBDPutc)(fp->kbddev, (int)*cp);
}
break;
}
case QIOCADDR:
*(PM_Info **)data = &fp->fbu->scrInfo;
break;
case QIOWCURSOR:
xcfbLoadCursor((unsigned short *)data);
break;
case QIOWCURSORCOLOR:
xcfbCursorColor((unsigned int *)data);
break;
case QIOSETCMAP:
xcfbLoadColorMap((ColorMap *)data);
break;
case QIOKERNLOOP:
s = spltty();
dtopDivertXInput = xcfbKbdEvent;
dtopMouseEvent = xcfbMouseEvent;
dtopMouseButtons = xcfbMouseButtons;
splx(s);
break;
case QIOKERNUNLOOP:
s = spltty();
dtopDivertXInput = (void (*)())0;
dtopMouseEvent = (void (*)())0;
dtopMouseButtons = (void (*)())0;
splx(s);
break;
case QIOVIDEOON:
xcfbRestoreCursorColor();
ims332_video_on();
break;
case QIOVIDEOOFF:
ims332_video_off();
break;
default:
printf("xcfb0: Unknown ioctl command %x\n", cmd);
return (EINVAL);
}
return (0);
}
/*
* Return the physical page number that corresponds to byte offset 'off'.
*/
/*ARGSUSED*/
xcfbmmap(dev, off, prot)
dev_t dev;
{
int len;
len = pmax_round_page(((vm_offset_t)&xcfbu & PGOFSET) + sizeof(xcfbu));
if (off < len)
return pmax_btop(MACH_CACHED_TO_PHYS(&xcfbu) + off);
off -= len;
if (off >= xcfbfb.fr_size)
return (-1);
return pmax_btop(MACH_UNCACHED_TO_PHYS(xcfbfb.fr_addr) + off);
}
xcfbselect(dev, flag, p)
dev_t dev;
int flag;
struct proc *p;
{
struct pmax_fb *fp = &xcfbfb;
switch (flag) {
case FREAD:
if (fp->fbu->scrInfo.qe.eHead != fp->fbu->scrInfo.qe.eTail)
return (1);
selrecord(p, &fp->selp);
break;
}
return (0);
}
static u_char cursor_RGB[6]; /* cursor color 2 & 3 */
/*
* Routines for the Inmos IMS-G332 Colour video controller
* Author: Alessandro Forin, Carnegie Mellon University
*/
static u_int
ims332_read_register(regno)
{
register u_char *regs = (u_char *)IMS332_ADDRESS;
unsigned char *rptr;
register u_int val, v1;
/* spec sez: */
rptr = regs + 0x80000 + (regno << 4);
val = *((volatile u_short *) rptr );
v1 = *((volatile u_short *) regs );
return (val & 0xffff) | ((v1 & 0xff00) << 8);
}
static void
ims332_write_register(regno, val)
register unsigned int val;
{
register u_char *regs = (u_char *)IMS332_ADDRESS;
u_char *wptr;
/* spec sez: */
wptr = regs + 0xa0000 + (regno << 4);
*((volatile u_int *)(regs)) = (val >> 8) & 0xff00;
*((volatile u_short *)(wptr)) = val;
}
#define assert_ims332_reset_bit(r) *r &= ~0x40
#define deassert_ims332_reset_bit(r) *r |= 0x40
/*
* Color map
*/
static void
xcfbLoadColorMap(ptr)
ColorMap *ptr;
{
register int i;
if (ptr->index > 256)
return;
ims332_load_colormap_entry(ptr->index, ptr);
}
static void
ims332_load_colormap_entry(entry, map)
ColorMap *map;
{
/* ?? stop VTG */
ims332_write_register(IMS332_REG_LUT_BASE + (entry & 0xff),
(map->Entry.blue << 16) |
(map->Entry.green << 8) |
(map->Entry.red));
}
static void
xcfbInitColorMap()
{
register int i;
ColorMap m;
m.Entry.red = m.Entry.green = m.Entry.blue = 0;
ims332_load_colormap_entry(0, &m);
m.Entry.red = m.Entry.green = m.Entry.blue = 0xff;
for (i = 1; i < 256; i++)
ims332_load_colormap_entry(i, &m);
for (i = 0; i < 3; i++) {
cursor_RGB[i] = 0x00;
cursor_RGB[i + 3] = 0xff;
}
xcfbRestoreCursorColor();
}
/*
* Video on/off
*
* It is unfortunate that X11 goes backward with white@0
* and black@1. So we must stash away the zero-th entry
* and fix it while screen is off. Also must remember
* it, sigh.
*/
static struct {
u_int save;
int off;
} xcfb_vstate;
static void
ims332_video_off()
{
register u_int csr;
if (xcfb_vstate.off)
return;
xcfb_vstate.save = ims332_read_register(IMS332_REG_LUT_BASE);
ims332_write_register(IMS332_REG_LUT_BASE, 0);
ims332_write_register(IMS332_REG_COLOR_MASK, 0);
/* cursor now */
csr = ims332_read_register(IMS332_REG_CSR_A);
csr |= IMS332_CSR_A_DISABLE_CURSOR;
ims332_write_register(IMS332_REG_CSR_A, csr);
xcfb_vstate.off = 1;
}
static void
ims332_video_on()
{
register u_int csr;
if (!xcfb_vstate.off)
return;
ims332_write_register(IMS332_REG_LUT_BASE, xcfb_vstate.save);
ims332_write_register(IMS332_REG_COLOR_MASK, 0xffffffff);
/* cursor now */
csr = ims332_read_register(IMS332_REG_CSR_A);
csr &= ~IMS332_CSR_A_DISABLE_CURSOR;
ims332_write_register(IMS332_REG_CSR_A, csr);
xcfb_vstate.off = 0;
}
/*
* Cursor
*/
void
xcfbPosCursor(x, y)
register int x, y;
{
register struct pmax_fb *fp = &xcfbfb;
if (y < fp->fbu->scrInfo.min_cur_y || y > fp->fbu->scrInfo.max_cur_y)
y = fp->fbu->scrInfo.max_cur_y;
if (x < fp->fbu->scrInfo.min_cur_x || x > fp->fbu->scrInfo.max_cur_x)
x = fp->fbu->scrInfo.max_cur_x;
fp->fbu->scrInfo.cursor.x = x; /* keep track of real cursor */
fp->fbu->scrInfo.cursor.y = y; /* position, indep. of mouse */
ims332_write_register(IMS332_REG_CURSOR_LOC,
((x & 0xfff) << 12) | (y & 0xfff));
}
/*
* xcfbRestoreCursorColor
*/
static void
xcfbRestoreCursorColor()
{
/* Bg is color[0], Fg is color[1] */
ims332_write_register(IMS332_REG_CURSOR_LUT_0,
(cursor_RGB[2] << 16) |
(cursor_RGB[1] << 8) |
(cursor_RGB[0]));
ims332_write_register(IMS332_REG_CURSOR_LUT_1, 0x7f0000);
ims332_write_register(IMS332_REG_CURSOR_LUT_2,
(cursor_RGB[5] << 16) |
(cursor_RGB[4] << 8) |
(cursor_RGB[3]));
}
/*
* ----------------------------------------------------------------------------
*
* xcfbCursorColor --
*
* Set the color of the cursor.
*
* Results:
* None.
*
* Side effects:
* None.
*
* ----------------------------------------------------------------------------
*/
static void
xcfbCursorColor(color)
unsigned int color[];
{
register int i, j;
for (i = 0; i < 6; i++)
cursor_RGB[i] = (u_char)(color[i] >> 8);
xcfbRestoreCursorColor();
}
static void
xcfbLoadCursor(cursor)
u_short *cursor;
{
register int i, j, k, pos;
register u_short ap, bp, out;
/*
* Fill in the cursor sprite using the A and B planes, as provided
* for the pmax.
* XXX This will have to change when the X server knows that this
* is not a pmax display.
*/
pos = 0;
for (k = 0; k < 16; k++) {
ap = *cursor;
bp = *(cursor + 16);
j = 0;
while (j < 2) {
out = 0;
for (i = 0; i < 8; i++) {
out = ((out >> 2) & 0x3fff) |
((ap & 0x1) << 15) |
((bp & 0x1) << 14);
ap >>= 1;
bp >>= 1;
}
ims332_write_register(IMS332_REG_CURSOR_RAM + pos, out);
pos++;
j++;
}
while (j < 8) {
ims332_write_register(IMS332_REG_CURSOR_RAM + pos, 0);
pos++;
j++;
}
cursor++;
}
while (pos < 512) {
ims332_write_register(IMS332_REG_CURSOR_RAM + pos, 0);
pos++;
}
}
/*
* Initialization
*/
int
xcfbinit()
xcfbinit(base, unit, silent)
caddr_t base;
int unit;
int silent;
{
register u_int *reset = (u_int *)IMS332_RESET_ADDRESS;
register struct pmax_fb *fp = &xcfbfb;
struct fbinfo *fi;
fp->isMono = 0;
unit = 0; /*XXX*/ /* FIXME */
/*XXX*/
/*
* Or Cached? A comment in the Mach driver suggests that the X server
* runs faster in cached address space, but the X server is going
* to blow away the data cache whenever it updates the screen, so..
*/
fp->fr_addr = (char *)
MACH_PHYS_TO_UNCACHED(XINE_PHYS_CFB_START + VRAM_OFFSET);
fp->fr_size = 0x100000;
base = (char *) MACH_PHYS_TO_UNCACHED(XINE_PHYS_CFB_START);
/* Fill in main frame buffer info struct. */
fi->fi_unit = unit;
fi->fi_pixels = (caddr_t)(base + VRAM_OFFSET);
fi->fi_pixelsize = 1024 * 768;
fi->fi_base = (caddr_t)IMS332_RESET_ADDRESS;
fi->fi_vdac = (caddr_t)IMS332_ADDRESS;
fi->fi_size = 0x100000;
fi->fi_linebytes = 1024;
fi->fi_driver = &xcfb_driver;
fi->fi_blanked = 0;
fi->fi_cmap_bits = (caddr_t)&cmap_bits [CMAP_BITS * unit];
/* Fill in Frame Buffer Type struct. */
fi->fi_type.fb_boardtype = PMAX_FBTYPE_CFB;
fi->fi_type.fb_width = 1024;
fi->fi_type.fb_height = 768;
fi->fi_type.fb_depth = 8;
fi->fi_type.fb_cmsize = 256;
fi->fi_type.fb_size = XCFB_FB_SIZE;
/*
* qvss/pm-style mmap()ed event queue compatibility glue
*/
/*
* Must be in Uncached space since the fbuaccess structure is
* mapped into the user's address space uncached.
*/
fp->fbu = (struct fbuaccess *)
fi->fi_fbu = (struct fbuaccess *)
MACH_PHYS_TO_UNCACHED(MACH_CACHED_TO_PHYS(&xcfbu));
fp->posCursor = xcfbPosCursor;
fp->KBDPutc = dtopKBDPutc;
fp->kbddev = makedev(DTOPDEV, DTOPKBD_PORT);
fi->fi_glasstty->KBDPutc = dtopKBDPutc;
fi->fi_glasstty->kbddev = makedev(DTOPDEV, DTOPKBD_PORT);
/* This is glass-tty state but it's in the shared structure. Ick. */
fi->fi_fbu->scrInfo.max_row = 50;
fi->fi_fbu->scrInfo.max_col = 80;
init_pmaxfbu(fi);
/*
* Initialize the screen.
* Initialize old-style pmax glass-tty screen info.
*/
#ifdef notdef
assert_ims332_reset_bit(reset);
DELAY(1); /* specs sez 50ns.. */
deassert_ims332_reset_bit(reset);
fi->fi_glasstty = &xcfbfb;
/* CLOCKIN appears to receive a 6.25 Mhz clock --> PLL 12 for 75Mhz monitor */
ims332_write_register(IMS332_REG_BOOT, 12 | IMS332_BOOT_CLOCK_PLL);
/*XXX*/
/* dimensions translated -15 pixels, for sprite origin? */
fi->fi_fbu->scrInfo.max_cur_x = 1008;
fi->fi_fbu->scrInfo.max_cur_y = 752;
/* initialize VTG */
ims332_write_register(IMS332_REG_CSR_A,
IMS332_BPP_8 | IMS332_CSR_A_DISABLE_CURSOR);
DELAY(50); /* spec does not say */
fi->fi_fbu->scrInfo.min_cur_x = -15;
fi->fi_fbu->scrInfo.min_cur_y = -15;
/* datapath registers (values taken from prom's settings) */
/* Initialize the RAMDAC. */
ims332init (fi);
ims332_write_register(IMS332_REG_HALF_SYNCH, 0x10);
ims332_write_register(IMS332_REG_BACK_PORCH, 0x21);
ims332_write_register(IMS332_REG_DISPLAY, 0x100);
ims332_write_register(IMS332_REG_SHORT_DIS, 0x5d);
ims332_write_register(IMS332_REG_BROAD_PULSE, 0x9f);
ims332_write_register(IMS332_REG_V_SYNC, 0xc);
ims332_write_register(IMS332_REG_V_PRE_EQUALIZE, 2);
ims332_write_register(IMS332_REG_V_POST_EQUALIZE, 2);
ims332_write_register(IMS332_REG_V_BLANK, 0x2a);
ims332_write_register(IMS332_REG_V_DISPLAY, 0x600);
ims332_write_register(IMS332_REG_LINE_TIME, 0x146);
ims332_write_register(IMS332_REG_LINE_START, 0x10);
ims332_write_register(IMS332_REG_MEM_INIT, 0xa);
ims332_write_register(IMS332_REG_XFER_DELAY, 0xa);
ims332_write_register(IMS332_REG_COLOR_MASK, 0xffffff);
#endif
/*
* Initialize screen info.
* Connect to the raster-console pseudo-driver
*/
fp->fbu->scrInfo.max_row = 50;
fp->fbu->scrInfo.max_col = 80;
fp->fbu->scrInfo.max_x = 1024;
fp->fbu->scrInfo.max_y = 768;
fp->fbu->scrInfo.max_cur_x = 1008;
fp->fbu->scrInfo.max_cur_y = 752;
fp->fbu->scrInfo.version = 11;
fp->fbu->scrInfo.mthreshold = 4;
fp->fbu->scrInfo.mscale = 2;
fp->fbu->scrInfo.min_cur_x = -15;
fp->fbu->scrInfo.min_cur_y = -15;
fp->fbu->scrInfo.qe.timestamp_ms = TO_MS(time);
fp->fbu->scrInfo.qe.eSize = PM_MAXEVQ;
fp->fbu->scrInfo.qe.eHead = fp->fbu->scrInfo.qe.eTail = 0;
fp->fbu->scrInfo.qe.tcSize = MOTION_BUFFER_SIZE;
fp->fbu->scrInfo.qe.tcNext = 0;
xcfbInitColorMap();
ims332_write_register(IMS332_REG_CSR_A,
IMS332_BPP_8 | IMS332_CSR_A_DMA_DISABLE | IMS332_CSR_A_VTG_ENABLE);
xcfbScreenInit();
fbScroll(fp);
fbconnect("PMAG-DV", fi, silent);
#ifdef fpinitialized
fp->initialized = 1;
if (cn_tab.cn_fb == (struct pmax_fb *)0)
cn_tab.cn_fb = fp;
#endif
return (1);
}
/*
* ----------------------------------------------------------------------------
*
* xcfbScreenInit --
*
* Initialize the screen.
*
* Results:
* None.
*
* Side effects:
* The screen is initialized.
*
* ----------------------------------------------------------------------------
*/
static void
xcfbScreenInit()
{
register struct pmax_fb *fp = &xcfbfb;
/*
* Home the cursor.
* We want an LSI terminal emulation. We want the graphics
* terminal to scroll from the bottom. So start at the bottom.
*/
fp->row = 49;
fp->col = 0;
/*
* Load the cursor with the default values
*
*/
xcfbLoadCursor(defCursor);
}
/*
* xcfb keyboard and mouse input. Just punt to the generic ones in fb.c
*/
void
xcfbKbdEvent(ch)
int ch;
{
fbKbdEvent(ch, &xcfbfb);
}
void
xcfbMouseEvent(newRepPtr)
MouseReport *newRepPtr;
{
fbMouseEvent(newRepPtr, &xcfbfb);
}
void
xcfbMouseButtons(newRepPtr)
MouseReport *newRepPtr;
{
fbMouseButtons(newRepPtr, &xcfbfb);
}
#endif /* NDTOP */
#endif /* NXCFB */

View File

@ -1,4 +1,4 @@
/* $NetBSD: cpu_cons.c,v 1.1 1995/04/11 10:08:42 mellon Exp $ */
/* $NetBSD: cpu_cons.c,v 1.2 1995/09/11 07:45:50 jonathan Exp $ */
/*
* Copyright (c) 1988 University of Utah.
@ -43,6 +43,8 @@
*/
#include <sys/param.h>
#include <sys/device.h>
#include <dev/cons.h>
#include <sys/proc.h>
#include <sys/systm.h>
#include <sys/buf.h>
@ -53,7 +55,6 @@
#include <pmax/stand/dec_prom.h>
#include <pmax/dev/device.h>
#include <pmax/dev/sccreg.h>
#include <pmax/pmax/kn01.h>
#include <pmax/pmax/kn02.h>
@ -63,18 +64,20 @@
#include <pmax/pmax/asic.h>
#include <pmax/pmax/turbochannel.h>
#include <pmax/pmax/pmaxtype.h>
/* #include <pmax/pmax/cons.h> */
#include <dev/cons.h>
#include <machine/machConst.h>
#include <machine/pmioctl.h>
#include <pmax/dev/fbreg.h>
#include <sys/device.h>
#include <machine/fbio.h>
#include <sparc/rcons/raster.h>
#include <machine/fbvar.h>
#include <pmax/dev/fbreg.h>
#include <machine/autoconf.h>
#include <pmax/tc/tc.h>
#include <pm.h>
#include <cfb.h>
#include <mfb.h>
@ -87,6 +90,7 @@
#include <asc.h>
#if NDC > 0
#include <machine/dc7085cons.h>
extern int dcGetc(), dcparam();
extern void dcPutc();
#endif
@ -101,6 +105,8 @@ static int romgetc __P ((dev_t));
static void romputc __P ((dev_t, int));
static void rompollc __P((dev_t, int));
extern int LKgetc __P((dev_t dev)); /* should be in header file, but which one? */
int pmax_boardtype; /* Mother board type */
/*
@ -109,6 +115,7 @@ int pmax_boardtype; /* Mother board type */
#define DTOPDEV 15
#define DCDEV 16
#define SCCDEV 17
#define RCONSDEV 85
/*
* Console I/O is redirected to the appropriate device, either a screen and
@ -116,6 +123,7 @@ int pmax_boardtype; /* Mother board type */
*/
extern struct consdev *cn_tab; /* Console I/O table... */
extern void rcons_vputc __P((dev_t, int)); /* XXX */
struct consdev cd = {
(void (*)(struct consdev *))0, /* probe */
@ -127,19 +135,42 @@ struct consdev cd = {
CN_DEAD,
};
/* should be locals of consinit, but that's split in two til
* new-style config of decstations is finished
*/
/*
* Forward declarations
*/
int consprobetc __P((int prom_slot));
int consprobeslot __P((caddr_t name, void *addr));
void consinit __P((void));
void xconsinit __P((void));
extern struct tc_cpu_desc * cpu_tcdesc __P ((int cputype));
int kbd;
int pending_remcons = 0;
/*
* Console initialization: called early on from main,
* before vm init or startup. Do enough configuration
* to choose and initialize a console.
*/
void
consinit()
{
register int kbd, crt;
int crt;
register char *oscon;
int screen = 0;
extern void (*v_putc) __P ((dev_t, int));
cn_tab = &cd;
(*callv -> _printf)("consinit\n");
/*
* First get the "osconsole" environment variable.
@ -148,9 +179,11 @@ consinit()
crt = kbd = -1;
if (oscon && *oscon >= '0' && *oscon <= '9') {
kbd = *oscon - '0';
/*cn_tab.cn_pri = CN_DEAD;*/
screen = 0;
while (*++oscon) {
if (*oscon == ',')
/*cn_tab.cn_pri = CN_INTERNAL;*/
screen = 1;
else if (screen &&
*oscon >= '0' && *oscon <= '9') {
@ -160,6 +193,12 @@ consinit()
}
}
}
/* we can't do anything until auto-configuration
* has run, and that requires kmalloc(), which
* hasn't been initialized yet. Just keep using
* whatever the PROM vector gave us.
*/
if (pmax_boardtype == DS_PMAX && kbd == 1)
screen = 1;
/*
@ -167,6 +206,7 @@ consinit()
* osconsole to '1' like the PMAX.
*/
if (pmax_boardtype == DS_3MAX && crt == -1 && kbd == 1) {
/* Try to use pmax onboard framebuffer */
screen = 1;
crt = 0;
kbd = 7;
@ -182,7 +222,8 @@ consinit()
#if NDC > 0 && NPM > 0
if (pminit()) {
cd.cn_dev = makedev(DCDEV, DCKBD_PORT);
cd.cn_getc = dcGetc;
cd.cn_getc = LKgetc;
lk_divert(dcGetc);
cd.cn_pri = CN_INTERNAL;
return;
}
@ -209,7 +250,8 @@ consinit()
#if NDC > 0
if (kbd == 7) {
cd.cn_dev = makedev(DCDEV, DCKBD_PORT);
cd.cn_getc = dcGetc;
cd.cn_getc = LKgetc;
lk_divert(dcGetc);
} else
#endif /* NDC */
goto remcons;
@ -220,7 +262,8 @@ consinit()
#if NSCC > 0
if (kbd == 3) {
cd.cn_dev = makedev(SCCDEV, SCCKBD_PORT);
cd.cn_getc = sccGetc;
lk_divert(sccGetc);
cd.cn_getc = LKgetc;
} else
#endif /* NSCC */
goto remcons;
@ -230,40 +273,52 @@ consinit()
goto remcons;
};
/*
* Check for a suitable turbochannel frame buffer.
*/
if (tc_slot_info[crt].driver_name) {
#if NMFB > 0
if (strcmp(tc_slot_info[crt].driver_name, "mfb") == 0 &&
mfbinit(tc_slot_info[crt].k1seg_address)) {
if (consprobetc(crt)) {
cd.cn_pri = CN_NORMAL;
#ifdef RCONS_HACK
/* FIXME */ cd.cn_putc = v_putc;
/* FIXME */ cd.cn_dev = makedev (RCONSDEV, 0);
#endif /* RCONS_HACK */
cd.cn_putc = rcons_vputc; /*XXX*/
return;
}
#endif /* NMFB */
#if NSFB > 0
if (strcmp(tc_slot_info[crt].driver_name, "sfb") == 0 &&
sfbinit(tc_slot_info[crt].k1seg_address, 0)) {
cd.cn_pri = CN_NORMAL;
return;
}
#endif /* NSFB */
#if NCFB > 0
if (strcmp(tc_slot_info[crt].driver_name, "cfb") == 0 &&
cfbinit(tc_slot_info[crt].k1seg_address)) {
cd.cn_pri = CN_NORMAL;
return;
}
#endif /* NCFB */
printf("crt: %s not supported as console device\n",
tc_slot_info[crt].driver_name);
} else
printf("No crt console device in slot %d\n", crt);
}
remcons:
/*
* Configure a serial port as a remote console.
*/
/* XXX serial drivers need to be rewritten to handle
* init this early. Defer switching to non-PROM
* driver until later.
*/
pending_remcons = 1;
printf("Using PROM serial output until serial drivers initialized\n");
/* We never cahnged output; go back to using PROM input */
cd.cn_dev = makedev (0, 0);
cd.cn_getc = /*(int (*)(dev_t)) */ romgetc;
}
/*
* Configure a serial port as a remote console.
*/
void
xconsinit()
{
if (!pending_remcons)
return;
pending_remcons = 0;
switch (pmax_boardtype) {
case DS_PMAX:
#if NDC > 0
@ -309,6 +364,91 @@ remcons:
printf("Can't configure console!\n");
}
/*
* Probe for a framebuffer option card. Configure the first one
* found as a console.
*/
int
consprobetc(prom_slot)
int prom_slot;
{
void *slotaddr;
int slot;
struct tc_cpu_desc * sc_desc = cpu_tcdesc(pmax_boardtype);
char namebuf[20];
if (sc_desc == NULL)
return;
/*printf("Looking for fb console in slot %d", slot);*/
/*
* Try to configure each turbochannel (or CPU-internal) device.
* Knows about gross internals of TurboChannel bus autoconfig
* descriptor, which needs to be fixed badly.
*/
for (slot = 0; slot < sc_desc->tcd_ndevs; slot++) {
slotaddr = (void *)sc_desc->tcd_slots[slot].tsd_dense;
/*printf("probing slot %d at 0x%x\n", slot, slotaddr);*/
if (tc_checkdevmem(slotaddr) == 0)
continue;
if (tc_checkslot(slotaddr, namebuf) == 0)
continue;
if (consprobeslot(namebuf, slotaddr))
return (1);
}
return (0);
}
/*
* Try and configure one slot as framebuffer console.
* Accept only the framebuffers configured in.
*/
int
consprobeslot(name, addr)
char *name;
void * addr;
{
/*printf(", trying to init a \"%s\"", name);*/
#define DRIVER_FOR_SLOT(slotname, drivername) \
(strcmp (slotname, drivername) == 0)
#if NMFB > 0
if (DRIVER_FOR_SLOT(name, "PMAG-AA ") &&
mfbinit(addr, 0, 1)) {
cd.cn_pri = CN_NORMAL;
return (1);
}
#endif /* NMFB */
#if NSFB > 0
if (DRIVER_FOR_SLOT(name, "PMAGB-BA") &&
sfbinit(addr, 0, 1)) {
cd.cn_pri = CN_NORMAL;
return (1);
}
#endif /* NSFB */
#if NCFB > 0
/*"cfb"*/
if (DRIVER_FOR_SLOT(name, "PMAG-BA ") &&
cfbinit(NULL, addr, 0, 1)) {
cd.cn_pri = CN_NORMAL;
return (1);
}
#endif /* NCFB */
return (0);
}
/*
* Get character from ROM console.
*/
@ -342,3 +482,33 @@ static void rompollc (dev, c)
return;
}
extern struct tty *constty; /* virtual console output device */
extern struct consdev *cn_tab; /* physical console device info */
extern struct vnode *cn_devvp; /* vnode for underlying device. */
/*ARGSUSED*/
int
pmax_cnselect(dev, rw, p)
dev_t dev;
int rw;
struct proc *p;
{
/*
* Redirect the ioctl, if that's appropriate.
* I don't want to think of the possible side effects
* of console redirection here.
*/
if (constty != NULL && (cn_tab == NULL || cn_tab->cn_pri != CN_REMOTE))
dev = constty->t_dev;
else if (cn_tab == NULL)
return ENXIO;
else
dev = cn_tab->cn_dev;
#ifdef RCONS
if (cn_tab -> cn_dev == makedev (85, 0))
return rconsselect (cn_tab -> cn_dev, rw, p);
#endif
return (ttselect(cn_tab->cn_dev, rw, p));
}