diff options
Diffstat (limited to 'sys/arch/hp300/dev/grf_hy.c')
-rw-r--r-- | sys/arch/hp300/dev/grf_hy.c | 682 |
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 */ |