1 /* $NetBSD: smg.c,v 1.55 2012/01/11 21:26:13 macallan Exp $ */ 2 /* 3 * Copyright (c) 1998 Ludd, University of Lule}, Sweden. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed at Ludd, University of 17 * Lule}, Sweden and its contributors. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include <sys/cdefs.h> 34 __KERNEL_RCSID(0, "$NetBSD: smg.c,v 1.55 2012/01/11 21:26:13 macallan Exp $"); 35 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/callout.h> 39 #include <sys/conf.h> 40 #include <sys/cpu.h> 41 #include <sys/device.h> 42 #include <sys/kernel.h> 43 #include <sys/malloc.h> 44 #include <sys/time.h> 45 46 #include <machine/vsbus.h> 47 #include <machine/sid.h> 48 #include <machine/ka420.h> 49 50 #include <dev/cons.h> 51 52 #include <dev/dec/dzreg.h> 53 #include <dev/dec/dzvar.h> 54 #include <dev/dec/dzkbdvar.h> 55 56 #include <dev/wscons/wsdisplayvar.h> 57 #include <dev/wscons/wsconsio.h> 58 #include <dev/wscons/wscons_callbacks.h> 59 #include <dev/wsfont/wsfont.h> 60 61 #include "dzkbd.h" 62 #include "opt_wsfont.h" 63 64 /* Screen hardware defs */ 65 #define SM_COLS 128 /* char width of screen */ 66 #define SM_ROWS 57 /* rows of char on screen */ 67 #define SM_CHEIGHT 15 /* lines a char consists of */ 68 #define SM_NEXTROW (SM_COLS * SM_CHEIGHT) 69 #define SM_YWIDTH 864 70 #define SM_XWIDTH 1024 71 72 /* Cursor register definitions */ 73 #define CUR_CMD 0 74 #define CUR_XPOS 4 75 #define CUR_YPOS 8 76 #define CUR_XMIN_1 12 77 #define CUR_XMAX_1 16 78 #define CUR_YMIN_1 20 79 #define CUR_YMAX_1 24 80 #define CUR_XMIN_2 28 81 #define CUR_XMAX_2 32 82 #define CUR_YMIN_2 36 83 #define CUR_YMAX_2 40 84 #define CUR_LOAD 44 85 86 #define CUR_CMD_TEST 0x8000 87 #define CUR_CMD_HSHI 0x4000 88 #define CUR_CMD_VBHI 0x2000 89 #define CUR_CMD_LODSA 0x1000 90 #define CUR_CMD_FORG2 0x0800 91 #define CUR_CMD_ENRG2 0x0400 92 #define CUR_CMD_FORG1 0x0200 93 #define CUR_CMD_ENRG1 0x0100 94 #define CUR_CMD_XHWID 0x0080 95 #define CUR_CMD_XHCL1 0x0040 96 #define CUR_CMD_XHCLP 0x0020 97 #define CUR_CMD_XHAIR 0x0010 98 #define CUR_CMD_FOPB 0x0008 99 #define CUR_CMD_ENPB 0x0004 100 #define CUR_CMD_FOPA 0x0002 101 #define CUR_CMD_ENPA 0x0001 102 103 #define CUR_XBIAS 216 /* Add to cursor position */ 104 #define CUR_YBIAS 33 105 106 #define WRITECUR(addr, val) *(volatile uint16_t *)(curaddr + (addr)) = (val) 107 static char *curaddr; 108 static uint16_t curcmd, curx, cury, hotX, hotY; 109 static int bgmask, fgmask; 110 111 static int smg_match(device_t, cfdata_t, void *); 112 static void smg_attach(device_t, device_t, void *); 113 114 CFATTACH_DECL_NEW(smg, 0, 115 smg_match, smg_attach, NULL, NULL); 116 117 static void smg_cursor(void *, int, int, int); 118 static int smg_mapchar(void *, int, unsigned int *); 119 static void smg_putchar(void *, int, int, u_int, long); 120 static void smg_copycols(void *, int, int, int,int); 121 static void smg_erasecols(void *, int, int, int, long); 122 static void smg_copyrows(void *, int, int, int); 123 static void smg_eraserows(void *, int, int, long); 124 static int smg_allocattr(void *, int, int, int, long *); 125 126 const struct wsdisplay_emulops smg_emulops = { 127 .cursor = smg_cursor, 128 .mapchar = smg_mapchar, 129 .putchar = smg_putchar, 130 .copycols = smg_copycols, 131 .erasecols = smg_erasecols, 132 .copyrows = smg_copyrows, 133 .eraserows = smg_eraserows, 134 .allocattr = smg_allocattr 135 }; 136 137 const struct wsscreen_descr smg_stdscreen = { 138 .name = "128x57", 139 .ncols = SM_COLS, 140 .nrows = SM_ROWS, 141 .textops = &smg_emulops, 142 .fontwidth = 8, 143 .fontheight = SM_CHEIGHT, 144 .capabilities = WSSCREEN_UNDERLINE|WSSCREEN_REVERSE, 145 }; 146 147 const struct wsscreen_descr *_smg_scrlist[] = { 148 &smg_stdscreen, 149 }; 150 151 const struct wsscreen_list smg_screenlist = { 152 .nscreens = __arraycount(_smg_scrlist), 153 .screens = _smg_scrlist, 154 }; 155 156 static char *sm_addr; 157 158 static u_char *qf; 159 160 #define QCHAR(c) (c < 32 ? 32 : (c > 127 ? c - 66 : c - 32)) 161 #define QFONT(c,line) qf[QCHAR(c) * 15 + line] 162 #define SM_ADDR(row, col, line) \ 163 sm_addr[col + (row * SM_CHEIGHT * SM_COLS) + line * SM_COLS] 164 165 166 static int smg_ioctl(void *, void *, u_long, void *, int, struct lwp *); 167 static paddr_t smg_mmap(void *, void *, off_t, int); 168 static int smg_alloc_screen(void *, const struct wsscreen_descr *, 169 void **, int *, int *, long *); 170 static void smg_free_screen(void *, void *); 171 static int smg_show_screen(void *, void *, int, 172 void (*) (void *, int, int), void *); 173 static void smg_crsr_blink(void *); 174 175 const struct wsdisplay_accessops smg_accessops = { 176 .ioctl = smg_ioctl, 177 .mmap = smg_mmap, 178 .alloc_screen = smg_alloc_screen, 179 .free_screen = smg_free_screen, 180 .show_screen = smg_show_screen, 181 }; 182 183 struct smg_screen { 184 int ss_curx; 185 int ss_cury; 186 u_char ss_image[SM_ROWS][SM_COLS]; /* Image of current screen */ 187 u_char ss_attr[SM_ROWS][SM_COLS]; /* Reversed etc... */ 188 }; 189 190 static struct smg_screen smg_conscreen; 191 static struct smg_screen *curscr; 192 193 static callout_t smg_cursor_ch; 194 195 int 196 smg_match(device_t parent, cfdata_t match, void *aux) 197 { 198 struct vsbus_attach_args * const va = aux; 199 volatile uint16_t *ccmd; 200 volatile uint16_t *cfgtst; 201 uint16_t tmp, tmp2; 202 203 if (vax_boardtype == VAX_BTYP_49 || vax_boardtype == VAX_BTYP_53) 204 return 0; 205 206 ccmd = (uint16_t *)va->va_addr; 207 cfgtst = (uint16_t *)vax_map_physmem(VS_CFGTST, 1); 208 /* 209 * Try to find the cursor chip by testing the flip-flop. 210 * If nonexistent, no glass tty. 211 */ 212 ccmd[0] = CUR_CMD_HSHI|CUR_CMD_FOPB; 213 DELAY(300000); 214 tmp = cfgtst[0]; 215 ccmd[0] = CUR_CMD_TEST|CUR_CMD_HSHI; 216 DELAY(300000); 217 tmp2 = cfgtst[0]; 218 vax_unmap_physmem((vaddr_t)cfgtst, 1); 219 220 if (tmp2 != tmp) 221 return 20; /* Using periodic interrupt */ 222 else 223 return 0; 224 } 225 226 void 227 smg_attach(device_t parent, device_t self, void *aux) 228 { 229 struct wsemuldisplaydev_attach_args aa; 230 struct wsdisplay_font *console_font; 231 int fcookie; 232 233 aprint_normal("\n"); 234 sm_addr = (void *)vax_map_physmem(SMADDR, (SMSIZE/VAX_NBPG)); 235 curaddr = (void *)vax_map_physmem(KA420_CUR_BASE, 1); 236 if (sm_addr == 0) { 237 aprint_error_dev(self, "Couldn't alloc graphics memory.\n"); 238 return; 239 } 240 if (curscr == NULL) 241 callout_init(&smg_cursor_ch, 0); 242 curscr = &smg_conscreen; 243 aa.console = (vax_confdata & (KA420_CFG_L3CON|KA420_CFG_MULTU)) == 0; 244 245 aa.scrdata = &smg_screenlist; 246 aa.accessops = &smg_accessops; 247 callout_reset(&smg_cursor_ch, hz / 2, smg_crsr_blink, NULL); 248 curcmd = CUR_CMD_HSHI; 249 WRITECUR(CUR_CMD, curcmd); 250 if ((fcookie = wsfont_find(NULL, 8, 15, 0, WSDISPLAY_FONTORDER_R2L, 251 WSDISPLAY_FONTORDER_L2R, WSFONT_FIND_BITMAP)) < 0) { 252 aprint_error_dev(self, "could not find 8x15 font\n"); 253 return; 254 } 255 if (wsfont_lock(fcookie, &console_font) != 0) { 256 aprint_error_dev(self, "could not lock 8x15 font\n"); 257 return; 258 } 259 qf = console_font->data; 260 261 config_found(self, &aa, wsemuldisplaydevprint); 262 } 263 264 static u_char *cursor; 265 static int cur_on; 266 267 static void 268 smg_crsr_blink(void *arg) 269 { 270 if (cur_on) 271 *cursor ^= 255; 272 callout_reset(&smg_cursor_ch, hz / 2, smg_crsr_blink, NULL); 273 } 274 275 void 276 smg_cursor(void *id, int on, int row, int col) 277 { 278 struct smg_screen * const ss = id; 279 280 if (ss == curscr) { 281 SM_ADDR(ss->ss_cury, ss->ss_curx, 14) = 282 QFONT(ss->ss_image[ss->ss_cury][ss->ss_curx], 14); 283 cursor = &SM_ADDR(row, col, 14); 284 if ((cur_on = on)) 285 *cursor ^= 255; 286 } 287 ss->ss_curx = col; 288 ss->ss_cury = row; 289 } 290 291 int 292 smg_mapchar(void *id, int uni, unsigned int *index) 293 { 294 if (uni < 256) { 295 *index = uni; 296 return (5); 297 } 298 *index = ' '; 299 return (0); 300 } 301 302 static void 303 smg_putchar(void *id, int row, int col, u_int c, long attr) 304 { 305 struct smg_screen * const ss = id; 306 int i; 307 308 c &= 0xff; 309 310 ss->ss_image[row][col] = c; 311 ss->ss_attr[row][col] = attr; 312 if (ss != curscr) 313 return; 314 for (i = 0; i < 15; i++) { 315 unsigned char ch = QFONT(c, i); 316 317 SM_ADDR(row, col, i) = (attr & WSATTR_REVERSE ? ~ch : ch); 318 319 } 320 if (attr & WSATTR_UNDERLINE) 321 SM_ADDR(row, col, 14) ^= SM_ADDR(row, col, 14); 322 } 323 324 /* 325 * copies columns inside a row. 326 */ 327 static void 328 smg_copycols(void *id, int row, int srccol, int dstcol, int ncols) 329 { 330 struct smg_screen * const ss = id; 331 int i; 332 333 memcpy(&ss->ss_image[row][dstcol], &ss->ss_image[row][srccol], ncols); 334 memcpy(&ss->ss_attr[row][dstcol], &ss->ss_attr[row][srccol], ncols); 335 if (ss != curscr) 336 return; 337 for (i = 0; i < SM_CHEIGHT; i++) 338 memcpy(&SM_ADDR(row, dstcol, i), &SM_ADDR(row, srccol, i), ncols); 339 } 340 341 /* 342 * Erases a bunch of chars inside one row. 343 */ 344 static void 345 smg_erasecols(void *id, int row, int startcol, int ncols, long fillattr) 346 { 347 struct smg_screen * const ss = id; 348 int i; 349 350 memset(&ss->ss_image[row][startcol], 0, ncols); 351 memset(&ss->ss_attr[row][startcol], 0, ncols); 352 if (ss != curscr) 353 return; 354 for (i = 0; i < SM_CHEIGHT; i++) 355 memset(&SM_ADDR(row, startcol, i), 0, ncols); 356 } 357 358 static void 359 smg_copyrows(void *id, int srcrow, int dstrow, int nrows) 360 { 361 struct smg_screen * const ss = id; 362 int frows; 363 364 memcpy(&ss->ss_image[dstrow][0], &ss->ss_image[srcrow][0], 365 nrows * SM_COLS); 366 memcpy(&ss->ss_attr[dstrow][0], &ss->ss_attr[srcrow][0], 367 nrows * SM_COLS); 368 if (ss != curscr) 369 return; 370 if (nrows > 25) { 371 frows = nrows >> 1; 372 if (srcrow > dstrow) { 373 bcopy(&sm_addr[(srcrow * SM_NEXTROW)], 374 &sm_addr[(dstrow * SM_NEXTROW)], 375 frows * SM_NEXTROW); 376 bcopy(&sm_addr[((srcrow + frows) * SM_NEXTROW)], 377 &sm_addr[((dstrow + frows) * SM_NEXTROW)], 378 (nrows - frows) * SM_NEXTROW); 379 } else { 380 bcopy(&sm_addr[((srcrow + frows) * SM_NEXTROW)], 381 &sm_addr[((dstrow + frows) * SM_NEXTROW)], 382 (nrows - frows) * SM_NEXTROW); 383 bcopy(&sm_addr[(srcrow * SM_NEXTROW)], 384 &sm_addr[(dstrow * SM_NEXTROW)], 385 frows * SM_NEXTROW); 386 } 387 } else 388 bcopy(&sm_addr[(srcrow * SM_NEXTROW)], 389 &sm_addr[(dstrow * SM_NEXTROW)], nrows * SM_NEXTROW); 390 } 391 392 static void 393 smg_eraserows(void *id, int startrow, int nrows, long fillattr) 394 { 395 struct smg_screen * const ss = id; 396 int frows; 397 398 memset(&ss->ss_image[startrow][0], 0, nrows * SM_COLS); 399 memset(&ss->ss_attr[startrow][0], 0, nrows * SM_COLS); 400 if (ss != curscr) 401 return; 402 if (nrows > 25) { 403 frows = nrows >> 1; 404 memset(&sm_addr[(startrow * SM_NEXTROW)], 0, frows * SM_NEXTROW); 405 memset(&sm_addr[((startrow + frows) * SM_NEXTROW)], 0, 406 (nrows - frows) * SM_NEXTROW); 407 } else 408 memset(&sm_addr[(startrow * SM_NEXTROW)], 0, nrows * SM_NEXTROW); 409 } 410 411 static int 412 smg_allocattr(void *id, int fg, int bg, int flags, long *attrp) 413 { 414 *attrp = flags; 415 return 0; 416 } 417 418 static void 419 setcursor(struct wsdisplay_cursor *v) 420 { 421 uint16_t red, green, blue; 422 uint32_t curfg[16], curmask[16]; 423 int i; 424 425 /* Enable cursor */ 426 if (v->which & WSDISPLAY_CURSOR_DOCUR) { 427 if (v->enable) 428 curcmd |= CUR_CMD_ENPB|CUR_CMD_ENPA; 429 else 430 curcmd &= ~(CUR_CMD_ENPB|CUR_CMD_ENPA); 431 WRITECUR(CUR_CMD, curcmd); 432 } 433 if (v->which & WSDISPLAY_CURSOR_DOHOT) { 434 hotX = v->hot.x; 435 hotY = v->hot.y; 436 } 437 if (v->which & WSDISPLAY_CURSOR_DOCMAP) { 438 /* First background */ 439 red = fusword(v->cmap.red); 440 green = fusword(v->cmap.green); 441 blue = fusword(v->cmap.blue); 442 bgmask = (((30L * red + 59L * green + 11L * blue) >> 8) >= 443 (((1<<8)-1)*50)) ? ~0 : 0; 444 red = fusword(v->cmap.red+2); 445 green = fusword(v->cmap.green+2); 446 blue = fusword(v->cmap.blue+2); 447 fgmask = (((30L * red + 59L * green + 11L * blue) >> 8) >= 448 (((1<<8)-1)*50)) ? ~0 : 0; 449 } 450 if (v->which & WSDISPLAY_CURSOR_DOSHAPE) { 451 WRITECUR(CUR_CMD, curcmd | CUR_CMD_LODSA); 452 copyin(v->image, curfg, sizeof(curfg)); 453 copyin(v->mask, curmask, sizeof(curmask)); 454 for (i = 0; i < sizeof(curfg)/sizeof(curfg[0]); i++) { 455 WRITECUR(CUR_LOAD, ((uint16_t)curfg[i] & fgmask) | 456 (((uint16_t)curmask[i] & (uint16_t)~curfg[i]) 457 & bgmask)); 458 } 459 for (i = 0; i < sizeof(curmask)/sizeof(curmask[0]); i++) { 460 WRITECUR(CUR_LOAD, (uint16_t)curmask[i]); 461 } 462 WRITECUR(CUR_CMD, curcmd); 463 } 464 } 465 466 int 467 smg_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l) 468 { 469 struct wsdisplay_fbinfo *fb = (void *)data; 470 static uint16_t curc; 471 472 switch (cmd) { 473 case WSDISPLAYIO_GTYPE: 474 *(u_int *)data = WSDISPLAY_TYPE_VAX_MONO; 475 break; 476 477 case WSDISPLAYIO_GINFO: 478 fb->height = SM_YWIDTH; 479 fb->width = SM_XWIDTH; 480 fb->depth = 1; 481 fb->cmsize = 2; 482 break; 483 484 case WSDISPLAYIO_SVIDEO: 485 if (*(u_int *)data == WSDISPLAYIO_VIDEO_ON) { 486 curcmd = curc; 487 } else { 488 curc = curcmd; 489 curcmd &= ~(CUR_CMD_FOPA|CUR_CMD_ENPA); 490 curcmd |= CUR_CMD_FOPB; 491 } 492 WRITECUR(CUR_CMD, curcmd); 493 break; 494 495 case WSDISPLAYIO_GVIDEO: 496 *(u_int *)data = (curcmd & CUR_CMD_FOPB ? 497 WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON); 498 break; 499 500 case WSDISPLAYIO_SCURSOR: 501 setcursor((struct wsdisplay_cursor *)data); 502 break; 503 504 case WSDISPLAYIO_SCURPOS: 505 curx = ((struct wsdisplay_curpos *)data)->x; 506 cury = ((struct wsdisplay_curpos *)data)->y; 507 WRITECUR(CUR_XPOS, curx + CUR_XBIAS); 508 WRITECUR(CUR_YPOS, cury + CUR_YBIAS); 509 break; 510 511 case WSDISPLAYIO_GCURPOS: 512 ((struct wsdisplay_curpos *)data)->x = curx; 513 ((struct wsdisplay_curpos *)data)->y = cury; 514 break; 515 516 case WSDISPLAYIO_GCURMAX: 517 ((struct wsdisplay_curpos *)data)->x = 16; 518 ((struct wsdisplay_curpos *)data)->y = 16; 519 break; 520 521 default: 522 return EPASSTHROUGH; 523 } 524 return 0; 525 } 526 527 static paddr_t 528 smg_mmap(void *v, void *vs, off_t offset, int prot) 529 { 530 if (offset >= SMSIZE || offset < 0) 531 return -1; 532 return (SMADDR + offset) >> PGSHIFT; 533 } 534 535 int 536 smg_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep, 537 int *curxp, int *curyp, long *defattrp) 538 { 539 *cookiep = malloc(sizeof(struct smg_screen), M_DEVBUF, M_WAITOK|M_ZERO); 540 *curxp = *curyp = *defattrp = 0; 541 return 0; 542 } 543 544 void 545 smg_free_screen(void *v, void *cookie) 546 { 547 } 548 549 int 550 smg_show_screen(void *v, void *cookie, int waitok, 551 void (*cb)(void *, int, int), void *cbarg) 552 { 553 struct smg_screen *ss = cookie; 554 int row, col, line; 555 556 if (ss == curscr) 557 return (0); 558 559 for (row = 0; row < SM_ROWS; row++) 560 for (line = 0; line < SM_CHEIGHT; line++) { 561 for (col = 0; col < SM_COLS; col++) { 562 u_char s, c = ss->ss_image[row][col]; 563 564 if (c < 32) 565 c = 32; 566 s = QFONT(c, line); 567 if (ss->ss_attr[row][col] & WSATTR_REVERSE) 568 s ^= 255; 569 SM_ADDR(row, col, line) = s; 570 if (ss->ss_attr[row][col] & WSATTR_UNDERLINE) 571 SM_ADDR(row, col, line) = 255; 572 } 573 } 574 cursor = &sm_addr[(ss->ss_cury * SM_CHEIGHT * SM_COLS) + ss->ss_curx + 575 ((SM_CHEIGHT - 1) * SM_COLS)]; 576 curscr = ss; 577 return (0); 578 } 579 580 cons_decl(smg); 581 582 void 583 smgcninit(struct consdev *cndev) 584 { 585 int fcookie; 586 struct wsdisplay_font *console_font; 587 extern void lkccninit(struct consdev *); 588 extern int lkccngetc(dev_t); 589 extern int dz_vsbus_lk201_cnattach(int); 590 /* Clear screen */ 591 memset(sm_addr, 0, 128*864); 592 593 callout_init(&smg_cursor_ch, 0); 594 595 curscr = &smg_conscreen; 596 wsdisplay_cnattach(&smg_stdscreen, &smg_conscreen, 0, 0, 0); 597 cn_tab->cn_pri = CN_INTERNAL; 598 if ((fcookie = wsfont_find(NULL, 8, 15, 0, WSDISPLAY_FONTORDER_R2L, 599 WSDISPLAY_FONTORDER_L2R, WSFONT_FIND_BITMAP)) < 0) 600 { 601 printf("smg: could not find 8x15 font\n"); 602 return; 603 } 604 if (wsfont_lock(fcookie, &console_font) != 0) { 605 printf("smg: could not lock 8x15 font\n"); 606 return; 607 } 608 qf = console_font->data; 609 610 #if NDZKBD > 0 611 dzkbd_cnattach(0); /* Connect keyboard and screen together */ 612 #endif 613 } 614 615 /* 616 * Called very early to setup the glass tty as console. 617 * Because it's called before the VM system is inited, virtual memory 618 * for the framebuffer can be stolen directly without disturbing anything. 619 */ 620 void 621 smgcnprobe(struct consdev *cndev) 622 { 623 extern vaddr_t virtual_avail; 624 extern const struct cdevsw wsdisplay_cdevsw; 625 626 switch (vax_boardtype) { 627 case VAX_BTYP_410: 628 case VAX_BTYP_420: 629 case VAX_BTYP_43: 630 if ((vax_confdata & KA420_CFG_L3CON) || 631 (vax_confdata & KA420_CFG_MULTU)) 632 break; /* doesn't use graphics console */ 633 sm_addr = (void *)virtual_avail; 634 virtual_avail += SMSIZE; 635 ioaccess((vaddr_t)sm_addr, SMADDR, (SMSIZE/VAX_NBPG)); 636 cndev->cn_pri = CN_INTERNAL; 637 cndev->cn_dev = makedev(cdevsw_lookup_major(&wsdisplay_cdevsw), 638 0); 639 break; 640 641 default: 642 break; 643 } 644 } 645