#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: smg.c,v 1.67 2024/02/03 16:35:10 tsutsui Exp $");
#include "dzkbd.h"
#include "wsdisplay.h"
#include <sys/param.h>
#include <sys/device.h>
#include <sys/systm.h>
#include <sys/kmem.h>
#include <sys/conf.h>
#include <machine/vsbus.h>
#include <machine/sid.h>
#include <machine/cpu.h>
#include <machine/ka420.h>
#include <machine/scb.h>
#include <dev/cons.h>
#include <dev/ic/dc503reg.h>
#include <dev/dec/dzreg.h>
#include <dev/dec/dzvar.h>
#include <dev/dec/dzkbdvar.h>
#include <dev/wscons/wsconsio.h>
#include <dev/wscons/wsdisplayvar.h>
#include <dev/rasops/rasops.h>
#define SM_XWIDTH 1024
#define SM_YWIDTH 864
#define CUR_XBIAS 216
#define CUR_YBIAS 33
struct smg_screen {
struct rasops_info ss_ri;
uint8_t *ss_addr;
struct dc503reg *ss_cursor;
uint16_t ss_curcmd;
struct wsdisplay_curpos ss_curpos, ss_curhot;
uint16_t ss_curimg[PCC_CURSOR_SIZE];
uint16_t ss_curmask[PCC_CURSOR_SIZE];
};
struct smg_softc {
device_t sc_dev;
struct smg_screen *sc_scr;
int sc_nscreens;
};
static int smg_match(device_t, cfdata_t, void *);
static void smg_attach(device_t, device_t, void *);
static int smg_setup_screen(struct smg_screen *);
static int smg_ioctl(void *, void *, u_long, void *, int, struct lwp *);
static paddr_t smg_mmap(void *, void *, off_t, int);
static int smg_alloc_screen(void *, const struct wsscreen_descr *,
void **, int *, int *, long *);
static void smg_free_screen(void *, void *);
static int smg_show_screen(void *, void *, int, void (*) (void *, int, int),
void *);
static int smg_getcursor(struct smg_screen *, struct wsdisplay_cursor *);
static int smg_setcursor(struct smg_screen *, struct wsdisplay_cursor *);
static void smg_updatecursor(struct smg_screen *, u_int);
static void smg_putchar(void *, int, int, u_int, long);
static void smg_cursor(void *, int, int, int);
static void smg_blockmove(struct rasops_info *, u_int, u_int, u_int, u_int,
u_int, int);
static void smg_copycols(void *, int, int, int, int);
static void smg_erasecols(void *, int, int, int, long);
static struct smg_screen smg_consscr;
CFATTACH_DECL_NEW(smg, sizeof(struct smg_softc),
smg_match, smg_attach, NULL, NULL);
static struct wsscreen_descr smg_stdscreen = {
.name = "std",
};
static const struct wsscreen_descr *_smg_scrlist[] = {
&smg_stdscreen,
};
static const struct wsscreen_list smg_screenlist = {
.nscreens = sizeof(_smg_scrlist) / sizeof(struct wsscreen_descr *),
.screens = _smg_scrlist,
};
static const struct wsdisplay_accessops smg_accessops = {
.ioctl = smg_ioctl,
.mmap = smg_mmap,
.alloc_screen = smg_alloc_screen,
.free_screen = smg_free_screen,
.show_screen = smg_show_screen,
.load_font = NULL
};
static int
smg_match(device_t parent, cfdata_t cf, void *aux)
{
struct vsbus_attach_args *va = aux;
volatile short *curcmd;
volatile short *cfgtst;
short tmp, tmp2;
switch (vax_boardtype) {
default:
return 0;
case VAX_BTYP_410:
case VAX_BTYP_420:
case VAX_BTYP_43:
if (va->va_paddr != KA420_CUR_BASE)
return 0;
if ((vax_confdata & KA420_CFG_MULTU) != 0)
return 0;
if ((vax_confdata & KA420_CFG_VIDOPT) != 0 &&
(cf->cf_flags & 1) == 0)
return 0;
break;
}
if ((vax_confdata & (KA420_CFG_L3CON | KA420_CFG_VIDOPT)) == 0
#if NWSDISPLAY > 0
&& cn_tab->cn_putc == wsdisplay_cnputc
#endif
) {
struct vsbus_softc *sc = device_private(parent);
sc->sc_mask = 0x08;
scb_fake(0x44, 0x15);
return 20;
} else {
curcmd = (short *)va->va_addr;
cfgtst = (short *)vax_map_physmem(VS_CFGTST, 1);
curcmd[0] = PCCCMD_HSHI | PCCCMD_FOPB;
DELAY(300000);
tmp = cfgtst[0];
curcmd[0] = PCCCMD_TEST | PCCCMD_HSHI;
DELAY(300000);
tmp2 = cfgtst[0];
vax_unmap_physmem((vaddr_t)cfgtst, 1);
if (tmp2 != tmp)
return 20;
else
return 0;
}
}
static void
smg_attach(device_t parent, device_t self, void *aux)
{
struct smg_softc *sc = device_private(self);
struct smg_screen *scr;
struct wsemuldisplaydev_attach_args aa;
int console;
console =
#if NWSDISPLAY > 0
(vax_confdata & (KA420_CFG_L3CON | KA420_CFG_VIDOPT)) == 0 &&
cn_tab->cn_putc == wsdisplay_cnputc;
#else
(vax_confdata & (KA420_CFG_L3CON | KA420_CFG_VIDOPT)) == 0;
#endif
if (console) {
scr = &smg_consscr;
sc->sc_nscreens = 1;
} else {
scr = kmem_zalloc(sizeof(*scr), KM_SLEEP);
scr->ss_addr =
(void *)vax_map_physmem(SMADDR, SMSIZE / VAX_NBPG);
if (scr->ss_addr == NULL) {
aprint_error(": can not map frame buffer\n");
kmem_free(scr, sizeof(*scr));
return;
}
scr->ss_cursor =
(struct dc503reg *)vax_map_physmem(KA420_CUR_BASE, 1);
if (scr->ss_cursor == NULL) {
aprint_error(": can not map cursor chip\n");
vax_unmap_physmem((vaddr_t)scr->ss_addr,
SMSIZE / VAX_NBPG);
kmem_free(scr, sizeof(*scr));
return;
}
if (smg_setup_screen(scr) != 0) {
aprint_error(": initialization failed\n");
vax_unmap_physmem((vaddr_t)scr->ss_cursor, 1);
vax_unmap_physmem((vaddr_t)scr->ss_addr,
SMSIZE / VAX_NBPG);
kmem_free(scr, sizeof(*scr));
return;
}
}
sc->sc_scr = scr;
aprint_normal("\n");
aprint_normal_dev(self, "%dx%d on-board monochrome framebuffer\n",
SM_XWIDTH, SM_YWIDTH);
aa.console = console;
aa.scrdata = &smg_screenlist;
aa.accessops = &smg_accessops;
aa.accesscookie = sc;
config_found(self, &aa, wsemuldisplaydevprint, CFARGS_NONE);
}
static int
smg_setup_screen(struct smg_screen *ss)
{
struct rasops_info *ri = &ss->ss_ri;
int cookie;
memset(ri, 0, sizeof(*ri));
ri->ri_depth = 1;
ri->ri_width = SM_XWIDTH;
ri->ri_height = SM_YWIDTH;
ri->ri_stride = SM_XWIDTH >> 3;
ri->ri_flg = RI_CLEAR | RI_CENTER;
ri->ri_bits = (void *)ss->ss_addr;
ri->ri_hw = ss;
if (ss == &smg_consscr)
ri->ri_flg |= RI_NO_AUTO;
wsfont_init();
cookie = wsfont_find(NULL, 12, 0, 0, WSDISPLAY_FONTORDER_R2L,
WSDISPLAY_FONTORDER_R2L, WSFONT_FIND_BITMAP);
if (cookie < 0)
cookie = wsfont_find(NULL, 8, 0, 0, WSDISPLAY_FONTORDER_R2L,
WSDISPLAY_FONTORDER_R2L, WSFONT_FIND_BITMAP);
if (cookie < 0)
cookie = wsfont_find(NULL, 0, 0, 0, WSDISPLAY_FONTORDER_R2L,
WSDISPLAY_FONTORDER_R2L, WSFONT_FIND_BITMAP);
if (cookie < 0)
return -1;
if (wsfont_lock(cookie, &ri->ri_font) != 0)
return -1;
ri->ri_wsfcookie = cookie;
if (rasops_init(ri, 160, 160) != 0)
return -1;
ri->ri_ops.cursor = smg_cursor;
ri->ri_ops.putchar = smg_putchar;
ri->ri_ops.copycols = smg_copycols;
ri->ri_ops.erasecols = smg_erasecols;
smg_stdscreen.ncols = ri->ri_cols;
smg_stdscreen.nrows = ri->ri_rows;
smg_stdscreen.textops = &ri->ri_ops;
smg_stdscreen.fontwidth = ri->ri_font->fontwidth;
smg_stdscreen.fontheight = ri->ri_font->fontheight;
smg_stdscreen.capabilities = ri->ri_caps;
ss->ss_curcmd = PCCCMD_HSHI;
ss->ss_cursor->cmdr = ss->ss_curcmd;
return 0;
}
static int
smg_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l)
{
struct smg_softc *sc = v;
struct smg_screen *ss = sc->sc_scr;
struct wsdisplay_fbinfo *wdf;
struct wsdisplay_curpos *pos;
switch (cmd) {
case WSDISPLAYIO_GTYPE:
*(u_int *)data = WSDISPLAY_TYPE_VAX_MONO;
break;
case WSDISPLAYIO_GINFO:
wdf = (struct wsdisplay_fbinfo *)data;
wdf->height = ss->ss_ri.ri_height;
wdf->width = ss->ss_ri.ri_width;
wdf->depth = ss->ss_ri.ri_depth;
wdf->cmsize = 0;
break;
case WSDISPLAYIO_LINEBYTES:
*(u_int *)data = ss->ss_ri.ri_stride;
break;
case WSDISPLAYIO_GETCMAP:
case WSDISPLAYIO_PUTCMAP:
case WSDISPLAYIO_GVIDEO:
case WSDISPLAYIO_SVIDEO:
break;
case WSDISPLAYIO_GCURPOS:
pos = (struct wsdisplay_curpos *)data;
pos->x = ss->ss_curpos.x;
pos->y = ss->ss_curpos.y;
break;
case WSDISPLAYIO_SCURPOS:
pos = (struct wsdisplay_curpos *)data;
ss->ss_curpos.x = pos->x;
ss->ss_curpos.y = pos->y;
smg_updatecursor(ss, WSDISPLAY_CURSOR_DOPOS);
break;
case WSDISPLAYIO_GCURMAX:
pos = (struct wsdisplay_curpos *)data;
pos->x = pos->y = PCC_CURSOR_SIZE;
case WSDISPLAYIO_GCURSOR:
return smg_getcursor(ss, (struct wsdisplay_cursor *)data);
case WSDISPLAYIO_SCURSOR:
return smg_setcursor(ss, (struct wsdisplay_cursor *)data);
default:
return EPASSTHROUGH;
}
return 0;
}
static paddr_t
smg_mmap(void *v, void *vs, off_t offset, int prot)
{
if (offset >= SMSIZE || offset < 0)
return -1;
return (SMADDR + offset) >> PGSHIFT;
}
static int
smg_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
int *curxp, int *curyp, long *defattrp)
{
struct smg_softc *sc = v;
struct smg_screen *ss = sc->sc_scr;
struct rasops_info *ri = &ss->ss_ri;
if (sc->sc_nscreens > 0)
return ENOMEM;
*cookiep = ri;
*curxp = *curyp = 0;
(*ri->ri_ops.allocattr)(ri, 0, 0, 0, defattrp);
sc->sc_nscreens++;
return 0;
}
static void
smg_free_screen(void *v, void *cookie)
{
struct smg_softc *sc = v;
sc->sc_nscreens--;
}
static int
smg_show_screen(void *v, void *cookie, int waitok,
void (*cb)(void *, int, int), void *cbarg)
{
return 0;
}
static int
smg_getcursor(struct smg_screen *ss, struct wsdisplay_cursor *wdc)
{
int error;
if ((wdc->which & WSDISPLAY_CURSOR_DOCUR) != 0)
wdc->enable = ss->ss_curcmd & PCCCMD_ENPA ? 1 : 0;
if ((wdc->which & WSDISPLAY_CURSOR_DOPOS) != 0) {
wdc->pos.x = ss->ss_curpos.x;
wdc->pos.y = ss->ss_curpos.y;
}
if ((wdc->which & WSDISPLAY_CURSOR_DOHOT) != 0) {
wdc->hot.x = ss->ss_curhot.x;
wdc->hot.y = ss->ss_curhot.y;
}
if ((wdc->which & WSDISPLAY_CURSOR_DOCMAP) != 0) {
wdc->cmap.index = 0;
wdc->cmap.count = 0;
}
if ((wdc->which & WSDISPLAY_CURSOR_DOSHAPE) != 0) {
wdc->size.x = wdc->size.y = PCC_CURSOR_SIZE;
error = copyout(ss->ss_curimg, wdc->image,
sizeof(ss->ss_curimg));
if (error != 0)
return error;
error = copyout(ss->ss_curmask, wdc->mask,
sizeof(ss->ss_curmask));
if (error != 0)
return error;
}
return 0;
}
static int
smg_setcursor(struct smg_screen *ss, struct wsdisplay_cursor *wdc)
{
uint16_t curfg[PCC_CURSOR_SIZE], curmask[PCC_CURSOR_SIZE];
int error;
if ((wdc->which & WSDISPLAY_CURSOR_DOCMAP) != 0) {
if (wdc->cmap.count != 0)
return EINVAL;
}
if ((wdc->which & WSDISPLAY_CURSOR_DOSHAPE) != 0) {
if (wdc->size.x != PCC_CURSOR_SIZE ||
wdc->size.y != PCC_CURSOR_SIZE)
return EINVAL;
error = copyin(wdc->image, curfg, sizeof(curfg));
if (error != 0)
return error;
error = copyin(wdc->mask, curmask, sizeof(curmask));
if (error != 0)
return error;
}
if ((wdc->which & WSDISPLAY_CURSOR_DOCUR) != 0) {
if (wdc->enable)
ss->ss_curcmd |= PCCCMD_ENPB | PCCCMD_ENPA;
else
ss->ss_curcmd &= ~(PCCCMD_ENPB | PCCCMD_ENPA);
}
if ((wdc->which & WSDISPLAY_CURSOR_DOPOS) != 0) {
ss->ss_curpos.x = wdc->pos.x;
ss->ss_curpos.y = wdc->pos.y;
}
if ((wdc->which & WSDISPLAY_CURSOR_DOHOT) != 0) {
ss->ss_curhot.x = wdc->hot.x;
ss->ss_curhot.y = wdc->hot.y;
}
if ((wdc->which & WSDISPLAY_CURSOR_DOSHAPE) != 0) {
memcpy(ss->ss_curimg, curfg, sizeof(ss->ss_curimg));
memcpy(ss->ss_curmask, curmask, sizeof(ss->ss_curmask));
}
smg_updatecursor(ss, wdc->which);
return 0;
}
static void
smg_updatecursor(struct smg_screen *ss, u_int which)
{
u_int i;
if ((which & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT)) != 0) {
ss->ss_cursor->xpos =
ss->ss_curpos.x - ss->ss_curhot.x + CUR_XBIAS;
ss->ss_cursor->ypos =
ss->ss_curpos.y - ss->ss_curhot.y + CUR_YBIAS;
}
if ((which & WSDISPLAY_CURSOR_DOSHAPE) != 0) {
ss->ss_cursor->cmdr = ss->ss_curcmd | PCCCMD_LODSA;
for (i = 0; i < PCC_CURSOR_SIZE; i++)
ss->ss_cursor->load = ss->ss_curimg[i];
for (i = 0; i < PCC_CURSOR_SIZE; i++)
ss->ss_cursor->load = ss->ss_curmask[i];
ss->ss_cursor->cmdr = ss->ss_curcmd;
} else
if ((which & WSDISPLAY_CURSOR_DOCUR) != 0)
ss->ss_cursor->cmdr = ss->ss_curcmd;
}
#include <vax/vsa/maskbits.h>
#define ALL1BITS (~0U)
#define ALL0BITS (0U)
#define BLITWIDTH (32)
#define ALIGNMASK (0x1f)
#define BYTESDONE (4)
static void
smg_putchar(void *cookie, int row, int startcol, u_int uc, long attr)
{
struct rasops_info *ri = cookie;
uint8_t *p;
int scanspan, startx, height, width, align, y;
uint32_t lmask, rmask, glyph, inverse;
int i;
uint8_t *fb;
scanspan = ri->ri_stride;
y = ri->ri_font->fontheight * row;
startx = ri->ri_font->fontwidth * startcol;
height = ri->ri_font->fontheight;
fb = (uint8_t *)ri->ri_font->data +
(uc - ri->ri_font->firstchar) * ri->ri_fontscale;
inverse = ((attr & WSATTR_REVERSE) != 0) ? ALL1BITS : ALL0BITS;
p = (uint8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4);
align = startx & ALIGNMASK;
width = ri->ri_font->fontwidth + align;
lmask = ALL1BITS << align;
rmask = ALL1BITS >> (-width & ALIGNMASK);
if (width <= BLITWIDTH) {
uint32_t mask = lmask & rmask;
while (height > 0) {
uint32_t image;
glyph = 0;
for (i = ri->ri_font->stride; i != 0; i--)
glyph = (glyph << 8) | *fb++;
glyph = (glyph << align) ^ inverse;
image = *(uint32_t *)p;
*(uint32_t *)p = (image & ~mask) | (glyph & mask);
p += scanspan;
height--;
}
} else {
uint8_t *q = p;
uint32_t lhalf, rhalf;
while (height > 0) {
uint32_t image;
glyph = 0;
for (i = ri->ri_font->stride; i != 0; i--)
glyph = (glyph << 8) | *fb++;
lhalf = (glyph << align) ^ inverse;
image = *(uint32_t *)p;
*(uint32_t *)p = (image & ~lmask) | (lhalf & lmask);
p += BYTESDONE;
rhalf = (glyph >> (BLITWIDTH - align)) ^ inverse;
image = *(uint32_t *)p;
*(uint32_t *)p = (rhalf & rmask) | (image & ~rmask);
p = (q += scanspan);
height--;
}
}
}
static void
smg_cursor(void *cookie, int on, int row, int col)
{
struct rasops_info *ri = cookie;
uint8_t *p;
int scanspan, startx, height, width, align, y;
uint32_t lmask, rmask, image;
if (!on) {
if ((ri->ri_flg & RI_CURSOR) == 0)
return;
row = ri->ri_crow;
col = ri->ri_ccol;
} else {
ri->ri_crow = row;
ri->ri_ccol = col;
}
scanspan = ri->ri_stride;
y = ri->ri_font->fontheight * row;
startx = ri->ri_font->fontwidth * col;
height = ri->ri_font->fontheight;
p = (uint8_t *)ri->ri_bits + y * scanspan + ((startx / 32) * 4);
align = startx & ALIGNMASK;
width = ri->ri_font->fontwidth + align;
lmask = ALL1BITS << align;
rmask = ALL1BITS >> (-width & ALIGNMASK);
if (width <= BLITWIDTH) {
uint32_t mask = lmask & rmask;
while (height > 0) {
image = *(uint32_t *)p;
*(uint32_t *)p =
(image & ~mask) | ((image ^ ALL1BITS) & mask);
p += scanspan;
height--;
}
} else {
uint8_t *q = p;
while (height > 0) {
image = *(uint32_t *)p;
*(uint32_t *)p =
(image & ~lmask) | ((image ^ ALL1BITS) & lmask);
p += BYTESDONE;
image = *(uint32_t *)p;
*(uint32_t *)p =
((image ^ ALL1BITS) & rmask) | (image & ~rmask);
p = (q += scanspan);
height--;
}
}
ri->ri_flg ^= RI_CURSOR;
}
static void
smg_blockmove(struct rasops_info *ri, u_int sx, u_int y, u_int dx, u_int cx,
u_int cy, int rop)
{
int width;
unsigned int *psrcLine, *pdstLine;
unsigned int *psrc;
unsigned int *pdst;
unsigned int startmask, endmask;
int nlMiddle;
int nl;
int xoffSrc;
int nstart;
int nend;
int srcStartOver;
width = SM_XWIDTH >> 5;
psrcLine = pdstLine = ((u_int *)ri->ri_bits) + (y * width);
if (cx <= 32) {
int srcBit, dstBit;
pdstLine += (dx >> 5);
psrcLine += (sx >> 5);
psrc = psrcLine;
pdst = pdstLine;
srcBit = sx & ALIGNMASK;
dstBit = dx & ALIGNMASK;
while (cy--) {
getandputrop(psrc, srcBit, dstBit, cx, pdst, rop);
pdst += width;
psrc += width;
}
} else {
startmask = ALL1BITS << (dx & ALIGNMASK);
endmask = ALL1BITS >> (~cx & ALIGNMASK);
if (startmask)
nlMiddle = (cx - (32 - (dx & ALIGNMASK))) >> 5;
else
nlMiddle = cx >> 5;
if (startmask)
nstart = 32 - (dx & ALIGNMASK);
else
nstart = 0;
if (endmask)
nend = (dx + cx) & ALIGNMASK;
else
nend = 0;
xoffSrc = ((sx & ALIGNMASK) + nstart) & ALIGNMASK;
srcStartOver = ((sx & ALIGNMASK) + nstart) > 31;
if (sx >= dx) {
pdstLine += (dx >> 5);
psrcLine += (sx >> 5);
while (cy--) {
psrc = psrcLine;
pdst = pdstLine;
if (startmask) {
getandputrop(psrc, (sx & ALIGNMASK),
(dx & ALIGNMASK), nstart, pdst,
rop);
pdst++;
if (srcStartOver)
psrc++;
}
if (xoffSrc == 0) {
nl = nlMiddle;
while (nl--) {
switch (rop) {
case RR_CLEAR:
*pdst = 0;
break;
case RR_SET:
*pdst = ~0;
break;
default:
*pdst = *psrc;
break;
}
psrc++;
pdst++;
}
} else {
nl = nlMiddle + 1;
while (--nl) {
switch (rop) {
case RR_CLEAR:
*pdst = 0;
break;
case RR_SET:
*pdst = ~0;
break;
default:
getunalignedword(psrc,
xoffSrc, *pdst);
break;
}
pdst++;
psrc++;
}
}
if (endmask) {
getandputrop(psrc, xoffSrc, 0, nend,
pdst, rop);
}
pdstLine += width;
psrcLine += width;
}
} else {
pdstLine += ((dx + cx) >> 5);
psrcLine += ((sx + cx) >> 5);
if (xoffSrc + nend >= 32)
--psrcLine;
while (cy--) {
psrc = psrcLine;
pdst = pdstLine;
if (endmask) {
getandputrop(psrc, xoffSrc, 0, nend,
pdst, rop);
}
nl = nlMiddle + 1;
while (--nl) {
--psrc;
--pdst;
switch (rop) {
case RR_CLEAR:
*pdst = 0;
break;
case RR_SET:
*pdst = ~0;
break;
default:
getunalignedword(psrc, xoffSrc,
*pdst);
break;
}
}
if (startmask) {
if (srcStartOver)
--psrc;
--pdst;
getandputrop(psrc, (sx & ALIGNMASK),
(dx & ALIGNMASK), nstart, pdst,
rop);
}
pdstLine += width;
psrcLine += width;
}
}
}
}
static void
smg_copycols(void *cookie, int row, int src, int dst, int n)
{
struct rasops_info *ri = cookie;
n *= ri->ri_font->fontwidth;
src *= ri->ri_font->fontwidth;
dst *= ri->ri_font->fontwidth;
row *= ri->ri_font->fontheight;
smg_blockmove(ri, src, row, dst, n, ri->ri_font->fontheight,
RR_COPY);
}
static void
smg_erasecols(void *cookie, int row, int col, int num, long attr)
{
struct rasops_info *ri = cookie;
int fg, bg;
rasops_unpack_attr(attr, &fg, &bg, NULL);
num *= ri->ri_font->fontwidth;
col *= ri->ri_font->fontwidth;
row *= ri->ri_font->fontheight;
smg_blockmove(ri, col, row, col, num, ri->ri_font->fontheight,
bg == 0 ? RR_CLEAR : RR_SET);
}
cons_decl(smg);
void
smgcnprobe(struct consdev *cndev)
{
extern const struct cdevsw wsdisplay_cdevsw;
switch (vax_boardtype) {
case VAX_BTYP_410:
case VAX_BTYP_420:
case VAX_BTYP_43:
if ((vax_confdata & (KA420_CFG_L3CON | KA420_CFG_MULTU)) != 0)
break;
if ((vax_confdata & KA420_CFG_VIDOPT) != 0)
break;
cndev->cn_pri = CN_INTERNAL;
cndev->cn_dev =
makedev(cdevsw_lookup_major(&wsdisplay_cdevsw), 0);
break;
default:
break;
}
}
void
smgcninit(struct consdev *cndev)
{
struct smg_screen *ss = &smg_consscr;
vaddr_t ova;
long defattr;
struct rasops_info *ri;
extern vaddr_t virtual_avail;
ova = virtual_avail;
ss->ss_addr = (uint8_t *)virtual_avail;
ioaccess(virtual_avail, SMADDR, SMSIZE / VAX_NBPG);
virtual_avail += SMSIZE;
ss->ss_cursor = (struct dc503reg *)virtual_avail;
ioaccess(virtual_avail, KA420_CUR_BASE, 1);
virtual_avail += VAX_NBPG;
virtual_avail = round_page(virtual_avail);
if (smg_setup_screen(ss) != 0) {
iounaccess((vaddr_t)ss->ss_addr, SMSIZE / VAX_NBPG);
iounaccess((vaddr_t)ss->ss_cursor, 1);
virtual_avail = ova;
return;
}
ri = &ss->ss_ri;
(*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
wsdisplay_cnattach(&smg_stdscreen, ri, 0, 0, defattr);
cn_tab->cn_pri = CN_INTERNAL;
#if NDZKBD > 0
dzkbd_cnattach(0);
#endif
}