1 /* $NetBSD: sti.c,v 1.30 2021/04/24 23:36:55 thorpej 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 on more models. 35 */ 36 37 #include <sys/cdefs.h> 38 __KERNEL_RCSID(0, "$NetBSD: sti.c,v 1.30 2021/04/24 23:36:55 thorpej 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_extern.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 #ifdef STIDEBUG 58 59 #define DPRINTF(s) do { \ 60 if (stidebug) \ 61 printf s; \ 62 } while(0) 63 64 int stidebug = 1; 65 #else 66 #define DPRINTF(s) /* */ 67 #endif 68 69 void sti_cursor(void *, int, int, int); 70 int sti_mapchar(void *, int, u_int *); 71 void sti_putchar(void *, int, int, u_int, long); 72 void sti_copycols(void *, int, int, int, int); 73 void sti_erasecols(void *, int, int, int, long); 74 void sti_copyrows(void *, int, int, int); 75 void sti_eraserows(void *, int, int, long); 76 int sti_alloc_attr(void *, int, int, int, long *); 77 78 /* pseudo attribute ops for sti ROM putchar function */ 79 #define WSATTR_FG_SHIFT 24 80 #define WSATTR_BG_SHIFT 16 81 #define WSATTR_UNPACK_FG(attr) (((attr) >> WSATTR_FG_SHIFT) & 0xff) 82 #define WSATTR_UNPACK_BG(attr) (((attr) >> WSATTR_BG_SHIFT) & 0xff) 83 #define WSATTR_UNPACK_FLAG(attr) ((attr) & WSATTR_USERMASK) 84 #define WSATTR_PACK_FG(fg) ((fg) << WSATTR_FG_SHIFT) 85 #define WSATTR_PACK_BG(bg) ((bg) << WSATTR_BG_SHIFT) 86 #define WSATTR_PACK_FLAG(flag) ((flag)) 87 #define WSATTR_PACK(fg, bg, flag) \ 88 (WSATTR_PACK_FG(fg) | WSATTR_PACK_BG(bg) | WSATTR_PACK_FLAG(flag)) 89 90 struct wsdisplay_emulops sti_emulops = { 91 .cursor = sti_cursor, 92 .mapchar = sti_mapchar, 93 .putchar = sti_putchar, 94 .copycols = sti_copycols, 95 .erasecols = sti_erasecols, 96 .copyrows = sti_copyrows, 97 .eraserows = sti_eraserows, 98 .allocattr = sti_alloc_attr 99 }; 100 101 const struct wsdisplay_accessops sti_accessops = { 102 .ioctl = sti_ioctl, 103 .mmap = sti_mmap, 104 .alloc_screen = sti_alloc_screen, 105 .free_screen = sti_free_screen, 106 .show_screen = sti_show_screen, 107 .load_font = sti_load_font 108 }; 109 110 enum sti_bmove_funcs { 111 bmf_clear, bmf_copy, bmf_invert, bmf_underline 112 }; 113 114 void sti_bmove(struct sti_screen *, int, int, int, int, int, int, 115 enum sti_bmove_funcs); 116 int sti_inqcfg(struct sti_screen *, struct sti_inqconfout *); 117 int sti_setcment(struct sti_screen *, u_int, u_char, u_char, u_char); 118 119 struct sti_screen *sti_attach_screen(struct sti_softc *, int); 120 void sti_describe_screen(struct sti_softc *, struct sti_screen *); 121 122 int sti_fetchfonts(struct sti_screen *, struct sti_inqconfout *, uint32_t, 123 u_int); 124 void sti_region_setup(struct sti_screen *); 125 int sti_rom_setup(struct sti_rom *, bus_space_tag_t, bus_space_tag_t, 126 bus_space_handle_t, bus_addr_t *, u_int); 127 int sti_screen_setup(struct sti_screen *, int); 128 129 int ngle_default_putcmap(struct sti_screen *, u_int, u_int); 130 131 #ifndef SMALL_KERNEL 132 void ngle_artist_setupfb(struct sti_screen *); 133 void ngle_elk_setupfb(struct sti_screen *); 134 void ngle_timber_setupfb(struct sti_screen *); 135 int ngle_putcmap(struct sti_screen *, u_int, u_int); 136 #endif 137 138 #define STI_ENABLE_ROM(sc) \ 139 do { \ 140 if ((sc) != NULL && (sc)->sc_enable_rom != NULL) \ 141 (*(sc)->sc_enable_rom)(sc); \ 142 } while (0) 143 #define STI_DISABLE_ROM(sc) \ 144 do { \ 145 if ((sc) != NULL && (sc)->sc_disable_rom != NULL) \ 146 (*(sc)->sc_disable_rom)(sc); \ 147 } while (0) 148 149 /* Macros to read larger than 8 bit values from byte roms */ 150 #define parseshort(o) \ 151 ((bus_space_read_1(memt, romh, (o) + 3) << 8) | \ 152 (bus_space_read_1(memt, romh, (o) + 7))) 153 #define parseword(o) \ 154 ((bus_space_read_1(memt, romh, (o) + 3) << 24) | \ 155 (bus_space_read_1(memt, romh, (o) + 7) << 16) | \ 156 (bus_space_read_1(memt, romh, (o) + 11) << 8) | \ 157 (bus_space_read_1(memt, romh, (o) + 15))) 158 159 int 160 sti_attach_common(struct sti_softc *sc, bus_space_tag_t iot, 161 bus_space_tag_t memt, bus_space_handle_t romh, u_int codebase) 162 { 163 struct sti_rom *rom; 164 int rc; 165 166 rom = (struct sti_rom *)malloc(sizeof(*rom), M_DEVBUF, 167 M_WAITOK | M_ZERO); 168 rom->rom_softc = sc; 169 rc = sti_rom_setup(rom, iot, memt, romh, sc->bases, codebase); 170 if (rc != 0) { 171 free(rom, M_DEVBUF); 172 return rc; 173 } 174 175 sc->sc_rom = rom; 176 177 sti_describe(sc); 178 179 sc->sc_scr = sti_attach_screen(sc, 180 sc->sc_flags & STI_CONSOLE ? 0 : STI_CLEARSCR); 181 if (sc->sc_scr == NULL) 182 rc = ENOMEM; 183 184 return rc; 185 } 186 187 struct sti_screen * 188 sti_attach_screen(struct sti_softc *sc, int flags) 189 { 190 struct sti_screen *scr; 191 int rc; 192 193 scr = (struct sti_screen *)malloc(sizeof(*scr), M_DEVBUF, 194 M_WAITOK | M_ZERO); 195 scr->scr_rom = sc->sc_rom; 196 rc = sti_screen_setup(scr, flags); 197 if (rc != 0) { 198 free(scr, M_DEVBUF); 199 return NULL; 200 } 201 202 sti_describe_screen(sc, scr); 203 204 return scr; 205 } 206 207 int 208 sti_rom_setup(struct sti_rom *rom, bus_space_tag_t iot, bus_space_tag_t memt, 209 bus_space_handle_t romh, bus_addr_t *bases, u_int codebase) 210 { 211 struct sti_dd *dd; 212 int error, size, i; 213 214 KASSERT(rom != NULL); 215 STI_ENABLE_ROM(rom->rom_softc); 216 217 rom->iot = iot; 218 rom->memt = memt; 219 rom->romh = romh; 220 rom->bases = bases; 221 222 /* 223 * Get ROM header and code function pointers. 224 */ 225 226 dd = &rom->rom_dd; 227 rom->rom_devtype = bus_space_read_1(memt, romh, 3); 228 if (rom->rom_devtype == STI_DEVTYPE1) { 229 dd->dd_type = bus_space_read_1(memt, romh, 0x03); 230 dd->dd_nmon = bus_space_read_1(memt, romh, 0x07); 231 dd->dd_grrev = bus_space_read_1(memt, romh, 0x0b); 232 dd->dd_lrrev = bus_space_read_1(memt, romh, 0x0f); 233 dd->dd_grid[0] = parseword(0x10); 234 dd->dd_grid[1] = parseword(0x20); 235 dd->dd_fntaddr = parseword(0x30) & ~3; 236 dd->dd_maxst = parseword(0x40); 237 dd->dd_romend = parseword(0x50) & ~3; 238 dd->dd_reglst = parseword(0x60) & ~3; 239 dd->dd_maxreent = parseshort(0x70); 240 dd->dd_maxtimo = parseshort(0x78); 241 dd->dd_montbl = parseword(0x80) & ~3; 242 dd->dd_udaddr = parseword(0x90) & ~3; 243 dd->dd_stimemreq = parseword(0xa0); 244 dd->dd_udsize = parseword(0xb0); 245 dd->dd_pwruse = parseshort(0xc0); 246 dd->dd_bussup = bus_space_read_1(memt, romh, 0xcb); 247 dd->dd_ebussup = bus_space_read_1(memt, romh, 0xcf); 248 dd->dd_altcodet = bus_space_read_1(memt, romh, 0xd3); 249 dd->dd_eddst[0] = bus_space_read_1(memt, romh, 0xd7); 250 dd->dd_eddst[1] = bus_space_read_1(memt, romh, 0xdb); 251 dd->dd_eddst[2] = bus_space_read_1(memt, romh, 0xdf); 252 dd->dd_cfbaddr = parseword(0xe0) & ~3; 253 254 codebase <<= 2; 255 dd->dd_pacode[0x0] = parseword(codebase + 0x000) & ~3; 256 dd->dd_pacode[0x1] = parseword(codebase + 0x010) & ~3; 257 dd->dd_pacode[0x2] = parseword(codebase + 0x020) & ~3; 258 dd->dd_pacode[0x3] = parseword(codebase + 0x030) & ~3; 259 dd->dd_pacode[0x4] = parseword(codebase + 0x040) & ~3; 260 dd->dd_pacode[0x5] = parseword(codebase + 0x050) & ~3; 261 dd->dd_pacode[0x6] = parseword(codebase + 0x060) & ~3; 262 dd->dd_pacode[0x7] = parseword(codebase + 0x070) & ~3; 263 dd->dd_pacode[0x8] = parseword(codebase + 0x080) & ~3; 264 dd->dd_pacode[0x9] = parseword(codebase + 0x090) & ~3; 265 dd->dd_pacode[0xa] = parseword(codebase + 0x0a0) & ~3; 266 dd->dd_pacode[0xb] = parseword(codebase + 0x0b0) & ~3; 267 dd->dd_pacode[0xc] = parseword(codebase + 0x0c0) & ~3; 268 dd->dd_pacode[0xd] = parseword(codebase + 0x0d0) & ~3; 269 dd->dd_pacode[0xe] = parseword(codebase + 0x0e0) & ~3; 270 dd->dd_pacode[0xf] = parseword(codebase + 0x0f0) & ~3; 271 } else { /* STI_DEVTYPE4 */ 272 bus_space_read_region_stream_4(memt, romh, 0, (uint32_t *)dd, 273 sizeof(*dd) / 4); 274 /* fix pacode... */ 275 bus_space_read_region_stream_4(memt, romh, codebase, 276 (uint32_t *)dd->dd_pacode, sizeof(dd->dd_pacode) / 4); 277 } 278 279 STI_DISABLE_ROM(rom->rom_softc); 280 281 DPRINTF(("dd:\n" 282 "devtype=%x, rev=%x;%d, altt=%x, gid=%08x%08x, font=%x, mss=%x\n" 283 "end=%x, regions=%x, msto=%x, timo=%d, mont=%x, user=%x[%x]\n" 284 "memrq=%x, pwr=%d, bus=%x, ebus=%x, cfb=%x\n" 285 "code=", 286 dd->dd_type & 0xff, dd->dd_grrev, dd->dd_lrrev, dd->dd_altcodet, 287 dd->dd_grid[0], dd->dd_grid[1], dd->dd_fntaddr, dd->dd_maxst, 288 dd->dd_romend, dd->dd_reglst, dd->dd_maxreent, dd->dd_maxtimo, 289 dd->dd_montbl, dd->dd_udaddr, dd->dd_udsize, dd->dd_stimemreq, 290 dd->dd_pwruse, dd->dd_bussup, dd->dd_ebussup, dd->dd_cfbaddr)); 291 DPRINTF(("%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x\n", 292 dd->dd_pacode[0x0], dd->dd_pacode[0x1], dd->dd_pacode[0x2], 293 dd->dd_pacode[0x3], dd->dd_pacode[0x4], dd->dd_pacode[0x5], 294 dd->dd_pacode[0x6], dd->dd_pacode[0x7], dd->dd_pacode[0x8], 295 dd->dd_pacode[0x9], dd->dd_pacode[0xa], dd->dd_pacode[0xb], 296 dd->dd_pacode[0xc], dd->dd_pacode[0xd], dd->dd_pacode[0xe], 297 dd->dd_pacode[0xf])); 298 299 /* 300 * Figure out how many bytes we need for the STI code. 301 * Note there could be fewer than STI_END pointer entries 302 * populated, especially on older devices. 303 */ 304 for (i = STI_END; dd->dd_pacode[i] == 0; i--) 305 ; 306 307 size = dd->dd_pacode[i] - dd->dd_pacode[STI_BEGIN]; 308 309 if (rom->rom_devtype == STI_DEVTYPE1) 310 size = (size + 3) / 4; 311 if (size == 0) { 312 aprint_error(": no code for the requested platform\n"); 313 return EINVAL; 314 } 315 316 if (!(rom->rom_code = uvm_km_alloc(kernel_map, round_page(size), 0, 317 UVM_KMF_WIRED))) { 318 aprint_error(": cannot allocate %u bytes for code\n", size); 319 return ENOMEM; 320 } 321 DPRINTF(("code=0x%lx[%x]\n", rom->rom_code, size)); 322 323 /* 324 * Copy code into memory and make it executable. 325 */ 326 327 STI_ENABLE_ROM(rom->rom_softc); 328 329 if (rom->rom_devtype == STI_DEVTYPE1) { 330 uint8_t *p; 331 uint32_t addr, eaddr; 332 333 p = (uint8_t *)rom->rom_code; 334 335 for (addr = dd->dd_pacode[STI_BEGIN], eaddr = addr + size * 4; 336 addr < eaddr; addr += 4 ) { 337 *p++ = bus_space_read_4(memt, romh, addr) & 0xff; 338 } 339 } else { /* STI_DEVTYPE4 */ 340 bus_space_read_region_stream_4(memt, romh, 341 dd->dd_pacode[STI_BEGIN], (uint32_t *)rom->rom_code, 342 size / 4); 343 } 344 345 STI_DISABLE_ROM(rom->rom_softc); 346 347 if ((error = uvm_map_protect(kernel_map, rom->rom_code, 348 rom->rom_code + round_page(size), UVM_PROT_RX, FALSE))) { 349 aprint_error(": uvm_map_protect failed (%d)\n", error); 350 uvm_km_free(kernel_map, rom->rom_code, round_page(size), 351 UVM_KMF_WIRED); 352 return error; 353 } 354 355 /* 356 * Setup code function pointers. 357 */ 358 359 #define O(i) \ 360 (dd->dd_pacode[(i)] == 0 ? 0 : \ 361 (rom->rom_code + (dd->dd_pacode[(i)] - dd->dd_pacode[0]) / \ 362 (rom->rom_devtype == STI_DEVTYPE1 ? 4 : 1))) 363 364 rom->init = (sti_init_t)O(STI_INIT_GRAPH); 365 rom->mgmt = (sti_mgmt_t)O(STI_STATE_MGMT); 366 rom->unpmv = (sti_unpmv_t)O(STI_FONT_UNPMV); 367 rom->blkmv = (sti_blkmv_t)O(STI_BLOCK_MOVE); 368 rom->test = (sti_test_t)O(STI_SELF_TEST); 369 rom->exhdl = (sti_exhdl_t)O(STI_EXCEP_HDLR); 370 rom->inqconf = (sti_inqconf_t)O(STI_INQ_CONF); 371 rom->scment = (sti_scment_t)O(STI_SCM_ENT); 372 rom->dmac = (sti_dmac_t)O(STI_DMA_CTRL); 373 rom->flowc = (sti_flowc_t)O(STI_FLOW_CTRL); 374 rom->utiming = (sti_utiming_t)O(STI_UTIMING); 375 rom->pmgr = (sti_pmgr_t)O(STI_PROC_MGR); 376 rom->util = (sti_util_t)O(STI_UTIL); 377 378 #undef O 379 380 /* 381 * Set colormap entry is not implemented until 8.04, so force 382 * a NULL pointer here. 383 */ 384 if (dd->dd_grrev < STI_REVISION(8, 4)) { 385 rom->scment = NULL; 386 } 387 388 return 0; 389 } 390 391 /* 392 * Map all regions. 393 */ 394 void 395 sti_region_setup(struct sti_screen *scr) 396 { 397 struct sti_rom *rom = scr->scr_rom; 398 bus_space_tag_t memt = rom->memt; 399 bus_space_handle_t romh = rom->romh; 400 bus_addr_t *bases = rom->bases; 401 struct sti_dd *dd = &rom->rom_dd; 402 struct sti_cfg *cc = &scr->scr_cfg; 403 struct sti_region regions[STI_REGION_MAX], *r; 404 u_int regno, regcnt; 405 bus_addr_t addr; 406 407 DPRINTF(("stiregions @ %x:\n", dd->dd_reglst)); 408 409 /* 410 * Read the region information. 411 */ 412 413 STI_ENABLE_ROM(rom->rom_softc); 414 415 if (rom->rom_devtype == STI_DEVTYPE1) { 416 for (regno = 0; regno < STI_REGION_MAX; regno++) 417 *(u_int *)(regions + regno) = 418 parseword(dd->dd_reglst + regno * 0x10); 419 } else { 420 bus_space_read_region_stream_4(memt, romh, dd->dd_reglst, 421 (uint32_t *)regions, sizeof(regions) / 4); 422 } 423 424 STI_DISABLE_ROM(rom->rom_softc); 425 426 /* 427 * Count them. 428 */ 429 430 for (regcnt = 0, r = regions; regcnt < STI_REGION_MAX; regcnt++, r++) 431 if (r->last) 432 break; 433 regcnt++; 434 435 /* 436 * Map them. 437 */ 438 439 for (regno = 0, r = regions; regno < regcnt; regno++, r++) { 440 if (r->length == 0) 441 continue; 442 443 /* 444 * Assume an existing mapping exists. 445 */ 446 addr = bases[regno] + (r->offset << PGSHIFT); 447 DPRINTF(("%08x @ 0x%08x%s%s%s%s", 448 r->length << PGSHIFT, (int)addr, r->sys_only ? " sys" : "", 449 r->cache ? " cache" : "", r->btlb ? " btlb" : "", 450 r->last ? " last" : "")); 451 452 /* 453 * Region #0 is always the rom, and it should have been 454 * mapped already. 455 * XXX This expects a 1:1 mapping... 456 */ 457 if (regno == 0 && romh == bases[0]) { 458 cc->regions[0] = addr; 459 DPRINTF(("\n")); 460 continue; 461 } 462 463 if (bus_space_map(memt, addr, r->length << PGSHIFT, 464 BUS_SPACE_MAP_LINEAR | (r->cache ? 465 BUS_SPACE_MAP_CACHEABLE : 0), &rom->regh[regno]) != 0) { 466 rom->regh[regno] = romh; /* XXX */ 467 DPRINTF((" - already mapped region\n")); 468 } else { 469 addr = (bus_addr_t) 470 bus_space_vaddr(memt, rom->regh[regno]); 471 if (regno == 1) { 472 DPRINTF((" - fb")); 473 scr->fbaddr = addr; 474 scr->fblen = r->length << PGSHIFT; 475 } 476 DPRINTF(("\n")); 477 } 478 479 cc->regions[regno] = addr; 480 } 481 482 #ifdef STIDEBUG 483 /* 484 * Make sure we'll trap accessing unmapped regions 485 */ 486 for (regno = 0; regno < STI_REGION_MAX; regno++) 487 if (cc->regions[regno] == 0) 488 cc->regions[regno] = 0x81234567; 489 #endif 490 } 491 492 int 493 sti_screen_setup(struct sti_screen *scr, int flags) 494 { 495 struct sti_rom *rom = scr->scr_rom; 496 bus_space_tag_t memt = rom->memt; 497 bus_space_handle_t romh = rom->romh; 498 struct sti_dd *dd = &rom->rom_dd; 499 struct sti_cfg *cc = &scr->scr_cfg; 500 struct sti_inqconfout cfg; 501 struct sti_einqconfout ecfg; 502 #ifdef STIDEBUG 503 char buf[256]; 504 #endif 505 int error, i; 506 int geometry_kluge = 0; 507 u_int fontindex = 0; 508 509 KASSERT(scr != NULL); 510 memset(cc, 0, sizeof(*cc)); 511 cc->ext_cfg = &scr->scr_ecfg; 512 memset(cc->ext_cfg, 0, sizeof(*cc->ext_cfg)); 513 514 if (dd->dd_stimemreq) { 515 scr->scr_ecfg.addr = 516 malloc(dd->dd_stimemreq, M_DEVBUF, M_WAITOK); 517 } 518 519 sti_region_setup(scr); 520 521 if ((error = sti_init(scr, 0))) { 522 aprint_error(": cannot initialize (%d)\n", error); 523 goto fail; 524 } 525 526 memset(&cfg, 0, sizeof(cfg)); 527 memset(&ecfg, 0, sizeof(ecfg)); 528 cfg.ext = &ecfg; 529 if ((error = sti_inqcfg(scr, &cfg))) { 530 aprint_error(": error %d inquiring config\n", error); 531 goto fail; 532 } 533 534 /* 535 * Older (rev 8.02) boards report wrong offset values, 536 * similar to the displayable area size, at least in m68k mode. 537 * Attempt to detect this and adjust here. 538 */ 539 if (cfg.owidth == cfg.width && 540 cfg.oheight == cfg.height) 541 geometry_kluge = 1; 542 543 if (geometry_kluge) { 544 scr->scr_cfg.oscr_width = cfg.owidth = 545 cfg.fbwidth - cfg.width; 546 scr->scr_cfg.oscr_height = cfg.oheight = 547 cfg.fbheight - cfg.height; 548 } 549 550 /* 551 * Save a few fields for sti_describe_screen() later 552 */ 553 scr->fbheight = cfg.fbheight; 554 scr->fbwidth = cfg.fbwidth; 555 scr->oheight = cfg.oheight; 556 scr->owidth = cfg.owidth; 557 memcpy(scr->name, cfg.name, sizeof(scr->name)); 558 559 if ((error = sti_init(scr, STI_TEXTMODE | flags))) { 560 aprint_error(": cannot initialize (%d)\n", error); 561 goto fail; 562 } 563 #ifdef STIDEBUG 564 snprintb(buf, sizeof(buf), STI_INQCONF_BITS, cfg.attributes); 565 DPRINTF(("conf: bpp=%d planes=%d attr=%s\n" 566 "crt=0x%x:0x%x:0x%x hw=0x%x:0x%x:0x%x\n", cfg.bpp, 567 cfg.planes, buf, 568 ecfg.crt_config[0], ecfg.crt_config[1], ecfg.crt_config[2], 569 ecfg.crt_hw[0], ecfg.crt_hw[1], ecfg.crt_hw[2])); 570 #endif 571 scr->scr_bpp = cfg.bppu; 572 573 /* 574 * Although scr->scr_ecfg.current_monitor is not filled by 575 * sti_init() as expected, we can nevertheless walk the monitor 576 * list, if there is any, and if we find a mode matching our 577 * resolution, pick its font index. 578 */ 579 if (dd->dd_montbl != 0) { 580 STI_ENABLE_ROM(rom->rom_softc); 581 582 for (i = 0; i < dd->dd_nmon; i++) { 583 u_int offs = dd->dd_montbl + 8 * i; 584 uint32_t m[2]; 585 sti_mon_t mon = (void *)m; 586 if (rom->rom_devtype == STI_DEVTYPE1) { 587 m[0] = parseword(4 * offs); 588 m[1] = parseword(4 * (offs + 4)); 589 } else { 590 bus_space_read_region_stream_4(memt, romh, offs, 591 (uint32_t *)mon, sizeof(*mon) / 4); 592 } 593 594 if (mon->width == scr->scr_cfg.scr_width && 595 mon->height == scr->scr_cfg.scr_height) { 596 fontindex = mon->font; 597 break; 598 } 599 } 600 601 STI_DISABLE_ROM(rom->rom_softc); 602 603 DPRINTF(("font index: %d\n", fontindex)); 604 } 605 606 if ((error = sti_fetchfonts(scr, &cfg, dd->dd_fntaddr, fontindex))) { 607 aprint_error(": cannot fetch fonts (%d)\n", error); 608 goto fail; 609 } 610 611 /* 612 * setup screen descriptions: 613 * figure number of fonts supported; 614 * allocate wscons structures; 615 * calculate dimensions. 616 */ 617 618 scr->scr_wsd.name = "std"; 619 scr->scr_wsd.ncols = cfg.width / scr->scr_curfont.width; 620 scr->scr_wsd.nrows = cfg.height / scr->scr_curfont.height; 621 scr->scr_wsd.textops = &sti_emulops; 622 scr->scr_wsd.fontwidth = scr->scr_curfont.width; 623 scr->scr_wsd.fontheight = scr->scr_curfont.height; 624 scr->scr_wsd.capabilities = WSSCREEN_REVERSE; 625 626 scr->scr_scrlist[0] = &scr->scr_wsd; 627 scr->scr_screenlist.nscreens = 1; 628 scr->scr_screenlist.screens = scr->scr_scrlist; 629 630 #ifndef SMALL_KERNEL 631 /* 632 * Decide which board-specific routines to use. 633 */ 634 635 switch (dd->dd_grid[0]) { 636 case STI_DD_CRX: 637 scr->setupfb = ngle_elk_setupfb; 638 scr->putcmap = ngle_putcmap; 639 640 scr->reg10_value = 0x13601000; 641 if (scr->scr_bpp > 8) 642 scr->reg12_value = NGLE_BUFF1_CMAP3; 643 else 644 scr->reg12_value = NGLE_BUFF1_CMAP0; 645 scr->cmap_finish_register = NGLE_REG_1; 646 break; 647 648 case STI_DD_TIMBER: 649 scr->setupfb = ngle_timber_setupfb; 650 scr->putcmap = ngle_putcmap; 651 652 scr->reg10_value = 0x13602000; 653 scr->reg12_value = NGLE_BUFF1_CMAP0; 654 scr->cmap_finish_register = NGLE_REG_1; 655 break; 656 657 case STI_DD_ARTIST: 658 scr->setupfb = ngle_artist_setupfb; 659 scr->putcmap = ngle_putcmap; 660 661 scr->reg10_value = 0x13601000; 662 scr->reg12_value = NGLE_ARTIST_CMAP0; 663 scr->cmap_finish_register = NGLE_REG_26; 664 break; 665 666 case STI_DD_EG: 667 scr->setupfb = ngle_artist_setupfb; 668 scr->putcmap = ngle_putcmap; 669 670 scr->reg10_value = 0x13601000; 671 if (scr->scr_bpp > 8) { 672 scr->reg12_value = NGLE_BUFF1_CMAP3; 673 scr->cmap_finish_register = NGLE_REG_1; 674 } else { 675 scr->reg12_value = NGLE_ARTIST_CMAP0; 676 scr->cmap_finish_register = NGLE_REG_26; 677 } 678 break; 679 680 case STI_DD_GRX: 681 case STI_DD_CRX24: 682 case STI_DD_EVRX: 683 case STI_DD_3X2V: 684 case STI_DD_DUAL_CRX: 685 case STI_DD_HCRX: 686 case STI_DD_LEGO: 687 case STI_DD_SUMMIT: 688 case STI_DD_PINNACLE: 689 default: 690 scr->setupfb = NULL; 691 scr->putcmap = 692 rom->scment == NULL ? NULL : ngle_default_putcmap; 693 break; 694 } 695 #endif 696 697 return 0; 698 699 fail: 700 /* XXX free resources */ 701 if (scr->scr_ecfg.addr != NULL) { 702 free(scr->scr_ecfg.addr, M_DEVBUF); 703 scr->scr_ecfg.addr = NULL; 704 } 705 706 return ENXIO; 707 } 708 709 void 710 sti_describe_screen(struct sti_softc *sc, struct sti_screen *scr) 711 { 712 struct sti_font *fp = &scr->scr_curfont; 713 714 aprint_normal("%s: %s, %dx%d frame buffer, %dx%dx%d display\n", 715 device_xname(sc->sc_dev), scr->name, scr->fbwidth, scr->fbheight, 716 scr->scr_cfg.scr_width, scr->scr_cfg.scr_height, scr->scr_bpp); 717 718 aprint_normal("%s: %dx%d font type %d, %d bpc, charset %d-%d\n", 719 device_xname(sc->sc_dev), fp->width, fp->height, 720 fp->type, fp->bpc, fp->first, fp->last); 721 } 722 723 void 724 sti_describe(struct sti_softc *sc) 725 { 726 struct sti_rom *rom = sc->sc_rom; 727 struct sti_dd *dd = &rom->rom_dd; 728 729 aprint_normal(": rev %d.%02d;%d, ID 0x%08X%08X\n", 730 dd->dd_grrev >> 4, dd->dd_grrev & 0xf, 731 dd->dd_lrrev, dd->dd_grid[0], dd->dd_grid[1]); 732 733 if (sc->sc_scr != NULL) 734 sti_describe_screen(sc, sc->sc_scr); 735 } 736 737 /* 738 * Final part of attachment. On hppa where we use the PDC console 739 * during autoconf, this has to be postponed until autoconf has 740 * completed. 741 */ 742 void 743 sti_end_attach(struct sti_softc *sc) 744 { 745 struct sti_screen *scr = sc->sc_scr; 746 747 if (scr == NULL) 748 return; 749 #if NWSDISPLAY > 0 750 else { 751 struct wsemuldisplaydev_attach_args waa; 752 scr->scr_wsmode = WSDISPLAYIO_MODE_EMUL; 753 754 waa.console = sc->sc_flags & STI_CONSOLE ? 1 : 0; 755 waa.scrdata = &scr->scr_screenlist; 756 waa.accessops = &sti_accessops; 757 waa.accesscookie = scr; 758 759 /* attach as console if required */ 760 if (waa.console && !ISSET(sc->sc_flags, STI_ATTACHED)) { 761 long defattr; 762 763 sti_alloc_attr(scr, 0, 0, 0, &defattr); 764 wsdisplay_cnattach(&scr->scr_wsd, scr, 765 0, scr->scr_wsd.nrows - 1, defattr); 766 sc->sc_flags |= STI_ATTACHED; 767 } 768 769 config_found(sc->sc_dev, &waa, wsemuldisplaydevprint, 770 CFARG_EOL); 771 } 772 #endif 773 } 774 775 u_int 776 sti_rom_size(bus_space_tag_t memt, bus_space_handle_t romh) 777 { 778 int devtype; 779 u_int romend; 780 781 devtype = bus_space_read_1(memt, romh, 3); 782 if (devtype == STI_DEVTYPE4) { 783 bus_space_read_region_stream_4(memt, romh, STI_DEV4_DD_ROMEND, 784 (uint32_t *)&romend, 1); 785 } else { 786 romend = parseword(STI_DEV1_DD_ROMEND); 787 } 788 789 DPRINTF(("%s: %08x (%08x)\n", __func__, romend, round_page(romend))); 790 791 return round_page(romend); 792 } 793 794 int 795 sti_fetchfonts(struct sti_screen *scr, struct sti_inqconfout *cfg, 796 uint32_t baseaddr, u_int fontindex) 797 { 798 struct sti_rom *rom = scr->scr_rom; 799 bus_space_tag_t memt = rom->memt; 800 bus_space_handle_t romh = rom->romh; 801 struct sti_font *fp = &scr->scr_curfont; 802 uint32_t addr; 803 int size; 804 #ifdef notyet 805 int uc; 806 struct { 807 struct sti_unpmvflags flags; 808 struct sti_unpmvin in; 809 struct sti_unpmvout out; 810 } a; 811 #endif 812 813 /* 814 * Get the first PROM font in memory 815 */ 816 817 STI_ENABLE_ROM(rom->rom_softc); 818 819 rescan: 820 addr = baseaddr; 821 do { 822 if (rom->rom_devtype == STI_DEVTYPE1) { 823 fp->first = parseshort(addr + 0x00); 824 fp->last = parseshort(addr + 0x08); 825 fp->width = bus_space_read_1(memt, romh, addr + 0x13); 826 fp->height = bus_space_read_1(memt, romh, addr + 0x17); 827 fp->type = bus_space_read_1(memt, romh, addr + 0x1b); 828 fp->bpc = bus_space_read_1(memt, romh, addr + 0x1f); 829 fp->next = parseword(addr + 0x20); 830 fp->uheight= bus_space_read_1(memt, romh, addr + 0x33); 831 fp->uoffset= bus_space_read_1(memt, romh, addr + 0x37); 832 } else { /* STI_DEVTYPE4 */ 833 bus_space_read_region_stream_4(memt, romh, addr, 834 (uint32_t *)fp, sizeof(struct sti_font) / 4); 835 } 836 837 #ifdef STIDEBUG 838 STI_DISABLE_ROM(rom->rom_softc); 839 DPRINTF(("%s: %dx%d font type %d, %d bpc, charset %d-%d\n", 840 device_xname(scr->scr_rom->rom_softc->sc_dev), fp->width, 841 fp->height, fp->type, fp->bpc, fp->first, fp->last)); 842 STI_ENABLE_ROM(rom->rom_softc); 843 #endif 844 845 if (fontindex == 0) { 846 size = sizeof(struct sti_font) + 847 (fp->last - fp->first + 1) * fp->bpc; 848 if (rom->rom_devtype == STI_DEVTYPE1) 849 size *= 4; 850 scr->scr_romfont = malloc(size, M_DEVBUF, M_WAITOK); 851 852 bus_space_read_region_stream_4(memt, romh, addr, 853 (uint32_t *)scr->scr_romfont, size / 4); 854 break; 855 } 856 857 addr = baseaddr + fp->next; 858 fontindex--; 859 } while (fp->next != 0); 860 861 /* 862 * If our font index was bogus, we did not find the expected font. 863 * In this case, pick the first one and be done with it. 864 */ 865 if (fp->next == 0 && scr->scr_romfont == NULL) { 866 fontindex = 0; 867 goto rescan; 868 } 869 870 STI_DISABLE_ROM(rom->rom_softc); 871 872 #ifdef notyet 873 /* 874 * If there is enough room in the off-screen framebuffer memory, 875 * display all the characters there in order to display them 876 * faster with blkmv operations rather than unpmv later on. 877 */ 878 if (size <= cfg->fbheight * 879 (cfg->fbwidth - cfg->width - cfg->owidth)) { 880 memset(&a, 0, sizeof(a)); 881 a.flags.flags = STI_UNPMVF_WAIT; 882 a.in.fg_colour = STI_COLOUR_WHITE; 883 a.in.bg_colour = STI_COLOUR_BLACK; 884 a.in.font_addr = scr->scr_romfont; 885 886 scr->scr_fontmaxcol = cfg->fbheight / fp->height; 887 scr->scr_fontbase = cfg->width + cfg->owidth; 888 for (uc = fp->first; uc <= fp->last; uc++) { 889 a.in.x = ((uc - fp->first) / scr->scr_fontmaxcol) * 890 fp->width + scr->scr_fontbase; 891 a.in.y = ((uc - fp->first) % scr->scr_fontmaxcol) * 892 fp->height; 893 a.in.index = uc; 894 895 (*scr->unpmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg); 896 if (a.out.errno) { 897 aprint_error_dev(sc->sc_dev, "unpmv %d " 898 "returned %d\n", uc, a.out.errno); 899 return 0; 900 } 901 } 902 903 free(scr->scr_romfont, M_DEVBUF); 904 scr->scr_romfont = NULL; 905 } 906 #endif 907 908 return 0; 909 } 910 911 /* 912 * Wrappers around STI code pointers 913 */ 914 915 int 916 sti_init(struct sti_screen *scr, int mode) 917 { 918 struct sti_rom *rom = scr->scr_rom; 919 struct { 920 struct sti_initflags flags; 921 struct sti_initin in; 922 struct sti_einitin ein; 923 struct sti_initout out; 924 } a; 925 926 KASSERT(rom != NULL); 927 memset(&a, 0, sizeof(a)); 928 929 a.flags.flags = STI_INITF_WAIT | STI_INITF_EBET; 930 if ((mode & STI_TEXTMODE) != 0) { 931 a.flags.flags |= STI_INITF_TEXT | STI_INITF_CMB | 932 STI_INITF_PBET | STI_INITF_PBETI | STI_INITF_ICMT; 933 } else { 934 a.flags.flags |= STI_INITF_NTEXT; 935 } 936 if ((mode & STI_CLEARSCR) != 0) 937 a.flags.flags |= STI_INITF_CLEAR; 938 939 a.in.text_planes = 1; 940 a.in.ext_in = &a.ein; 941 942 DPRINTF(("%s: init,%p(%x, %p, %p, %p)\n", 943 device_xname(rom->rom_softc->sc_dev), rom->init, a.flags.flags, 944 &a.in, &a.out, &scr->scr_cfg)); 945 946 (*rom->init)(&a.flags, &a.in, &a.out, &scr->scr_cfg); 947 948 if (a.out.text_planes != a.in.text_planes) 949 return -1; /* not colliding with sti errno values */ 950 return a.out.errno; 951 } 952 953 int 954 sti_inqcfg(struct sti_screen *scr, struct sti_inqconfout *out) 955 { 956 struct sti_rom *rom = scr->scr_rom; 957 struct { 958 struct sti_inqconfflags flags; 959 struct sti_inqconfin in; 960 } a; 961 962 memset(&a, 0, sizeof(a)); 963 964 a.flags.flags = STI_INQCONFF_WAIT; 965 (*rom->inqconf)(&a.flags, &a.in, out, &scr->scr_cfg); 966 967 return out->errno; 968 } 969 970 void 971 sti_bmove(struct sti_screen *scr, int x1, int y1, int x2, int y2, int h, int w, 972 enum sti_bmove_funcs f) 973 { 974 struct sti_rom *rom = scr->scr_rom; 975 struct { 976 struct sti_blkmvflags flags; 977 struct sti_blkmvin in; 978 struct sti_blkmvout out; 979 } a; 980 981 memset(&a, 0, sizeof(a)); 982 983 a.flags.flags = STI_BLKMVF_WAIT; 984 switch (f) { 985 case bmf_clear: 986 a.flags.flags |= STI_BLKMVF_CLR; 987 a.in.bg_colour = STI_COLOUR_BLACK; 988 break; 989 case bmf_underline: 990 case bmf_copy: 991 a.in.fg_colour = STI_COLOUR_WHITE; 992 a.in.bg_colour = STI_COLOUR_BLACK; 993 break; 994 case bmf_invert: 995 a.flags.flags |= STI_BLKMVF_COLR; 996 a.in.fg_colour = STI_COLOUR_BLACK; 997 a.in.bg_colour = STI_COLOUR_WHITE; 998 break; 999 } 1000 a.in.srcx = x1; 1001 a.in.srcy = y1; 1002 a.in.dstx = x2; 1003 a.in.dsty = y2; 1004 a.in.height = h; 1005 a.in.width = w; 1006 1007 (*rom->blkmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg); 1008 #ifdef STIDEBUG 1009 if (a.out.errno) 1010 printf("%s: blkmv returned %d\n", 1011 device_xname(rom->rom_softc->sc_dev), a.out.errno); 1012 #endif 1013 } 1014 1015 int 1016 sti_setcment(struct sti_screen *scr, u_int i, u_char r, u_char g, u_char b) 1017 { 1018 struct sti_rom *rom = scr->scr_rom; 1019 struct { 1020 struct sti_scmentflags flags; 1021 struct sti_scmentin in; 1022 struct sti_scmentout out; 1023 } a; 1024 1025 memset(&a, 0, sizeof(a)); 1026 1027 a.flags.flags = STI_SCMENTF_WAIT; 1028 a.in.entry = i; 1029 a.in.value = (r << 16) | (g << 8) | b; 1030 1031 (*rom->scment)(&a.flags, &a.in, &a.out, &scr->scr_cfg); 1032 1033 return a.out.errno; 1034 } 1035 1036 /* 1037 * wsdisplay accessops 1038 */ 1039 int 1040 sti_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l) 1041 { 1042 struct sti_screen *scr = (struct sti_screen *)v; 1043 struct wsdisplay_fbinfo *wdf; 1044 struct wsdisplay_cmap *cmapp; 1045 u_int mode, idx, count; 1046 int ret; 1047 1048 ret = 0; 1049 switch (cmd) { 1050 case WSDISPLAYIO_GMODE: 1051 *(u_int *)data = scr->scr_wsmode; 1052 break; 1053 1054 case WSDISPLAYIO_SMODE: 1055 mode = *(u_int *)data; 1056 switch (mode) { 1057 case WSDISPLAYIO_MODE_EMUL: 1058 if (scr->scr_wsmode != WSDISPLAYIO_MODE_EMUL) 1059 ret = sti_init(scr, STI_TEXTMODE); 1060 break; 1061 case WSDISPLAYIO_MODE_DUMBFB: 1062 if (scr->scr_wsmode != WSDISPLAYIO_MODE_DUMBFB) { 1063 sti_init(scr, 0); 1064 if (scr->setupfb != NULL) 1065 scr->setupfb(scr); 1066 else 1067 #if 0 1068 ret = sti_init(scr, STI_FBMODE); 1069 #else 1070 ret = EINVAL; 1071 #endif 1072 } 1073 break; 1074 case WSDISPLAYIO_MODE_MAPPED: 1075 default: 1076 ret = EINVAL; 1077 break; 1078 } 1079 if (ret == 0) 1080 scr->scr_wsmode = mode; 1081 break; 1082 1083 case WSDISPLAYIO_GTYPE: 1084 *(u_int *)data = WSDISPLAY_TYPE_STI; 1085 break; 1086 1087 case WSDISPLAYIO_GINFO: 1088 wdf = (struct wsdisplay_fbinfo *)data; 1089 wdf->height = scr->scr_cfg.scr_height; 1090 wdf->width = scr->scr_cfg.scr_width; 1091 wdf->depth = scr->scr_bpp; 1092 if (scr->putcmap == NULL || scr->scr_bpp > 8) 1093 wdf->cmsize = 0; 1094 else 1095 wdf->cmsize = STI_NCMAP; 1096 break; 1097 1098 case WSDISPLAYIO_LINEBYTES: 1099 if (scr->scr_bpp > 8) 1100 *(u_int *)data = scr->scr_cfg.fb_width * 4; 1101 else 1102 *(u_int *)data = scr->scr_cfg.fb_width; 1103 break; 1104 1105 case WSDISPLAYIO_GETCMAP: 1106 if (scr->putcmap == NULL || scr->scr_bpp > 8) 1107 return ENODEV; 1108 cmapp = (struct wsdisplay_cmap *)data; 1109 idx = cmapp->index; 1110 count = cmapp->count; 1111 if (idx >= STI_NCMAP || count > STI_NCMAP - idx) 1112 return EINVAL; 1113 if ((ret = copyout(&scr->scr_rcmap[idx], cmapp->red, count))) 1114 break; 1115 if ((ret = copyout(&scr->scr_gcmap[idx], cmapp->green, count))) 1116 break; 1117 if ((ret = copyout(&scr->scr_bcmap[idx], cmapp->blue, count))) 1118 break; 1119 break; 1120 1121 case WSDISPLAYIO_PUTCMAP: 1122 if (scr->putcmap == NULL || scr->scr_bpp > 8) 1123 return ENODEV; 1124 if (scr->scr_wsmode == WSDISPLAYIO_MODE_EMUL) { 1125 /* 1126 * The hardware palette settings are handled by 1127 * the STI ROM in STI_TEXTMODE and changing cmap 1128 * could cause mangled text colors at least on CRX. 1129 * Updating CMAP in EMUL mode isn't expected anyway 1130 * so just ignore it. 1131 */ 1132 return 0; 1133 } 1134 cmapp = (struct wsdisplay_cmap *)data; 1135 idx = cmapp->index; 1136 count = cmapp->count; 1137 if (idx >= STI_NCMAP || count > STI_NCMAP - idx) 1138 return EINVAL; 1139 if ((ret = copyin(cmapp->red, &scr->scr_rcmap[idx], count))) 1140 break; 1141 if ((ret = copyin(cmapp->green, &scr->scr_gcmap[idx], count))) 1142 break; 1143 if ((ret = copyin(cmapp->blue, &scr->scr_bcmap[idx], count))) 1144 break; 1145 ret = scr->putcmap(scr, idx, count); 1146 break; 1147 1148 case WSDISPLAYIO_SVIDEO: 1149 case WSDISPLAYIO_GVIDEO: 1150 case WSDISPLAYIO_GCURPOS: 1151 case WSDISPLAYIO_SCURPOS: 1152 case WSDISPLAYIO_GCURMAX: 1153 case WSDISPLAYIO_GCURSOR: 1154 case WSDISPLAYIO_SCURSOR: 1155 default: 1156 return ENOTTY; /* not supported yet */ 1157 } 1158 1159 return ret; 1160 } 1161 1162 paddr_t 1163 sti_mmap(void *v, void *vs, off_t offset, int prot) 1164 { 1165 struct sti_screen *scr = (struct sti_screen *)v; 1166 struct sti_rom *rom = scr->scr_rom; 1167 paddr_t pa; 1168 1169 if ((offset & PAGE_MASK) != 0) 1170 return -1; 1171 1172 if (offset < 0 || offset >= scr->fblen) 1173 return -1; 1174 1175 if (scr->scr_wsmode != WSDISPLAYIO_MODE_DUMBFB) 1176 return -1; 1177 1178 pa = bus_space_mmap(rom->memt, scr->fbaddr, offset, prot, 1179 BUS_SPACE_MAP_LINEAR); 1180 1181 if (pa == -1) 1182 pa = scr->fbaddr + offset; 1183 1184 return pa; 1185 } 1186 1187 int 1188 sti_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep, 1189 int *cxp, int *cyp, long *defattr) 1190 { 1191 struct sti_screen *scr = (struct sti_screen *)v; 1192 1193 if (scr->scr_nscreens > 0) 1194 return ENOMEM; 1195 1196 *cookiep = scr; 1197 *cxp = 0; 1198 *cyp = 0; 1199 sti_alloc_attr(scr, 0, 0, 0, defattr); 1200 scr->scr_nscreens++; 1201 return 0; 1202 } 1203 1204 void 1205 sti_free_screen(void *v, void *cookie) 1206 { 1207 struct sti_screen *scr = (struct sti_screen *)v; 1208 1209 scr->scr_nscreens--; 1210 } 1211 1212 int 1213 sti_show_screen(void *v, void *cookie, int waitok, void (*cb)(void *, int, int), 1214 void *cbarg) 1215 { 1216 #if 0 1217 struct sti_screen *scr = (struct sti_screen *)v; 1218 #endif 1219 1220 return 0; 1221 } 1222 1223 int 1224 sti_load_font(void *v, void *cookie, struct wsdisplay_font *font) 1225 { 1226 #if 0 1227 struct sti_screen *scr = (struct sti_screen *)v; 1228 #endif 1229 1230 return -1; 1231 } 1232 1233 /* 1234 * wsdisplay emulops 1235 */ 1236 void 1237 sti_cursor(void *v, int on, int row, int col) 1238 { 1239 struct sti_screen *scr = (struct sti_screen *)v; 1240 struct sti_font *fp = &scr->scr_curfont; 1241 1242 sti_bmove(scr, 1243 col * fp->width, row * fp->height, 1244 col * fp->width, row * fp->height, 1245 fp->height, fp->width, bmf_invert); 1246 } 1247 1248 /* 1249 * ISO 8859-1 part of Unicode to HP Roman font index conversion array. 1250 */ 1251 static const uint8_t 1252 sti_unitoroman[0x100 - 0xa0] = { 1253 0xa0, 0xb8, 0xbf, 0xbb, 0xba, 0xbc, 0, 0xbd, 1254 0xab, 0, 0xf9, 0xfb, 0, 0xf6, 0, 0xb0, 1255 1256 0xb3, 0xfe, 0, 0, 0xa8, 0xf3, 0xf4, 0xf2, 1257 0, 0, 0xfa, 0xfd, 0xf7, 0xf8, 0, 0xb9, 1258 1259 0xa1, 0xe0, 0xa2, 0xe1, 0xd8, 0xd0, 0xd3, 0xb4, 1260 0xa3, 0xdc, 0xa4, 0xa5, 0xe6, 0xe5, 0xa6, 0xa7, 1261 1262 0xe3, 0xb6, 0xe8, 0xe7, 0xdf, 0xe9, 0xda, 0, 1263 0xd2, 0xad, 0xed, 0xae, 0xdb, 0xb1, 0xf0, 0xde, 1264 1265 0xc8, 0xc4, 0xc0, 0xe2, 0xcc, 0xd4, 0xd7, 0xb5, 1266 0xc9, 0xc5, 0xc1, 0xcd, 0xd9, 0xd5, 0xd1, 0xdd, 1267 1268 0xe4, 0xb7, 0xca, 0xc6, 0xc2, 0xea, 0xce, 0, 1269 0xd6, 0xcb, 0xc7, 0xc3, 0xcf, 0xb2, 0xf1, 0xef 1270 }; 1271 1272 int 1273 sti_mapchar(void *v, int uni, u_int *index) 1274 { 1275 struct sti_screen *scr = (struct sti_screen *)v; 1276 struct sti_font *fp = &scr->scr_curfont; 1277 int c; 1278 1279 switch (fp->type) { 1280 case STI_FONT_HPROMAN8: 1281 if (uni >= 0x80 && uni < 0xa0) 1282 c = -1; 1283 else if (uni >= 0xa0 && uni < 0x100) { 1284 c = (int)sti_unitoroman[uni - 0xa0]; 1285 if (c == 0) 1286 c = -1; 1287 } else 1288 c = uni; 1289 break; 1290 default: 1291 c = uni; 1292 break; 1293 } 1294 1295 if (c == -1 || c < fp->first || c > fp->last) { 1296 *index = ' '; 1297 return 0; 1298 } 1299 1300 *index = c; 1301 return 5; 1302 } 1303 1304 void 1305 sti_putchar(void *v, int row, int col, u_int uc, long attr) 1306 { 1307 struct sti_screen *scr = (struct sti_screen *)v; 1308 struct sti_rom *rom = scr->scr_rom; 1309 struct sti_font *fp = &scr->scr_curfont; 1310 int bg, fg; 1311 1312 fg = WSATTR_UNPACK_FG(attr); 1313 bg = WSATTR_UNPACK_BG(attr); 1314 1315 if (scr->scr_romfont != NULL) { 1316 /* 1317 * Font is in memory, use unpmv 1318 */ 1319 struct { 1320 struct sti_unpmvflags flags; 1321 struct sti_unpmvin in; 1322 struct sti_unpmvout out; 1323 } a; 1324 1325 memset(&a, 0, sizeof(a)); 1326 1327 a.flags.flags = STI_UNPMVF_WAIT; 1328 a.in.fg_colour = fg; 1329 a.in.bg_colour = bg; 1330 a.in.x = col * fp->width; 1331 a.in.y = row * fp->height; 1332 a.in.font_addr = scr->scr_romfont; 1333 a.in.index = uc; 1334 1335 (*rom->unpmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg); 1336 } else { 1337 /* 1338 * Font is in frame buffer, use blkmv 1339 */ 1340 struct { 1341 struct sti_blkmvflags flags; 1342 struct sti_blkmvin in; 1343 struct sti_blkmvout out; 1344 } a; 1345 1346 memset(&a, 0, sizeof(a)); 1347 1348 a.flags.flags = STI_BLKMVF_WAIT; 1349 a.in.fg_colour = fg; 1350 a.in.bg_colour = bg; 1351 1352 a.in.srcx = ((uc - fp->first) / scr->scr_fontmaxcol) * 1353 fp->width + scr->scr_fontbase; 1354 a.in.srcy = ((uc - fp->first) % scr->scr_fontmaxcol) * 1355 fp->height; 1356 a.in.dstx = col * fp->width; 1357 a.in.dsty = row * fp->height; 1358 a.in.height = fp->height; 1359 a.in.width = fp->width; 1360 1361 (*rom->blkmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg); 1362 } 1363 } 1364 1365 void 1366 sti_copycols(void *v, int row, int srccol, int dstcol, int ncols) 1367 { 1368 struct sti_screen *scr = (struct sti_screen *)v; 1369 struct sti_font *fp = &scr->scr_curfont; 1370 1371 sti_bmove(scr, 1372 srccol * fp->width, row * fp->height, 1373 dstcol * fp->width, row * fp->height, 1374 fp->height, ncols * fp->width, bmf_copy); 1375 } 1376 1377 void 1378 sti_erasecols(void *v, int row, int startcol, int ncols, long attr) 1379 { 1380 struct sti_screen *scr = (struct sti_screen *)v; 1381 struct sti_font *fp = &scr->scr_curfont; 1382 1383 sti_bmove(scr, 1384 startcol * fp->width, row * fp->height, 1385 startcol * fp->width, row * fp->height, 1386 fp->height, ncols * fp->width, bmf_clear); 1387 } 1388 1389 void 1390 sti_copyrows(void *v, int srcrow, int dstrow, int nrows) 1391 { 1392 struct sti_screen *scr = (struct sti_screen *)v; 1393 struct sti_font *fp = &scr->scr_curfont; 1394 1395 sti_bmove(scr, 0, srcrow * fp->height, 0, dstrow * fp->height, 1396 nrows * fp->height, scr->scr_cfg.scr_width, bmf_copy); 1397 } 1398 1399 void 1400 sti_eraserows(void *v, int srcrow, int nrows, long attr) 1401 { 1402 struct sti_screen *scr = (struct sti_screen *)v; 1403 struct sti_font *fp = &scr->scr_curfont; 1404 1405 sti_bmove(scr, 0, srcrow * fp->height, 0, srcrow * fp->height, 1406 nrows * fp->height, scr->scr_cfg.scr_width, bmf_clear); 1407 } 1408 1409 int 1410 sti_alloc_attr(void *v, int fg, int bg, int flags, long *pattr) 1411 { 1412 #if 0 1413 struct sti_screen *scr = (struct sti_screen *)v; 1414 #endif 1415 1416 if ((flags & (WSATTR_HILIT | WSATTR_BLINK | 1417 WSATTR_UNDERLINE | WSATTR_WSCOLORS)) != 0) 1418 return EINVAL; 1419 if ((flags & WSATTR_REVERSE) != 0) { 1420 fg = STI_COLOUR_BLACK; 1421 bg = STI_COLOUR_WHITE; 1422 } else { 1423 fg = STI_COLOUR_WHITE; 1424 bg = STI_COLOUR_BLACK; 1425 } 1426 1427 *pattr = WSATTR_PACK(fg, bg, flags); 1428 return 0; 1429 } 1430 1431 /* 1432 * Early console support. Only used on hp300, currently 1433 */ 1434 int 1435 sti_cnattach(struct sti_rom *rom, struct sti_screen *scr, bus_space_tag_t memt, 1436 bus_addr_t *bases, u_int codebase) 1437 { 1438 bus_space_handle_t romh; 1439 u_int romend; 1440 int error; 1441 long defattr; 1442 1443 if ((error = bus_space_map(memt, bases[0], PAGE_SIZE, 0, &romh)) != 0) 1444 return error; 1445 1446 /* 1447 * Compute real PROM size 1448 */ 1449 romend = sti_rom_size(memt, romh); 1450 1451 bus_space_unmap(memt, romh, PAGE_SIZE); 1452 1453 if ((error = bus_space_map(memt, bases[0], romend, 0, &romh)) != 0) 1454 return error; 1455 1456 bases[0] = romh; 1457 if (sti_rom_setup(rom, memt, memt, romh, bases, codebase) != 0) 1458 return -1; 1459 scr->scr_rom = rom; 1460 if (sti_screen_setup(scr, STI_CLEARSCR) != 0) 1461 return -1; 1462 1463 sti_alloc_attr(scr, 0, 0, 0, &defattr); 1464 wsdisplay_cnattach(&scr->scr_wsd, scr, 0, 0, defattr); 1465 1466 return 0; 1467 } 1468 1469 int 1470 ngle_default_putcmap(struct sti_screen *scr, u_int idx, u_int count) 1471 { 1472 int i, ret; 1473 1474 for (i = idx + count - 1; i >= (int)idx; i--) 1475 if ((ret = sti_setcment(scr, i, scr->scr_rcmap[i], 1476 scr->scr_gcmap[i], scr->scr_bcmap[i]))) 1477 return EINVAL; 1478 1479 return 0; 1480 } 1481 1482 #ifndef SMALL_KERNEL 1483 1484 void ngle_setup_hw(bus_space_tag_t, bus_space_handle_t); 1485 void ngle_setup_fb(bus_space_tag_t, bus_space_handle_t, uint32_t); 1486 void ngle_setup_attr_planes(struct sti_screen *scr); 1487 void ngle_setup_bt458(struct sti_screen *scr); 1488 1489 #define ngle_bt458_write(memt, memh, r, v) \ 1490 bus_space_write_4(memt, memh, NGLE_REG_RAMDAC + ((r) << 2), (v) << 24) 1491 1492 void 1493 ngle_artist_setupfb(struct sti_screen *scr) 1494 { 1495 struct sti_rom *rom = scr->scr_rom; 1496 bus_space_tag_t memt = rom->memt; 1497 bus_space_handle_t memh = rom->regh[2]; 1498 1499 ngle_setup_bt458(scr); 1500 1501 ngle_setup_hw(memt, memh); 1502 ngle_setup_fb(memt, memh, scr->reg10_value); 1503 1504 ngle_setup_attr_planes(scr); 1505 1506 ngle_setup_hw(memt, memh); 1507 bus_space_write_4(memt, memh, NGLE_REG_21, 1508 bus_space_read_4(memt, memh, NGLE_REG_21) | 0x0a000000); 1509 bus_space_write_4(memt, memh, NGLE_REG_27, 1510 bus_space_read_4(memt, memh, NGLE_REG_27) | 0x00800000); 1511 } 1512 1513 void 1514 ngle_elk_setupfb(struct sti_screen *scr) 1515 { 1516 struct sti_rom *rom = scr->scr_rom; 1517 bus_space_tag_t memt = rom->memt; 1518 bus_space_handle_t memh = rom->regh[2]; 1519 1520 ngle_setup_bt458(scr); 1521 1522 ngle_setup_hw(memt, memh); 1523 ngle_setup_fb(memt, memh, scr->reg10_value); 1524 1525 ngle_setup_attr_planes(scr); 1526 1527 ngle_setup_hw(memt, memh); 1528 /* enable overlay planes in Bt458 command register */ 1529 ngle_bt458_write(memt, memh, 0x0c, 0x06); 1530 ngle_bt458_write(memt, memh, 0x0e, 0x43); 1531 } 1532 1533 void 1534 ngle_timber_setupfb(struct sti_screen *scr) 1535 { 1536 struct sti_rom *rom = scr->scr_rom; 1537 bus_space_tag_t memt = rom->memt; 1538 bus_space_handle_t memh = rom->regh[2]; 1539 1540 ngle_setup_bt458(scr); 1541 1542 ngle_setup_hw(memt, memh); 1543 /* enable overlay planes in Bt458 command register */ 1544 ngle_bt458_write(memt, memh, 0x0c, 0x06); 1545 ngle_bt458_write(memt, memh, 0x0e, 0x43); 1546 } 1547 1548 void 1549 ngle_setup_bt458(struct sti_screen *scr) 1550 { 1551 struct sti_rom *rom = scr->scr_rom; 1552 bus_space_tag_t memt = rom->memt; 1553 bus_space_handle_t memh = rom->regh[2]; 1554 1555 ngle_setup_hw(memt, memh); 1556 /* set Bt458 read mask register to all planes */ 1557 ngle_bt458_write(memt, memh, 0x08, 0x04); 1558 ngle_bt458_write(memt, memh, 0x0a, 0xff); 1559 } 1560 1561 void 1562 ngle_setup_attr_planes(struct sti_screen *scr) 1563 { 1564 struct sti_rom *rom = scr->scr_rom; 1565 bus_space_tag_t memt = rom->memt; 1566 bus_space_handle_t memh = rom->regh[2]; 1567 1568 ngle_setup_hw(memt, memh); 1569 bus_space_write_4(memt, memh, NGLE_REG_11, 0x2ea0d000); 1570 bus_space_write_4(memt, memh, NGLE_REG_14, 0x23000302); 1571 bus_space_write_4(memt, memh, NGLE_REG_12, scr->reg12_value); 1572 bus_space_write_4(memt, memh, NGLE_REG_8, 0xffffffff); 1573 1574 bus_space_write_4(memt, memh, NGLE_REG_6, 0x00000000); 1575 bus_space_write_4(memt, memh, NGLE_REG_9, 1576 (scr->scr_cfg.scr_width << 16) | scr->scr_cfg.scr_height); 1577 bus_space_write_4(memt, memh, NGLE_REG_6, 0x05000000); 1578 bus_space_write_4(memt, memh, NGLE_REG_9, 0x00040001); 1579 1580 ngle_setup_hw(memt, memh); 1581 bus_space_write_4(memt, memh, NGLE_REG_12, 0x00000000); 1582 1583 ngle_setup_fb(memt, memh, scr->reg10_value); 1584 } 1585 1586 int 1587 ngle_putcmap(struct sti_screen *scr, u_int idx, u_int count) 1588 { 1589 struct sti_rom *rom = scr->scr_rom; 1590 bus_space_tag_t memt = rom->memt; 1591 bus_space_handle_t memh = rom->regh[2]; 1592 uint8_t *r, *g, *b; 1593 uint32_t cmap_finish; 1594 1595 if (scr->scr_bpp > 8) 1596 cmap_finish = 0x83000100; 1597 else 1598 cmap_finish = 0x80000100; 1599 1600 r = scr->scr_rcmap + idx; 1601 g = scr->scr_gcmap + idx; 1602 b = scr->scr_bcmap + idx; 1603 1604 ngle_setup_hw(memt, memh); 1605 bus_space_write_4(memt, memh, NGLE_REG_10, 0xbbe0f000); 1606 bus_space_write_4(memt, memh, NGLE_REG_14, 0x03000300); 1607 bus_space_write_4(memt, memh, NGLE_REG_13, 0xffffffff); 1608 1609 while (count-- != 0) { 1610 ngle_setup_hw(memt, memh); 1611 bus_space_write_4(memt, memh, NGLE_REG_3, 0x400 | (idx << 2)); 1612 bus_space_write_4(memt, memh, NGLE_REG_4, 1613 (*r << 16) | (*g << 8) | *b); 1614 1615 idx++; 1616 r++, g++, b++; 1617 } 1618 1619 bus_space_write_4(memt, memh, NGLE_REG_2, 0x400); 1620 bus_space_write_4(memt, memh, scr->cmap_finish_register, cmap_finish); 1621 ngle_setup_fb(memt, memh, scr->reg10_value); 1622 1623 1624 return 0; 1625 } 1626 1627 void 1628 ngle_setup_hw(bus_space_tag_t memt, bus_space_handle_t memh) 1629 { 1630 uint8_t stat; 1631 1632 do { 1633 stat = bus_space_read_1(memt, memh, NGLE_REG_15b0); 1634 if (stat == 0) 1635 stat = bus_space_read_1(memt, memh, NGLE_REG_15b0); 1636 } while (stat != 0); 1637 } 1638 1639 void 1640 ngle_setup_fb(bus_space_tag_t memt, bus_space_handle_t memh, uint32_t reg10) 1641 { 1642 1643 ngle_setup_hw(memt, memh); 1644 bus_space_write_4(memt, memh, NGLE_REG_10, reg10); 1645 bus_space_write_4(memt, memh, NGLE_REG_14, 0x83000300); 1646 ngle_setup_hw(memt, memh); 1647 bus_space_write_1(memt, memh, NGLE_REG_16b1, 1); 1648 } 1649 #endif /* SMALL_KERNEL */ 1650