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