summaryrefslogtreecommitdiff
path: root/sys/arch/hp300/dev/grf_hy.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/hp300/dev/grf_hy.c')
-rw-r--r--sys/arch/hp300/dev/grf_hy.c682
1 files changed, 646 insertions, 36 deletions
diff --git a/sys/arch/hp300/dev/grf_hy.c b/sys/arch/hp300/dev/grf_hy.c
index a394b737df1..9598a9d4da5 100644
--- a/sys/arch/hp300/dev/grf_hy.c
+++ b/sys/arch/hp300/dev/grf_hy.c
@@ -1,6 +1,7 @@
-/* $NetBSD: grf_hy.c,v 1.2 1994/10/26 07:23:55 cgd Exp $ */
+/* $NetBSD: grf_hy.c,v 1.5 1996/03/03 16:49:00 thorpej Exp $ */
/*
+ * Copyright (c) 1996 Jason R. Thorpe. All rights reserved.
* Copyright (c) 1991 University of Utah.
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
@@ -50,23 +51,67 @@
* Graphics routines for HYPERION frame buffer
*/
#include <sys/param.h>
+#include <sys/conf.h>
#include <sys/errno.h>
+#include <sys/proc.h>
+#include <sys/ioctl.h>
+#include <sys/tty.h>
+#include <sys/systm.h>
+#include <sys/uio.h>
+
+#include <machine/autoconf.h>
+#include <machine/cpu.h>
+
+#include <dev/cons.h>
#include <hp300/dev/grfioctl.h>
#include <hp300/dev/grfvar.h>
+#include <hp300/dev/grfreg.h>
#include <hp300/dev/grf_hyreg.h>
-#include <machine/cpu.h>
+#include <hp300/dev/itevar.h>
+#include <hp300/dev/itereg.h>
+
+#include "ite.h"
caddr_t badhyaddr = (caddr_t) -1;
+int hy_init __P((struct grf_data *gp, int, caddr_t));
+int hy_mode __P((struct grf_data *gp, int, caddr_t));
+void hyper_ite_fontinit __P((struct ite_data *));
+
+/* Hyperion grf switch */
+struct grfsw hyper_grfsw = {
+ GID_HYPERION, GRFHYPERION, "hyperion", hy_init, hy_mode
+};
+
+#if NITE > 0
+void hyper_init __P((struct ite_data *));
+void hyper_deinit __P((struct ite_data *));
+void hyper_int_fontinit __P((struct ite_data *));
+void hyper_putc __P((struct ite_data *, int, int, int, int));
+void hyper_cursor __P((struct ite_data *, int));
+void hyper_clear __P((struct ite_data *, int, int, int, int));
+void hyper_scroll __P((struct ite_data *, int, int, int, int));
+void hyper_windowmove __P((struct ite_data *, int, int, int, int,
+ int, int, int));
+
+/* Hyperion ite switch */
+struct itesw hyper_itesw = {
+ hyper_init, hyper_deinit, hyper_clear, hyper_putc,
+ hyper_cursor, hyper_scroll, ite_readbyte, ite_writeglyph
+};
+#endif /* NITE > 0 */
+
/*
* Initialize hardware.
* Must fill in the grfinfo structure in g_softc.
* Returns 0 if hardware not present, non-zero ow.
*/
-hy_init(gp, addr)
- struct grf_softc *gp;
+int
+hy_init(gp, scode, addr)
+ struct grf_data *gp;
+ int scode;
caddr_t addr;
{
register struct hyboxfb *hy = (struct hyboxfb *) addr;
@@ -74,38 +119,45 @@ hy_init(gp, addr)
int fboff;
extern caddr_t sctopa(), iomap();
- if (ISIIOVA(addr))
- gi->gd_regaddr = (caddr_t) IIOP(addr);
- else
- gi->gd_regaddr = sctopa(vatosc(addr));
- gi->gd_regsize = 0x20000;
- gi->gd_fbwidth = (hy->fbwmsb << 8) | hy->fbwlsb;
- gi->gd_fbheight = (hy->fbhmsb << 8) | hy->fbhlsb;
- gi->gd_fbsize = (gi->gd_fbwidth * gi->gd_fbheight) >> 3;
- fboff = (hy->fbomsb << 8) | hy->fbolsb;
- gi->gd_fbaddr = (caddr_t) (*((u_char *)addr + fboff) << 16);
- if (gi->gd_regaddr >= (caddr_t)DIOIIBASE) {
- /*
- * For DIO II space the fbaddr just computed is the offset
- * from the select code base (regaddr) of the framebuffer.
- * Hence it is also implicitly the size of the register set.
- */
- gi->gd_regsize = (int) gi->gd_fbaddr;
- gi->gd_fbaddr += (int) gi->gd_regaddr;
- gp->g_regkva = addr;
- gp->g_fbkva = addr + gi->gd_regsize;
- } else {
- /*
- * For DIO space we need to map the seperate framebuffer.
- */
- gp->g_regkva = addr;
- gp->g_fbkva = iomap(gi->gd_fbaddr, gi->gd_fbsize);
+ /*
+ * If the console has been initialized, and it was us, there's
+ * no need to repeat this.
+ */
+ if (consinit_active || (scode != conscode)) {
+ if (ISIIOVA(addr))
+ gi->gd_regaddr = (caddr_t) IIOP(addr);
+ else
+ gi->gd_regaddr = sctopa(scode);
+ gi->gd_regsize = 0x20000;
+ gi->gd_fbwidth = (hy->fbwmsb << 8) | hy->fbwlsb;
+ gi->gd_fbheight = (hy->fbhmsb << 8) | hy->fbhlsb;
+ gi->gd_fbsize = (gi->gd_fbwidth * gi->gd_fbheight) >> 3;
+ fboff = (hy->fbomsb << 8) | hy->fbolsb;
+ gi->gd_fbaddr = (caddr_t) (*((u_char *)addr + fboff) << 16);
+ if (gi->gd_regaddr >= (caddr_t)DIOIIBASE) {
+ /*
+ * For DIO II space the fbaddr just computed is
+ * the offset from the select code base (regaddr)
+ * of the framebuffer. Hence it is also implicitly
+ * the size of the register set.
+ */
+ gi->gd_regsize = (int) gi->gd_fbaddr;
+ gi->gd_fbaddr += (int) gi->gd_regaddr;
+ gp->g_regkva = addr;
+ gp->g_fbkva = addr + gi->gd_regsize;
+ } else {
+ /*
+ * For DIO space we need to map the seperate
+ * framebuffer.
+ */
+ gp->g_regkva = addr;
+ gp->g_fbkva = iomap(gi->gd_fbaddr, gi->gd_fbsize);
+ }
+ gi->gd_dwidth = (hy->dwmsb << 8) | hy->dwlsb;
+ gi->gd_dheight = (hy->dhmsb << 8) | hy->dhlsb;
+ gi->gd_planes = hy->num_planes;
+ gi->gd_colors = 1 << gi->gd_planes;
}
- gi->gd_dwidth = (hy->dwmsb << 8) | hy->dwlsb;
- gi->gd_dheight = (hy->dhmsb << 8) | hy->dhlsb;
- gi->gd_planes = hy->num_planes;
- gi->gd_colors = 1 << gi->gd_planes;
-
return(1);
}
@@ -115,8 +167,9 @@ hy_init(gp, addr)
* Return a UNIX error number or 0 for success.
* Function may not be needed anymore.
*/
+int
hy_mode(gp, cmd, data)
- struct grf_softc *gp;
+ struct grf_data *gp;
int cmd;
caddr_t data;
{
@@ -182,4 +235,561 @@ hy_mode(gp, cmd, data)
}
return(error);
}
+
+#if NITE > 0
+
+/*
+ * Hyperion ite routines
+ */
+
+#define REGBASE ((struct hyboxfb *)(ip->regbase))
+#define WINDOWMOVER hyper_windowmove
+
+#undef charX
+#define charX(ip,c) \
+ (((c) % (ip)->cpl) * ((((ip)->ftwidth + 7) / 8) * 8) + (ip)->fontx)
+
+void
+hyper_init(ip)
+ struct ite_data *ip;
+{
+ int width;
+
+ /* XXX */
+ if (ip->regbase == NULL) {
+ struct grf_data *gp = ip->grf;
+
+ ip->regbase = gp->g_regkva;
+ ip->fbbase = gp->g_fbkva;
+ ip->fbwidth = gp->g_display.gd_fbwidth;
+ ip->fbheight = gp->g_display.gd_fbheight;
+ ip->dwidth = gp->g_display.gd_dwidth;
+ ip->dheight = gp->g_display.gd_dheight;
+ }
+
+ ite_fontinfo(ip);
+ width = ((ip->ftwidth + 7) / 8) * 8;
+ ip->cpl = (ip->fbwidth - ip->dwidth) / width;
+ ip->cblanky = ip->fonty + ((128 / ip->cpl) +1) * ip->ftheight;
+
+ /*
+ * Clear the framebuffer on all planes.
+ */
+ hyper_windowmove(ip, 0, 0, 0, 0, ip->fbheight, ip->fbwidth, RR_CLEAR);
+
+ hyper_ite_fontinit(ip);
+
+ REGBASE->nblank = 0x05;
+
+ /*
+ * Stash the inverted cursor.
+ */
+ hyper_windowmove(ip, charY(ip, ' '), charX(ip, ' '),
+ ip->cblanky, ip->cblankx, ip->ftheight,
+ ip->ftwidth, RR_COPYINVERTED);
+}
+
+void
+hyper_deinit(ip)
+ struct ite_data *ip;
+{
+ hyper_windowmove(ip, 0, 0, 0, 0, ip->fbheight, ip->fbwidth, RR_CLEAR);
+
+ REGBASE->nblank = 0x05;
+ ip->flags &= ~ITE_INITED;
+}
+
+void
+hyper_ite_fontinit(ip)
+ struct ite_data *ip;
+{
+ register u_char *fbmem, *dp;
+ int c, l, b;
+ int stride, width;
+
+ dp = (u_char *)(getword(ip, getword(ip, FONTROM) + FONTADDR) +
+ ip->regbase) + FONTDATA;
+ stride = ip->fbwidth >> 3;
+ width = (ip->ftwidth + 7) / 8;
+
+ for (c = 0; c < 128; c++) {
+ fbmem = (u_char *) FBBASE +
+ (ip->fonty + (c / ip->cpl) * ip->ftheight) *
+ stride;
+ fbmem += (ip->fontx >> 3) + (c % ip->cpl) * width;
+ for (l = 0; l < ip->ftheight; l++) {
+ for (b = 0; b < width; b++) {
+ *fbmem++ = *dp;
+ dp += 2;
+ }
+ fbmem -= width;
+ fbmem += stride;
+ }
+ }
+}
+
+void
+hyper_putc(ip, c, dy, dx, mode)
+ struct ite_data *ip;
+ int c, dy, dx, mode;
+{
+ int wmrr = ((mode == ATTR_INV) ? RR_COPYINVERTED : RR_COPY);
+
+ hyper_windowmove(ip, charY(ip, c), charX(ip, c),
+ dy * ip->ftheight, dx * ip->ftwidth,
+ ip->ftheight, ip->ftwidth, wmrr);
+}
+
+void
+hyper_cursor(ip, flag)
+ struct ite_data *ip;
+ int flag;
+{
+ if (flag == DRAW_CURSOR)
+ draw_cursor(ip)
+ else if (flag == MOVE_CURSOR) {
+ erase_cursor(ip)
+ draw_cursor(ip)
+ }
+ else
+ erase_cursor(ip)
+}
+
+void
+hyper_clear(ip, sy, sx, h, w)
+ struct ite_data *ip;
+ int sy, sx, h, w;
+{
+ hyper_windowmove(ip, sy * ip->ftheight, sx * ip->ftwidth,
+ sy * ip->ftheight, sx * ip->ftwidth,
+ h * ip->ftheight, w * ip->ftwidth,
+ RR_CLEAR);
+}
+
+void
+hyper_scroll(ip, sy, sx, count, dir)
+ struct ite_data *ip;
+ int sy, count, dir, sx;
+{
+ register int dy;
+ register int dx = sx;
+ register int height = 1;
+ register int width = ip->cols;
+
+ if (dir == SCROLL_UP) {
+ dy = sy - count;
+ height = ip->rows - sy;
+ }
+ else if (dir == SCROLL_DOWN) {
+ dy = sy + count;
+ height = ip->rows - dy - 1;
+ }
+ else if (dir == SCROLL_RIGHT) {
+ dy = sy;
+ dx = sx + count;
+ width = ip->cols - dx;
+ }
+ else {
+ dy = sy;
+ dx = sx - count;
+ width = ip->cols - sx;
+ }
+
+ hyper_windowmove(ip, sy * ip->ftheight, sx * ip->ftwidth,
+ dy * ip->ftheight, dx * ip->ftwidth,
+ height * ip->ftheight,
+ width * ip->ftwidth, RR_COPY);
+}
+
+#include <hp300/dev/maskbits.h>
+
+/* NOTE:
+ * the first element in starttab could be 0xffffffff. making it 0
+ * lets us deal with a full first word in the middle loop, rather
+ * than having to do the multiple reads and masks that we'd
+ * have to do if we thought it was partial.
+ */
+int starttab[32] =
+ {
+ 0x00000000,
+ 0x7FFFFFFF,
+ 0x3FFFFFFF,
+ 0x1FFFFFFF,
+ 0x0FFFFFFF,
+ 0x07FFFFFF,
+ 0x03FFFFFF,
+ 0x01FFFFFF,
+ 0x00FFFFFF,
+ 0x007FFFFF,
+ 0x003FFFFF,
+ 0x001FFFFF,
+ 0x000FFFFF,
+ 0x0007FFFF,
+ 0x0003FFFF,
+ 0x0001FFFF,
+ 0x0000FFFF,
+ 0x00007FFF,
+ 0x00003FFF,
+ 0x00001FFF,
+ 0x00000FFF,
+ 0x000007FF,
+ 0x000003FF,
+ 0x000001FF,
+ 0x000000FF,
+ 0x0000007F,
+ 0x0000003F,
+ 0x0000001F,
+ 0x0000000F,
+ 0x00000007,
+ 0x00000003,
+ 0x00000001
+ };
+
+int endtab[32] =
+ {
+ 0x00000000,
+ 0x80000000,
+ 0xC0000000,
+ 0xE0000000,
+ 0xF0000000,
+ 0xF8000000,
+ 0xFC000000,
+ 0xFE000000,
+ 0xFF000000,
+ 0xFF800000,
+ 0xFFC00000,
+ 0xFFE00000,
+ 0xFFF00000,
+ 0xFFF80000,
+ 0xFFFC0000,
+ 0xFFFE0000,
+ 0xFFFF0000,
+ 0xFFFF8000,
+ 0xFFFFC000,
+ 0xFFFFE000,
+ 0xFFFFF000,
+ 0xFFFFF800,
+ 0xFFFFFC00,
+ 0xFFFFFE00,
+ 0xFFFFFF00,
+ 0xFFFFFF80,
+ 0xFFFFFFC0,
+ 0xFFFFFFE0,
+ 0xFFFFFFF0,
+ 0xFFFFFFF8,
+ 0xFFFFFFFC,
+ 0xFFFFFFFE
+ };
+
+void
+hyper_windowmove(ip, sy, sx, dy, dx, h, w, func)
+ struct ite_data *ip;
+ int sy, sx, dy, dx, h, w, func;
+{
+ int width; /* add to get to same position in next line */
+
+ unsigned int *psrcLine, *pdstLine;
+ /* pointers to line with current src and dst */
+ register unsigned int *psrc; /* pointer to current src longword */
+ register unsigned int *pdst; /* pointer to current dst longword */
+
+ /* following used for looping through a line */
+ unsigned int startmask, endmask; /* masks for writing ends of dst */
+ int nlMiddle; /* whole longwords in dst */
+ register int nl; /* temp copy of nlMiddle */
+ register unsigned int tmpSrc;
+ /* place to store full source word */
+ register int xoffSrc; /* offset (>= 0, < 32) from which to
+ fetch whole longwords fetched
+ in src */
+ int nstart; /* number of ragged bits at start of dst */
+ int nend; /* number of ragged bits at end of dst */
+ int srcStartOver; /* pulling nstart bits from src
+ overflows into the next word? */
+
+ if (h == 0 || w == 0)
+ return;
+
+ width = ip->fbwidth >> 5;
+
+ if (sy < dy) /* start at last scanline of rectangle */
+ {
+ psrcLine = ((unsigned int *) ip->fbbase) + ((sy+h-1) * width);
+ pdstLine = ((unsigned int *) ip->fbbase) + ((dy+h-1) * width);
+ width = -width;
+ }
+ else /* start at first scanline */
+ {
+ psrcLine = ((unsigned int *) ip->fbbase) + (sy * width);
+ pdstLine = ((unsigned int *) ip->fbbase) + (dy * width);
+ }
+
+ /* x direction doesn't matter for < 1 longword */
+ if (w <= 32)
+ {
+ int srcBit, dstBit; /* bit offset of src and dst */
+
+ pdstLine += (dx >> 5);
+ psrcLine += (sx >> 5);
+ psrc = psrcLine;
+ pdst = pdstLine;
+
+ srcBit = sx & 0x1f;
+ dstBit = dx & 0x1f;
+
+ while(h--)
+ {
+ getandputrop(psrc, srcBit, dstBit, w, pdst, func)
+ pdst += width;
+ psrc += width;
+ }
+ }
+ else
+ {
+ maskbits(dx, w, startmask, endmask, nlMiddle)
+ if (startmask)
+ nstart = 32 - (dx & 0x1f);
+ else
+ nstart = 0;
+ if (endmask)
+ nend = (dx + w) & 0x1f;
+ else
+ nend = 0;
+
+ xoffSrc = ((sx & 0x1f) + nstart) & 0x1f;
+ srcStartOver = ((sx & 0x1f) + nstart) > 31;
+
+ if (sx >= dx) /* move left to right */
+ {
+ pdstLine += (dx >> 5);
+ psrcLine += (sx >> 5);
+
+ while (h--)
+ {
+ psrc = psrcLine;
+ pdst = pdstLine;
+
+ if (startmask)
+ {
+ getandputrop(psrc, (sx & 0x1f),
+ (dx & 0x1f), nstart, pdst, func)
+ pdst++;
+ if (srcStartOver)
+ psrc++;
+ }
+
+ /* special case for aligned operations */
+ if (xoffSrc == 0)
+ {
+ nl = nlMiddle;
+ while (nl--)
+ {
+ DoRop (*pdst, func, *psrc++, *pdst);
+ pdst++;
+ }
+ }
+ else
+ {
+ nl = nlMiddle + 1;
+ while (--nl)
+ {
+ getunalignedword (psrc, xoffSrc, tmpSrc)
+ DoRop (*pdst, func, tmpSrc, *pdst);
+ pdst++;
+ psrc++;
+ }
+ }
+
+ if (endmask)
+ {
+ getandputrop0(psrc, xoffSrc, nend, pdst, func);
+ }
+
+ pdstLine += width;
+ psrcLine += width;
+ }
+ }
+ else /* move right to left */
+ {
+ pdstLine += (dx+w >> 5);
+ psrcLine += (sx+w >> 5);
+ /* if fetch of last partial bits from source crosses
+ a longword boundary, start at the previous longword
+ */
+ if (xoffSrc + nend >= 32)
+ --psrcLine;
+
+ while (h--)
+ {
+ psrc = psrcLine;
+ pdst = pdstLine;
+
+ if (endmask)
+ {
+ getandputrop0(psrc, xoffSrc, nend, pdst, func);
+ }
+
+ nl = nlMiddle + 1;
+ while (--nl)
+ {
+ --psrc;
+ --pdst;
+ getunalignedword(psrc, xoffSrc, tmpSrc)
+ DoRop(*pdst, func, tmpSrc, *pdst);
+ }
+
+ if (startmask)
+ {
+ if (srcStartOver)
+ --psrc;
+ --pdst;
+ getandputrop(psrc, (sx & 0x1f),
+ (dx & 0x1f), nstart, pdst, func)
+ }
+
+ pdstLine += width;
+ psrcLine += width;
+ }
+ } /* move right to left */
+ }
+}
+
+/*
+ * Hyperion console support
+ */
+
+int
+hyper_console_scan(scode, va, arg)
+ int scode;
+ caddr_t va;
+ void *arg;
+{
+ struct grfreg *grf = (struct grfreg *)va;
+ struct consdev *cp = arg;
+ u_char *dioiidev;
+ int force = 0, pri;
+
+ if ((grf->gr_id == GRFHWID) && (grf->gr_id2 == GID_HYPERION)) {
+ pri = CN_NORMAL;
+
+#ifdef CONSCODE
+ /*
+ * Raise our prioity, if appropriate.
+ */
+ if (scode == CONSCODE) {
+ pri = CN_REMOTE;
+ force = conforced = 1;
+ }
#endif
+
+ /* Only raise priority. */
+ if (pri > cp->cn_pri)
+ cp->cn_pri = pri;
+
+ /*
+ * If our priority is higher than the currently-remembered
+ * console, stash our priority.
+ */
+ if (((cn_tab == NULL) || (cp->cn_pri > cn_tab->cn_pri))
+ || force) {
+ cn_tab = cp;
+ if (scode >= 132) {
+ dioiidev = (u_char *)va;
+ return ((dioiidev[0x101] + 1) * 0x100000);
+ }
+ return (DIOCSIZE);
+ }
+ }
+ return (0);
+}
+
+void
+hypercnprobe(cp)
+ struct consdev *cp;
+{
+ int maj;
+ caddr_t va;
+ struct grfreg *grf;
+ int force = 0;
+
+ maj = ite_major();
+
+ /* initialize required fields */
+ cp->cn_dev = makedev(maj, 0); /* XXX */
+ cp->cn_pri = CN_DEAD;
+
+ /* Abort early if console is already forced. */
+ if (conforced)
+ return;
+
+ /* Look for "internal" framebuffer. */
+ va = (caddr_t)IIOV(GRFIADDR);
+ grf = (struct grfreg *)va;
+ if (!badaddr(va) &&
+ ((grf->gr_id == GRFHWID) && (grf->gr_id2 == GID_HYPERION))) {
+ cp->cn_pri = CN_INTERNAL;
+
+#ifdef CONSCODE
+ /*
+ * Raise our priority and save some work, if appropriate.
+ */
+ if (CONSCODE == -1) {
+ cp->cn_pri = CN_REMOTE;
+ force = conforced = 1;
+ }
+#endif
+
+ /*
+ * If our priority is higher than the currently
+ * remembered console, stash our priority, and
+ * unmap whichever device might be currently mapped.
+ * Since we're internal, we set the saved size to 0
+ * so they don't attempt to unmap our fixed VA later.
+ */
+ if (((cn_tab == NULL) || (cp->cn_pri > cn_tab->cn_pri))
+ || force) {
+ cn_tab = cp;
+ if (convasize)
+ iounmap(conaddr, convasize);
+ conscode = -1;
+ conaddr = va;
+ convasize = 0;
+ }
+ }
+
+ console_scan(hyper_console_scan, cp);
+}
+
+void
+hypercninit(cp)
+ struct consdev *cp;
+{
+ struct ite_data *ip = &ite_cn;
+ struct grf_data *gp = &grf_cn;
+
+ /*
+ * Initialize the framebuffer hardware.
+ */
+ (void)hy_init(gp, conscode, conaddr);
+
+ /*
+ * Set up required grf data.
+ */
+ gp->g_sw = &hyper_grfsw;
+ gp->g_display.gd_id = gp->g_sw->gd_swid;
+ gp->g_flags = GF_ALIVE;
+
+ /*
+ * Set up required ite data and initialize ite.
+ */
+ ip->isw = &hyper_itesw;
+ ip->grf = gp;
+ ip->flags = ITE_ALIVE|ITE_CONSOLE|ITE_ACTIVE|ITE_ISCONS;
+ ip->attrbuf = console_attributes;
+ iteinit(ip);
+
+ kbd_ite = ip; /* XXX */
+}
+
+#endif /* NITE > 0 */
+#endif /* NGRF > 0 */