1 /* $NetBSD: sti.c,v 1.18 2014/06/29 04:08:43 tsutsui Exp $ */ 2 3 /* $OpenBSD: sti.c,v 1.61 2009/09/05 14:09:35 miod Exp $ */ 4 5 /* 6 * Copyright (c) 2000-2003 Michael Shalayeff 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, 22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 27 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 28 * THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 /* 31 * TODO: 32 * call sti procs asynchronously; 33 * implement console scroll-back; 34 * X11 support. 35 */ 36 37 #include <sys/cdefs.h> 38 __KERNEL_RCSID(0, "$NetBSD: sti.c,v 1.18 2014/06/29 04:08:43 tsutsui Exp $"); 39 40 #include "wsdisplay.h" 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/device.h> 45 #include <sys/malloc.h> 46 47 #include <uvm/uvm.h> 48 49 #include <sys/bus.h> 50 51 #include <dev/wscons/wsdisplayvar.h> 52 #include <dev/wscons/wsconsio.h> 53 54 #include <dev/ic/stireg.h> 55 #include <dev/ic/stivar.h> 56 57 #ifndef hp300 /* XXX */ 58 #include "sti_pci.h" 59 #endif 60 61 #ifdef STIDEBUG 62 63 #define DPRINTF(s) do { \ 64 if (stidebug) \ 65 printf s; \ 66 } while(0) 67 68 int stidebug = 1; 69 #else 70 #define DPRINTF(s) /* */ 71 #endif 72 73 void sti_cursor(void *, int, int, int); 74 int sti_mapchar(void *, int, u_int *); 75 void sti_putchar(void *, int, int, u_int, long); 76 void sti_copycols(void *, int, int, int, int); 77 void sti_erasecols(void *, int, int, int, long); 78 void sti_copyrows(void *, int, int, int); 79 void sti_eraserows(void *, int, int, long); 80 int sti_alloc_attr(void *, int, int, int, long *); 81 82 struct wsdisplay_emulops sti_emulops = { 83 sti_cursor, 84 sti_mapchar, 85 sti_putchar, 86 sti_copycols, 87 sti_erasecols, 88 sti_copyrows, 89 sti_eraserows, 90 sti_alloc_attr 91 }; 92 93 const struct wsdisplay_accessops sti_accessops = { 94 sti_ioctl, 95 sti_mmap, 96 sti_alloc_screen, 97 sti_free_screen, 98 sti_show_screen, 99 sti_load_font 100 }; 101 102 enum sti_bmove_funcs { 103 bmf_clear, bmf_copy, bmf_invert, bmf_underline 104 }; 105 106 int sti_init(struct sti_screen *, int); 107 #define STI_TEXTMODE 0x01 108 #define STI_CLEARSCR 0x02 109 int sti_inqcfg(struct sti_screen *, struct sti_inqconfout *); 110 void sti_bmove(struct sti_screen *, int, int, int, int, int, int, 111 enum sti_bmove_funcs); 112 int sti_setcment(struct sti_screen *, u_int, u_char, u_char, u_char); 113 114 struct sti_screen *sti_attach_screen(struct sti_softc *, int); 115 void sti_describe_screen(struct sti_softc *, struct sti_screen *); 116 117 int sti_fetchfonts(struct sti_screen *, struct sti_inqconfout *, uint32_t, 118 u_int); 119 void sti_region_setup(struct sti_screen *); 120 int sti_rom_setup(struct sti_rom *, bus_space_tag_t, bus_space_tag_t, 121 bus_space_handle_t, bus_addr_t *, u_int); 122 int sti_screen_setup(struct sti_screen *, int); 123 124 #if NSTI_PCI > 0 125 #define STI_ENABLE_ROM(sc) \ 126 do { \ 127 if ((sc) != NULL && (sc)->sc_enable_rom != NULL) \ 128 (*(sc)->sc_enable_rom)(sc); \ 129 } while (0) 130 #define STI_DISABLE_ROM(sc) \ 131 do { \ 132 if ((sc) != NULL && (sc)->sc_disable_rom != NULL) \ 133 (*(sc)->sc_disable_rom)(sc); \ 134 } while (0) 135 #else 136 #define STI_ENABLE_ROM(sc) do { /* nothing */ } while (0) 137 #define STI_DISABLE_ROM(sc) do { /* nothing */ } while (0) 138 #endif 139 140 /* Macros to read larger than 8 bit values from byte roms */ 141 #define parseshort(o) \ 142 ((bus_space_read_1(memt, romh, (o) + 3) << 8) | \ 143 (bus_space_read_1(memt, romh, (o) + 7))) 144 #define parseword(o) \ 145 ((bus_space_read_1(memt, romh, (o) + 3) << 24) | \ 146 (bus_space_read_1(memt, romh, (o) + 7) << 16) | \ 147 (bus_space_read_1(memt, romh, (o) + 11) << 8) | \ 148 (bus_space_read_1(memt, romh, (o) + 15))) 149 150 int 151 sti_attach_common(struct sti_softc *sc, bus_space_tag_t iot, 152 bus_space_tag_t memt, bus_space_handle_t romh, u_int codebase) 153 { 154 struct sti_rom *rom; 155 int rc; 156 157 rom = (struct sti_rom *)malloc(sizeof(*rom), M_DEVBUF, 158 M_NOWAIT | M_ZERO); 159 if (rom == NULL) { 160 aprint_error("cannot allocate rom data\n"); 161 return ENOMEM; 162 } 163 164 rom->rom_softc = sc; 165 rc = sti_rom_setup(rom, iot, memt, romh, sc->bases, codebase); 166 if (rc != 0) { 167 free(rom, M_DEVBUF); 168 return rc; 169 } 170 171 sc->sc_rom = rom; 172 173 sti_describe(sc); 174 175 sc->sc_scr = sti_attach_screen(sc, 176 sc->sc_flags & STI_CONSOLE ? 0 : STI_CLEARSCR); 177 if (sc->sc_scr == NULL) 178 rc = ENOMEM; 179 180 return rc; 181 } 182 183 struct sti_screen * 184 sti_attach_screen(struct sti_softc *sc, int flags) 185 { 186 struct sti_screen *scr; 187 int rc; 188 189 scr = (struct sti_screen *)malloc(sizeof(*scr), M_DEVBUF, 190 M_NOWAIT | M_ZERO); 191 if (scr == NULL) { 192 aprint_error("cannot allocate screen data\n"); 193 return NULL; 194 } 195 196 scr->scr_rom = sc->sc_rom; 197 rc = sti_screen_setup(scr, flags); 198 if (rc != 0) { 199 free(scr, M_DEVBUF); 200 return NULL; 201 } 202 203 sti_describe_screen(sc, scr); 204 205 return scr; 206 } 207 208 int 209 sti_rom_setup(struct sti_rom *rom, bus_space_tag_t iot, bus_space_tag_t memt, 210 bus_space_handle_t romh, bus_addr_t *bases, u_int codebase) 211 { 212 struct sti_dd *dd; 213 int error, size, i; 214 215 KASSERT(rom != NULL); 216 STI_ENABLE_ROM(rom->rom_softc); 217 218 rom->iot = iot; 219 rom->memt = memt; 220 rom->romh = romh; 221 rom->bases = bases; 222 223 /* 224 * Get ROM header and code function pointers. 225 */ 226 dd = &rom->rom_dd; 227 rom->rom_devtype = bus_space_read_1(memt, romh, 3); 228 if (rom->rom_devtype == STI_DEVTYPE1) { 229 dd->dd_type = bus_space_read_1(memt, romh, 0x03); 230 dd->dd_nmon = bus_space_read_1(memt, romh, 0x07); 231 dd->dd_grrev = bus_space_read_1(memt, romh, 0x0b); 232 dd->dd_lrrev = bus_space_read_1(memt, romh, 0x0f); 233 dd->dd_grid[0] = parseword(0x10); 234 dd->dd_grid[1] = parseword(0x20); 235 dd->dd_fntaddr = parseword(0x30) & ~3; 236 dd->dd_maxst = parseword(0x40); 237 dd->dd_romend = parseword(0x50) & ~3; 238 dd->dd_reglst = parseword(0x60) & ~3; 239 dd->dd_maxreent= parseshort(0x70); 240 dd->dd_maxtimo = parseshort(0x78); 241 dd->dd_montbl = parseword(0x80) & ~3; 242 dd->dd_udaddr = parseword(0x90) & ~3; 243 dd->dd_stimemreq=parseword(0xa0); 244 dd->dd_udsize = parseword(0xb0); 245 dd->dd_pwruse = parseshort(0xc0); 246 dd->dd_bussup = bus_space_read_1(memt, romh, 0xcb); 247 dd->dd_ebussup = bus_space_read_1(memt, romh, 0xcf); 248 dd->dd_altcodet= bus_space_read_1(memt, romh, 0xd3); 249 dd->dd_eddst[0]= bus_space_read_1(memt, romh, 0xd7); 250 dd->dd_eddst[1]= bus_space_read_1(memt, romh, 0xdb); 251 dd->dd_eddst[2]= bus_space_read_1(memt, romh, 0xdf); 252 dd->dd_cfbaddr = parseword(0xe0) & ~3; 253 254 codebase <<= 2; 255 dd->dd_pacode[0x0] = parseword(codebase + 0x00) & ~3; 256 dd->dd_pacode[0x1] = parseword(codebase + 0x10) & ~3; 257 dd->dd_pacode[0x2] = parseword(codebase + 0x20) & ~3; 258 dd->dd_pacode[0x3] = parseword(codebase + 0x30) & ~3; 259 dd->dd_pacode[0x4] = parseword(codebase + 0x40) & ~3; 260 dd->dd_pacode[0x5] = parseword(codebase + 0x50) & ~3; 261 dd->dd_pacode[0x6] = parseword(codebase + 0x60) & ~3; 262 dd->dd_pacode[0x7] = parseword(codebase + 0x70) & ~3; 263 dd->dd_pacode[0x8] = parseword(codebase + 0x80) & ~3; 264 dd->dd_pacode[0x9] = parseword(codebase + 0x90) & ~3; 265 dd->dd_pacode[0xa] = parseword(codebase + 0xa0) & ~3; 266 dd->dd_pacode[0xb] = parseword(codebase + 0xb0) & ~3; 267 dd->dd_pacode[0xc] = parseword(codebase + 0xc0) & ~3; 268 dd->dd_pacode[0xd] = parseword(codebase + 0xd0) & ~3; 269 dd->dd_pacode[0xe] = parseword(codebase + 0xe0) & ~3; 270 dd->dd_pacode[0xf] = parseword(codebase + 0xf0) & ~3; 271 } else { /* STI_DEVTYPE4 */ 272 bus_space_read_region_stream_4(memt, romh, 0, (uint32_t *)dd, 273 sizeof(*dd) / 4); 274 /* fix pacode... */ 275 bus_space_read_region_stream_4(memt, romh, codebase, 276 (uint32_t *)dd->dd_pacode, sizeof(dd->dd_pacode) / 4); 277 } 278 279 STI_DISABLE_ROM(rom->rom_softc); 280 281 DPRINTF(("dd:\n" 282 "devtype=%x, rev=%x;%d, altt=%x, gid=%08x%08x, font=%x, mss=%x\n" 283 "end=%x, regions=%x, msto=%x, timo=%d, mont=%x, user=%x[%x]\n" 284 "memrq=%x, pwr=%d, bus=%x, ebus=%x, cfb=%x\n" 285 "code=", 286 dd->dd_type & 0xff, dd->dd_grrev, dd->dd_lrrev, dd->dd_altcodet, 287 dd->dd_grid[0], dd->dd_grid[1], dd->dd_fntaddr, dd->dd_maxst, 288 dd->dd_romend, dd->dd_reglst, dd->dd_maxreent, dd->dd_maxtimo, 289 dd->dd_montbl, dd->dd_udaddr, dd->dd_udsize, dd->dd_stimemreq, 290 dd->dd_pwruse, dd->dd_bussup, dd->dd_ebussup, dd->dd_cfbaddr)); 291 DPRINTF(("%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x\n", 292 dd->dd_pacode[0x0], dd->dd_pacode[0x1], dd->dd_pacode[0x2], 293 dd->dd_pacode[0x3], dd->dd_pacode[0x4], dd->dd_pacode[0x5], 294 dd->dd_pacode[0x6], dd->dd_pacode[0x7], dd->dd_pacode[0x8], 295 dd->dd_pacode[0x9], dd->dd_pacode[0xa], dd->dd_pacode[0xb], 296 dd->dd_pacode[0xc], dd->dd_pacode[0xd], dd->dd_pacode[0xe], 297 dd->dd_pacode[0xf])); 298 299 /* 300 * Figure out how many bytes we need for the STI code. 301 * Note there could be fewer than STI_END pointer entries 302 * populated, especially on older devices. 303 */ 304 for (i = STI_END; !dd->dd_pacode[i]; i--) 305 ; 306 307 size = dd->dd_pacode[i] - dd->dd_pacode[STI_BEGIN]; 308 309 if (rom->rom_devtype == STI_DEVTYPE1) 310 size = (size + 3) / 4; 311 if (size == 0) { 312 aprint_error(": no code for the requested platform\n"); 313 return EINVAL; 314 } 315 316 DPRINTF(("code size %x/%x\n", size, round_page(size))); 317 318 if (!(rom->rom_code = uvm_km_alloc(kernel_map, round_page(size), 0, 319 UVM_KMF_WIRED))) { 320 aprint_error(": cannot allocate %u bytes for code\n", size); 321 return ENOMEM; 322 } 323 324 /* 325 * Copy code into memory and make it executable. 326 */ 327 328 STI_ENABLE_ROM(rom->rom_softc); 329 330 if (rom->rom_devtype == STI_DEVTYPE1) { 331 uint8_t *p; 332 uint32_t addr, eaddr; 333 334 p = (uint8_t *)rom->rom_code; 335 336 for (addr = dd->dd_pacode[STI_BEGIN], eaddr = addr + size * 4; 337 addr < eaddr; addr += 4 ) { 338 *p++ = bus_space_read_4(memt, romh, addr) 339 & 0xff; 340 } 341 } else { /* STI_DEVTYPE4 */ 342 bus_space_read_region_stream_4(memt, romh, 343 dd->dd_pacode[STI_BEGIN], (uint32_t *)rom->rom_code, 344 size / 4); 345 } 346 347 STI_DISABLE_ROM(rom->rom_softc); 348 349 if ((error = uvm_map_protect(kernel_map, rom->rom_code, 350 rom->rom_code + round_page(size), UVM_PROT_RX, FALSE))) { 351 aprint_error(": uvm_map_protect failed (%d)\n", error); 352 uvm_km_free(kernel_map, rom->rom_code, round_page(size), 353 UVM_KMF_WIRED); 354 return error; 355 } 356 357 /* 358 * Setup code function pointers. 359 */ 360 361 #define O(i) \ 362 (dd->dd_pacode[(i)] == 0 ? 0 : \ 363 (rom->rom_code + (dd->dd_pacode[(i)] - dd->dd_pacode[0]) / \ 364 (rom->rom_devtype == STI_DEVTYPE1 ? 4 : 1))) 365 rom->init = (sti_init_t) O(STI_INIT_GRAPH); 366 rom->mgmt = (sti_mgmt_t) O(STI_STATE_MGMT); 367 rom->unpmv = (sti_unpmv_t) O(STI_FONT_UNPMV); 368 rom->blkmv = (sti_blkmv_t) O(STI_BLOCK_MOVE); 369 rom->test = (sti_test_t) O(STI_SELF_TEST); 370 rom->exhdl = (sti_exhdl_t) O(STI_EXCEP_HDLR); 371 rom->inqconf = (sti_inqconf_t)O(STI_INQ_CONF); 372 rom->scment = (sti_scment_t)O(STI_SCM_ENT); 373 rom->dmac = (sti_dmac_t) O(STI_DMA_CTRL); 374 rom->flowc = (sti_flowc_t) O(STI_FLOW_CTRL); 375 rom->utiming = (sti_utiming_t)O(STI_UTIMING); 376 rom->pmgr = (sti_pmgr_t) O(STI_PROC_MGR); 377 rom->util = (sti_util_t) O(STI_UTIL); 378 379 #undef O 380 /* 381 * Set colormap entry is not implemented until 8.04, so force 382 * a NULL pointer here. 383 */ 384 385 if (dd->dd_grrev < STI_REVISION(8, 4)) { 386 rom->scment = NULL; 387 } 388 389 return 0; 390 } 391 392 /* 393 * Map all regions. 394 */ 395 void 396 sti_region_setup(struct sti_screen *scr) 397 { 398 struct sti_rom *rom = scr->scr_rom; 399 bus_space_tag_t memt = rom->memt; 400 bus_space_handle_t romh = rom->romh; 401 bus_addr_t *bases = rom->bases; 402 struct sti_dd *dd = &rom->rom_dd; 403 struct sti_cfg *cc = &scr->scr_cfg; 404 bus_space_handle_t bh; 405 struct sti_region regions[STI_REGION_MAX], *r; 406 u_int regno, regcnt; 407 bus_addr_t addr; 408 409 DPRINTF(("stiregions @ %x:\n", dd->dd_reglst)); 410 411 /* 412 * Read the region information. 413 */ 414 415 STI_ENABLE_ROM(rom->rom_softc); 416 417 if (rom->rom_devtype == STI_DEVTYPE1) { 418 for (regno = 0; regno < STI_REGION_MAX; regno++) 419 *(u_int *)(regions + regno) = 420 parseword(dd->dd_reglst + regno * 0x10); 421 } else { 422 bus_space_read_region_stream_4(memt, romh, dd->dd_reglst, 423 (uint32_t *)regions, sizeof(regions) / 4); 424 } 425 426 STI_DISABLE_ROM(rom->rom_softc); 427 428 /* 429 * Count them. 430 */ 431 432 for (regcnt = 0, r = regions; regcnt < STI_REGION_MAX; regcnt++, r++) 433 if (r->last) 434 break; 435 regcnt++; 436 437 /* 438 * Map them. 439 */ 440 441 for (regno = 0, r = regions; regno < regcnt; regno++, r++) { 442 if (r->length == 0) 443 continue; 444 445 /* 446 * Assume an existing mapping exists. 447 */ 448 addr = bases[regno] + (r->offset << PGSHIFT); 449 DPRINTF(("%08x @ 0x%08x%s%s%s%s", 450 r->length << PGSHIFT, (int)addr, r->sys_only ? " sys" : "", 451 r->cache ? " cache" : "", r->btlb ? " btlb" : "", 452 r->last ? " last" : "")); 453 454 /* 455 * Region #0 is always the rom, and it should have been 456 * mapped already. 457 * XXX This expects a 1:1 mapping... 458 */ 459 if (regno == 0 && romh == bases[0]) { 460 cc->regions[0] = addr; 461 DPRINTF(("\n")); 462 continue; 463 } 464 465 /* XXXNH BUS_SPACE_MAP_CACHEABLE */ 466 if (bus_space_map(memt, addr, r->length << PGSHIFT, 467 r->cache ? BUS_SPACE_MAP_CACHEABLE : 0, &bh)) { 468 DPRINTF((" - already mapped region\n")); 469 } else { 470 471 /* XXX should use bus_space_vaddr */ 472 addr = (bus_addr_t)bh; 473 if (regno == 1) { 474 DPRINTF((" - fb")); 475 scr->fbaddr = addr; 476 scr->fblen = r->length << PGSHIFT; 477 } 478 DPRINTF(("\n")); 479 } 480 481 cc->regions[regno] = addr; 482 } 483 484 #ifdef STIDEBUG 485 /* 486 * Make sure we'll trap accessing unmapped regions 487 */ 488 for (regno = 0; regno < STI_REGION_MAX; regno++) 489 if (cc->regions[regno] == 0) 490 cc->regions[regno] = 0x81234567; 491 #endif 492 } 493 494 int 495 sti_screen_setup(struct sti_screen *scr, int flags) 496 { 497 struct sti_rom *rom = scr->scr_rom; 498 bus_space_tag_t memt = rom->memt; 499 bus_space_handle_t romh = rom->romh; 500 struct sti_dd *dd = &rom->rom_dd; 501 struct sti_cfg *cc = &scr->scr_cfg; 502 struct sti_inqconfout cfg; 503 struct sti_einqconfout ecfg; 504 #ifdef STIDEBUG 505 char buf[256]; 506 #endif 507 int error, i; 508 int geometry_kluge = 0; 509 u_int fontindex = 0; 510 511 KASSERT(scr != NULL); 512 memset(cc, 0, sizeof(*cc)); 513 cc->ext_cfg = &scr->scr_ecfg; 514 memset(cc->ext_cfg, 0, sizeof(*cc->ext_cfg)); 515 516 if (dd->dd_stimemreq) { 517 scr->scr_ecfg.addr = 518 malloc(dd->dd_stimemreq, M_DEVBUF, M_NOWAIT); 519 if (!scr->scr_ecfg.addr) { 520 aprint_error("cannot allocate %d bytes for STI\n", 521 dd->dd_stimemreq); 522 return ENOMEM; 523 } 524 } 525 526 sti_region_setup(scr); 527 528 if ((error = sti_init(scr, 0))) { 529 aprint_error(": cannot initialize (%d)\n", error); 530 goto fail; 531 } 532 533 memset(&cfg, 0, sizeof(cfg)); 534 memset(&ecfg, 0, sizeof(ecfg)); 535 cfg.ext = &ecfg; 536 if ((error = sti_inqcfg(scr, &cfg))) { 537 aprint_error(": error %d inquiring config\n", error); 538 goto fail; 539 } 540 541 /* 542 * Older (rev 8.02) boards report wrong offset values, 543 * similar to the displayable area size, at least in m68k mode. 544 * Attempt to detect this and adjust here. 545 */ 546 if (cfg.owidth == cfg.width && 547 cfg.oheight == cfg.height) 548 geometry_kluge = 1; 549 550 if (geometry_kluge) { 551 scr->scr_cfg.oscr_width = cfg.owidth = 552 cfg.fbwidth - cfg.width; 553 scr->scr_cfg.oscr_height = cfg.oheight = 554 cfg.fbheight - cfg.height; 555 } 556 557 /* 558 * Save a few fields for sti_describe_screen() later 559 */ 560 scr->fbheight = cfg.fbheight; 561 scr->fbwidth = cfg.fbwidth; 562 scr->oheight = cfg.oheight; 563 scr->owidth = cfg.owidth; 564 memcpy(scr->name, cfg.name, sizeof(scr->name)); 565 566 if ((error = sti_init(scr, STI_TEXTMODE | flags))) { 567 aprint_error(": cannot initialize (%d)\n", error); 568 goto fail; 569 } 570 #ifdef STIDEBUG 571 snprintb(buf, sizeof(buf), STI_INQCONF_BITS, cfg.attributes); 572 DPRINTF(("conf: bpp=%d planes=%d attr=%s\n" 573 "crt=0x%x:0x%x:0x%x hw=0x%x:0x%x:0x%x\n", cfg.bpp, 574 cfg.planes, buf, 575 ecfg.crt_config[0], ecfg.crt_config[1], ecfg.crt_config[2], 576 ecfg.crt_hw[0], ecfg.crt_hw[1], ecfg.crt_hw[2])); 577 #endif 578 scr->scr_bpp = cfg.bppu; 579 580 /* 581 * Although scr->scr_ecfg.current_monitor is not filled by 582 * sti_init() as expected, we can nevertheless walk the monitor 583 * list, if there is any, and if we find a mode matching our 584 * resolution, pick its font index. 585 */ 586 if (dd->dd_montbl != 0) { 587 STI_ENABLE_ROM(rom->rom_softc); 588 589 for (i = 0; i < dd->dd_nmon; i++) { 590 u_int offs = dd->dd_montbl + 8 * i; 591 uint32_t m[2]; 592 sti_mon_t mon = (void *)m; 593 if (rom->rom_devtype == STI_DEVTYPE1) { 594 m[0] = parseword(4 * offs); 595 m[1] = parseword(4 * (offs + 4)); 596 } else { 597 bus_space_read_region_stream_4(memt, romh, offs, 598 (uint32_t *)mon, sizeof(*mon) / 4); 599 } 600 601 if (mon->width == scr->scr_cfg.scr_width && 602 mon->height == scr->scr_cfg.scr_height) { 603 fontindex = mon->font; 604 break; 605 } 606 } 607 608 STI_DISABLE_ROM(rom->rom_softc); 609 610 DPRINTF(("font index: %d\n", fontindex)); 611 } 612 613 if ((error = sti_fetchfonts(scr, &cfg, dd->dd_fntaddr, fontindex))) { 614 aprint_error(": cannot fetch fonts (%d)\n", error); 615 goto fail; 616 } 617 618 /* 619 * setup screen descriptions: 620 * figure number of fonts supported; 621 * allocate wscons structures; 622 * calculate dimensions. 623 */ 624 625 scr->scr_wsd.name = "std"; 626 scr->scr_wsd.ncols = cfg.width / scr->scr_curfont.width; 627 scr->scr_wsd.nrows = cfg.height / scr->scr_curfont.height; 628 scr->scr_wsd.textops = &sti_emulops; 629 scr->scr_wsd.fontwidth = scr->scr_curfont.width; 630 scr->scr_wsd.fontheight = scr->scr_curfont.height; 631 scr->scr_wsd.capabilities = WSSCREEN_REVERSE | WSSCREEN_UNDERLINE; 632 633 scr->scr_scrlist[0] = &scr->scr_wsd; 634 scr->scr_screenlist.nscreens = 1; 635 scr->scr_screenlist.screens = scr->scr_scrlist; 636 637 return 0; 638 639 fail: 640 /* XXX free resources */ 641 if (scr->scr_ecfg.addr != NULL) { 642 free(scr->scr_ecfg.addr, M_DEVBUF); 643 scr->scr_ecfg.addr = NULL; 644 } 645 646 return ENXIO; 647 } 648 649 void 650 sti_describe_screen(struct sti_softc *sc, struct sti_screen *scr) 651 { 652 struct sti_font *fp = &scr->scr_curfont; 653 654 aprint_normal("%s: %s, %dx%d frame buffer, %dx%dx%d display\n", 655 device_xname(sc->sc_dev), scr->name, scr->fbwidth, scr->fbheight, 656 scr->scr_cfg.scr_width, scr->scr_cfg.scr_height, scr->scr_bpp); 657 658 aprint_normal("%s: %dx%d font type %d, %d bpc, charset %d-%d\n", 659 device_xname(sc->sc_dev), fp->width, fp->height, 660 fp->type, fp->bpc, fp->first, fp->last); 661 } 662 663 void 664 sti_describe(struct sti_softc *sc) 665 { 666 struct sti_rom *rom = sc->sc_rom; 667 struct sti_dd *dd = &rom->rom_dd; 668 669 aprint_normal(": rev %d.%02d;%d, ID 0x%08X%08X\n", 670 dd->dd_grrev >> 4, dd->dd_grrev & 0xf, 671 dd->dd_lrrev, dd->dd_grid[0], dd->dd_grid[1]); 672 673 if (sc->sc_scr != NULL) 674 sti_describe_screen(sc, sc->sc_scr); 675 } 676 677 void 678 sti_end_attach(struct sti_softc *sc) 679 { 680 struct sti_screen *scr = sc->sc_scr; 681 682 if (scr == NULL) 683 return; 684 #if NWSDISPLAY > 0 685 else { 686 struct wsemuldisplaydev_attach_args waa; 687 scr->scr_wsmode = WSDISPLAYIO_MODE_EMUL; 688 689 waa.console = sc->sc_flags & STI_CONSOLE ? 1 : 0; 690 waa.scrdata = &scr->scr_screenlist; 691 waa.accessops = &sti_accessops; 692 waa.accesscookie = scr; 693 694 /* attach as console if required */ 695 if (waa.console && !ISSET(sc->sc_flags, STI_ATTACHED)) { 696 long defattr; 697 698 sti_alloc_attr(scr, 0, 0, 0, &defattr); 699 wsdisplay_cnattach(&scr->scr_wsd, scr, 700 0, scr->scr_wsd.nrows - 1, defattr); 701 sc->sc_flags |= STI_ATTACHED; 702 } 703 704 config_found(sc->sc_dev, &waa, wsemuldisplaydevprint); 705 } 706 #endif 707 } 708 709 u_int 710 sti_rom_size(bus_space_tag_t memt, bus_space_handle_t romh) 711 { 712 int devtype; 713 u_int romend; 714 715 devtype = bus_space_read_1(memt, romh, 3); 716 if (devtype == STI_DEVTYPE4) { 717 bus_space_read_region_stream_4(memt, romh, STI_DEV4_DD_ROMEND, 718 (uint32_t *)&romend, 1); 719 } else { 720 romend = parseword(STI_DEV1_DD_ROMEND); 721 } 722 723 DPRINTF(("%s: %08x (%08x)\n", __func__, romend, round_page(romend))); 724 725 return round_page(romend); 726 } 727 728 int 729 sti_fetchfonts(struct sti_screen *scr, struct sti_inqconfout *cfg, 730 uint32_t baseaddr, u_int fontindex) 731 { 732 struct sti_rom *rom = scr->scr_rom; 733 bus_space_tag_t memt = rom->memt; 734 bus_space_handle_t romh = rom->romh; 735 struct sti_font *fp = &scr->scr_curfont; 736 uint32_t addr; 737 int size; 738 #ifdef notyet 739 int uc; 740 struct { 741 struct sti_unpmvflags flags; 742 struct sti_unpmvin in; 743 struct sti_unpmvout out; 744 } a; 745 #endif 746 747 /* 748 * Get the first PROM font in memory 749 */ 750 751 STI_ENABLE_ROM(rom->rom_softc); 752 753 rescan: 754 addr = baseaddr; 755 do { 756 if (rom->rom_devtype == STI_DEVTYPE1) { 757 fp->first = parseshort(addr + 0x00); 758 fp->last = parseshort(addr + 0x08); 759 fp->width = bus_space_read_1(memt, romh, addr + 0x13); 760 fp->height = bus_space_read_1(memt, romh, addr + 0x17); 761 fp->type = bus_space_read_1(memt, romh, addr + 0x1b); 762 fp->bpc = bus_space_read_1(memt, romh, addr + 0x1f); 763 fp->next = parseword(addr + 0x20); 764 fp->uheight= bus_space_read_1(memt, romh, addr + 0x33); 765 fp->uoffset= bus_space_read_1(memt, romh, addr + 0x37); 766 } else { /* STI_DEVTYPE4 */ 767 bus_space_read_region_stream_4(memt, romh, addr, 768 (uint32_t *)fp, sizeof(struct sti_font) / 4); 769 } 770 771 #ifdef STIDEBUG 772 STI_DISABLE_ROM(rom->rom_softc); 773 DPRINTF(("%s: %dx%d font type %d, %d bpc, charset %d-%d\n", 774 device_xname(scr->scr_rom->rom_softc->sc_dev), fp->width, 775 fp->height, fp->type, fp->bpc, fp->first, fp->last)); 776 STI_ENABLE_ROM(rom->rom_softc); 777 #endif 778 779 if (fontindex == 0) { 780 size = sizeof(struct sti_font) + 781 (fp->last - fp->first + 1) * fp->bpc; 782 if (rom->rom_devtype == STI_DEVTYPE1) 783 size *= 4; 784 scr->scr_romfont = malloc(size, M_DEVBUF, M_NOWAIT); 785 if (scr->scr_romfont == NULL) 786 return ENOMEM; 787 788 bus_space_read_region_stream_4(memt, romh, addr, 789 (uint32_t *)scr->scr_romfont, size / 4); 790 break; 791 } 792 793 addr = baseaddr + fp->next; 794 fontindex--; 795 } while (fp->next != 0); 796 797 /* 798 * If our font index was bogus, we did not find the expected font. 799 * In this case, pick the first one and be done with it. 800 */ 801 if (fp->next == 0 && scr->scr_romfont == NULL) { 802 fontindex = 0; 803 goto rescan; 804 } 805 806 STI_DISABLE_ROM(rom->rom_softc); 807 808 #ifdef notyet 809 /* 810 * If there is enough room in the off-screen framebuffer memory, 811 * display all the characters there in order to display them 812 * faster with blkmv operations rather than unpmv later on. 813 */ 814 if (size <= cfg->fbheight * 815 (cfg->fbwidth - cfg->width - cfg->owidth)) { 816 memset(&a, 0, sizeof(a)); 817 a.flags.flags = STI_UNPMVF_WAIT; 818 a.in.fg_colour = STI_COLOUR_WHITE; 819 a.in.bg_colour = STI_COLOUR_BLACK; 820 a.in.font_addr = scr->scr_romfont; 821 822 scr->scr_fontmaxcol = cfg->fbheight / fp->height; 823 scr->scr_fontbase = cfg->width + cfg->owidth; 824 for (uc = fp->first; uc <= fp->last; uc++) { 825 a.in.x = ((uc - fp->first) / scr->scr_fontmaxcol) * 826 fp->width + scr->scr_fontbase; 827 a.in.y = ((uc - fp->first) % scr->scr_fontmaxcol) * 828 fp->height; 829 a.in.index = uc; 830 831 (*scr->unpmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg); 832 if (a.out.errno) { 833 aprint_error_dev(sc->sc_dev, "unpmv %d " 834 "returned %d\n", uc, a.out.errno); 835 return 0; 836 } 837 } 838 839 free(scr->scr_romfont, M_DEVBUF); 840 scr->scr_romfont = NULL; 841 } 842 #endif 843 844 return 0; 845 } 846 847 /* 848 * Wrappers around STI code pointers 849 */ 850 int 851 sti_init(struct sti_screen *scr, int mode) 852 { 853 struct sti_rom *rom = scr->scr_rom; 854 struct { 855 struct sti_initflags flags; 856 struct sti_initin in; 857 struct sti_einitin ein; 858 struct sti_initout out; 859 } a; 860 861 KASSERT(rom != NULL); 862 memset(&a, 0, sizeof(a)); 863 864 a.flags.flags = STI_INITF_WAIT | STI_INITF_CMB | STI_INITF_EBET | 865 (mode & STI_TEXTMODE ? STI_INITF_TEXT | STI_INITF_PBET | 866 STI_INITF_PBETI | STI_INITF_ICMT : 0) | 867 (mode & STI_CLEARSCR ? STI_INITF_CLEAR : 0); 868 a.in.text_planes = 1; 869 a.in.ext_in = &a.ein; 870 871 DPRINTF(("%s: init,%p(%x, %p, %p, %p)\n", 872 device_xname(rom->rom_softc->sc_dev), rom->init, a.flags.flags, 873 &a.in, &a.out, &scr->scr_cfg)); 874 875 (*rom->init)(&a.flags, &a.in, &a.out, &scr->scr_cfg); 876 877 if (a.out.text_planes != a.in.text_planes) 878 return -1; /* not colliding with sti errno values */ 879 return a.out.errno; 880 } 881 882 int 883 sti_inqcfg(struct sti_screen *scr, struct sti_inqconfout *out) 884 { 885 struct sti_rom *rom = scr->scr_rom; 886 struct { 887 struct sti_inqconfflags flags; 888 struct sti_inqconfin in; 889 } a; 890 891 memset(&a, 0, sizeof(a)); 892 893 a.flags.flags = STI_INQCONFF_WAIT; 894 (*rom->inqconf)(&a.flags, &a.in, out, &scr->scr_cfg); 895 896 return out->errno; 897 } 898 899 void 900 sti_bmove(struct sti_screen *scr, int x1, int y1, int x2, int y2, int h, int w, 901 enum sti_bmove_funcs f) 902 { 903 struct sti_rom *rom = scr->scr_rom; 904 struct { 905 struct sti_blkmvflags flags; 906 struct sti_blkmvin in; 907 struct sti_blkmvout out; 908 } a; 909 910 memset(&a, 0, sizeof(a)); 911 912 a.flags.flags = STI_BLKMVF_WAIT; 913 switch (f) { 914 case bmf_clear: 915 a.flags.flags |= STI_BLKMVF_CLR; 916 a.in.bg_colour = STI_COLOUR_BLACK; 917 break; 918 case bmf_underline: 919 case bmf_copy: 920 a.in.fg_colour = STI_COLOUR_WHITE; 921 a.in.bg_colour = STI_COLOUR_BLACK; 922 break; 923 case bmf_invert: 924 a.flags.flags |= STI_BLKMVF_COLR; 925 a.in.fg_colour = STI_COLOUR_BLACK; 926 a.in.bg_colour = STI_COLOUR_WHITE; 927 break; 928 } 929 a.in.srcx = x1; 930 a.in.srcy = y1; 931 a.in.dstx = x2; 932 a.in.dsty = y2; 933 a.in.height = h; 934 a.in.width = w; 935 936 (*rom->blkmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg); 937 #ifdef STIDEBUG 938 if (a.out.errno) 939 printf("%s: blkmv returned %d\n", 940 device_xname(rom->rom_softc->sc_dev), a.out.errno); 941 #endif 942 } 943 944 int 945 sti_setcment(struct sti_screen *scr, u_int i, u_char r, u_char g, u_char b) 946 { 947 struct sti_rom *rom = scr->scr_rom; 948 struct { 949 struct sti_scmentflags flags; 950 struct sti_scmentin in; 951 struct sti_scmentout out; 952 } a; 953 954 memset(&a, 0, sizeof(a)); 955 956 a.flags.flags = STI_SCMENTF_WAIT; 957 a.in.entry = i; 958 a.in.value = (r << 16) | (g << 8) | b; 959 960 (*rom->scment)(&a.flags, &a.in, &a.out, &scr->scr_cfg); 961 962 return a.out.errno; 963 } 964 965 /* 966 * wsdisplay accessops 967 */ 968 int 969 sti_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l) 970 { 971 struct sti_screen *scr = (struct sti_screen *)v; 972 struct sti_rom *rom = scr->scr_rom; 973 struct wsdisplay_fbinfo *wdf; 974 struct wsdisplay_cmap *cmapp; 975 u_int mode, idx, count; 976 int i, ret; 977 978 ret = 0; 979 switch (cmd) { 980 case WSDISPLAYIO_GMODE: 981 *(u_int *)data = scr->scr_wsmode; 982 break; 983 984 case WSDISPLAYIO_SMODE: 985 mode = *(u_int *)data; 986 if (scr->scr_wsmode == WSDISPLAYIO_MODE_EMUL && 987 mode == WSDISPLAYIO_MODE_DUMBFB) 988 ret = sti_init(scr, 0); 989 else if (scr->scr_wsmode == WSDISPLAYIO_MODE_DUMBFB && 990 mode == WSDISPLAYIO_MODE_EMUL) 991 ret = sti_init(scr, STI_TEXTMODE); 992 scr->scr_wsmode = mode; 993 break; 994 995 case WSDISPLAYIO_GTYPE: 996 *(u_int *)data = WSDISPLAY_TYPE_STI; 997 break; 998 999 case WSDISPLAYIO_GINFO: 1000 wdf = (struct wsdisplay_fbinfo *)data; 1001 wdf->height = scr->scr_cfg.scr_height; 1002 wdf->width = scr->scr_cfg.scr_width; 1003 wdf->depth = scr->scr_bpp; 1004 if (rom->scment == NULL) 1005 wdf->cmsize = 0; 1006 else 1007 wdf->cmsize = STI_NCMAP; 1008 break; 1009 1010 case WSDISPLAYIO_LINEBYTES: 1011 *(u_int *)data = scr->scr_cfg.fb_width; 1012 break; 1013 1014 case WSDISPLAYIO_GETCMAP: 1015 if (rom->scment == NULL) 1016 return ENOTTY; 1017 cmapp = (struct wsdisplay_cmap *)data; 1018 idx = cmapp->index; 1019 count = cmapp->count; 1020 if (idx >= STI_NCMAP || idx + count > STI_NCMAP) 1021 return EINVAL; 1022 if ((ret = copyout(&scr->scr_rcmap[idx], cmapp->red, count))) 1023 break; 1024 if ((ret = copyout(&scr->scr_gcmap[idx], cmapp->green, count))) 1025 break; 1026 if ((ret = copyout(&scr->scr_bcmap[idx], cmapp->blue, count))) 1027 break; 1028 break; 1029 1030 case WSDISPLAYIO_PUTCMAP: 1031 if (rom->scment == NULL) 1032 return ENOTTY; 1033 cmapp = (struct wsdisplay_cmap *)data; 1034 idx = cmapp->index; 1035 count = cmapp->count; 1036 if (idx >= STI_NCMAP || idx + count > STI_NCMAP) 1037 return EINVAL; 1038 if ((ret = copyin(cmapp->red, &scr->scr_rcmap[idx], count))) 1039 break; 1040 if ((ret = copyin(cmapp->green, &scr->scr_gcmap[idx], count))) 1041 break; 1042 if ((ret = copyin(cmapp->blue, &scr->scr_bcmap[idx], count))) 1043 break; 1044 for (i = idx + count - 1; i >= idx; i--) 1045 if ((ret = sti_setcment(scr, i, scr->scr_rcmap[i], 1046 scr->scr_gcmap[i], scr->scr_bcmap[i]))) { 1047 1048 DPRINTF(("sti_ioctl: " 1049 "sti_setcment(%d, %u, %u, %u): %%d\n", i, 1050 (u_int)scr->scr_rcmap[i], 1051 (u_int)scr->scr_gcmap[i], 1052 (u_int)scr->scr_bcmap[i])); 1053 1054 ret = EINVAL; 1055 break; 1056 } 1057 break; 1058 1059 case WSDISPLAYIO_SVIDEO: 1060 case WSDISPLAYIO_GVIDEO: 1061 case WSDISPLAYIO_GCURPOS: 1062 case WSDISPLAYIO_SCURPOS: 1063 case WSDISPLAYIO_GCURMAX: 1064 case WSDISPLAYIO_GCURSOR: 1065 case WSDISPLAYIO_SCURSOR: 1066 default: 1067 return ENOTTY; /* not supported yet */ 1068 } 1069 1070 return ret; 1071 } 1072 1073 paddr_t 1074 sti_mmap(void *v, void *vs, off_t offset, int prot) 1075 { 1076 #if 0 1077 struct sti_screen *scr = (struct sti_screen *)v; 1078 #endif 1079 /* XXX not finished */ 1080 return -1; 1081 } 1082 1083 int 1084 sti_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep, 1085 int *cxp, int *cyp, long *defattr) 1086 { 1087 struct sti_screen *scr = (struct sti_screen *)v; 1088 1089 if (scr->scr_nscreens > 0) 1090 return ENOMEM; 1091 1092 *cookiep = scr; 1093 *cxp = 0; 1094 *cyp = 0; 1095 sti_alloc_attr(scr, 0, 0, 0, defattr); 1096 scr->scr_nscreens++; 1097 1098 return 0; 1099 } 1100 1101 void 1102 sti_free_screen(void *v, void *cookie) 1103 { 1104 struct sti_screen *scr = (struct sti_screen *)v; 1105 1106 scr->scr_nscreens--; 1107 } 1108 1109 int 1110 sti_show_screen(void *v, void *cookie, int waitok, void (*cb)(void *, int, int), 1111 void *cbarg) 1112 { 1113 #if 0 1114 struct sti_screen *scr = (struct sti_screen *)v; 1115 #endif 1116 1117 return 0; 1118 } 1119 1120 int 1121 sti_load_font(void *v, void *cookie, struct wsdisplay_font *font) 1122 { 1123 #if 0 1124 struct sti_screen *scr = (struct sti_screen *)v; 1125 #endif 1126 1127 return -1; 1128 } 1129 1130 /* 1131 * wsdisplay emulops 1132 */ 1133 void 1134 sti_cursor(void *v, int on, int row, int col) 1135 { 1136 struct sti_screen *scr = (struct sti_screen *)v; 1137 struct sti_font *fp = &scr->scr_curfont; 1138 1139 sti_bmove(scr, col * fp->width, row * fp->height, col * fp->width, 1140 row * fp->height, fp->height, fp->width, bmf_invert); 1141 } 1142 1143 /* 1144 * ISO 8859-1 part of Unicode to HP Roman font index conversion array. 1145 */ 1146 static const uint8_t 1147 sti_unitoroman[0x100 - 0xa0] = { 1148 0xa0, 0xb8, 0xbf, 0xbb, 0xba, 0xbc, 0, 0xbd, 1149 0xab, 0, 0xf9, 0xfb, 0, 0xf6, 0, 0xb0, 1150 1151 0xb3, 0xfe, 0, 0, 0xa8, 0xf3, 0xf4, 0xf2, 1152 0, 0, 0xfa, 0xfd, 0xf7, 0xf8, 0, 0xb9, 1153 1154 0xa1, 0xe0, 0xa2, 0xe1, 0xd8, 0xd0, 0xd3, 0xb4, 1155 0xa3, 0xdc, 0xa4, 0xa5, 0xe6, 0xe5, 0xa6, 0xa7, 1156 1157 0xe3, 0xb6, 0xe8, 0xe7, 0xdf, 0xe9, 0xda, 0, 1158 0xd2, 0xad, 0xed, 0xae, 0xdb, 0xb1, 0xf0, 0xde, 1159 1160 0xc8, 0xc4, 0xc0, 0xe2, 0xcc, 0xd4, 0xd7, 0xb5, 1161 0xc9, 0xc5, 0xc1, 0xcd, 0xd9, 0xd5, 0xd1, 0xdd, 1162 1163 0xe4, 0xb7, 0xca, 0xc6, 0xc2, 0xea, 0xce, 0, 1164 0xd6, 0xcb, 0xc7, 0xc3, 0xcf, 0xb2, 0xf1, 0xef 1165 }; 1166 1167 int 1168 sti_mapchar(void *v, int uni, u_int *index) 1169 { 1170 struct sti_screen *scr = (struct sti_screen *)v; 1171 struct sti_font *fp = &scr->scr_curfont; 1172 int c; 1173 1174 switch (fp->type) { 1175 case STI_FONT_HPROMAN8: 1176 if (uni >= 0x80 && uni < 0xa0) 1177 c = -1; 1178 else if (uni >= 0xa0 && uni < 0x100) { 1179 c = (int)sti_unitoroman[uni - 0xa0]; 1180 if (c == 0) 1181 c = -1; 1182 } else 1183 c = uni; 1184 break; 1185 default: 1186 c = uni; 1187 break; 1188 } 1189 1190 if (c == -1 || c < fp->first || c > fp->last) { 1191 *index = ' '; 1192 return 0; 1193 } 1194 1195 *index = c; 1196 return 5; 1197 } 1198 1199 void 1200 sti_putchar(void *v, int row, int col, u_int uc, long attr) 1201 { 1202 struct sti_screen *scr = (struct sti_screen *)v; 1203 struct sti_rom *rom = scr->scr_rom; 1204 struct sti_font *fp = &scr->scr_curfont; 1205 1206 if (scr->scr_romfont != NULL) { 1207 /* 1208 * Font is in memory, use unpmv 1209 */ 1210 struct { 1211 struct sti_unpmvflags flags; 1212 struct sti_unpmvin in; 1213 struct sti_unpmvout out; 1214 } a; 1215 1216 memset(&a, 0, sizeof(a)); 1217 1218 a.flags.flags = STI_UNPMVF_WAIT; 1219 /* XXX does not handle text attributes */ 1220 a.in.fg_colour = STI_COLOUR_WHITE; 1221 a.in.bg_colour = STI_COLOUR_BLACK; 1222 a.in.x = col * fp->width; 1223 a.in.y = row * fp->height; 1224 a.in.font_addr = scr->scr_romfont; 1225 a.in.index = uc; 1226 1227 (*rom->unpmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg); 1228 } else { 1229 /* 1230 * Font is in frame buffer, use blkmv 1231 */ 1232 struct { 1233 struct sti_blkmvflags flags; 1234 struct sti_blkmvin in; 1235 struct sti_blkmvout out; 1236 } a; 1237 1238 memset(&a, 0, sizeof(a)); 1239 1240 a.flags.flags = STI_BLKMVF_WAIT; 1241 /* XXX does not handle text attributes */ 1242 a.in.fg_colour = STI_COLOUR_WHITE; 1243 a.in.bg_colour = STI_COLOUR_BLACK; 1244 1245 a.in.srcx = ((uc - fp->first) / scr->scr_fontmaxcol) * 1246 fp->width + scr->scr_fontbase; 1247 a.in.srcy = ((uc - fp->first) % scr->scr_fontmaxcol) * 1248 fp->height; 1249 a.in.dstx = col * fp->width; 1250 a.in.dsty = row * fp->height; 1251 a.in.height = fp->height; 1252 a.in.width = fp->width; 1253 1254 (*rom->blkmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg); 1255 } 1256 } 1257 1258 void 1259 sti_copycols(void *v, int row, int srccol, int dstcol, int ncols) 1260 { 1261 struct sti_screen *scr = (struct sti_screen *)v; 1262 struct sti_font *fp = &scr->scr_curfont; 1263 1264 sti_bmove(scr, srccol * fp->width, row * fp->height, dstcol * fp->width, 1265 row * fp->height, fp->height, ncols * fp->width, bmf_copy); 1266 } 1267 1268 void 1269 sti_erasecols(void *v, int row, int startcol, int ncols, long attr) 1270 { 1271 struct sti_screen *scr = (struct sti_screen *)v; 1272 struct sti_font *fp = &scr->scr_curfont; 1273 1274 sti_bmove(scr, startcol * fp->width, row * fp->height, 1275 startcol * fp->width, row * fp->height, fp->height, 1276 ncols * fp->width, bmf_clear); 1277 } 1278 1279 void 1280 sti_copyrows(void *v, int srcrow, int dstrow, int nrows) 1281 { 1282 struct sti_screen *scr = (struct sti_screen *)v; 1283 struct sti_font *fp = &scr->scr_curfont; 1284 1285 sti_bmove(scr, 0, srcrow * fp->height, 0, dstrow * fp->height, 1286 nrows * fp->height, scr->scr_cfg.scr_width, bmf_copy); 1287 } 1288 1289 void 1290 sti_eraserows(void *v, int srcrow, int nrows, long attr) 1291 { 1292 struct sti_screen *scr = (struct sti_screen *)v; 1293 struct sti_font *fp = &scr->scr_curfont; 1294 1295 sti_bmove(scr, 0, srcrow * fp->height, 0, srcrow * fp->height, 1296 nrows * fp->height, scr->scr_cfg.scr_width, bmf_clear); 1297 } 1298 1299 int 1300 sti_alloc_attr(void *v, int fg, int bg, int flags, long *pattr) 1301 { 1302 #if 0 1303 struct sti_screen *scr = (struct sti_screen *)v; 1304 #endif 1305 1306 *pattr = 0; 1307 1308 return 0; 1309 } 1310 1311 #ifdef hp300 /* XXX */ 1312 /* 1313 * Early console support. Only used on hp300. 1314 */ 1315 int 1316 sti_cnattach(struct sti_rom *rom, struct sti_screen *scr, bus_space_tag_t memt, 1317 bus_addr_t *bases, u_int codebase) 1318 { 1319 bus_space_handle_t romh; 1320 u_int romend; 1321 int error; 1322 long defattr; 1323 1324 if ((error = bus_space_map(memt, bases[0], PAGE_SIZE, 0, &romh)) != 0) 1325 return error; 1326 1327 /* 1328 * Compute real PROM size 1329 */ 1330 romend = sti_rom_size(memt, romh); 1331 1332 bus_space_unmap(memt, romh, PAGE_SIZE); 1333 1334 if ((error = bus_space_map(memt, bases[0], romend, 0, &romh)) != 0) 1335 return error; 1336 1337 bases[0] = romh; 1338 if (sti_rom_setup(rom, memt, memt, romh, bases, codebase) != 0) 1339 return -1; 1340 scr->scr_rom = rom; 1341 if (sti_screen_setup(scr, STI_CLEARSCR) != 0) 1342 return -1; 1343 1344 sti_alloc_attr(scr, 0, 0, 0, &defattr); 1345 wsdisplay_cnattach(&scr->scr_wsd, scr, 0, 0, defattr); 1346 1347 return 0; 1348 } 1349 #endif 1350