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