1*2b6fd3cdSjakllsch /* $NetBSD: lcg.c,v 1.11 2022/12/10 19:50:43 jakllsch Exp $ */
27e580c6eSjklos /*
37e580c6eSjklos * LCG accelerated framebuffer driver
47e580c6eSjklos * Copyright (c) 2003, 2004 Blaz Antonic
57e580c6eSjklos * All rights reserved.
67e580c6eSjklos *
77e580c6eSjklos * Redistribution and use in source and binary forms, with or without
87e580c6eSjklos * modification, are permitted provided that the following conditions
97e580c6eSjklos * are met:
107e580c6eSjklos * 1. Redistributions of source code must retain the above copyright
117e580c6eSjklos * notice, this list of conditions and the following disclaimer.
127e580c6eSjklos * 2. Redistributions in binary form must reproduce the above copyright
137e580c6eSjklos * notice, this list of conditions and the following disclaimer in the
147e580c6eSjklos * documentation and/or other materials provided with the distribution.
157e580c6eSjklos * 3. All advertising materials mentioning features or use of this software
167e580c6eSjklos * must display the abovementioned copyrights
177e580c6eSjklos * 4. The name of the author may not be used to endorse or promote products
187e580c6eSjklos * derived from this software without specific prior written permission
197e580c6eSjklos *
207e580c6eSjklos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
217e580c6eSjklos * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
227e580c6eSjklos * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
237e580c6eSjklos * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
247e580c6eSjklos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
257e580c6eSjklos * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
267e580c6eSjklos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
277e580c6eSjklos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
287e580c6eSjklos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
297e580c6eSjklos * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
307e580c6eSjklos */
317e580c6eSjklos /*
327e580c6eSjklos * Resurrection and dumb framebuffer mode by Björn Johannesson
337e580c6eSjklos * rherdware@yahoo.com in December 2014
347e580c6eSjklos */
357e580c6eSjklos
367e580c6eSjklos #include <sys/cdefs.h>
37*2b6fd3cdSjakllsch __KERNEL_RCSID(0, "$NetBSD: lcg.c,v 1.11 2022/12/10 19:50:43 jakllsch Exp $");
387e580c6eSjklos
397e580c6eSjklos #define LCG_NO_ACCEL
407e580c6eSjklos
417e580c6eSjklos #include <sys/param.h>
427e580c6eSjklos #include <sys/device.h>
437e580c6eSjklos #include <sys/systm.h>
447e580c6eSjklos #include <sys/callout.h>
457e580c6eSjklos #include <sys/time.h>
4674ee8752Sthorpej #include <sys/kmem.h>
477e580c6eSjklos #include <sys/conf.h>
487e580c6eSjklos #include <sys/kernel.h>
497e580c6eSjklos #include <sys/systm.h>
507e580c6eSjklos
517e580c6eSjklos #include <machine/vsbus.h>
527e580c6eSjklos #include <machine/sid.h>
537e580c6eSjklos #include <machine/cpu.h>
547e580c6eSjklos #include <machine/lcgreg.h>
557e580c6eSjklos
567e580c6eSjklos #include <dev/cons.h>
577e580c6eSjklos
587e580c6eSjklos #include <dev/dec/dzreg.h>
597e580c6eSjklos #include <dev/dec/dzvar.h>
607e580c6eSjklos #include <dev/dec/dzkbdvar.h>
617e580c6eSjklos
627e580c6eSjklos #include <dev/wscons/wsdisplayvar.h>
637e580c6eSjklos #include <dev/wscons/wsconsio.h>
647e580c6eSjklos #include <dev/wscons/wscons_callbacks.h>
657e580c6eSjklos #include <dev/wsfont/wsfont.h>
667e580c6eSjklos
677e580c6eSjklos #include "machine/scb.h"
687e580c6eSjklos
697e580c6eSjklos #include "dzkbd.h"
707e580c6eSjklos
717e580c6eSjklos /* Screen hardware defs */
727e580c6eSjklos
737e580c6eSjklos #define LCG_FB_ADDR 0x21801000 /* Frame buffer */
747e580c6eSjklos
757e580c6eSjklos /* FIFO defines */
767e580c6eSjklos #define LCG_FIFO_SIZE 0x10000 /* 64 KB */
777e580c6eSjklos #define LCG_FIFO_WIN_ADDR 0x20180000
787e580c6eSjklos #define LCG_FIFO_WIN_SIZE VAX_NBPG
797e580c6eSjklos #define LCG_FIFO_ALIGN 0x10000
807e580c6eSjklos
817e580c6eSjklos /* font rendering defines */
827e580c6eSjklos #define LCG_FONT_ADDR (LCG_FB_ADDR + lcg_fb_size)
8332cded6cSdholland #define LCG_FONT_STORAGE_SIZE 0x40000 /* 16 KB, enough to accommodate 16x32 font bitmaps */
847e580c6eSjklos
857e580c6eSjklos /* register space defines */
867e580c6eSjklos #define LCG_REG_ADDR 0x20100000 /* LCG registers */
877e580c6eSjklos #define LCG_REG_SIZE 0x4000 /* 16384 bytes */
887e580c6eSjklos #define LCG_REG(reg) regaddr[(reg / 4)]
897e580c6eSjklos
907e580c6eSjklos /* LUT defines */
917e580c6eSjklos #define LCG_LUT_ADDR 0x21800800 /* LUT right before onscreen FB */
927e580c6eSjklos #define LCG_LUT_OFFSET 0x00000800
937e580c6eSjklos #define LCG_LUT_SIZE 0x800 /* 2048 bytes */
947e580c6eSjklos
957e580c6eSjklos #define LCG_BG_COLOR WSCOL_BLACK
967e580c6eSjklos #define LCG_FG_COLOR WSCOL_WHITE
977e580c6eSjklos
987e580c6eSjklos #define LCG_CONFIG 0x200f0010 /* LCG model information */
997e580c6eSjklos
1007e580c6eSjklos /* implement sanity checks at certain points to ensure safer operation */
1017e580c6eSjklos #define LCG_SAFE
1027e580c6eSjklos //#define LCG_DEBUG
1037e580c6eSjklos
1047e580c6eSjklos static int lcg_match(struct device *, struct cfdata *, void *);
1057e580c6eSjklos static void lcg_attach(struct device *, struct device *, void *);
1067e580c6eSjklos
1077e580c6eSjklos struct lcg_softc {
1087e580c6eSjklos bus_dmamap_t sc_dm;
1097e580c6eSjklos };
1107e580c6eSjklos
1117e580c6eSjklos CFATTACH_DECL_NEW(lcg, sizeof(struct lcg_softc),
1127e580c6eSjklos lcg_match, lcg_attach, NULL, NULL);
1137e580c6eSjklos
1147e580c6eSjklos static void lcg_cursor(void *, int, int, int);
1157e580c6eSjklos static int lcg_mapchar(void *, int, unsigned int *);
1167e580c6eSjklos static void lcg_putchar(void *, int, int, u_int, long);
1177e580c6eSjklos static void lcg_copycols(void *, int, int, int,int);
1187e580c6eSjklos static void lcg_erasecols(void *, int, int, int, long);
1197e580c6eSjklos static void lcg_copyrows(void *, int, int, int);
1207e580c6eSjklos static void lcg_eraserows(void *, int, int, long);
1217e580c6eSjklos static int lcg_allocattr(void *, int, int, int, long *);
1227e580c6eSjklos static int lcg_get_cmap(struct wsdisplay_cmap *);
1237e580c6eSjklos static int lcg_set_cmap(struct wsdisplay_cmap *);
1247e580c6eSjklos static void lcg_init_common(struct device *, struct vsbus_attach_args *);
1257e580c6eSjklos
1267e580c6eSjklos const struct wsdisplay_emulops lcg_emulops = {
1277e580c6eSjklos lcg_cursor,
1287e580c6eSjklos lcg_mapchar,
1297e580c6eSjklos lcg_putchar,
1307e580c6eSjklos lcg_copycols,
1317e580c6eSjklos lcg_erasecols,
1327e580c6eSjklos lcg_copyrows,
1337e580c6eSjklos lcg_eraserows,
1347e580c6eSjklos lcg_allocattr
1357e580c6eSjklos };
1367e580c6eSjklos
1377e580c6eSjklos static char lcg_stdscreen_name[10] = "160x68";
1387e580c6eSjklos struct wsscreen_descr lcg_stdscreen = {
1397e580c6eSjklos lcg_stdscreen_name, 160, 68, /* dynamically set */
1407e580c6eSjklos &lcg_emulops,
1417e580c6eSjklos 8, 15, /* dynamically set */
1427e580c6eSjklos WSSCREEN_UNDERLINE|WSSCREEN_REVERSE|WSSCREEN_WSCOLORS,
1437e580c6eSjklos };
1447e580c6eSjklos
1457e580c6eSjklos const struct wsscreen_descr *_lcg_scrlist[] = {
1467e580c6eSjklos &lcg_stdscreen,
1477e580c6eSjklos };
1487e580c6eSjklos
1497e580c6eSjklos const struct wsscreen_list lcg_screenlist = {
1507e580c6eSjklos sizeof(_lcg_scrlist) / sizeof(struct wsscreen_descr *),
1517e580c6eSjklos _lcg_scrlist,
1527e580c6eSjklos };
1537e580c6eSjklos
1547e580c6eSjklos static char *lcgaddr;
1557e580c6eSjklos static char *lutaddr;
1567e580c6eSjklos static volatile long *regaddr;
1577e580c6eSjklos static volatile long *fifoaddr;
1587e580c6eSjklos #ifndef LCG_NO_ACCEL
1597e580c6eSjklos static char *fontaddr;
1607e580c6eSjklos #endif
1617e580c6eSjklos
1627e580c6eSjklos static int lcg_xsize;
1637e580c6eSjklos static int lcg_ysize;
1647e580c6eSjklos static int lcg_depth;
1657e580c6eSjklos static int lcg_cols;
1667e580c6eSjklos static int lcg_rows;
1677e580c6eSjklos static int lcg_onerow;
1687e580c6eSjklos static int lcg_fb_size;
1697e580c6eSjklos static int lcg_glyph_size; /* bitmap size in bits */
1707e580c6eSjklos
1717e580c6eSjklos static char *cursor;
1727e580c6eSjklos
1737e580c6eSjklos static int cur_on;
1747e580c6eSjklos
1757e580c6eSjklos static int cur_fg, cur_bg;
1767e580c6eSjklos
1777e580c6eSjklos
1787e580c6eSjklos /* Our current hardware colormap */
1797e580c6eSjklos static struct hwcmap256 {
1807e580c6eSjklos #define CMAP_SIZE 256 /* 256 R/G/B entries */
1817e580c6eSjklos u_int8_t r[CMAP_SIZE];
1827e580c6eSjklos u_int8_t g[CMAP_SIZE];
1837e580c6eSjklos u_int8_t b[CMAP_SIZE];
1847e580c6eSjklos } lcg_cmap;
1857e580c6eSjklos
1867e580c6eSjklos /* The default colormap */
1877e580c6eSjklos static struct {
1887e580c6eSjklos u_int8_t r[8];
1897e580c6eSjklos u_int8_t g[8];
1907e580c6eSjklos u_int8_t b[8];
1917e580c6eSjklos } lcg_default_cmap = {
1927e580c6eSjklos { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff },
1937e580c6eSjklos { 0x00, 0x00, 0xff, 0x7f, 0x00, 0x00, 0xff, 0xff },
1947e580c6eSjklos { 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff }
1957e580c6eSjklos };
1967e580c6eSjklos
1977e580c6eSjklos struct wsdisplay_font lcg_font;
1987e580c6eSjklos static u_char *qf;
1997e580c6eSjklos static u_short *qf2;
2007e580c6eSjklos
2017e580c6eSjklos #define QCHAR(c) (c < lcg_font.firstchar ? 0 : \
2027e580c6eSjklos (c >= (lcg_font.firstchar + lcg_font.numchars) ? 0 : c - lcg_font.firstchar))
2037e580c6eSjklos #define QFONT(c,line) ((lcg_font.stride == 2 ? \
2047e580c6eSjklos qf2[QCHAR(c) * lcg_font.fontheight + line] : \
2057e580c6eSjklos qf[QCHAR(c) * lcg_font.fontheight + line]))
2067e580c6eSjklos #define LCG_ADDR(row, col, line, dot) \
2077e580c6eSjklos lcgaddr[((col) * lcg_font.fontwidth) + ((row) * lcg_font.fontheight * lcg_xsize) + \
2087e580c6eSjklos (line) * lcg_xsize + dot]
2097e580c6eSjklos
2107e580c6eSjklos
2117e580c6eSjklos static int lcg_ioctl(void *, void *, u_long, void *, int, struct lwp *);
2127e580c6eSjklos static paddr_t lcg_mmap(void *, void *, off_t, int);
2137e580c6eSjklos static int lcg_alloc_screen(void *, const struct wsscreen_descr *,
2147e580c6eSjklos void **, int *, int *, long *);
2157e580c6eSjklos static void lcg_free_screen(void *, void *);
2167e580c6eSjklos static int lcg_show_screen(void *, void *, int,
2177e580c6eSjklos void (*) (void *, int, int), void *);
2187e580c6eSjklos static void lcg_crsr_blink(void *);
2197e580c6eSjklos
2207e580c6eSjklos /* LCG HW accel functions */
2217e580c6eSjklos #ifndef LCG_NO_ACCEL
2227e580c6eSjklos static void fifo_put(long data);
2237e580c6eSjklos static int fifo_fill(int iterations);
2247e580c6eSjklos static u_char fifo_counter = 0;
2257e580c6eSjklos
2267e580c6eSjklos static void blkcpy(long source, long dest, int xdim, int ydim);
2277e580c6eSjklos static void blkset(long dest, int xdim, int ydim, char color);
2287e580c6eSjklos static void renderchar(long source, long dest, int xdim, int ydim, char fg, char bg);
2297e580c6eSjklos #endif /* LCG_NO_ACCEL */
2307e580c6eSjklos
2317e580c6eSjklos const struct wsdisplay_accessops lcg_accessops = {
2327e580c6eSjklos lcg_ioctl,
2337e580c6eSjklos lcg_mmap,
2347e580c6eSjklos lcg_alloc_screen,
2357e580c6eSjklos lcg_free_screen,
2367e580c6eSjklos lcg_show_screen,
2377e580c6eSjklos 0 /* load_font */
2387e580c6eSjklos };
2397e580c6eSjklos
2407e580c6eSjklos /* TODO allocate ss_image dynamically for consoles beyond first one */
2417e580c6eSjklos struct lcg_screen {
2427e580c6eSjklos int ss_curx;
2437e580c6eSjklos int ss_cury;
2447e580c6eSjklos int ss_cur_fg;
2457e580c6eSjklos int ss_cur_bg;
2467e580c6eSjklos struct {
2477e580c6eSjklos u_char data; /* Image character */
2487e580c6eSjklos u_char attr; /* Attribute: 80/70/08/07 */
2497e580c6eSjklos } ss_image[160 * 128]; /* allow for maximum possible cell matrix */
2507e580c6eSjklos };
2517e580c6eSjklos #define LCG_ATTR_UNDERLINE 0x80
2527e580c6eSjklos #define LCG_BG_MASK 0x70
2537e580c6eSjklos #define LCG_ATTR_REVERSE 0x08
2547e580c6eSjklos #define LCG_FG_MASK 0x07
2557e580c6eSjklos
2567e580c6eSjklos static struct lcg_screen lcg_conscreen;
2577e580c6eSjklos static struct lcg_screen *curscr;
2587e580c6eSjklos static struct lcg_screen *savescr;
2597e580c6eSjklos
2607e580c6eSjklos static callout_t lcg_cursor_ch;
2617e580c6eSjklos
2627e580c6eSjklos #ifndef LCG_NO_ACCEL
fifo_put(long data)2637e580c6eSjklos void fifo_put(long data)
2647e580c6eSjklos {
2657e580c6eSjklos fifo_counter &= 0x3;
2667e580c6eSjklos fifoaddr[fifo_counter] = data;
2677e580c6eSjklos fifo_counter++;
2687e580c6eSjklos }
2697e580c6eSjklos
fifo_fill(int iterations)2707e580c6eSjklos int fifo_fill(int iterations)
2717e580c6eSjklos {
2727e580c6eSjklos long status;
273a50c0670Smaya int counter = 0;
2747e580c6eSjklos
2757e580c6eSjklos while (fifo_counter % 4)
2767e580c6eSjklos fifo_put(0);
2777e580c6eSjklos
2787e580c6eSjklos #ifdef LCG_SAFE
2797e580c6eSjklos status = LCG_REG(LCG_REG_GRAPHICS_SUB_STATUS);
2807e580c6eSjklos while ((counter < iterations) && ((status & 0x80000000) == 0x80000000)) {
2817e580c6eSjklos delay(1000);
2827e580c6eSjklos status = LCG_REG(LCG_REG_GRAPHICS_SUB_STATUS);
2837e580c6eSjklos counter++;
2847e580c6eSjklos }
2857e580c6eSjklos #endif
2867e580c6eSjklos
2877e580c6eSjklos if (counter == 0)
2887e580c6eSjklos return 0;
2897e580c6eSjklos else
2907e580c6eSjklos return 1;
2917e580c6eSjklos }
2927e580c6eSjklos
blkcpy(long source,long dest,int xdim,int ydim)2937e580c6eSjklos void blkcpy(long source, long dest, int xdim, int ydim)
2947e580c6eSjklos {
2957e580c6eSjklos int err;
2967e580c6eSjklos
2977e580c6eSjklos #ifdef LCG_SAFE
2987e580c6eSjklos if ((source < LCG_FB_ADDR) || (source > LCG_FB_ADDR + lcg_fb_size)) {
2997e580c6eSjklos printf("lcg: blkcpy: invalid source 0x%lx\n", source);
3007e580c6eSjklos return;
3017e580c6eSjklos }
3027e580c6eSjklos if ((dest < LCG_FB_ADDR) || (dest > LCG_FB_ADDR + lcg_fb_size)) {
3037e580c6eSjklos printf("lcg: blkcpy: invalid destination 0x%lx\n", dest);
3047e580c6eSjklos return;
3057e580c6eSjklos }
3067e580c6eSjklos #endif
3077e580c6eSjklos
3087e580c6eSjklos #ifdef LCG_SAFE
3097e580c6eSjklos fifo_put(0x0c010000 | (cur_fg & 0xff));
3107e580c6eSjklos #endif
3117e580c6eSjklos fifo_put(0x01020006);
3127e580c6eSjklos
3137e580c6eSjklos fifo_put(0x06800000);
3147e580c6eSjklos fifo_put(source);
3157e580c6eSjklos fifo_put(lcg_xsize);
3167e580c6eSjklos
3177e580c6eSjklos fifo_put(0x05800000);
3187e580c6eSjklos fifo_put(dest);
3197e580c6eSjklos fifo_put(lcg_xsize);
3207e580c6eSjklos
3217e580c6eSjklos fifo_put(0x03400000);
3227e580c6eSjklos fifo_put(0xff);
3237e580c6eSjklos
3247e580c6eSjklos fifo_put(0x02000003);
3257e580c6eSjklos
3267e580c6eSjklos #ifdef LCG_SAFE
3277e580c6eSjklos fifo_put(0x04c00000);
3287e580c6eSjklos fifo_put(0);
3297e580c6eSjklos fifo_put(lcg_xsize);
3307e580c6eSjklos fifo_put(lcg_fb_size - (dest - LCG_FB_ADDR));
3317e580c6eSjklos #endif
3327e580c6eSjklos
3337e580c6eSjklos fifo_put(0x09c00000);
3347e580c6eSjklos fifo_put(((ydim & 0xffff) << 16) | xdim);
3357e580c6eSjklos fifo_put(0);
3367e580c6eSjklos fifo_put(0);
3377e580c6eSjklos
3387e580c6eSjklos err = fifo_fill(200);
3397e580c6eSjklos if (err)
3407e580c6eSjklos printf("lcg: AG still busy after 200 msec\n");
3417e580c6eSjklos }
3427e580c6eSjklos
blkset(long dest,int xdim,int ydim,char color)3437e580c6eSjklos void blkset(long dest, int xdim, int ydim, char color)
3447e580c6eSjklos {
3457e580c6eSjklos int err;
3467e580c6eSjklos
3477e580c6eSjklos #ifdef LCG_SAFE
3487e580c6eSjklos if ((dest < LCG_FB_ADDR) || (dest > LCG_FB_ADDR + lcg_fb_size)) {
3497e580c6eSjklos printf("lcg: blkset: invalid destination 0x%lx\n", dest);
3507e580c6eSjklos return;
3517e580c6eSjklos }
3527e580c6eSjklos #endif
3537e580c6eSjklos
3547e580c6eSjklos fifo_put(0x0c010000 | (color & 0xff));
3557e580c6eSjklos
3567e580c6eSjklos fifo_put(0x01000000);
3577e580c6eSjklos
3587e580c6eSjklos fifo_put(0x05800000);
3597e580c6eSjklos fifo_put(dest);
3607e580c6eSjklos fifo_put(lcg_xsize);
3617e580c6eSjklos
3627e580c6eSjklos fifo_put(0x03400000);
3637e580c6eSjklos fifo_put(0xff);
3647e580c6eSjklos
3657e580c6eSjklos fifo_put(0x02000003);
3667e580c6eSjklos
3677e580c6eSjklos #ifdef LCG_SAFE
3687e580c6eSjklos fifo_put(0x04c00000);
3697e580c6eSjklos fifo_put(0);
3707e580c6eSjklos fifo_put(lcg_xsize);
3717e580c6eSjklos fifo_put(lcg_fb_size - (dest - LCG_FB_ADDR));
3727e580c6eSjklos #endif
3737e580c6eSjklos
3747e580c6eSjklos fifo_put(0x09c00000);
3757e580c6eSjklos fifo_put(((ydim & 0xffff) << 16) | xdim);
3767e580c6eSjklos fifo_put(0);
3777e580c6eSjklos fifo_put(0);
3787e580c6eSjklos
3797e580c6eSjklos err = fifo_fill(200);
3807e580c6eSjklos if (err)
3817e580c6eSjklos printf("lcg: AG still busy after 200 msec\n");
3827e580c6eSjklos }
3837e580c6eSjklos
renderchar(long source,long dest,int xdim,int ydim,char fg,char bg)3847e580c6eSjklos void renderchar(long source, long dest, int xdim, int ydim, char fg, char bg)
3857e580c6eSjklos {
3867e580c6eSjklos int err;
3877e580c6eSjklos #ifdef LCG_SAFE
3887e580c6eSjklos if ((dest < LCG_FB_ADDR) || (dest > LCG_FB_ADDR + lcg_fb_size)) {
3897e580c6eSjklos printf("lcg: blkset: invalid destination 0x%lx\n", dest);
3907e580c6eSjklos return;
3917e580c6eSjklos }
3927e580c6eSjklos #endif
3937e580c6eSjklos
3947e580c6eSjklos fifo_put(0x0c050000 | (bg & 0xff));
3957e580c6eSjklos fifo_put(0x0c010000 | (fg & 0xff));
3967e580c6eSjklos
3977e580c6eSjklos fifo_put(0x01030008);
3987e580c6eSjklos
3997e580c6eSjklos fifo_put(0x06800000);
4007e580c6eSjklos fifo_put(source);
4017e580c6eSjklos //fifo_put(lcg_xsize);
4027e580c6eSjklos fifo_put(lcg_font.stride);
4037e580c6eSjklos
4047e580c6eSjklos fifo_put(0x05800000);
4057e580c6eSjklos fifo_put(dest);
4067e580c6eSjklos fifo_put(lcg_xsize);
4077e580c6eSjklos
4087e580c6eSjklos fifo_put(0x03400000);
4097e580c6eSjklos fifo_put(0xff);
4107e580c6eSjklos
4117e580c6eSjklos fifo_put(0x02000003);
4127e580c6eSjklos
4137e580c6eSjklos #ifdef LCG_SAFE
4147e580c6eSjklos fifo_put(0x04c00000);
4157e580c6eSjklos fifo_put(0);
4167e580c6eSjklos fifo_put(lcg_xsize);
4177e580c6eSjklos fifo_put(lcg_fb_size - (dest - LCG_FB_ADDR));
4187e580c6eSjklos #endif
4197e580c6eSjklos
4207e580c6eSjklos fifo_put(0x09c00000);
4217e580c6eSjklos fifo_put(((ydim & 0xffff) << 16) | (xdim & 0xffff));
4227e580c6eSjklos fifo_put(0);
4237e580c6eSjklos fifo_put(0);
4247e580c6eSjklos
4257e580c6eSjklos err = fifo_fill(200);
4267e580c6eSjklos if (err)
4277e580c6eSjklos printf("lcg: AG still busy after 200 msec\n");
4287e580c6eSjklos }
4297e580c6eSjklos #endif /* LCG_NO_ACCEL */
4307e580c6eSjklos
4317e580c6eSjklos int
lcg_match(struct device * parent,struct cfdata * match,void * aux)4327e580c6eSjklos lcg_match(struct device *parent, struct cfdata *match, void *aux)
4337e580c6eSjklos {
4347e580c6eSjklos struct vsbus_softc *sc = device_private(parent);
4357e580c6eSjklos struct vsbus_attach_args *va = aux;
436*2b6fd3cdSjakllsch volatile char * const ch = (char *)va->va_addr;
4377e580c6eSjklos
4387e580c6eSjklos if ((vax_boardtype != VAX_BTYP_46) && (vax_boardtype != VAX_BTYP_48))
4397e580c6eSjklos return 0;
4407e580c6eSjklos
4417e580c6eSjklos *ch = 1;
4427e580c6eSjklos if ((*ch & 1) == 0)
4437e580c6eSjklos return 0;
4447e580c6eSjklos *ch = 0;
4457e580c6eSjklos if ((*ch & 1) != 0)
4467e580c6eSjklos return 0;
4477e580c6eSjklos
4487e580c6eSjklos /* XXX use vertical interrupt? */
4497e580c6eSjklos sc->sc_mask = 0x04; /* XXX - should be generated */
4507e580c6eSjklos scb_fake(0x120, 0x15);
4517e580c6eSjklos return 20;
4527e580c6eSjklos }
4537e580c6eSjklos
4547e580c6eSjklos void
lcg_attach(struct device * parent,struct device * self,void * aux)4557e580c6eSjklos lcg_attach(struct device *parent, struct device *self, void *aux)
4567e580c6eSjklos {
4577e580c6eSjklos struct vsbus_attach_args *va = aux;
4587e580c6eSjklos struct wsemuldisplaydev_attach_args aa;
4597e580c6eSjklos
4607e580c6eSjklos printf("\n");
4617e580c6eSjklos aa.console = lcgaddr != NULL;
4627e580c6eSjklos
4637e580c6eSjklos lcg_init_common(self, va);
4647e580c6eSjklos
4657e580c6eSjklos curscr = &lcg_conscreen;
4667e580c6eSjklos
4677e580c6eSjklos aa.scrdata = &lcg_screenlist;
4687e580c6eSjklos aa.accessops = &lcg_accessops;
4697e580c6eSjklos
4707e580c6eSjklos /* enable software cursor */
4717e580c6eSjklos callout_init(&lcg_cursor_ch, 0);
4727e580c6eSjklos callout_reset(&lcg_cursor_ch, hz / 2, lcg_crsr_blink, NULL);
4737e580c6eSjklos
474c7fb772bSthorpej config_found(self, &aa, wsemuldisplaydevprint, CFARGS_NONE);
4757e580c6eSjklos }
4767e580c6eSjklos
4777e580c6eSjklos static void
lcg_crsr_blink(void * arg)4787e580c6eSjklos lcg_crsr_blink(void *arg)
4797e580c6eSjklos {
4807e580c6eSjklos int dot;
4817e580c6eSjklos
4827e580c6eSjklos if (cur_on && curscr != NULL)
4837e580c6eSjklos for (dot = 0; dot < lcg_font.fontwidth; dot++)
4847e580c6eSjklos cursor[dot] = ((cursor[dot] & 0x0f) == cur_fg) ? cur_bg : cur_fg;
4857e580c6eSjklos
4867e580c6eSjklos callout_reset(&lcg_cursor_ch, hz / 2, lcg_crsr_blink, NULL);
4877e580c6eSjklos }
4887e580c6eSjklos
4897e580c6eSjklos void
lcg_cursor(void * id,int on,int row,int col)4907e580c6eSjklos lcg_cursor(void *id, int on, int row, int col)
4917e580c6eSjklos {
4927e580c6eSjklos struct lcg_screen *ss = id;
4937e580c6eSjklos int dot, attr;
4947e580c6eSjklos
4957e580c6eSjklos attr = ss->ss_image[row * lcg_cols + col].attr;
4967e580c6eSjklos if (ss == curscr) {
4977e580c6eSjklos if (cursor != NULL) {
4987e580c6eSjklos int ch = QFONT(ss->ss_image[ss->ss_cury * lcg_cols +
4997e580c6eSjklos ss->ss_curx].data, lcg_font.fontheight - 1);
5007e580c6eSjklos attr = ss->ss_image[ss->ss_cury * lcg_cols +
5017e580c6eSjklos ss->ss_curx].attr;
5027e580c6eSjklos
5037e580c6eSjklos if (attr & LCG_ATTR_REVERSE) {
5047e580c6eSjklos cur_bg = attr & LCG_FG_MASK;
5057e580c6eSjklos cur_fg = (attr & LCG_BG_MASK) >> 4;
5067e580c6eSjklos } else {
5077e580c6eSjklos cur_fg = attr & LCG_FG_MASK;
5087e580c6eSjklos cur_bg = (attr & LCG_BG_MASK) >> 4;
5097e580c6eSjklos }
5107e580c6eSjklos for (dot = 0; dot < lcg_font.fontwidth; dot++)
5117e580c6eSjklos cursor[dot] = (ch & (1 << dot)) ?
5127e580c6eSjklos cur_fg : cur_bg;
5137e580c6eSjklos }
5147e580c6eSjklos
5157e580c6eSjklos cursor = &LCG_ADDR(row, col, lcg_font.fontheight - 1, 0);
5167e580c6eSjklos cur_on = on;
5177e580c6eSjklos if (attr & LCG_ATTR_REVERSE) {
5187e580c6eSjklos cur_bg = attr & LCG_FG_MASK;
5197e580c6eSjklos cur_fg = (attr & LCG_BG_MASK) >> 4;
5207e580c6eSjklos } else {
5217e580c6eSjklos cur_fg = attr & LCG_FG_MASK;
5227e580c6eSjklos cur_bg = (attr & LCG_BG_MASK) >> 4;
5237e580c6eSjklos }
5247e580c6eSjklos }
5257e580c6eSjklos ss->ss_curx = col;
5267e580c6eSjklos ss->ss_cury = row;
5277e580c6eSjklos if (attr & LCG_ATTR_REVERSE) {
5287e580c6eSjklos ss->ss_cur_bg = attr & LCG_FG_MASK;
5297e580c6eSjklos ss->ss_cur_fg = (attr & LCG_BG_MASK) >> 4;
5307e580c6eSjklos } else {
5317e580c6eSjklos ss->ss_cur_fg = attr & LCG_FG_MASK;
5327e580c6eSjklos ss->ss_cur_bg = (attr & LCG_BG_MASK) >> 4;
5337e580c6eSjklos }
5347e580c6eSjklos }
5357e580c6eSjklos
5367e580c6eSjklos int
lcg_mapchar(void * id,int uni,unsigned int * index)5377e580c6eSjklos lcg_mapchar(void *id, int uni, unsigned int *index)
5387e580c6eSjklos {
5397e580c6eSjklos if (uni < 256) {
5407e580c6eSjklos *index = uni;
5417e580c6eSjklos return (5);
5427e580c6eSjklos }
5437e580c6eSjklos *index = ' ';
5447e580c6eSjklos return (0);
5457e580c6eSjklos }
5467e580c6eSjklos
5477e580c6eSjklos static void
lcg_putchar(void * id,int row,int col,u_int c,long attr)5487e580c6eSjklos lcg_putchar(void *id, int row, int col, u_int c, long attr)
5497e580c6eSjklos {
5507e580c6eSjklos struct lcg_screen *ss = id;
5517e580c6eSjklos int i;
5527e580c6eSjklos char dot_fg, dot_bg;
5537e580c6eSjklos
5547e580c6eSjklos c &= 0xff;
5557e580c6eSjklos
5567e580c6eSjklos ss->ss_image[row * lcg_cols + col].data = c;
5577e580c6eSjklos ss->ss_image[row * lcg_cols + col].attr = attr;
5587e580c6eSjklos if (ss != curscr)
5597e580c6eSjklos return;
5607e580c6eSjklos
5617e580c6eSjklos dot_fg = attr & LCG_FG_MASK;
5627e580c6eSjklos dot_bg = (attr & LCG_BG_MASK) >> 4;
5637e580c6eSjklos if (attr & LCG_ATTR_REVERSE) {
5647e580c6eSjklos dot_fg = (attr & LCG_BG_MASK) >> 4;
5657e580c6eSjklos dot_bg = attr & LCG_FG_MASK;
5667e580c6eSjklos }
5677e580c6eSjklos
5687e580c6eSjklos #ifndef LCG_NO_ACCEL
5697e580c6eSjklos renderchar(LCG_FONT_ADDR + (c * lcg_glyph_size),
5707e580c6eSjklos LCG_FB_ADDR + (row * lcg_onerow) + (col * lcg_font.fontwidth),
5717e580c6eSjklos lcg_font.fontwidth, lcg_font.fontheight, dot_fg, dot_bg);
5727e580c6eSjklos #else
5737e580c6eSjklos for (i = 0; i < lcg_font.fontheight; i++) {
5747e580c6eSjklos unsigned char ch = QFONT(c,i);
5757e580c6eSjklos for (int j = 0; j < lcg_font.fontwidth; j++) {
5767e580c6eSjklos LCG_ADDR(row, col, i, j) = ((ch >> j) & 1) ? dot_fg : dot_bg;
5777e580c6eSjklos }
5787e580c6eSjklos }
5797e580c6eSjklos #endif /* LCG_NO_ACCEL */
5807e580c6eSjklos if (attr & LCG_ATTR_UNDERLINE) {
5817e580c6eSjklos char *p = &LCG_ADDR(row, col, lcg_font.fontheight - 1, 0);
5827e580c6eSjklos for (i = 0; i < lcg_font.fontwidth; i++)
5837e580c6eSjklos p[i] = ~p[i];
5847e580c6eSjklos }
5857e580c6eSjklos }
5867e580c6eSjklos
5877e580c6eSjklos
5887e580c6eSjklos
5897e580c6eSjklos /*
5907e580c6eSjklos * copies columns inside a row.
5917e580c6eSjklos */
5927e580c6eSjklos static void
lcg_copycols(void * id,int row,int srccol,int dstcol,int ncols)5937e580c6eSjklos lcg_copycols(void *id, int row, int srccol, int dstcol, int ncols)
5947e580c6eSjklos {
5957e580c6eSjklos struct lcg_screen *ss = id;
5967e580c6eSjklos #ifdef LCG_NO_ACCEL
5977e580c6eSjklos int i = 0;
5987e580c6eSjklos #endif
5997e580c6eSjklos
6007e580c6eSjklos bcopy(&ss->ss_image[row * lcg_cols + srccol], &ss->ss_image[row *
6017e580c6eSjklos lcg_cols + dstcol], ncols * sizeof(ss->ss_image[0]));
6027e580c6eSjklos if (ss != curscr)
6037e580c6eSjklos return;
6047e580c6eSjklos #ifdef LCG_NO_ACCEL
6057e580c6eSjklos for (i = 0; i < lcg_font.fontheight; i++)
6067e580c6eSjklos memcpy(&LCG_ADDR(row, dstcol, i, 0),
6077e580c6eSjklos &LCG_ADDR(row,srccol, i, 0), ncols * lcg_font.fontwidth);
6087e580c6eSjklos
6097e580c6eSjklos #else
6107e580c6eSjklos blkcpy(LCG_FB_ADDR + (row * lcg_onerow) + (srccol * lcg_font.fontwidth),
6117e580c6eSjklos LCG_FB_ADDR + (row * lcg_onerow) + (dstcol * lcg_font.fontwidth),
6127e580c6eSjklos (ncols * lcg_font.fontwidth), lcg_font.fontheight);
6137e580c6eSjklos #endif
6147e580c6eSjklos }
6157e580c6eSjklos
6167e580c6eSjklos /*
6177e580c6eSjklos * Erases a bunch of chars inside one row.
6187e580c6eSjklos */
6197e580c6eSjklos static void
lcg_erasecols(void * id,int row,int startcol,int ncols,long fillattr)6207e580c6eSjklos lcg_erasecols(void *id, int row, int startcol, int ncols, long fillattr)
6217e580c6eSjklos {
6227e580c6eSjklos struct lcg_screen *ss = id;
6237e580c6eSjklos int i;
6247e580c6eSjklos
6257e580c6eSjklos bzero(&ss->ss_image[row * lcg_cols + startcol], ncols * sizeof(ss->ss_image[0]));
6267e580c6eSjklos for (i = row * lcg_cols + startcol; i < row * lcg_cols + startcol + ncols; ++i)
6277e580c6eSjklos ss->ss_image[i].attr = fillattr;
6287e580c6eSjklos if (ss != curscr)
6297e580c6eSjklos return;
6307e580c6eSjklos #ifdef LCG_NO_ACCEL
6317e580c6eSjklos for (i = 0; i < lcg_font.fontheight; i++)
6327e580c6eSjklos memset(&LCG_ADDR(row, startcol, i, 0), 0, ncols * lcg_font.fontwidth);
6337e580c6eSjklos #else
6347e580c6eSjklos blkset(LCG_FB_ADDR + (row * lcg_onerow) + (startcol * lcg_font.fontwidth),
6357e580c6eSjklos (ncols * lcg_font.fontwidth), lcg_font.fontheight, (fillattr & LCG_BG_MASK) >> 4);
6367e580c6eSjklos #endif
6377e580c6eSjklos }
6387e580c6eSjklos
6397e580c6eSjklos static void
lcg_copyrows(void * id,int srcrow,int dstrow,int nrows)6407e580c6eSjklos lcg_copyrows(void *id, int srcrow, int dstrow, int nrows)
6417e580c6eSjklos {
6427e580c6eSjklos struct lcg_screen *ss = id;
6437e580c6eSjklos
6447e580c6eSjklos bcopy(&ss->ss_image[srcrow * lcg_cols], &ss->ss_image[dstrow * lcg_cols],
6457e580c6eSjklos nrows * lcg_cols * sizeof(ss->ss_image[0]));
6467e580c6eSjklos if (ss != curscr)
6477e580c6eSjklos return;
6487e580c6eSjklos #ifdef LCG_NO_ACCEL
6497e580c6eSjklos memcpy(&lcgaddr[dstrow * lcg_onerow],
6507e580c6eSjklos &lcgaddr[srcrow * lcg_onerow], nrows * lcg_onerow);
6517e580c6eSjklos #else
6527e580c6eSjklos blkcpy(LCG_FB_ADDR + (srcrow * lcg_onerow), LCG_FB_ADDR + (dstrow * lcg_onerow),
6537e580c6eSjklos (lcg_cols * lcg_font.fontwidth), (nrows * lcg_font.fontheight));
6547e580c6eSjklos #endif
6557e580c6eSjklos }
6567e580c6eSjklos
6577e580c6eSjklos static void
lcg_eraserows(void * id,int startrow,int nrows,long fillattr)6587e580c6eSjklos lcg_eraserows(void *id, int startrow, int nrows, long fillattr)
6597e580c6eSjklos {
6607e580c6eSjklos struct lcg_screen *ss = id;
6617e580c6eSjklos int i;
6627e580c6eSjklos
6637e580c6eSjklos bzero(&ss->ss_image[startrow * lcg_cols], nrows * lcg_cols *
6647e580c6eSjklos sizeof(ss->ss_image[0]));
6657e580c6eSjklos for (i = startrow * lcg_cols; i < (startrow + nrows) * lcg_cols; ++i)
6667e580c6eSjklos ss->ss_image[i].attr = fillattr;
6677e580c6eSjklos if (ss != curscr)
6687e580c6eSjklos return;
6697e580c6eSjklos #ifdef LCG_NO_ACCEL
6707e580c6eSjklos memset(&lcgaddr[startrow * lcg_onerow], 0, nrows * lcg_onerow);
6717e580c6eSjklos #else
6727e580c6eSjklos blkset(LCG_FB_ADDR + (startrow * lcg_onerow), (lcg_cols * lcg_font.fontwidth),
6737e580c6eSjklos (nrows * lcg_font.fontheight), (fillattr & LCG_BG_MASK) >> 4);
6747e580c6eSjklos #endif
6757e580c6eSjklos }
6767e580c6eSjklos
6777e580c6eSjklos static int
lcg_allocattr(void * id,int fg,int bg,int flags,long * attrp)6787e580c6eSjklos lcg_allocattr(void *id, int fg, int bg, int flags, long *attrp)
6797e580c6eSjklos {
6807e580c6eSjklos long myattr;
6817e580c6eSjklos
6827e580c6eSjklos if (flags & WSATTR_WSCOLORS)
6837e580c6eSjklos myattr = (fg & LCG_FG_MASK) | ((bg << 4) & LCG_BG_MASK);
6847e580c6eSjklos else
6857e580c6eSjklos myattr = WSCOL_WHITE << 4; /* XXXX */
6867e580c6eSjklos if (flags & WSATTR_REVERSE)
6877e580c6eSjklos myattr |= LCG_ATTR_REVERSE;
6887e580c6eSjklos if (flags & WSATTR_UNDERLINE)
6897e580c6eSjklos myattr |= LCG_ATTR_UNDERLINE;
6907e580c6eSjklos *attrp = myattr;
6917e580c6eSjklos return 0;
6927e580c6eSjklos }
6937e580c6eSjklos
6947e580c6eSjklos static int
lcg_ioctl(void * v,void * vs,u_long cmd,void * data,int flag,struct lwp * l)6957e580c6eSjklos lcg_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l)
6967e580c6eSjklos {
6977e580c6eSjklos struct wsdisplay_fbinfo *fb = (void *)data;
6987e580c6eSjklos int i;
6997e580c6eSjklos
7007e580c6eSjklos switch (cmd) {
7017e580c6eSjklos case WSDISPLAYIO_GTYPE:
7027e580c6eSjklos *(u_int *)data = WSDISPLAY_TYPE_LCG;
7037e580c6eSjklos break;
7047e580c6eSjklos
7057e580c6eSjklos case WSDISPLAYIO_GINFO:
7067e580c6eSjklos fb->height = lcg_ysize;
7077e580c6eSjklos fb->width = lcg_xsize;
7087e580c6eSjklos fb->depth = lcg_depth;
7097e580c6eSjklos fb->cmsize = 1 << lcg_depth;
7107e580c6eSjklos break;
7117e580c6eSjklos
7125ebf3ef3Sjklos case WSDISPLAYIO_LINEBYTES:
7135ebf3ef3Sjklos *(u_int *)data = lcg_xsize;
7145ebf3ef3Sjklos break;
7155ebf3ef3Sjklos
7167e580c6eSjklos case WSDISPLAYIO_GETCMAP:
7177e580c6eSjklos return lcg_get_cmap((struct wsdisplay_cmap *)data);
7187e580c6eSjklos
7197e580c6eSjklos case WSDISPLAYIO_PUTCMAP:
7207e580c6eSjklos return lcg_set_cmap((struct wsdisplay_cmap *)data);
7217e580c6eSjklos
7227e580c6eSjklos case WSDISPLAYIO_GMODE:
7237e580c6eSjklos return EPASSTHROUGH;
7247e580c6eSjklos
7257e580c6eSjklos case WSDISPLAYIO_SMODE:
7267e580c6eSjklos /* if setting WSDISPLAYIO_MODE_EMUL, restore console cmap, current screen */
7277e580c6eSjklos if (*(u_int *)data == WSDISPLAYIO_MODE_EMUL) {
7287e580c6eSjklos /* FIXME: if this is meant to reset palette LUT reload has to be triggered too */
7297e580c6eSjklos bzero(lutaddr, LCG_LUT_SIZE);
7307e580c6eSjklos for (i = 0; i < 8; ++i) {
7317e580c6eSjklos lcg_cmap.r[i] = lcg_default_cmap.r[i];
7327e580c6eSjklos lcg_cmap.g[i] = lcg_default_cmap.g[i];
7337e580c6eSjklos lcg_cmap.b[i] = lcg_default_cmap.b[i];
7347e580c6eSjklos lutaddr[i * 8 + 1] = i;
7357e580c6eSjklos lutaddr[i * 8 + 2] = 1;
7367e580c6eSjklos lutaddr[i * 8 + 3] = lcg_cmap.r[i] >> (lcg_depth & 7);
7377e580c6eSjklos lutaddr[i * 8 + 4] = 1;
7387e580c6eSjklos lutaddr[i * 8 + 5] = lcg_cmap.g[i] >> (lcg_depth & 7);
7397e580c6eSjklos lutaddr[i * 8 + 6] = 1;
7407e580c6eSjklos lutaddr[i * 8 + 7] = lcg_cmap.b[i] >> (lcg_depth & 7);
7417e580c6eSjklos }
7427e580c6eSjklos if (savescr != NULL)
7437e580c6eSjklos lcg_show_screen(NULL, savescr, 0, NULL, NULL);
7447e580c6eSjklos savescr = NULL;
7457e580c6eSjklos } else { /* WSDISPLAYIO_MODE_MAPPED */
7467e580c6eSjklos savescr = curscr;
7477e580c6eSjklos curscr = NULL;
7487e580c6eSjklos /* clear screen? */
7497e580c6eSjklos }
7507e580c6eSjklos
7517e580c6eSjklos return EPASSTHROUGH;
7527e580c6eSjklos #if 0
7537e580c6eSjklos case WSDISPLAYIO_SVIDEO:
7547e580c6eSjklos if (*(u_int *)data == WSDISPLAYIO_VIDEO_ON) {
7557e580c6eSjklos curcmd = curc;
7567e580c6eSjklos } else {
7577e580c6eSjklos curc = curcmd;
7587e580c6eSjklos curcmd &= ~(CUR_CMD_FOPA|CUR_CMD_ENPA);
7597e580c6eSjklos curcmd |= CUR_CMD_FOPB;
7607e580c6eSjklos }
7617e580c6eSjklos WRITECUR(CUR_CMD, curcmd);
7627e580c6eSjklos break;
7637e580c6eSjklos
7647e580c6eSjklos case WSDISPLAYIO_GVIDEO:
7657e580c6eSjklos *(u_int *)data = (curcmd & CUR_CMD_FOPB ?
7667e580c6eSjklos WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON);
7677e580c6eSjklos break;
7687e580c6eSjklos
7697e580c6eSjklos #endif
7707e580c6eSjklos default:
7717e580c6eSjklos return EPASSTHROUGH;
7727e580c6eSjklos }
7737e580c6eSjklos return 0;
7747e580c6eSjklos }
7757e580c6eSjklos
7767e580c6eSjklos static paddr_t
lcg_mmap(void * v,void * vs,off_t offset,int prot)7777e580c6eSjklos lcg_mmap(void *v, void *vs, off_t offset, int prot)
7787e580c6eSjklos {
7797e580c6eSjklos if (offset >= lcg_fb_size || offset < 0)
7807e580c6eSjklos return -1;
7817e580c6eSjklos return (LCG_FB_ADDR + offset) >> PGSHIFT;
7827e580c6eSjklos }
7837e580c6eSjklos
7847e580c6eSjklos int
lcg_alloc_screen(void * v,const struct wsscreen_descr * type,void ** cookiep,int * curxp,int * curyp,long * defattrp)7857e580c6eSjklos lcg_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
7867e580c6eSjklos int *curxp, int *curyp, long *defattrp)
7877e580c6eSjklos {
7887e580c6eSjklos int i;
7897e580c6eSjklos struct lcg_screen *ss;
7907e580c6eSjklos
79174ee8752Sthorpej *cookiep = kmem_alloc(sizeof(struct lcg_screen), KM_SLEEP);
7927e580c6eSjklos bzero(*cookiep, sizeof(struct lcg_screen));
7937e580c6eSjklos *curxp = *curyp = 0;
7947e580c6eSjklos *defattrp = (LCG_BG_COLOR << 4) | LCG_FG_COLOR;
7957e580c6eSjklos ss = *cookiep;
7967e580c6eSjklos for (i = 0; i < lcg_cols * lcg_rows; ++i)
7977e580c6eSjklos ss->ss_image[i].attr = (LCG_BG_COLOR << 4) | LCG_FG_COLOR;
7987e580c6eSjklos return 0;
7997e580c6eSjklos }
8007e580c6eSjklos
8017e580c6eSjklos void
lcg_free_screen(void * v,void * cookie)8027e580c6eSjklos lcg_free_screen(void *v, void *cookie)
8037e580c6eSjklos {
8047e580c6eSjklos }
8057e580c6eSjklos
8067e580c6eSjklos int
lcg_show_screen(void * v,void * cookie,int waitok,void (* cb)(void *,int,int),void * cbarg)8077e580c6eSjklos lcg_show_screen(void *v, void *cookie, int waitok,
8087e580c6eSjklos void (*cb)(void *, int, int), void *cbarg)
8097e580c6eSjklos {
8107e580c6eSjklos struct lcg_screen *ss = cookie;
8117e580c6eSjklos int row, col, dot_fg, dot_bg, j, attr;
8127e580c6eSjklos #ifdef LCG_NO_ACCEL
8137e580c6eSjklos int iter, jter;
8147e580c6eSjklos unsigned char ch;
8157e580c6eSjklos #endif
8167e580c6eSjklos
8177e580c6eSjklos if (ss == curscr)
8187e580c6eSjklos return (0);
8197e580c6eSjklos #ifdef LCG_NO_ACCEL
8207e580c6eSjklos memset(lcgaddr, LCG_BG_COLOR, lcg_xsize * lcg_ysize);
8217e580c6eSjklos #endif
8227e580c6eSjklos
8237e580c6eSjklos for (row = 0; row < lcg_rows; row++)
8247e580c6eSjklos for (col = 0; col < lcg_cols; col++) {
8257e580c6eSjklos attr = ss->ss_image[row * lcg_cols + col].attr;
8267e580c6eSjklos if (attr & LCG_ATTR_REVERSE) {
8277e580c6eSjklos dot_fg = (attr & LCG_BG_MASK) >> 4;
8287e580c6eSjklos dot_bg = attr & LCG_FG_MASK;
8297e580c6eSjklos } else {
8307e580c6eSjklos dot_fg = attr & LCG_FG_MASK;
8317e580c6eSjklos dot_bg = (attr & LCG_BG_MASK) >> 4;
8327e580c6eSjklos }
8337e580c6eSjklos u_char c = ss->ss_image[row * lcg_cols + col].data;
8347e580c6eSjklos
8357e580c6eSjklos if (c < 32)
8367e580c6eSjklos c = 32;
8377e580c6eSjklos #ifndef LCG_NO_ACCEL
8387e580c6eSjklos renderchar(LCG_FONT_ADDR + (c * lcg_glyph_size),
8397e580c6eSjklos LCG_FB_ADDR + (row * lcg_onerow) + (col * lcg_font.fontwidth),
8407e580c6eSjklos lcg_font.fontwidth, lcg_font.fontheight, dot_fg, dot_bg);
8417e580c6eSjklos #else
8427e580c6eSjklos for (iter = 0; iter < lcg_font.fontheight; iter++) {
8437e580c6eSjklos ch = QFONT(c,iter);
8447e580c6eSjklos for (jter = 0; jter < lcg_font.fontwidth; jter++) {
8457e580c6eSjklos LCG_ADDR(row, col, iter, jter) = ((ch >> jter) & 1) ? dot_fg : dot_bg;
8467e580c6eSjklos }
8477e580c6eSjklos }
8487e580c6eSjklos #endif
8497e580c6eSjklos if (attr & LCG_ATTR_UNDERLINE)
8507e580c6eSjklos for (j = 0; j < lcg_font.fontwidth; j++)
8517e580c6eSjklos LCG_ADDR(row, col,
8527e580c6eSjklos lcg_font.fontheight - 1, j) = dot_fg;
8537e580c6eSjklos }
8547e580c6eSjklos
8557e580c6eSjklos cursor = &lcgaddr[(ss->ss_cury * lcg_onerow) +
8567e580c6eSjklos ((lcg_font.fontheight - 1) * lcg_xsize) +
8577e580c6eSjklos (ss->ss_curx * lcg_font.fontwidth)];
8587e580c6eSjklos cur_fg = ss->ss_cur_fg;
8597e580c6eSjklos cur_bg = ss->ss_cur_bg;
8607e580c6eSjklos
8617e580c6eSjklos curscr = ss;
8627e580c6eSjklos return (0);
8637e580c6eSjklos }
8647e580c6eSjklos
8657e580c6eSjklos static int
lcg_get_cmap(struct wsdisplay_cmap * p)8667e580c6eSjklos lcg_get_cmap(struct wsdisplay_cmap *p)
8677e580c6eSjklos {
8687e580c6eSjklos u_int index = p->index, count = p->count;
8697e580c6eSjklos int error;
8707e580c6eSjklos
8717e580c6eSjklos if (index >= (1 << lcg_depth) || count > (1 << lcg_depth) - index)
8727e580c6eSjklos return (EINVAL);
8737e580c6eSjklos
8747e580c6eSjklos error = copyout(&lcg_cmap.r[index], p->red, count);
8757e580c6eSjklos if (error)
8767e580c6eSjklos return error;
8777e580c6eSjklos error = copyout(&lcg_cmap.g[index], p->green, count);
8787e580c6eSjklos if (error)
8797e580c6eSjklos return error;
8807e580c6eSjklos error = copyout(&lcg_cmap.b[index], p->blue, count);
8817e580c6eSjklos return error;
8827e580c6eSjklos }
8837e580c6eSjklos
8847e580c6eSjklos static int
lcg_set_cmap(struct wsdisplay_cmap * p)8857e580c6eSjklos lcg_set_cmap(struct wsdisplay_cmap *p)
8867e580c6eSjklos {
8877e580c6eSjklos u_int index = p->index, count = p->count;
8887e580c6eSjklos int error, s;
8897e580c6eSjklos
8907e580c6eSjklos if (index >= (1 << lcg_depth) || count > (1 << lcg_depth) - index)
8917e580c6eSjklos return (EINVAL);
8927e580c6eSjklos
8937e580c6eSjklos error = copyin(p->red, &lcg_cmap.r[index], count);
8947e580c6eSjklos if (error)
8957e580c6eSjklos return error;
8967e580c6eSjklos error = copyin(p->green, &lcg_cmap.g[index], count);
8977e580c6eSjklos if (error)
8987e580c6eSjklos return error;
8997e580c6eSjklos error = copyin(p->blue, &lcg_cmap.b[index], count);
9007e580c6eSjklos if (error)
9017e580c6eSjklos return error;
9027e580c6eSjklos
9037e580c6eSjklos s = spltty();
9047e580c6eSjklos /* FIXME: if this is meant to set palette LUT reload has to be triggered too */
9057e580c6eSjklos while (count-- > 0) {
9067e580c6eSjklos lutaddr[index * 8 + 0] = 0;
9077e580c6eSjklos lutaddr[index * 8 + 1] = index;
9087e580c6eSjklos lutaddr[index * 8 + 2] = 1;
9097e580c6eSjklos lutaddr[index * 8 + 3] = lcg_cmap.r[index] >> (lcg_depth & 7);
9107e580c6eSjklos lutaddr[index * 8 + 4] = 1;
9117e580c6eSjklos lutaddr[index * 8 + 5] = lcg_cmap.g[index] >> (lcg_depth & 7);
9127e580c6eSjklos lutaddr[index * 8 + 6] = 1;
9137e580c6eSjklos lutaddr[index * 8 + 7] = lcg_cmap.b[index] >> (lcg_depth & 7);
9147e580c6eSjklos ++index;
9157e580c6eSjklos }
9167e580c6eSjklos splx(s);
9177e580c6eSjklos return (0);
9187e580c6eSjklos }
9197e580c6eSjklos
9207e580c6eSjklos cons_decl(lcg);
9217e580c6eSjklos
9227e580c6eSjklos void
lcgcninit(struct consdev * cndev)9237e580c6eSjklos lcgcninit(struct consdev *cndev)
9247e580c6eSjklos {
9257e580c6eSjklos int i;
9267e580c6eSjklos /* Clear screen */
9277e580c6eSjklos memset(lcgaddr, LCG_BG_COLOR, lcg_xsize * lcg_ysize);
9287e580c6eSjklos
9297e580c6eSjklos curscr = &lcg_conscreen;
9307e580c6eSjklos for (i = 0; i < lcg_cols * lcg_rows; ++i)
9317e580c6eSjklos lcg_conscreen.ss_image[i].attr =
9327e580c6eSjklos (LCG_BG_COLOR << 4) | LCG_FG_COLOR;
9337e580c6eSjklos wsdisplay_cnattach(&lcg_stdscreen, &lcg_conscreen, 0, 0,
9347e580c6eSjklos (LCG_BG_COLOR << 4) | LCG_FG_COLOR);
9357e580c6eSjklos cn_tab->cn_pri = CN_INTERNAL;
9367e580c6eSjklos
9377e580c6eSjklos
9387e580c6eSjklos #if NDZKBD > 0
9397e580c6eSjklos dzkbd_cnattach(0); /* Connect keyboard and screen together */
9407e580c6eSjklos #endif
9417e580c6eSjklos }
9427e580c6eSjklos
9437e580c6eSjklos /*
9447e580c6eSjklos * Called very early to setup the glass tty as console.
9457e580c6eSjklos * Because it's called before the VM system is inited, virtual memory
9467e580c6eSjklos * for the framebuffer can be stolen directly without disturbing anything.
9477e580c6eSjklos */
9487e580c6eSjklos void
lcgcnprobe(struct consdev * cndev)9497e580c6eSjklos lcgcnprobe(struct consdev *cndev)
9507e580c6eSjklos {
9517e580c6eSjklos extern const struct cdevsw wsdisplay_cdevsw;
9527e580c6eSjklos
9537e580c6eSjklos if ((vax_boardtype != VAX_BTYP_46) && (vax_boardtype != VAX_BTYP_48))
9547e580c6eSjklos return; /* Only for VS 4000/60 and VLC */
9557e580c6eSjklos
9567e580c6eSjklos if (vax_confdata & 0x100)
9577e580c6eSjklos return; /* Diagnostic console */
9587e580c6eSjklos
9597e580c6eSjklos lcg_init_common(NULL, NULL);
9607e580c6eSjklos
9617e580c6eSjklos /* Set up default LUT */
9627e580c6eSjklos
9637e580c6eSjklos cndev->cn_pri = CN_INTERNAL;
9647e580c6eSjklos cndev->cn_dev = makedev(cdevsw_lookup_major(&wsdisplay_cdevsw), 0);
9657e580c6eSjklos }
9667e580c6eSjklos
9677e580c6eSjklos void
lcg_init_common(struct device * self,struct vsbus_attach_args * va)9687e580c6eSjklos lcg_init_common(struct device *self, struct vsbus_attach_args *va)
9697e580c6eSjklos {
9707e580c6eSjklos u_int magic, *lcg_config;
9717e580c6eSjklos int i;
9727e580c6eSjklos extern vaddr_t virtual_avail;
9737e580c6eSjklos long video_conf;
9747e580c6eSjklos int cookie;
9757e580c6eSjklos struct wsdisplay_font *wf;
9767e580c6eSjklos
9777e580c6eSjklos struct lcg_softc *sc = (void *)self;
9787e580c6eSjklos bus_dma_segment_t seg;
9797e580c6eSjklos int rseg, err;
9807e580c6eSjklos void *fifo_mem_vaddr;
9817e580c6eSjklos #ifndef LCG_NO_ACCEL
9827e580c6eSjklos u_char line;
9837e580c6eSjklos u_int ch, temp;
9847e580c6eSjklos #endif
9857e580c6eSjklos
9867e580c6eSjklos if (regaddr != NULL)
9877e580c6eSjklos return;
9887e580c6eSjklos
9897e580c6eSjklos /* map LCG registers first */
9907e580c6eSjklos if (self != NULL) {
9917e580c6eSjklos regaddr = (long*)vax_map_physmem(LCG_REG_ADDR, (LCG_REG_SIZE/VAX_NBPG));
9927e580c6eSjklos if (regaddr == 0) {
9933aa5a3aeSriastradh device_printf(self,
9943aa5a3aeSriastradh "Couldn't allocate register memory.\n");
9957e580c6eSjklos return;
9967e580c6eSjklos }
9977e580c6eSjklos } else {
9987e580c6eSjklos regaddr = (long*)virtual_avail;
9997e580c6eSjklos virtual_avail += LCG_REG_SIZE;
10007e580c6eSjklos ioaccess((vaddr_t)regaddr, LCG_REG_ADDR, (LCG_REG_SIZE/VAX_NBPG));
10017e580c6eSjklos }
10027e580c6eSjklos
10037e580c6eSjklos /*
10047e580c6eSjklos * v = *0x200f0010 & VLC ? 0x07 : 0xf0;
10057e580c6eSjklos * switch(v) {
10067e580c6eSjklos * 0x05: 1280x1024
10077e580c6eSjklos * 0x06: conf & 0x80 ? 1024x768 : 640x480
10087e580c6eSjklos * 0x07: conf & 0x80 ? 1024x768 ? 1024x864
10097e580c6eSjklos * 0x20: 1024x864
10107e580c6eSjklos * 0x40: 1024x768
10117e580c6eSjklos * 0x60: 1024x864
10127e580c6eSjklos * 0x80: 1280x1024 4BPN
10137e580c6eSjklos * 0x90: 1280x1024 8BPN
10147e580c6eSjklos * 0xb0: 1280x1024 8BPN 2HD
10157e580c6eSjklos */
10167e580c6eSjklos if (self != NULL) {
10177e580c6eSjklos lcg_config = (u_int *)vax_map_physmem(LCG_CONFIG, 1);
10187e580c6eSjklos } else {
10197e580c6eSjklos lcg_config = (u_int *)virtual_avail;
10207e580c6eSjklos ioaccess((vaddr_t)lcg_config, LCG_CONFIG, 1);
10217e580c6eSjklos }
10227e580c6eSjklos magic = *lcg_config & (vax_boardtype == VAX_BTYP_46 ? 0xf0 : 0x07);
10237e580c6eSjklos if (self != NULL) {
10247e580c6eSjklos vax_unmap_physmem((vaddr_t)lcg_config, 1);
10257e580c6eSjklos } else {
10267e580c6eSjklos iounaccess((vaddr_t)lcg_config, 1);
10277e580c6eSjklos }
10287e580c6eSjklos lcg_depth = 8;
10297e580c6eSjklos switch(magic) {
10307e580c6eSjklos case 0x80: /* KA46 HR 1280x1024 4BPLN */
10317e580c6eSjklos lcg_depth = 4;
10327e580c6eSjklos case 0x05: /* KA48 HR 1280x1024 8BPLN */
10337e580c6eSjklos case 0x90: /* KA46 HR 1280x1024 8BPLN */
10347e580c6eSjklos case 0xb0: /* KA46 HR 1280x1024 8BPLN 2HD */
10357e580c6eSjklos lcg_xsize = 1280;
10367e580c6eSjklos lcg_ysize = 1024;
10377e580c6eSjklos break;
10387e580c6eSjklos case 0x06: /* KA48 1024x768 or 640x480 */
10397e580c6eSjklos if (vax_confdata & 0x80) {
10407e580c6eSjklos lcg_xsize = 1024;
10417e580c6eSjklos lcg_ysize = 768;
10427e580c6eSjklos } else {
10437e580c6eSjklos lcg_xsize = 640;
10447e580c6eSjklos lcg_ysize = 480;
10457e580c6eSjklos }
10467e580c6eSjklos break;
10477e580c6eSjklos case 0x07: /* KA48 1024x768 or 1024x864 */
10487e580c6eSjklos lcg_xsize = 1024;
10497e580c6eSjklos lcg_ysize = (vax_confdata & 0x80) ? 768 : 864;
10507e580c6eSjklos break;
10517e580c6eSjklos case 0x20: /* KA46 1024x864 */
10527e580c6eSjklos case 0x60: /* KA46 1024x864 */
10537e580c6eSjklos lcg_xsize = 1024;
10547e580c6eSjklos lcg_ysize = 864;
10557e580c6eSjklos break;
10567e580c6eSjklos case 0x40: /* KA46 1024x768 */
10577e580c6eSjklos lcg_xsize = 1024;
10587e580c6eSjklos lcg_ysize = 768;
10597e580c6eSjklos break;
10607e580c6eSjklos default:
10617e580c6eSjklos panic("LCG model not supported");
10627e580c6eSjklos }
10637e580c6eSjklos if (self != NULL)
10643aa5a3aeSriastradh aprint_normal_dev(self,
10653aa5a3aeSriastradh "framebuffer size %dx%d, depth %d (magic 0x%x)\n",
10663aa5a3aeSriastradh lcg_xsize, lcg_ysize, lcg_depth, magic);
10677e580c6eSjklos
10687e580c6eSjklos wsfont_init();
10697e580c6eSjklos cookie = wsfont_find(NULL, 12, 22, 0, WSDISPLAY_FONTORDER_R2L,
10707e580c6eSjklos WSDISPLAY_FONTORDER_L2R, WSFONT_FIND_BITMAP);
10717e580c6eSjklos if (cookie == -1)
10727e580c6eSjklos cookie = wsfont_find(NULL, 8, 0, 0, WSDISPLAY_FONTORDER_R2L, 0,
10737e580c6eSjklos WSFONT_FIND_BITMAP);
10747e580c6eSjklos if (cookie == -1)
10757e580c6eSjklos cookie = wsfont_find(NULL, 0, 0, 0, WSDISPLAY_FONTORDER_R2L,
10767e580c6eSjklos WSDISPLAY_FONTORDER_L2R, WSFONT_FIND_BITMAP);
10777e580c6eSjklos if (cookie == -1 || wsfont_lock(cookie, &wf))
10787e580c6eSjklos panic("lcg_common_init: can't load console font");
10797e580c6eSjklos lcg_font = *wf;
10807e580c6eSjklos lcg_cols = lcg_xsize / lcg_font.fontwidth;
10817e580c6eSjklos lcg_rows = lcg_ysize / lcg_font.fontheight;
10827e580c6eSjklos if (self != NULL) {
10833aa5a3aeSriastradh aprint_normal_dev(self, "using font %s (%dx%d), ",
10843aa5a3aeSriastradh lcg_font.name,
10857e580c6eSjklos lcg_font.fontwidth, lcg_font.fontheight);
10867e580c6eSjklos aprint_normal("console size: %dx%d\n", lcg_cols, lcg_rows);
10877e580c6eSjklos }
10887e580c6eSjklos lcg_onerow = lcg_xsize * lcg_font.fontheight;
10897e580c6eSjklos lcg_fb_size = lcg_xsize * lcg_ysize;
10907e580c6eSjklos lcg_stdscreen.ncols = lcg_cols;
10917e580c6eSjklos lcg_stdscreen.nrows = lcg_rows;
10927e580c6eSjklos lcg_stdscreen.fontwidth = lcg_font.fontwidth;
10937e580c6eSjklos lcg_stdscreen.fontheight = lcg_font.fontheight;
10947e580c6eSjklos lcg_glyph_size = lcg_font.stride * lcg_font.fontheight;
10957e580c6eSjklos snprintf(lcg_stdscreen_name, sizeof(lcg_stdscreen_name), "%dx%d", lcg_cols, lcg_rows);
10967e580c6eSjklos qf = lcg_font.data;
10977e580c6eSjklos qf2 = (u_short *)lcg_font.data;
10987e580c6eSjklos
10997e580c6eSjklos if (self != NULL) {
11007e580c6eSjklos lcgaddr = (void *)vax_map_physmem(va->va_paddr,
11017e580c6eSjklos ((lcg_fb_size + LCG_FONT_STORAGE_SIZE)/VAX_NBPG));
11027e580c6eSjklos if (lcgaddr == 0) {
11033aa5a3aeSriastradh device_printf(self,
11043aa5a3aeSriastradh "unable to allocate framebuffer memory.\n");
11057e580c6eSjklos return;
11067e580c6eSjklos }
11077e580c6eSjklos #ifndef LCG_NO_ACCEL
11087e580c6eSjklos fontaddr = lcgaddr + lcg_fb_size;
11097e580c6eSjklos
11107e580c6eSjklos /* copy font bitmaps */
11117e580c6eSjklos for (ch = 0; ch < 256; ch++)
11127e580c6eSjklos for (line = 0; line < lcg_font.fontheight; line++) {
11137e580c6eSjklos temp = QFONT(ch, line);
11147e580c6eSjklos if (lcg_font.stride == 1)
11157e580c6eSjklos fontaddr[(ch * lcg_font.fontheight) + line] = temp;
11167e580c6eSjklos else {
11177e580c6eSjklos /* stride == 2 */
11187e580c6eSjklos fontaddr[(ch * lcg_font.stride * lcg_font.fontheight) + line] = temp & 0xff;
11197e580c6eSjklos fontaddr[(ch * lcg_font.stride * lcg_font.fontheight) + line + 1] = (temp >> 16) & 0xff;
11207e580c6eSjklos }
11217e580c6eSjklos }
11227e580c6eSjklos #endif
11237e580c6eSjklos
11247e580c6eSjklos lutaddr = (void *)vax_map_physmem(LCG_LUT_ADDR, (LCG_LUT_SIZE/VAX_NBPG));
11257e580c6eSjklos if (lutaddr == 0) {
11263aa5a3aeSriastradh device_printf(self,
11273aa5a3aeSriastradh "unable to allocate LUT memory.\n");
11287e580c6eSjklos return;
11297e580c6eSjklos }
11307e580c6eSjklos fifoaddr = (long*)vax_map_physmem(LCG_FIFO_WIN_ADDR, (LCG_FIFO_WIN_SIZE/VAX_NBPG));
11317e580c6eSjklos if (regaddr == 0) {
11323aa5a3aeSriastradh device_printf(self, "unable to map FIFO window\n");
11337e580c6eSjklos return;
11347e580c6eSjklos }
11357e580c6eSjklos
11367e580c6eSjklos /* allocate contiguous physical memory block for FIFO */
11377e580c6eSjklos err = bus_dmamem_alloc(va->va_dmat, LCG_FIFO_SIZE,
11387e580c6eSjklos LCG_FIFO_ALIGN, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT);
11397e580c6eSjklos if (err) {
11403aa5a3aeSriastradh device_printf(self,
11413aa5a3aeSriastradh "unable to allocate FIFO memory block, err = %d\n",
11423aa5a3aeSriastradh err);
11437e580c6eSjklos return;
11447e580c6eSjklos }
11457e580c6eSjklos
11467e580c6eSjklos err = bus_dmamem_map(va->va_dmat, &seg, rseg, LCG_FIFO_SIZE,
11477e580c6eSjklos &fifo_mem_vaddr, BUS_DMA_NOWAIT);
11487e580c6eSjklos if (err) {
11493aa5a3aeSriastradh device_printf(self,
11503aa5a3aeSriastradh "unable to map FIFO memory block, err = %d\n",
11513aa5a3aeSriastradh err);
11527e580c6eSjklos bus_dmamem_free(va->va_dmat, &seg, rseg);
11537e580c6eSjklos return;
11547e580c6eSjklos }
11557e580c6eSjklos
11567e580c6eSjklos err = bus_dmamap_create(va->va_dmat, LCG_FIFO_SIZE, rseg,
11577e580c6eSjklos LCG_FIFO_SIZE, 0, BUS_DMA_NOWAIT, &sc->sc_dm);
11587e580c6eSjklos if (err) {
11593aa5a3aeSriastradh device_printf(self,
11603aa5a3aeSriastradh "unable to create DMA map, err = %d\n",
11613aa5a3aeSriastradh err);
11627e580c6eSjklos bus_dmamem_unmap(va->va_dmat, fifo_mem_vaddr, LCG_FIFO_SIZE);
11637e580c6eSjklos bus_dmamem_free(va->va_dmat, &seg, rseg);
11647e580c6eSjklos return;
11657e580c6eSjklos }
11667e580c6eSjklos
11677e580c6eSjklos err = bus_dmamap_load(va->va_dmat, sc->sc_dm, fifo_mem_vaddr,
11687e580c6eSjklos LCG_FIFO_SIZE, NULL, BUS_DMA_NOWAIT);
11697e580c6eSjklos if (err) {
11703aa5a3aeSriastradh device_printf(self,
11713aa5a3aeSriastradh "unable to load DMA map, err = %d\n",
11723aa5a3aeSriastradh err);
11737e580c6eSjklos bus_dmamap_destroy(va->va_dmat, sc->sc_dm);
11747e580c6eSjklos bus_dmamem_unmap(va->va_dmat, fifo_mem_vaddr, LCG_FIFO_SIZE);
11757e580c6eSjklos bus_dmamem_free(va->va_dmat, &seg, rseg);
11767e580c6eSjklos return;
11777e580c6eSjklos }
11787e580c6eSjklos
11797e580c6eSjklos /* initialize LCG hardware */
11807e580c6eSjklos LCG_REG(LCG_REG_GRAPHICS_CONTROL) = 0xd8000000; /* gfx reset, FIFO and AG enable */
11817e580c6eSjklos // LCG_REG(LCG_REG_WRITE_PROTECT_LOW_HIGH) = (((LCG_FB_ADDR + lcg_fb_size) & 0xffff0000) | (LCG_FB_ADDR >> 16));
11827e580c6eSjklos LCG_REG(LCG_REG_WRITE_PROTECT_LOW_HIGH) = 0xffff0000;
11837e580c6eSjklos LCG_REG(LCG_REG_FIFO_BASE) = sc->sc_dm->dm_segs[0].ds_addr;
11847e580c6eSjklos LCG_REG(LCG_REG_FIFO_BASE2) = sc->sc_dm->dm_segs[0].ds_addr;
11857e580c6eSjklos LCG_REG(LCG_REG_FIFO_MASKS) = 0xffff;
11867e580c6eSjklos LCG_REG(LCG_REG_FIFO_SAVE_HEAD_OFFSET) = sc->sc_dm->dm_segs[0].ds_addr;
11877e580c6eSjklos // LCG_REG(LCG_REG_GRAPHICS_INT_STATUS) = 0;
11887e580c6eSjklos // LCG_REG(LCG_REG_GRAPHICS_CONTROL) = 0x50000000; /* FIFO and AG enable */
11897e580c6eSjklos LCG_REG(LCG_REG_GRAPHICS_INT_STATUS) = 0xffffffff;
11907e580c6eSjklos LCG_REG(LCG_REG_GRAPHICS_INT_SET_ENABLE) = 0;
11917e580c6eSjklos LCG_REG(LCG_REG_GRAPHICS_INT_CLR_ENABLE) = 0xffffffff;
11927e580c6eSjklos LCG_REG(LCG_REG_LCG_GO) = 3; /* FIFO and AG go */
11937e580c6eSjklos // LCG_REG(LCG_REG_BREAKPT_ADDRESS) = 0x2fffffff;
11947e580c6eSjklos
11957e580c6eSjklos } else {
11967e580c6eSjklos lcgaddr = (void *)virtual_avail;
11977e580c6eSjklos virtual_avail += lcg_fb_size + LCG_FONT_STORAGE_SIZE;
11987e580c6eSjklos ioaccess((vaddr_t)lcgaddr, LCG_FB_ADDR, (lcg_fb_size/VAX_NBPG));
11997e580c6eSjklos
12007e580c6eSjklos lutaddr = (void *)virtual_avail;
12017e580c6eSjklos virtual_avail += LCG_LUT_SIZE;
12027e580c6eSjklos ioaccess((vaddr_t)lutaddr, LCG_LUT_ADDR, (LCG_LUT_SIZE/VAX_NBPG));
12037e580c6eSjklos
12047e580c6eSjklos fifoaddr = (long*)virtual_avail;
12057e580c6eSjklos virtual_avail += LCG_FIFO_WIN_SIZE;
12067e580c6eSjklos ioaccess((vaddr_t)fifoaddr, LCG_FIFO_WIN_ADDR, (LCG_FIFO_WIN_SIZE/VAX_NBPG));
12077e580c6eSjklos }
12087e580c6eSjklos
12097e580c6eSjklos bzero(lutaddr, LCG_LUT_SIZE);
12107e580c6eSjklos for (i = 0; i < 8; ++i) {
12117e580c6eSjklos lcg_cmap.r[i] = lcg_default_cmap.r[i];
12127e580c6eSjklos lcg_cmap.g[i] = lcg_default_cmap.g[i];
12137e580c6eSjklos lcg_cmap.b[i] = lcg_default_cmap.b[i];
12147e580c6eSjklos lutaddr[i * 8 + 1] = i;
12157e580c6eSjklos lutaddr[i * 8 + 2] = 1;
12167e580c6eSjklos lutaddr[i * 8 + 3] = lcg_cmap.r[i] >> (lcg_depth & 7);
12177e580c6eSjklos lutaddr[i * 8 + 4] = 1;
12187e580c6eSjklos lutaddr[i * 8 + 5] = lcg_cmap.g[i] >> (lcg_depth & 7);
12197e580c6eSjklos lutaddr[i * 8 + 6] = 1;
12207e580c6eSjklos lutaddr[i * 8 + 7] = lcg_cmap.b[i] >> (lcg_depth & 7);
12217e580c6eSjklos }
12227e580c6eSjklos
12237e580c6eSjklos /*
12247e580c6eSjklos * 0xf100165b 4000/60
12257e580c6eSjklos * 1111 0001 0000 0000 0001 0110 0101 1011
12267e580c6eSjklos * vvvv vvvv vvvv vvvv vvvv vvvv vvvv vvvv
12277e580c6eSjklos * 3322 2222 2222 1111 1111 11
12287e580c6eSjklos * 1098 7654 3210 9876 5432 1098 7654 3210
12297e580c6eSjklos *
12307e580c6eSjklos * 0xf1001d7b 4000/VLC
12317e580c6eSjklos * 1111 0001 0000 0000 0001 1101 0111 1011
12327e580c6eSjklos * vvvv vvvv vvvv vvvv vvvv vvvv vvvv vvvv
12337e580c6eSjklos * 3322 2222 2222 1111 1111 11
12347e580c6eSjklos * 1098 7654 3210 9876 5432 1098 7654 3210
12357e580c6eSjklos *
12367e580c6eSjklos * 31-30 11 Vertical state
12377e580c6eSjklos * 29-38 11 Horizontal state
12387e580c6eSjklos * 27-26 00
12397e580c6eSjklos * 25 0 console LUT select
12407e580c6eSjklos * 24 1 control LUT select
12417e580c6eSjklos * 23 0
12427e580c6eSjklos * 22 0 cursor active
12437e580c6eSjklos * 21-16 000000
12447e580c6eSjklos * 15 0 video subsystem reset
12457e580c6eSjklos * 14 0
12467e580c6eSjklos * 13 0 LUT load size 2KB
12477e580c6eSjklos * 12 1 enable H sync
12487e580c6eSjklos * 11 0 Full LUT load 1
12497e580c6eSjklos * 10 1 video clock select
12507e580c6eSjklos * 9- 8 10 memory refresh rate 01
12517e580c6eSjklos * 7- 6 01 video refresh rate
12527e580c6eSjklos * 5 0 load select 1
12537e580c6eSjklos * 4 1 read cursor output
12547e580c6eSjklos * 3 1 LUT load enable
12557e580c6eSjklos * 2 0 cursor enable
12567e580c6eSjklos * 1 1 video enable
12577e580c6eSjklos * 0 1 refresh clock enable
12587e580c6eSjklos */
1259a299e660Sandvar /* prepare video_config reg for LUT reload */
12607e580c6eSjklos video_conf
12617e580c6eSjklos = (3 << 30) /* vertical state */
12627e580c6eSjklos | (3 << 28) /* horizontal state */
12637e580c6eSjklos | (0 << 26) /* unused */
12647e580c6eSjklos | (0 << 25) /* console LUT select */
12657e580c6eSjklos | (0 << 24) /* control LUT select */
12667e580c6eSjklos | (0 << 23) /* unused */
12677e580c6eSjklos | (0 << 22) /* cursor active */
12687e580c6eSjklos | (0 << 16) /* current cursor scanline showing */
12697e580c6eSjklos | (0 << 15) /* video subsystem reset */
12707e580c6eSjklos | (0 << 14) /* unused */
12717e580c6eSjklos | (1 << 13) /* LUT load size 2 KB */
12727e580c6eSjklos | (1 << 12) /* enable horizontal sync */
12737e580c6eSjklos | (1 << 10) /* video clock select */
12747e580c6eSjklos | (1 << 6) /* video refresh select */
1275a299e660Sandvar | (1 << 4) /* read cursor output */
12767e580c6eSjklos | (1 << 3) /* LUT load enable */
12777e580c6eSjklos | (0 << 2) /* cursor enable */
12787e580c6eSjklos | (1 << 1) /* video enable */
12797e580c6eSjklos | (1 << 0); /* refresh clock enable */
12807e580c6eSjklos /* FIXME needs updating for all supported models */
12817e580c6eSjklos if (lcg_xsize == 1280) { /* 4000/60 HR 4PLN */
12827e580c6eSjklos video_conf |= (0 << 11); /* split LUT load */
12837e580c6eSjklos video_conf |= (2 << 8); /* memory refresh select */
12847e580c6eSjklos video_conf |= (0 << 5); /* split shift register load */
12857e580c6eSjklos } else { /* 4000/VLC LR 8PLN */
12867e580c6eSjklos video_conf |= (1 << 11); /* Full LUT load */
12877e580c6eSjklos video_conf |= (1 << 8); /* memory refresh select */
12887e580c6eSjklos video_conf |= (1 << 5); /* split shift register load */
12897e580c6eSjklos }
12907e580c6eSjklos
12917e580c6eSjklos LCG_REG(LCG_REG_VIDEO_CONFIG) = video_conf;
12927e580c6eSjklos /* vital !!! */
12937e580c6eSjklos LCG_REG(LCG_REG_LUT_CONSOLE_SEL) = 1;
12947e580c6eSjklos LCG_REG(LCG_REG_LUT_COLOR_BASE_W) = LCG_LUT_OFFSET;
12957e580c6eSjklos
12967e580c6eSjklos delay(1000);
12977e580c6eSjklos LCG_REG(LCG_REG_LUT_CONSOLE_SEL) = 0;
12987e580c6eSjklos
12997e580c6eSjklos #ifdef LCG_DEBUG
13007e580c6eSjklos if (self != NULL)
13013aa5a3aeSriastradh device_printf(self, "video config register set 0x%08lx\n",
13023aa5a3aeSriastradh video_conf);
13037e580c6eSjklos #endif
13047e580c6eSjklos }
1305