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