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 68int stidebug = 1; 69#else 70#define DPRINTF(s) /* */ 71#endif 72 73void sti_cursor(void *, int, int, int); 74int sti_mapchar(void *, int, u_int *); 75void sti_putchar(void *, int, int, u_int, long); 76void sti_copycols(void *, int, int, int, int); 77void sti_erasecols(void *, int, int, int, long); 78void sti_copyrows(void *, int, int, int); 79void sti_eraserows(void *, int, int, long); 80int sti_alloc_attr(void *, int, int, int, long *); 81 82struct 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 93int sti_ioctl(void *, void *, u_long, void *, int, struct lwp *); 94paddr_t sti_mmap(void *, void *, off_t, int); 95int sti_alloc_screen(void *, const struct wsscreen_descr *, 96 void **, int *, int *, long *); 97 void sti_free_screen(void *, void *); 98int sti_show_screen(void *, void *, int, void (*cb)(void *, int, int), void *); 99int sti_load_font(void *, void *, struct wsdisplay_font *); 100 101const 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 110enum sti_bmove_funcs { 111 bmf_clear, bmf_copy, bmf_invert, bmf_underline 112}; 113 114int sti_init(struct sti_screen *, int); 115#define STI_TEXTMODE 0x01 116#define STI_CLEARSCR 0x02 117int sti_inqcfg(struct sti_screen *, struct sti_inqconfout *); 118void sti_bmove(struct sti_screen *, int, int, int, int, int, int, 119 enum sti_bmove_funcs); 120int sti_setcment(struct sti_screen *, u_int, u_char, u_char, u_char); 121 122struct sti_screen *sti_attach_screen(struct sti_softc *, int); 123void sti_describe_screen(struct sti_softc *, struct sti_screen *); 124 125int sti_fetchfonts(struct sti_screen *, struct sti_inqconfout *, uint32_t, 126 u_int); 127void sti_region_setup(struct sti_screen *); 128int sti_rom_setup(struct sti_rom *, bus_space_tag_t, bus_space_tag_t, 129 bus_space_handle_t, bus_addr_t *, u_int); 130int sti_screen_setup(struct sti_screen *, int); 131 132#if NSTI_PCI > 0 133#define STI_ENABLE_ROM(sc) \ 134do { \ 135 if ((sc) != NULL && (sc)->sc_enable_rom != NULL) \ 136 (*(sc)->sc_enable_rom)(sc); \ 137} while (0) 138#define STI_DISABLE_ROM(sc) \ 139do { \ 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 158int 159sti_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 191struct sti_screen * 192sti_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 216int 217sti_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 */ 403void 404sti_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 502int 503sti_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 = scr->scr_scrlist; 644 645 return 0; 646 647fail: 648 /* XXX free resources */ 649 if (scr->scr_ecfg.addr != NULL) { 650 free(scr->scr_ecfg.addr, M_DEVBUF); 651 scr->scr_ecfg.addr = NULL; 652 } 653 654 return ENXIO; 655} 656 657void 658sti_describe_screen(struct sti_softc *sc, struct sti_screen *scr) 659{ 660 struct sti_font *fp = &scr->scr_curfont; 661 662 aprint_normal("%s: %s, %dx%d frame buffer, %dx%dx%d display\n", 663 device_xname(sc->sc_dev), scr->name, scr->fbwidth, scr->fbheight, 664 scr->scr_cfg.scr_width, scr->scr_cfg.scr_height, scr->scr_bpp); 665 666 aprint_normal("%s: %dx%d font type %d, %d bpc, charset %d-%d\n", 667 device_xname(sc->sc_dev), fp->width, fp->height, 668 fp->type, fp->bpc, fp->first, fp->last); 669} 670 671void 672sti_describe(struct sti_softc *sc) 673{ 674 struct sti_rom *rom = sc->sc_rom; 675 struct sti_dd *dd = &rom->rom_dd; 676 677 aprint_normal(": rev %d.%02d;%d, ID 0x%08X%08X\n", 678 dd->dd_grrev >> 4, dd->dd_grrev & 0xf, 679 dd->dd_lrrev, dd->dd_grid[0], dd->dd_grid[1]); 680 681 if (sc->sc_scr != NULL) 682 sti_describe_screen(sc, sc->sc_scr); 683} 684 685void 686sti_end_attach(struct sti_softc *sc) 687{ 688 struct sti_screen *scr = sc->sc_scr; 689 690 if (scr == NULL) 691 return; 692#if NWSDISPLAY > 0 693 else { 694 struct wsemuldisplaydev_attach_args waa; 695 scr->scr_wsmode = WSDISPLAYIO_MODE_EMUL; 696 697 waa.console = sc->sc_flags & STI_CONSOLE ? 1 : 0; 698 waa.scrdata = &scr->scr_screenlist; 699 waa.accessops = &sti_accessops; 700 waa.accesscookie = scr; 701 702 /* attach as console if required */ 703 if (waa.console && !ISSET(sc->sc_flags, STI_ATTACHED)) { 704 long defattr; 705 706 sti_alloc_attr(scr, 0, 0, 0, &defattr); 707 wsdisplay_cnattach(&scr->scr_wsd, scr, 708 0, scr->scr_wsd.nrows - 1, defattr); 709 sc->sc_flags |= STI_ATTACHED; 710 } 711 712 config_found(sc->sc_dev, &waa, wsemuldisplaydevprint); 713 } 714#endif 715} 716 717u_int 718sti_rom_size(bus_space_tag_t memt, bus_space_handle_t romh) 719{ 720 int devtype; 721 u_int romend; 722 723 devtype = bus_space_read_1(memt, romh, 3); 724 if (devtype == STI_DEVTYPE4) { 725 bus_space_read_region_stream_4(memt, romh, STI_DEV4_DD_ROMEND, 726 (uint32_t *)&romend, 1); 727 } else { 728 romend = parseword(STI_DEV1_DD_ROMEND); 729 } 730 731 DPRINTF(("%s: %08x (%08x)\n", __func__, romend, round_page(romend))); 732 733 return round_page(romend); 734} 735 736int 737sti_fetchfonts(struct sti_screen *scr, struct sti_inqconfout *cfg, 738 uint32_t baseaddr, u_int fontindex) 739{ 740 struct sti_rom *rom = scr->scr_rom; 741 bus_space_tag_t memt = rom->memt; 742 bus_space_handle_t romh = rom->romh; 743 struct sti_font *fp = &scr->scr_curfont; 744 uint32_t addr; 745 int size; 746#ifdef notyet 747 int uc; 748 struct { 749 struct sti_unpmvflags flags; 750 struct sti_unpmvin in; 751 struct sti_unpmvout out; 752 } a; 753#endif 754 755 /* 756 * Get the first PROM font in memory 757 */ 758 759 STI_ENABLE_ROM(rom->rom_softc); 760 761rescan: 762 addr = baseaddr; 763 do { 764 if (rom->rom_devtype == STI_DEVTYPE1) { 765 fp->first = parseshort(addr + 0x00); 766 fp->last = parseshort(addr + 0x08); 767 fp->width = bus_space_read_1(memt, romh, addr + 0x13); 768 fp->height = bus_space_read_1(memt, romh, addr + 0x17); 769 fp->type = bus_space_read_1(memt, romh, addr + 0x1b); 770 fp->bpc = bus_space_read_1(memt, romh, addr + 0x1f); 771 fp->next = parseword(addr + 0x20); 772 fp->uheight= bus_space_read_1(memt, romh, addr + 0x33); 773 fp->uoffset= bus_space_read_1(memt, romh, addr + 0x37); 774 } else { /* STI_DEVTYPE4 */ 775 bus_space_read_region_stream_4(memt, romh, addr, 776 (uint32_t *)fp, sizeof(struct sti_font) / 4); 777 } 778 779#ifdef STIDEBUG 780 STI_DISABLE_ROM(rom->rom_softc); 781 DPRINTF(("%s: %dx%d font type %d, %d bpc, charset %d-%d\n", 782 device_xname(scr->scr_rom->rom_softc->sc_dev), fp->width, 783 fp->height, fp->type, fp->bpc, fp->first, fp->last)); 784 STI_ENABLE_ROM(rom->rom_softc); 785#endif 786 787 if (fontindex == 0) { 788 size = sizeof(struct sti_font) + 789 (fp->last - fp->first + 1) * fp->bpc; 790 if (rom->rom_devtype == STI_DEVTYPE1) 791 size *= 4; 792 scr->scr_romfont = malloc(size, M_DEVBUF, M_NOWAIT); 793 if (scr->scr_romfont == NULL) 794 return ENOMEM; 795 796 bus_space_read_region_stream_4(memt, romh, addr, 797 (uint32_t *)scr->scr_romfont, size / 4); 798 break; 799 } 800 801 addr = baseaddr + fp->next; 802 fontindex--; 803 } while (fp->next != 0); 804 805 /* 806 * If our font index was bogus, we did not find the expected font. 807 * In this case, pick the first one and be done with it. 808 */ 809 if (fp->next == 0 && scr->scr_romfont == NULL) { 810 fontindex = 0; 811 goto rescan; 812 } 813 814 STI_DISABLE_ROM(rom->rom_softc); 815 816#ifdef notyet 817 /* 818 * If there is enough room in the off-screen framebuffer memory, 819 * display all the characters there in order to display them 820 * faster with blkmv operations rather than unpmv later on. 821 */ 822 if (size <= cfg->fbheight * 823 (cfg->fbwidth - cfg->width - cfg->owidth)) { 824 memset(&a, 0, sizeof(a)); 825 a.flags.flags = STI_UNPMVF_WAIT; 826 a.in.fg_colour = STI_COLOUR_WHITE; 827 a.in.bg_colour = STI_COLOUR_BLACK; 828 a.in.font_addr = scr->scr_romfont; 829 830 scr->scr_fontmaxcol = cfg->fbheight / fp->height; 831 scr->scr_fontbase = cfg->width + cfg->owidth; 832 for (uc = fp->first; uc <= fp->last; uc++) { 833 a.in.x = ((uc - fp->first) / scr->scr_fontmaxcol) * 834 fp->width + scr->scr_fontbase; 835 a.in.y = ((uc - fp->first) % scr->scr_fontmaxcol) * 836 fp->height; 837 a.in.index = uc; 838 839 (*scr->unpmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg); 840 if (a.out.errno) { 841 aprint_error_dev(sc->sc_dev, "unpmv %d " 842 "returned %d\n", uc, a.out.errno); 843 return 0; 844 } 845 } 846 847 free(scr->scr_romfont, M_DEVBUF); 848 scr->scr_romfont = NULL; 849 } 850#endif 851 852 return 0; 853} 854 855/* 856 * Wrappers around STI code pointers 857 */ 858int 859sti_init(struct sti_screen *scr, int mode) 860{ 861 struct sti_rom *rom = scr->scr_rom; 862 struct { 863 struct sti_initflags flags; 864 struct sti_initin in; 865 struct sti_einitin ein; 866 struct sti_initout out; 867 } a; 868 869 KASSERT(rom != NULL); 870 memset(&a, 0, sizeof(a)); 871 872 a.flags.flags = STI_INITF_WAIT | STI_INITF_CMB | STI_INITF_EBET | 873 (mode & STI_TEXTMODE ? STI_INITF_TEXT | STI_INITF_PBET | 874 STI_INITF_PBETI | STI_INITF_ICMT : 0) | 875 (mode & STI_CLEARSCR ? STI_INITF_CLEAR : 0); 876 a.in.text_planes = 1; 877 a.in.ext_in = &a.ein; 878 879 DPRINTF(("%s: init,%p(%x, %p, %p, %p)\n", 880 device_xname(rom->rom_softc->sc_dev), rom->init, a.flags.flags, 881 &a.in, &a.out, &scr->scr_cfg)); 882 883 (*rom->init)(&a.flags, &a.in, &a.out, &scr->scr_cfg); 884 885 if (a.out.text_planes != a.in.text_planes) 886 return -1; /* not colliding with sti errno values */ 887 return a.out.errno; 888} 889 890int 891sti_inqcfg(struct sti_screen *scr, struct sti_inqconfout *out) 892{ 893 struct sti_rom *rom = scr->scr_rom; 894 struct { 895 struct sti_inqconfflags flags; 896 struct sti_inqconfin in; 897 } a; 898 899 memset(&a, 0, sizeof(a)); 900 901 a.flags.flags = STI_INQCONFF_WAIT; 902 (*rom->inqconf)(&a.flags, &a.in, out, &scr->scr_cfg); 903 904 return out->errno; 905} 906 907void 908sti_bmove(struct sti_screen *scr, int x1, int y1, int x2, int y2, int h, int w, 909 enum sti_bmove_funcs f) 910{ 911 struct sti_rom *rom = scr->scr_rom; 912 struct { 913 struct sti_blkmvflags flags; 914 struct sti_blkmvin in; 915 struct sti_blkmvout out; 916 } a; 917 918 memset(&a, 0, sizeof(a)); 919 920 a.flags.flags = STI_BLKMVF_WAIT; 921 switch (f) { 922 case bmf_clear: 923 a.flags.flags |= STI_BLKMVF_CLR; 924 a.in.bg_colour = STI_COLOUR_BLACK; 925 break; 926 case bmf_underline: 927 case bmf_copy: 928 a.in.fg_colour = STI_COLOUR_WHITE; 929 a.in.bg_colour = STI_COLOUR_BLACK; 930 break; 931 case bmf_invert: 932 a.flags.flags |= STI_BLKMVF_COLR; 933 a.in.fg_colour = STI_COLOUR_BLACK; 934 a.in.bg_colour = STI_COLOUR_WHITE; 935 break; 936 } 937 a.in.srcx = x1; 938 a.in.srcy = y1; 939 a.in.dstx = x2; 940 a.in.dsty = y2; 941 a.in.height = h; 942 a.in.width = w; 943 944 (*rom->blkmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg); 945#ifdef STIDEBUG 946 if (a.out.errno) 947 printf("%s: blkmv returned %d\n", 948 device_xname(rom->rom_softc->sc_dev), a.out.errno); 949#endif 950} 951 952int 953sti_setcment(struct sti_screen *scr, u_int i, u_char r, u_char g, u_char b) 954{ 955 struct sti_rom *rom = scr->scr_rom; 956 struct { 957 struct sti_scmentflags flags; 958 struct sti_scmentin in; 959 struct sti_scmentout out; 960 } a; 961 962 memset(&a, 0, sizeof(a)); 963 964 a.flags.flags = STI_SCMENTF_WAIT; 965 a.in.entry = i; 966 a.in.value = (r << 16) | (g << 8) | b; 967 968 (*rom->scment)(&a.flags, &a.in, &a.out, &scr->scr_cfg); 969 970 return a.out.errno; 971} 972 973/* 974 * wsdisplay accessops 975 */ 976int 977sti_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l) 978{ 979 struct sti_screen *scr = (struct sti_screen *)v; 980 struct sti_rom *rom = scr->scr_rom; 981 struct wsdisplay_fbinfo *wdf; 982 struct wsdisplay_cmap *cmapp; 983 u_int mode, idx, count; 984 int i, ret; 985 986 ret = 0; 987 switch (cmd) { 988 case WSDISPLAYIO_GMODE: 989 *(u_int *)data = scr->scr_wsmode; 990 break; 991 992 case WSDISPLAYIO_SMODE: 993 mode = *(u_int *)data; 994 if (scr->scr_wsmode == WSDISPLAYIO_MODE_EMUL && 995 mode == WSDISPLAYIO_MODE_DUMBFB) 996 ret = sti_init(scr, 0); 997 else if (scr->scr_wsmode == WSDISPLAYIO_MODE_DUMBFB && 998 mode == WSDISPLAYIO_MODE_EMUL) 999 ret = sti_init(scr, STI_TEXTMODE); 1000 scr->scr_wsmode = mode; 1001 break; 1002 1003 case WSDISPLAYIO_GTYPE: 1004 *(u_int *)data = WSDISPLAY_TYPE_STI; 1005 break; 1006 1007 case WSDISPLAYIO_GINFO: 1008 wdf = (struct wsdisplay_fbinfo *)data; 1009 wdf->height = scr->scr_cfg.scr_height; 1010 wdf->width = scr->scr_cfg.scr_width; 1011 wdf->depth = scr->scr_bpp; 1012 if (rom->scment == NULL) 1013 wdf->cmsize = 0; 1014 else 1015 wdf->cmsize = STI_NCMAP; 1016 break; 1017 1018 case WSDISPLAYIO_LINEBYTES: 1019 *(u_int *)data = scr->scr_cfg.fb_width; 1020 break; 1021 1022 case WSDISPLAYIO_GETCMAP: 1023 if (rom->scment == NULL) 1024 return ENOTTY; 1025 cmapp = (struct wsdisplay_cmap *)data; 1026 idx = cmapp->index; 1027 count = cmapp->count; 1028 if (idx >= STI_NCMAP || idx + count > STI_NCMAP) 1029 return EINVAL; 1030 if ((ret = copyout(&scr->scr_rcmap[idx], cmapp->red, count))) 1031 break; 1032 if ((ret = copyout(&scr->scr_gcmap[idx], cmapp->green, count))) 1033 break; 1034 if ((ret = copyout(&scr->scr_bcmap[idx], cmapp->blue, count))) 1035 break; 1036 break; 1037 1038 case WSDISPLAYIO_PUTCMAP: 1039 if (rom->scment == NULL) 1040 return ENOTTY; 1041 cmapp = (struct wsdisplay_cmap *)data; 1042 idx = cmapp->index; 1043 count = cmapp->count; 1044 if (idx >= STI_NCMAP || idx + count > STI_NCMAP) 1045 return EINVAL; 1046 if ((ret = copyin(cmapp->red, &scr->scr_rcmap[idx], count))) 1047 break; 1048 if ((ret = copyin(cmapp->green, &scr->scr_gcmap[idx], count))) 1049 break; 1050 if ((ret = copyin(cmapp->blue, &scr->scr_bcmap[idx], count))) 1051 break; 1052 for (i = idx + count - 1; i >= idx; i--) 1053 if ((ret = sti_setcment(scr, i, scr->scr_rcmap[i], 1054 scr->scr_gcmap[i], scr->scr_bcmap[i]))) { 1055 1056 DPRINTF(("sti_ioctl: " 1057 "sti_setcment(%d, %u, %u, %u): %%d\n", i, 1058 (u_int)scr->scr_rcmap[i], 1059 (u_int)scr->scr_gcmap[i], 1060 (u_int)scr->scr_bcmap[i])); 1061 1062 ret = EINVAL; 1063 break; 1064 } 1065 break; 1066 1067 case WSDISPLAYIO_SVIDEO: 1068 case WSDISPLAYIO_GVIDEO: 1069 case WSDISPLAYIO_GCURPOS: 1070 case WSDISPLAYIO_SCURPOS: 1071 case WSDISPLAYIO_GCURMAX: 1072 case WSDISPLAYIO_GCURSOR: 1073 case WSDISPLAYIO_SCURSOR: 1074 default: 1075 return ENOTTY; /* not supported yet */ 1076 } 1077 1078 return ret; 1079} 1080 1081paddr_t 1082sti_mmap(void *v, void *vs, off_t offset, int prot) 1083{ 1084#if 0 1085 struct sti_screen *scr = (struct sti_screen *)v; 1086#endif 1087 /* XXX not finished */ 1088 return -1; 1089} 1090 1091int 1092sti_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep, 1093 int *cxp, int *cyp, long *defattr) 1094{ 1095 struct sti_screen *scr = (struct sti_screen *)v; 1096 1097 if (scr->scr_nscreens > 0) 1098 return ENOMEM; 1099 1100 *cookiep = scr; 1101 *cxp = 0; 1102 *cyp = 0; 1103 sti_alloc_attr(scr, 0, 0, 0, defattr); 1104 scr->scr_nscreens++; 1105 1106 return 0; 1107} 1108 1109void 1110sti_free_screen(void *v, void *cookie) 1111{ 1112 struct sti_screen *scr = (struct sti_screen *)v; 1113 1114 scr->scr_nscreens--; 1115} 1116 1117int 1118sti_show_screen(void *v, void *cookie, int waitok, void (*cb)(void *, int, int), 1119 void *cbarg) 1120{ 1121#if 0 1122 struct sti_screen *scr = (struct sti_screen *)v; 1123#endif 1124 1125 return 0; 1126} 1127 1128int 1129sti_load_font(void *v, void *cookie, struct wsdisplay_font *font) 1130{ 1131#if 0 1132 struct sti_screen *scr = (struct sti_screen *)v; 1133#endif 1134 1135 return -1; 1136} 1137 1138/* 1139 * wsdisplay emulops 1140 */ 1141void 1142sti_cursor(void *v, int on, int row, int col) 1143{ 1144 struct sti_screen *scr = (struct sti_screen *)v; 1145 struct sti_font *fp = &scr->scr_curfont; 1146 1147 sti_bmove(scr, col * fp->width, row * fp->height, col * fp->width, 1148 row * fp->height, fp->height, fp->width, bmf_invert); 1149} 1150 1151/* 1152 * ISO 8859-1 part of Unicode to HP Roman font index conversion array. 1153 */ 1154static const uint8_t 1155sti_unitoroman[0x100 - 0xa0] = { 1156 0xa0, 0xb8, 0xbf, 0xbb, 0xba, 0xbc, 0, 0xbd, 1157 0xab, 0, 0xf9, 0xfb, 0, 0xf6, 0, 0xb0, 1158 1159 0xb3, 0xfe, 0, 0, 0xa8, 0xf3, 0xf4, 0xf2, 1160 0, 0, 0xfa, 0xfd, 0xf7, 0xf8, 0, 0xb9, 1161 1162 0xa1, 0xe0, 0xa2, 0xe1, 0xd8, 0xd0, 0xd3, 0xb4, 1163 0xa3, 0xdc, 0xa4, 0xa5, 0xe6, 0xe5, 0xa6, 0xa7, 1164 1165 0xe3, 0xb6, 0xe8, 0xe7, 0xdf, 0xe9, 0xda, 0, 1166 0xd2, 0xad, 0xed, 0xae, 0xdb, 0xb1, 0xf0, 0xde, 1167 1168 0xc8, 0xc4, 0xc0, 0xe2, 0xcc, 0xd4, 0xd7, 0xb5, 1169 0xc9, 0xc5, 0xc1, 0xcd, 0xd9, 0xd5, 0xd1, 0xdd, 1170 1171 0xe4, 0xb7, 0xca, 0xc6, 0xc2, 0xea, 0xce, 0, 1172 0xd6, 0xcb, 0xc7, 0xc3, 0xcf, 0xb2, 0xf1, 0xef 1173}; 1174 1175int 1176sti_mapchar(void *v, int uni, u_int *index) 1177{ 1178 struct sti_screen *scr = (struct sti_screen *)v; 1179 struct sti_font *fp = &scr->scr_curfont; 1180 int c; 1181 1182 switch (fp->type) { 1183 case STI_FONT_HPROMAN8: 1184 if (uni >= 0x80 && uni < 0xa0) 1185 c = -1; 1186 else if (uni >= 0xa0 && uni < 0x100) { 1187 c = (int)sti_unitoroman[uni - 0xa0]; 1188 if (c == 0) 1189 c = -1; 1190 } else 1191 c = uni; 1192 break; 1193 default: 1194 c = uni; 1195 break; 1196 } 1197 1198 if (c == -1 || c < fp->first || c > fp->last) { 1199 *index = ' '; 1200 return 0; 1201 } 1202 1203 *index = c; 1204 return 5; 1205} 1206 1207void 1208sti_putchar(void *v, int row, int col, u_int uc, long attr) 1209{ 1210 struct sti_screen *scr = (struct sti_screen *)v; 1211 struct sti_rom *rom = scr->scr_rom; 1212 struct sti_font *fp = &scr->scr_curfont; 1213 1214 if (scr->scr_romfont != NULL) { 1215 /* 1216 * Font is in memory, use unpmv 1217 */ 1218 struct { 1219 struct sti_unpmvflags flags; 1220 struct sti_unpmvin in; 1221 struct sti_unpmvout out; 1222 } a; 1223 1224 memset(&a, 0, sizeof(a)); 1225 1226 a.flags.flags = STI_UNPMVF_WAIT; 1227 /* XXX does not handle text attributes */ 1228 a.in.fg_colour = STI_COLOUR_WHITE; 1229 a.in.bg_colour = STI_COLOUR_BLACK; 1230 a.in.x = col * fp->width; 1231 a.in.y = row * fp->height; 1232 a.in.font_addr = scr->scr_romfont; 1233 a.in.index = uc; 1234 1235 (*rom->unpmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg); 1236 } else { 1237 /* 1238 * Font is in frame buffer, use blkmv 1239 */ 1240 struct { 1241 struct sti_blkmvflags flags; 1242 struct sti_blkmvin in; 1243 struct sti_blkmvout out; 1244 } a; 1245 1246 memset(&a, 0, sizeof(a)); 1247 1248 a.flags.flags = STI_BLKMVF_WAIT; 1249 /* XXX does not handle text attributes */ 1250 a.in.fg_colour = STI_COLOUR_WHITE; 1251 a.in.bg_colour = STI_COLOUR_BLACK; 1252 1253 a.in.srcx = ((uc - fp->first) / scr->scr_fontmaxcol) * 1254 fp->width + scr->scr_fontbase; 1255 a.in.srcy = ((uc - fp->first) % scr->scr_fontmaxcol) * 1256 fp->height; 1257 a.in.dstx = col * fp->width; 1258 a.in.dsty = row * fp->height; 1259 a.in.height = fp->height; 1260 a.in.width = fp->width; 1261 1262 (*rom->blkmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg); 1263 } 1264} 1265 1266void 1267sti_copycols(void *v, int row, int srccol, int dstcol, int ncols) 1268{ 1269 struct sti_screen *scr = (struct sti_screen *)v; 1270 struct sti_font *fp = &scr->scr_curfont; 1271 1272 sti_bmove(scr, srccol * fp->width, row * fp->height, dstcol * fp->width, 1273 row * fp->height, fp->height, ncols * fp->width, bmf_copy); 1274} 1275 1276void 1277sti_erasecols(void *v, int row, int startcol, int ncols, long attr) 1278{ 1279 struct sti_screen *scr = (struct sti_screen *)v; 1280 struct sti_font *fp = &scr->scr_curfont; 1281 1282 sti_bmove(scr, startcol * fp->width, row * fp->height, 1283 startcol * fp->width, row * fp->height, fp->height, 1284 ncols * fp->width, bmf_clear); 1285} 1286 1287void 1288sti_copyrows(void *v, int srcrow, int dstrow, int nrows) 1289{ 1290 struct sti_screen *scr = (struct sti_screen *)v; 1291 struct sti_font *fp = &scr->scr_curfont; 1292 1293 sti_bmove(scr, 0, srcrow * fp->height, 0, dstrow * fp->height, 1294 nrows * fp->height, scr->scr_cfg.scr_width, bmf_copy); 1295} 1296 1297void 1298sti_eraserows(void *v, int srcrow, int nrows, long attr) 1299{ 1300 struct sti_screen *scr = (struct sti_screen *)v; 1301 struct sti_font *fp = &scr->scr_curfont; 1302 1303 sti_bmove(scr, 0, srcrow * fp->height, 0, srcrow * fp->height, 1304 nrows * fp->height, scr->scr_cfg.scr_width, bmf_clear); 1305} 1306 1307int 1308sti_alloc_attr(void *v, int fg, int bg, int flags, long *pattr) 1309{ 1310#if 0 1311 struct sti_screen *scr = (struct sti_screen *)v; 1312#endif 1313 1314 *pattr = 0; 1315 1316 return 0; 1317} 1318