1 /*$Header: /cvsroot/src/sys/arch/vax/uba/qv.c,v 1.32 2016/07/07 06:55:39 msaitoh Exp $*/ 2 /* 3 * Copyright (c) 2015 Charles H. Dickman. All rights reserved. 4 * Derived from smg.c 5 * Copyright (c) 1998 Ludd, University of Lule}, Sweden. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed at Ludd, University of 19 * Lule}, Sweden and its contributors. 20 * 4. The name of the author may not be used to endorse or promote products 21 * derived from this software without specific prior written permission 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 /* 1 2 3 4 5 6 7 */ 35 /*3456789012345678901234567890123456789012345678901234567890123456789012345678*/ 36 37 #include <sys/cdefs.h> 38 __KERNEL_RCSID(0, "$Header: /cvsroot/src/sys/arch/vax/uba/qv.c,v 1.32 2016/07/07 06:55:39 msaitoh Exp $"); 39 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/callout.h> 43 #include <sys/conf.h> 44 #include <sys/cpu.h> 45 #include <sys/device.h> 46 #include <sys/kernel.h> 47 #include <sys/malloc.h> 48 #include <sys/extent.h> /***/ 49 #include <sys/time.h> 50 #include <sys/bus.h> 51 #include <vax/include/pte.h> /* temporary */ 52 #include <machine/sid.h> 53 #include <dev/cons.h> 54 #include <dev/qbus/ubavar.h> 55 #include <dev/wscons/wsdisplayvar.h> 56 #include <dev/wscons/wsconsio.h> 57 #include <dev/wscons/wscons_callbacks.h> 58 #include <dev/wsfont/wsfont.h> 59 #include <dev/wsfb/genfbvar.h> 60 #include <vax/include/sgmap.h> /***/ 61 62 #include "uba_common.h" /***/ 63 #include "qv.h" 64 #include "qv_ic.h" 65 #include "qvaux.h" 66 #include "opt_wsfont.h" 67 68 #define QMEMBASE 0x30000000 69 #define QVSIZE 0x40000 70 #define QV_SCANMAP 0x3F800 71 #define QV_CURSRAM 0x3FFE0 72 73 #define QV_CSR 0 74 #define QV_CSR_1 (1 << 2) 75 #define QV_CSR_2 (1 << 3) 76 #define QV_CSR_BANK (15 << 11) 77 #define QV_CUR_X 2 78 #define QV_CRTC_AR 8 79 #define QV_CRTC_DR 10 80 #define QV_IC 12 81 #define QV_ICDR QV_ICDR 82 #define QV_ICSR (QV_ICDR + 2) 83 84 /* Screen hardware defs */ 85 #define QV_COLS 128 /* char width of screen */ 86 #define QV_ROWS 57 /* rows of char on screen */ 87 #define QV_CHEIGHT 15 /* lines a char consists of */ 88 #define QV_NEXTROW (QV_COLS * QV_CHEIGHT) 89 #define QV_YWIDTH 864 90 #define QV_XWIDTH 1024 91 92 /* hardware cursor */ 93 #define CUR_BLINKN 0x00 94 #define CUR_BLANK 0x20 95 #define CUR_BLINKS 0x40 96 #define CUR_BLINKF 0x60 97 #define CUR_BLINKM 0x60 98 #define CUR_OFF CUR_BLANK 99 #define CUR_ON CUR_BLINKS 100 #define CUR_START 10 101 #define CUR_END 11 102 #define CUR_HI 14 103 #define CUR_LO 15 104 105 //static uint16_t curcmd, curx, cury, hotX, hotY; 106 static int bgmask, fgmask; 107 108 static int qv_match(device_t, cfdata_t, void *); 109 static void qv_attach(device_t, device_t, void *); 110 111 static void qv_cursor(void *, int, int, int); 112 static int qv_mapchar(void *, int, unsigned int *); 113 static void qv_putchar(void *, int, int, u_int, long); 114 static void qv_copycols(void *, int, int, int,int); 115 static void qv_erasecols(void *, int, int, int, long); 116 static void qv_copyrows(void *, int, int, int); 117 static void qv_eraserows(void *, int, int, long); 118 static int qv_allocattr(void *, int, int, int, long *); 119 120 const struct wsdisplay_emulops qv_emulops = { 121 .cursor = qv_cursor, 122 .mapchar = qv_mapchar, 123 .putchar = qv_putchar, 124 .copycols = qv_copycols, 125 .erasecols = qv_erasecols, 126 .copyrows = qv_copyrows, 127 .eraserows = qv_eraserows, 128 .allocattr = qv_allocattr 129 }; 130 131 struct _wsscreen_descr { 132 const struct wsscreen_descr qv_stdscreen; /* MUST BE FIRST */ 133 const uint16_t qv_crtc_param[16]; 134 }; 135 136 /* 137 * Notes from the original Ultrix drivers 138 * 139 * Screen controller initialization parameters. The definations [sic] and use 140 * of these parameters can be found in the Motorola 68045 [sic] crtc specs. In 141 * essence they set the display parameters for the chip. The first set is 142 * for the 15" screen and the second is for the 19" separate sync. There 143 * is also a third set for a 19" composite sync monitor which we have not 144 * tested and which is not supported. 145 */ 146 147 const struct _wsscreen_descr qv_stdscreen[] = { 148 { { "80x30", 80, 30, &qv_emulops, 8, 149 QV_CHEIGHT, WSSCREEN_UNDERLINE|WSSCREEN_REVERSE }, 150 { 31, 25, 27, 0142, 31, 13, 30, 31, 4, 15, 040, 0, 0, 0, 0, 0 } }, 151 { { "120x55", 120, 55, &qv_emulops, 8, 152 QV_CHEIGHT, WSSCREEN_UNDERLINE|WSSCREEN_REVERSE }, 153 { 39, 30, 32, 0262, 55, 5, 54, 54, 4, 15, 040, 0, 0, 0, 0, 0 } }, 154 { { "128x57", QV_COLS, QV_ROWS, &qv_emulops, 8, 155 QV_CHEIGHT, WSSCREEN_UNDERLINE|WSSCREEN_REVERSE }, 156 { 39, 32, 33, 0264, 56, 5, 54, 54, 4, 15, 040, 0, 0, 0, 0, 0 } }, 157 }; 158 159 const struct wsscreen_descr *_qv_scrlist[] = { 160 &qv_stdscreen[2].qv_stdscreen, /* default */ 161 &qv_stdscreen[1].qv_stdscreen, 162 &qv_stdscreen[0].qv_stdscreen, 163 }; 164 165 const struct wsscreen_list qv_screenlist = { 166 .nscreens = __arraycount(_qv_scrlist), 167 .screens = _qv_scrlist, 168 }; 169 170 struct qv_softc { 171 device_t sc_dev; /* device pointer */ 172 bus_space_tag_t sc_iot; /* register base */ 173 bus_space_handle_t sc_ioh; 174 bus_space_tag_t sc_fbt; /* frame buffer base */ 175 bus_space_handle_t sc_fbh; 176 paddr_t sc_fbphys; /* frame buffer phys addr */ 177 char *sc_fb; /* frame buffer virt addr */ 178 uint16_t *sc_scanmap; /* scan map virt addr */ 179 char *sc_font; /* font glyph table */ 180 181 uint8_t sc_curon; /* cursor on */ 182 uint16_t sc_curx; /* cursor x position */ 183 uint16_t sc_cury; /* cursor y position */ 184 uint16_t sc_curhotX; /* cursor x hot spot */ 185 uint16_t sc_curhotY; /* cursor y hot spot */ 186 187 struct qv_screen *sc_curscr; /* current screen */ 188 }; 189 190 #if 0 191 struct genfb_qv_softc { 192 struct genfb_softc sc_gen; 193 bus_space_tag_t sc_iot; 194 bus_space_handle_t sc_ioh; 195 uint32_t sc_wstype; 196 }; 197 #endif 198 199 static void qv_crtc_wr(struct qv_softc *, uint16_t, uint16_t); 200 static void qv_setcrtc(struct qv_softc *, const uint16_t *); 201 202 static int qv_ioctl(void *, void *, u_long, void *, int, struct lwp *); 203 static paddr_t qv_mmap(void *, void *, off_t, int); 204 static int qv_alloc_screen(void *, const struct wsscreen_descr *, 205 void **, int *, int *, long *); 206 static void qv_free_screen(void *, void *); 207 static int qv_show_screen(void *, void *, int, 208 void (*) (void *, int, int), void *); 209 //static void qv_crsr_blink(void *); 210 211 int qvauxprint(void *, const char *); 212 213 const struct wsdisplay_accessops qv_accessops = { 214 .ioctl = qv_ioctl, 215 .mmap = qv_mmap, 216 .alloc_screen = qv_alloc_screen, 217 .free_screen = qv_free_screen, 218 .show_screen = qv_show_screen, 219 }; 220 221 struct qv_screen { 222 struct qv_softc *ss_sc; 223 const struct wsscreen_descr *ss_type; 224 int ss_curx; 225 int ss_cury; 226 u_char ss_image[QV_ROWS][QV_COLS]; /* Image of screen */ 227 u_char ss_attr[QV_ROWS][QV_COLS]; /* Reversed etc... */ 228 }; 229 230 static struct qv_screen qv_conscreen; /* XXX no console support */ 231 232 static callout_t qv_cursor_ch; 233 234 CFATTACH_DECL_NEW(qv, sizeof(struct qv_softc), 235 qv_match, qv_attach, NULL, NULL); 236 #if 0 237 static int genfb_match_qv(device_t, cfdata_t, void *); 238 static void genfb_attach_qv(device_t, device_t, void *); 239 static int genfb_ioctl_qv(void *, void *, u_long, void *, int, 240 struct lwp*); 241 static paddr_t genfb_mmap_qv(void *, void *, off_t, int); 242 static int genfb_borrow_qv(void *, bus_addr_t, bus_space_handle_t *); 243 244 CFATTACH_DECL_NEW(genfb_qv, sizeof(struct genfb_qv_softc), 245 genfb_match_qv, genfb_attach_qv, NULL, NULL); 246 #endif 247 248 /* 249 * autoconf match function 250 */ 251 int 252 qv_match(device_t parent, cfdata_t match, void *aux) 253 { 254 struct uba_attach_args *ua = aux; 255 struct uba_softc *uh = device_private(parent); 256 257 /* set up interrupts so the vector can be detected */ 258 259 /* initialize qv interrupt controller */ 260 qv_ic_init(ua, QV_IC); 261 262 /* set vertical retrace interrupt */ 263 qv_ic_setvec(ua, QV_IC, QV_SYNC_VEC, uh->uh_lastiv - 4); 264 qv_ic_enable(ua, QV_IC, QV_SYNC_VEC, QV_IC_ENA); 265 qv_ic_arm(ua, QV_IC, QV_SYNC_VEC); 266 267 /* enable interrupts */ 268 bus_space_write_2(ua->ua_iot, ua->ua_ioh, QV_CSR, 269 bus_space_read_2(ua->ua_iot, ua->ua_ioh, QV_CSR) | (1 << 6)); 270 271 qv_ic_force(ua, QV_IC, QV_SYNC_VEC); 272 273 DELAY(20000); 274 275 /* disable interrupts */ 276 qv_ic_enable(ua, QV_IC, QV_SYNC_VEC, QV_IC_DIS); 277 278 return 1; 279 } 280 281 /* controller register write helper function */ 282 static inline void 283 qv_reg_wr(struct qv_softc *sc, uint16_t addr, uint16_t data) 284 { 285 bus_space_write_2(sc->sc_iot, sc->sc_ioh, addr, data); 286 } 287 288 /* controller register read helper function */ 289 static inline uint16_t 290 qv_reg_rd(struct qv_softc *sc, uint16_t addr) 291 { 292 return bus_space_read_2(sc->sc_iot, sc->sc_ioh, addr); 293 } 294 295 /* 296 * write a 6845 CRT controller register 297 */ 298 static void 299 qv_crtc_wr(struct qv_softc *sc, uint16_t addr, uint16_t data) 300 { 301 qv_reg_wr(sc, QV_CRTC_AR, addr); 302 qv_reg_wr(sc, QV_CRTC_DR, data); 303 } 304 305 /* 306 * write a set of a set of video timing parameters to the CRTC 307 */ 308 static void 309 qv_setcrtc(struct qv_softc *sc, const uint16_t *pp) 310 { 311 int i; 312 313 for (i = 0; i < 14; i++) 314 qv_crtc_wr(sc, i, pp[i]); 315 } 316 317 static void inline 318 qv_ic_write(struct uba_attach_args *ua, bus_size_t offs, uint16_t value) 319 { 320 bus_space_write_2(ua->ua_iot, ua->ua_ioh, offs, value); 321 } 322 323 void 324 qv_ic_init(struct uba_attach_args *ua, bus_size_t offs) 325 { 326 static int initted; 327 int i; 328 329 if (!initted) { 330 /* init the interrupt controller */ 331 qv_ic_write(ua, QV_IC_SR + offs, QV_IC_RESET); 332 /* reset irr */ 333 qv_ic_write(ua, QV_IC_SR + offs, QV_IC_CLRIRR); 334 /* specify individual vectors */ 335 qv_ic_write(ua, QV_IC_SR + offs, QV_IC_MODE); 336 /* preset autoclear data */ 337 qv_ic_write(ua, QV_IC_SR + offs, QV_IC_ACREG); 338 /* all setup as autoclear */ 339 qv_ic_write(ua, QV_IC_DR + offs, 0xff); 340 341 /* clear all vector addresses */ 342 for (i = 0; i < 8; i++) 343 qv_ic_setvec(ua, offs, i, 0); 344 345 initted = 1; 346 } 347 } 348 349 void 350 qv_ic_setvec(struct uba_attach_args *ua, bus_size_t offs, int ic_vec, 351 int vecnum) 352 { 353 /* preset vector address */ 354 qv_ic_write(ua, QV_IC_SR + offs, QV_IC_RMEM | RMEM_BC_1 | ic_vec); 355 356 /* give it the vector number */ 357 qv_ic_write(ua, QV_IC_DR + offs, vecnum); 358 } 359 360 void 361 qv_ic_enable(struct uba_attach_args *ua, bus_size_t offs, int ic_vec, 362 int enable) 363 { 364 if (enable) 365 /* enable the interrupt */ 366 qv_ic_write(ua, QV_IC_SR + offs, QV_IC_CIMR | ic_vec); 367 else 368 /* disable the interrupt */ 369 qv_ic_write(ua, QV_IC_SR + offs, QV_IC_SIMR | ic_vec); 370 } 371 372 void 373 qv_ic_arm(struct uba_attach_args *ua, bus_size_t offs, int arm) 374 { 375 if (arm) 376 /* arm the interrupt ctrl */ 377 qv_ic_write(ua, QV_IC_SR + offs, QV_IC_ARM); 378 else 379 /* disarm the interrupt ctrl */ 380 qv_ic_write(ua, QV_IC_SR + offs, QV_IC_DISARM); 381 } 382 383 void 384 qv_ic_force(struct uba_attach_args *ua, bus_size_t offs, int ic_vec) 385 { 386 /* force an interrupt */ 387 qv_ic_write(ua, QV_IC_SR + offs, QV_IC_SIRR | ic_vec); 388 } 389 390 /* 391 * print attachment message 392 */ 393 int 394 qvauxprint(void *aux, const char *pnp) 395 { 396 if (pnp) { 397 aprint_normal("qvaux at %s", pnp); 398 return (UNCONF); 399 } 400 return 0; 401 } 402 403 /* 404 * autoconf attach function 405 */ 406 void 407 qv_attach(device_t parent, device_t self, void *aux) 408 { 409 struct qv_softc *sc = device_private(self); 410 struct uba_softc *uh = device_private(parent); 411 struct uba_attach_args *ua = aux; 412 struct uba_attach_args aa; 413 int fcookie; 414 struct wsemuldisplaydev_attach_args emulaa; 415 // struct wsdisplaydev_attach_args dispaa; 416 struct wsdisplay_font *console_font; 417 int line; 418 419 sc->sc_dev = self; 420 sc->sc_iot = ua->ua_iot; 421 sc->sc_ioh = ua->ua_ioh; 422 sc->sc_fbt = sc->sc_iot; 423 sc->sc_fbphys = QMEMBASE + ((qv_reg_rd(sc, QV_CSR) & QV_CSR_BANK) << 7); 424 if (bus_space_map(sc->sc_fbt, sc->sc_fbphys, QVSIZE, 425 BUS_SPACE_MAP_LINEAR, &sc->sc_fbh)) { 426 aprint_error_dev(self, "Couldn't alloc graphics memory.\n"); 427 return; 428 } 429 430 aprint_normal(": fb %8lo", sc->sc_fbphys & 0x3fffff); 431 sc->sc_fb = bus_space_vaddr(sc->sc_fbt, sc->sc_fbh); 432 sc->sc_scanmap = (uint16_t *)&sc->sc_fb[QV_SCANMAP]; 433 #if 0 434 if (extent_alloc_region(((struct uba_vsoftc*)uh)->uv_sgmap.aps_ex, 435 sc->sc_fbphys & 0x3fffff, QVSIZE, EX_NOWAIT)) { 436 aprint_error_dev(self, 437 "Couldn't alloc graphics memory in sgmap.\n"); 438 return; 439 } 440 #endif 441 //aprint_normal(": fb 0x%08lx", sc->sc_fbphys & 0x3fffff); 442 443 bzero(sc->sc_fb, QVSIZE); 444 445 for (line = 0; line < QV_YWIDTH; line++) { 446 sc->sc_scanmap[line] = line; 447 } 448 449 /* program crtc */ 450 qv_setcrtc(sc, qv_stdscreen[2].qv_crtc_param); 451 452 /* enable video output */ 453 qv_reg_wr(sc, QV_CSR, qv_reg_rd(sc, QV_CSR) | (1 << 2) | (1 << 3)); 454 #if 0 455 if (sc->sc_curscr == NULL) 456 callout_init(&qv_cursor_ch, 0); 457 sc->sc_curscr = &qv_conscreen; 458 459 callout_reset(&qv_cursor_ch, hz / 2, qv_crsr_blink, sc); 460 #endif 461 /* interrupt handlers - XXX */ 462 463 uh->uh_lastiv -= 4; 464 465 wsfont_init(); 466 if ((fcookie = wsfont_find(NULL, 8, 15, 0, WSDISPLAY_FONTORDER_R2L, 467 WSDISPLAY_FONTORDER_L2R, WSFONT_FIND_BITMAP)) < 0) { 468 aprint_error_dev(self, "could not find 8x15 font\n"); 469 return; 470 } 471 if (wsfont_lock(fcookie, &console_font) != 0) { 472 aprint_error_dev(self, "could not lock 8x15 font\n"); 473 return; 474 } 475 sc->sc_font = console_font->data; 476 477 aprint_normal("\n"); 478 479 aa.ua_iot = ua->ua_iot; 480 aa.ua_ioh = ua->ua_ioh + 32; // offset 481 aa.ua_cvec = ua->ua_cvec - 4; 482 if (config_search_ia(NULL, self, "qv", &aa) != NULL) { 483 config_found_ia(self, "qv", &aa, qvauxprint); 484 uh->uh_lastiv -= 4; 485 } 486 487 emulaa.console = 0; /* Not console */ 488 emulaa.scrdata = &qv_screenlist; 489 emulaa.accessops = &qv_accessops; 490 emulaa.accesscookie = self; 491 if (config_search_ia(NULL, self, "wsemuldisplaydev", &emulaa) != NULL) { 492 config_found_ia(self, "wsemuldisplaydev", &emulaa, 493 wsemuldisplaydevprint); 494 } 495 496 //console_debugger(); 497 return; 498 } 499 500 /* QVSS frame buffer */ 501 502 /* uint_32 is stored little endian in frame buffer */ 503 /* bits are stored little endian in frame buffer */ 504 505 /* uint_32 *fb; */ 506 /* fb = (int *)phystova(0x303c0000); */ 507 /* *fb = 0x00000001; */ /* sets bit in first column */ 508 509 /* Frame Buffer Usage */ 510 511 /* characters are 8 bits wide and QVHEIGHT high */ 512 /* the scan map is allocated in terms of character height, */ 513 /* so a pointer to the top line of a character can step to the */ 514 /* next row without looking up the memory location in the scan map */ 515 516 static char *cursor; 517 static int cur_on; 518 519 /* 520 * return pointer to line in character glyph 521 */ 522 static inline char * 523 qv_font(struct qv_softc *sc, int c, int line) 524 { 525 /* map char to font table offset */ 526 if (c < 32) 527 c = 32; 528 else if (c > 127) 529 c -= 66; 530 else 531 c -= 32; 532 533 /* return pointer line in font glyph */ 534 return &sc->sc_font[c*QV_CHEIGHT + line]; 535 } 536 537 /* 538 * return pointer to character line in frame buffer 539 */ 540 static inline char * 541 qv_fbp(struct qv_softc *sc, int row, int col, int line) 542 { 543 return &sc->sc_fb[col + sc->sc_scanmap[row*QV_CHEIGHT + line]*QV_COLS]; 544 } 545 546 /* 547 * callout callback function to blink cursor 548 */ 549 #if 0 550 static void 551 qv_crsr_blink(void *arg) 552 { 553 struct qv_softc *sc = arg; 554 555 if (cur_on) 556 *cursor ^= 255; 557 callout_reset(&qv_cursor_ch, hz / 2, qv_crsr_blink, sc); 558 } 559 #endif 560 /* 561 * emulop cursor 562 */ 563 void 564 qv_cursor(void *id, int on, int row, int col) 565 { 566 struct qv_screen * const ss = id; 567 568 if (ss == ss->ss_sc->sc_curscr) { 569 *qv_fbp(ss->ss_sc, ss->ss_cury, ss->ss_curx, 14) 570 = *qv_font(ss->ss_sc, 571 ss->ss_image[ss->ss_cury][ss->ss_curx], 14); 572 cursor = qv_fbp(ss->ss_sc, row, col, 14); 573 if ((cur_on = on)) 574 *cursor ^= 255; 575 } 576 ss->ss_curx = col; 577 ss->ss_cury = row; 578 } 579 580 /* 581 * emulop mapchar 582 */ 583 int 584 qv_mapchar(void *id, int uni, unsigned int *index) 585 { 586 if (uni < 256) { 587 *index = uni; 588 return (5); 589 } 590 *index = ' '; 591 return (0); 592 } 593 594 /* 595 * emulop putchar 596 */ 597 static void 598 qv_putchar(void *id, int row, int col, u_int c, long attr) 599 { 600 struct qv_screen * const ss = id; 601 int i; 602 char *gp; 603 char *fp; 604 char rvid; 605 606 c &= 0xff; 607 608 ss->ss_image[row][col] = c; 609 ss->ss_attr[row][col] = attr; 610 if (ss != ss->ss_sc->sc_curscr) 611 return; 612 613 gp = qv_font(ss->ss_sc, c, 0); 614 fp = qv_fbp(ss->ss_sc, row, col, 0); 615 rvid = (attr & WSATTR_REVERSE) ? 0xff : 0x00; 616 for (i = 0; i < QV_CHEIGHT; i++) { 617 *fp = *gp++ ^ rvid; 618 fp += QV_COLS; 619 } 620 621 if (attr & WSATTR_UNDERLINE) 622 *qv_fbp(ss->ss_sc, row, col, 14) 623 ^= *qv_fbp(ss->ss_sc, row, col, 14); 624 } 625 626 /* 627 * emulop copy columns - copies columns inside a row 628 */ 629 static void 630 qv_copycols(void *id, int row, int srccol, int dstcol, int ncols) 631 { 632 struct qv_screen * const ss = id; 633 int i; 634 635 memcpy(&ss->ss_image[row][dstcol], &ss->ss_image[row][srccol], ncols); 636 memcpy(&ss->ss_attr[row][dstcol], &ss->ss_attr[row][srccol], ncols); 637 if (ss != ss->ss_sc->sc_curscr) 638 return; 639 for (i = 0; i < QV_CHEIGHT; i++) 640 memcpy(qv_fbp(ss->ss_sc, row, dstcol, i), 641 qv_fbp(ss->ss_sc, row, srccol, i), ncols); 642 } 643 644 /* 645 * emulop erase columns - erases a bunch of chars inside one row 646 */ 647 static void 648 qv_erasecols(void *id, int row, int startcol, int ncols, long fillattr) 649 { 650 struct qv_screen * const ss = id; 651 int i; 652 653 memset(&ss->ss_image[row][startcol], 0, ncols); 654 memset(&ss->ss_attr[row][startcol], 0, ncols); 655 if (ss != ss->ss_sc->sc_curscr) 656 return; 657 for (i = 0; i < QV_CHEIGHT; i++) 658 memset(qv_fbp(ss->ss_sc, row, startcol, i), 0, ncols); 659 } 660 661 /* 662 * overlap check 663 * return 0 if no overlap 664 * -1 if overlap and dst is less than src (move up) 665 * +1 if overlap and src is less than dst (move down) 666 */ 667 static inline int 668 qv_rows_overlap(int srcrow, int dstrow, int nrows) 669 { 670 if (dstrow < srcrow) { 671 if (dstrow + nrows <= srcrow) 672 return 0; 673 else 674 return -1; 675 } 676 else { 677 if (srcrow + nrows <= dstrow) 678 return 0; 679 else 680 return 1; 681 } 682 } 683 684 /* 685 * emulop copyrows - copy entire rows 686 */ 687 static void 688 qv_copyrows(void *id, int srcrow, int dstrow, int nrows) 689 { 690 struct qv_screen * const ss = id; 691 int ol; 692 int n; 693 int line; 694 int tmp; 695 uint16_t *sp; 696 uint16_t *dp; 697 698 memcpy(&ss->ss_image[dstrow][0], &ss->ss_image[srcrow][0], 699 nrows * QV_COLS); 700 memcpy(&ss->ss_attr[dstrow][0], &ss->ss_attr[srcrow][0], 701 nrows * QV_COLS); 702 if (ss != ss->ss_sc->sc_curscr) 703 return; 704 705 ol = qv_rows_overlap(srcrow, dstrow, nrows); 706 if (ol == 0) 707 for (n = 0; n < nrows; n++) 708 bcopy(qv_fbp(ss->ss_sc, srcrow + n, 0, 0), 709 qv_fbp(ss->ss_sc, dstrow + n, 0, 0), QV_NEXTROW); 710 else if (ol < 0) { 711 for (n = 0; n < nrows; n++) { 712 dp = &ss->ss_sc->sc_scanmap[(dstrow + n)*QV_CHEIGHT]; 713 sp = &ss->ss_sc->sc_scanmap[(srcrow + n)*QV_CHEIGHT]; 714 for (line = 0; line < QV_CHEIGHT; line++) { 715 tmp = *dp; 716 *dp = *sp; 717 *sp = tmp; 718 dp++; 719 sp++; 720 } 721 } 722 qv_copyrows(id, dstrow + nrows - srcrow + dstrow, 723 dstrow + nrows, srcrow - dstrow); 724 } 725 else { 726 for (n = nrows - 1; n >= 0; n--) { 727 dp = &ss->ss_sc->sc_scanmap[(dstrow + n)*QV_CHEIGHT]; 728 sp = &ss->ss_sc->sc_scanmap[(srcrow + n)*QV_CHEIGHT]; 729 for (line = 0; line < QV_CHEIGHT; line++) { 730 tmp = *dp; 731 *dp = *sp; 732 *sp = tmp; 733 dp++; 734 sp++; 735 } 736 } 737 qv_copyrows(id, srcrow, dstrow, dstrow - srcrow); 738 } 739 } 740 741 /* 742 * emulop eraserows - erase a number of entire rows 743 */ 744 static void 745 qv_eraserows(void *id, int startrow, int nrows, long fillattr) 746 { 747 struct qv_screen * const ss = id; 748 int row; 749 750 memset(&ss->ss_image[startrow][0], 0, nrows * QV_COLS); 751 memset(&ss->ss_attr[startrow][0], 0, nrows * QV_COLS); 752 if (ss != ss->ss_sc->sc_curscr) 753 return; 754 755 for (row = startrow; row < startrow + nrows; row++) { 756 memset(qv_fbp(ss->ss_sc, row, 0, 0), 0, QV_NEXTROW); 757 } 758 } 759 760 /* 761 * emulop allocattr 762 */ 763 static int 764 qv_allocattr(void *id, int fg, int bg, int flags, long *attrp) 765 { 766 *attrp = flags; 767 return 0; 768 } 769 770 /* 771 * emulop setcursor 772 */ 773 static void 774 qv_setcursor(struct qv_softc *sc, struct wsdisplay_cursor *v) 775 { 776 uint16_t red, green, blue; 777 uint32_t curfg[16], curmask[16]; 778 uint16_t *curp; 779 int i; 780 781 /* Enable cursor */ 782 if (v->which & WSDISPLAY_CURSOR_DOCUR) { 783 sc->sc_curon = (v->enable) ? CUR_ON : CUR_OFF; 784 qv_crtc_wr(sc, CUR_START, sc->sc_curon | (sc->sc_cury & 0x0f)); 785 } 786 if (v->which & WSDISPLAY_CURSOR_DOHOT) { 787 sc->sc_curhotX = v->hot.x; 788 sc->sc_curhotY = v->hot.y; 789 } 790 if (v->which & WSDISPLAY_CURSOR_DOCMAP) { 791 /* First background */ 792 red = fusword(v->cmap.red); 793 green = fusword(v->cmap.green); 794 blue = fusword(v->cmap.blue); 795 bgmask = (((30L * red + 59L * green + 11L * blue) >> 8) >= 796 (((1<<8)-1)*50)) ? ~0 : 0; 797 red = fusword(v->cmap.red+2); 798 green = fusword(v->cmap.green+2); 799 blue = fusword(v->cmap.blue+2); 800 fgmask = (((30L * red + 59L * green + 11L * blue) >> 8) >= 801 (((1<<8)-1)*50)) ? ~0 : 0; 802 } 803 if (v->which & WSDISPLAY_CURSOR_DOSHAPE) { 804 copyin(v->image, curfg, sizeof(curfg)); 805 copyin(v->mask, curmask, sizeof(curmask)); /* not used */ 806 curp = (uint16_t *) &(sc->sc_fb)[QV_CURSRAM]; 807 for (i = 0; i < sizeof(curfg)/sizeof(curfg[0]); i++) { 808 curp[i] = (uint16_t)curfg[i]; 809 } 810 } 811 } 812 813 /* 814 * emulop ioctl 815 */ 816 int 817 qv_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l) 818 { 819 struct wsdisplay_fbinfo *fb = (void *)data; 820 //static uint16_t curc; 821 struct qv_softc *sc = device_private(v); 822 823 switch (cmd) { 824 case WSDISPLAYIO_GTYPE: 825 *(u_int *)data = WSDISPLAY_TYPE_VAX_MONO; 826 break; 827 828 case WSDISPLAYIO_GINFO: 829 fb->height = QV_YWIDTH; 830 fb->width = QV_XWIDTH; 831 fb->depth = 1; 832 fb->cmsize = 2; 833 break; 834 835 case WSDISPLAYIO_SVIDEO: 836 if (*(u_int *)data == WSDISPLAYIO_VIDEO_ON) { 837 /* enable video output */ 838 qv_reg_wr(sc, QV_CSR, 839 qv_reg_rd(sc, QV_CSR) | (1 << 2)); 840 } else { 841 /* disable video output */ 842 qv_reg_wr(sc, QV_CSR, 843 qv_reg_rd(sc, QV_CSR) & ~(1 << 2)); 844 } 845 break; 846 847 case WSDISPLAYIO_GVIDEO: 848 *(u_int *)data = (qv_reg_rd(sc, QV_CSR) & (1 << 2)) 849 ? WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON; 850 break; 851 852 case WSDISPLAYIO_SCURSOR: 853 qv_setcursor(sc, (struct wsdisplay_cursor *)data); 854 break; 855 856 case WSDISPLAYIO_SCURPOS: 857 sc->sc_curx = ((struct wsdisplay_curpos *)data)->x; 858 sc->sc_cury = ((struct wsdisplay_curpos *)data)->y; 859 qv_crtc_wr(sc, CUR_START, CUR_OFF | (sc->sc_cury & 0x0f)); 860 qv_crtc_wr(sc, CUR_HI, sc->sc_cury >> 4); 861 qv_reg_wr(sc, QV_CUR_X, sc->sc_curx); 862 qv_crtc_wr(sc, CUR_START, 863 sc->sc_curon | (sc->sc_cury & 0x0f)); 864 break; 865 866 case WSDISPLAYIO_GCURPOS: 867 ((struct wsdisplay_curpos *)data)->x = sc->sc_curx; 868 ((struct wsdisplay_curpos *)data)->y = sc->sc_cury; 869 break; 870 871 case WSDISPLAYIO_GCURMAX: 872 ((struct wsdisplay_curpos *)data)->x = 16; 873 ((struct wsdisplay_curpos *)data)->y = 16; 874 break; 875 876 default: 877 return EPASSTHROUGH; 878 } 879 return 0; 880 } 881 882 /* 883 * emulop mmap 884 */ 885 static paddr_t 886 qv_mmap(void *v, void *vs, off_t offset, int prot) 887 { 888 struct qv_softc *sc = device_private(v); 889 890 if (offset >= QVSIZE || offset < 0) 891 return -1; 892 return (sc->sc_fbphys) >> PGSHIFT; 893 } 894 895 /* 896 * emulop allocate screen 897 */ 898 int 899 qv_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep, 900 int *curxp, int *curyp, long *defattrp) 901 { 902 struct qv_softc *sc = device_private(v); 903 struct qv_screen *ss; 904 905 ss = malloc(sizeof(struct qv_screen), M_DEVBUF, M_WAITOK|M_ZERO); 906 ss->ss_sc = sc; 907 ss->ss_type = type; 908 *cookiep = ss; 909 *curxp = *curyp = *defattrp = 0; 910 printf("qv_alloc_screen: \"%s\" %p\n", type->name, ss); 911 return 0; 912 } 913 914 /* 915 * emulop free screen 916 */ 917 void 918 qv_free_screen(void *v, void *cookie) 919 { 920 printf("qv_free_screen: %p\n", cookie); 921 free(cookie, M_DEVBUF); 922 } 923 924 /* 925 * emulop show screen 926 */ 927 int 928 qv_show_screen(void *v, void *cookie, int waitok, 929 void (*cb)(void *, int, int), void *cbarg) 930 { 931 struct qv_screen *ss = cookie; 932 const struct _wsscreen_descr *descr; 933 int row, col, line; 934 printf("qv_show_screen: %p\n", cookie); 935 936 if (ss == ss->ss_sc->sc_curscr) 937 return (0); 938 939 descr = (const struct _wsscreen_descr *)(ss->ss_type); 940 qv_setcrtc(ss->ss_sc, descr->qv_crtc_param); 941 for (row = 0; row < QV_ROWS; row++) 942 for (line = 0; line < QV_CHEIGHT; line++) { 943 for (col = 0; col < QV_COLS; col++) { 944 u_char s, c = ss->ss_image[row][col]; 945 946 if (c < 32) 947 c = 32; 948 s = *qv_font(ss->ss_sc, c, line); 949 if (ss->ss_attr[row][col] & WSATTR_REVERSE) 950 s ^= 255; 951 *qv_fbp(ss->ss_sc, row, col, line) = s; 952 953 if (ss->ss_attr[row][col] & WSATTR_UNDERLINE) 954 *qv_fbp(ss->ss_sc, row, col, line) 955 = 255; 956 } 957 } 958 cursor = qv_fbp(ss->ss_sc, ss->ss_cury, ss->ss_curx, 14); 959 ss->ss_sc->sc_curscr = ss; 960 return (0); 961 } 962 963 #if 0 964 void 965 qv_reset_establish(void (*reset)(device_t), device_t dev) 966 { 967 uba_reset_establish(reset, device_parent(dev)); 968 } 969 #endif 970 cons_decl(qv); 971 972 void 973 qvcninit(struct consdev *cndev) 974 { 975 int fcookie; 976 struct wsdisplay_font *console_font; 977 extern void lkccninit(struct consdev *); 978 extern int lkccngetc(dev_t); 979 extern int dz_vsbus_lk201_cnattach(int); 980 981 //printf("qvcninit: \n"); 982 /* Clear screen */ 983 //memset(qv_addr, 0, 128*864); 984 985 callout_init(&qv_cursor_ch, 0); 986 //curscr = &qv_conscreen; 987 wsdisplay_cnattach(&qv_stdscreen[0].qv_stdscreen, 988 &qv_conscreen, 0, 0, 0); 989 cn_tab->cn_pri = CN_INTERNAL; 990 wsfont_init(); 991 if ((fcookie = wsfont_find(NULL, 8, 15, 0, WSDISPLAY_FONTORDER_R2L, 992 WSDISPLAY_FONTORDER_L2R, WSFONT_FIND_BITMAP)) < 0) 993 { 994 printf("qv: could not find 8x15 font\n"); 995 return; 996 } 997 if (wsfont_lock(fcookie, &console_font) != 0) { 998 printf("qv: could not lock 8x15 font\n"); 999 return; 1000 } 1001 //qf = console_font->data; 1002 1003 #if NQVKBD > 0 && 0 1004 qvkbd_cnattach(0); /* Connect keyboard and screen together */ 1005 #endif 1006 } 1007 1008 /* 1009 * Called very early to setup the glass tty as console. 1010 * Because it's called before the VM system is inited, virtual memory 1011 * for the framebuffer can be stolen directly without disturbing anything. 1012 */ 1013 void 1014 qvcnprobe(struct consdev *cndev) 1015 { 1016 printf("qvcnprobe: \n"); 1017 #if 0 1018 extern vaddr_t virtual_avail; 1019 extern const struct cdevsw wsdisplay_cdevsw; 1020 1021 switch (vax_boardtype) { 1022 case VAX_BTYP_410: 1023 case VAX_BTYP_420: 1024 case VAX_BTYP_43: 1025 if ((vax_confdata & KA420_CFG_L3CON) || 1026 (vax_confdata & KA420_CFG_MULTU)) 1027 break; /* doesn't use graphics console */ 1028 qv_addr = (void *)virtual_avail; 1029 virtual_avail += QVSIZE; 1030 ioaccess((vaddr_t)qv_addr, QVADDR, (QVSIZE/VAX_NBPG)); 1031 cndev->cn_pri = CN_INTERNAL; 1032 cndev->cn_dev = makedev(cdevsw_lookup_major(&wsdisplay_cdevsw), 1033 0); 1034 break; 1035 default: 1036 break; 1037 } 1038 #endif 1039 } 1040