1 /* $NetBSD: sti.c,v 1.43 2024/12/10 09:13:00 macallan 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.43 2024/12/10 09:13:00 macallan 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 << PGSHIFT); 451 DPRINTF(("%08x @ 0x%08x%s%s%s%s", 452 r->length << PGSHIFT, (int)addr, r->sys_only ? " sys" : "", 453 r->cache ? " cache" : "", r->btlb ? " btlb" : "", 454 r->last ? " last" : "")); 455 456 /* 457 * Region #0 is always the rom, and it should have been 458 * mapped already. 459 * XXX This expects a 1:1 mapping... 460 */ 461 if (regno == 0 && romh == bases[0]) { 462 cc->regions[0] = addr; 463 DPRINTF(("\n")); 464 continue; 465 } 466 467 if (bus_space_map(memt, addr, r->length << PGSHIFT, 468 BUS_SPACE_MAP_LINEAR | (r->cache ? 469 BUS_SPACE_MAP_CACHEABLE : 0), &rom->regh[regno]) != 0) { 470 rom->regh[regno] = romh; /* XXX */ 471 DPRINTF((" - already mapped region\n")); 472 } else { 473 addr = (bus_addr_t) 474 bus_space_vaddr(memt, rom->regh[regno]); 475 if (regno == 1) { 476 DPRINTF((" - fb")); 477 scr->fbaddr = addr; 478 scr->fblen = r->length << PGSHIFT; 479 } 480 DPRINTF(("\n")); 481 } 482 483 cc->regions[regno] = addr; 484 } 485 486 #ifdef STIDEBUG 487 /* 488 * Make sure we'll trap accessing unmapped regions 489 */ 490 for (regno = 0; regno < STI_REGION_MAX; regno++) 491 if (cc->regions[regno] == 0) 492 cc->regions[regno] = 0x81234567; 493 #endif 494 } 495 496 int 497 sti_screen_setup(struct sti_screen *scr, int flags) 498 { 499 struct sti_rom *rom = scr->scr_rom; 500 bus_space_tag_t memt = rom->memt; 501 bus_space_handle_t romh = rom->romh; 502 struct sti_dd *dd = &rom->rom_dd; 503 struct sti_cfg *cc = &scr->scr_cfg; 504 struct sti_inqconfout cfg; 505 struct sti_einqconfout ecfg; 506 #ifdef STIDEBUG 507 char buf[256]; 508 #endif 509 int error, i; 510 int geometry_kluge = 0; 511 u_int fontindex = 0; 512 513 KASSERT(scr != NULL); 514 memset(cc, 0, sizeof(*cc)); 515 cc->ext_cfg = &scr->scr_ecfg; 516 memset(cc->ext_cfg, 0, sizeof(*cc->ext_cfg)); 517 518 if (dd->dd_stimemreq) { 519 scr->scr_ecfg.addr = 520 malloc(dd->dd_stimemreq, M_DEVBUF, M_WAITOK); 521 } 522 523 sti_region_setup(scr); 524 525 if ((error = sti_init(scr, 0))) { 526 aprint_error(": cannot initialize (%d)\n", error); 527 goto fail; 528 } 529 530 memset(&cfg, 0, sizeof(cfg)); 531 memset(&ecfg, 0, sizeof(ecfg)); 532 cfg.ext = &ecfg; 533 if ((error = sti_inqcfg(scr, &cfg))) { 534 aprint_error(": error %d inquiring config\n", error); 535 goto fail; 536 } 537 538 /* 539 * Older (rev 8.02) boards report wrong offset values, 540 * similar to the displayable area size, at least in m68k mode. 541 * Attempt to detect this and adjust here. 542 */ 543 if (cfg.owidth == cfg.width && 544 cfg.oheight == cfg.height) 545 geometry_kluge = 1; 546 547 if (geometry_kluge) { 548 scr->scr_cfg.oscr_width = cfg.owidth = 549 cfg.fbwidth - cfg.width; 550 scr->scr_cfg.oscr_height = cfg.oheight = 551 cfg.fbheight - cfg.height; 552 } 553 554 /* 555 * Save a few fields for sti_describe_screen() later 556 */ 557 scr->fbheight = cfg.fbheight; 558 scr->fbwidth = cfg.fbwidth; 559 scr->oheight = cfg.oheight; 560 scr->owidth = cfg.owidth; 561 memcpy(scr->name, cfg.name, sizeof(scr->name)); 562 563 if (flags & STI_FBMODE) { 564 /* we're done here */ 565 sti_init(scr, STI_FBMODE); 566 return 0; 567 } 568 569 if ((error = sti_init(scr, STI_TEXTMODE | flags))) { 570 aprint_error(": cannot initialize (%d)\n", error); 571 goto fail; 572 } 573 #ifdef STIDEBUG 574 snprintb(buf, sizeof(buf), STI_INQCONF_BITS, cfg.attributes); 575 DPRINTF(("conf: bpp=%d planes=%d attr=%s\n" 576 "crt=0x%x:0x%x:0x%x hw=0x%x:0x%x:0x%x\n", cfg.bpp, 577 cfg.planes, buf, 578 ecfg.crt_config[0], ecfg.crt_config[1], ecfg.crt_config[2], 579 ecfg.crt_hw[0], ecfg.crt_hw[1], ecfg.crt_hw[2])); 580 #endif 581 scr->scr_bpp = cfg.bppu; 582 583 /* 584 * Although scr->scr_ecfg.current_monitor is not filled by 585 * sti_init() as expected, we can nevertheless walk the monitor 586 * list, if there is any, and if we find a mode matching our 587 * resolution, pick its font index. 588 */ 589 if (dd->dd_montbl != 0) { 590 STI_ENABLE_ROM(rom->rom_softc); 591 592 for (i = 0; i < dd->dd_nmon; i++) { 593 u_int offs = dd->dd_montbl + 8 * i; 594 uint32_t m[2]; 595 sti_mon_t mon = (void *)m; 596 if (rom->rom_devtype == STI_DEVTYPE1) { 597 m[0] = parseword(4 * offs); 598 m[1] = parseword(4 * (offs + 4)); 599 } else { 600 bus_space_read_region_stream_4(memt, romh, offs, 601 (uint32_t *)mon, sizeof(*mon) / 4); 602 } 603 604 if (mon->width == scr->scr_cfg.scr_width && 605 mon->height == scr->scr_cfg.scr_height) { 606 fontindex = mon->font; 607 break; 608 } 609 } 610 611 STI_DISABLE_ROM(rom->rom_softc); 612 613 DPRINTF(("font index: %d\n", fontindex)); 614 } 615 616 if ((error = sti_fetchfonts(scr, &cfg, dd->dd_fntaddr, fontindex))) { 617 aprint_error(": cannot fetch fonts (%d)\n", error); 618 goto fail; 619 } 620 621 /* 622 * setup screen descriptions: 623 * figure number of fonts supported; 624 * allocate wscons structures; 625 * calculate dimensions. 626 */ 627 628 scr->scr_wsd.name = "std"; 629 scr->scr_wsd.ncols = cfg.width / scr->scr_curfont.width; 630 scr->scr_wsd.nrows = cfg.height / scr->scr_curfont.height; 631 scr->scr_wsd.textops = &sti_emulops; 632 scr->scr_wsd.fontwidth = scr->scr_curfont.width; 633 scr->scr_wsd.fontheight = scr->scr_curfont.height; 634 scr->scr_wsd.capabilities = WSSCREEN_REVERSE; 635 636 scr->scr_scrlist[0] = &scr->scr_wsd; 637 scr->scr_screenlist.nscreens = 1; 638 scr->scr_screenlist.screens = scr->scr_scrlist; 639 640 #ifndef SMALL_KERNEL 641 /* 642 * Decide which board-specific routines to use. 643 */ 644 645 switch (dd->dd_grid[0]) { 646 case STI_DD_CRX: 647 scr->setupfb = ngle_elk_setupfb; 648 scr->putcmap = ngle_putcmap; 649 650 scr->reg10_value = 0x13601000; 651 if (scr->scr_bpp > 8) 652 scr->reg12_value = NGLE_BUFF1_CMAP3; 653 else 654 scr->reg12_value = NGLE_BUFF1_CMAP0; 655 scr->cmap_finish_register = NGLE_REG_1; 656 break; 657 658 case STI_DD_TIMBER: 659 scr->setupfb = ngle_timber_setupfb; 660 scr->putcmap = ngle_putcmap; 661 662 scr->reg10_value = 0x13602000; 663 scr->reg12_value = NGLE_BUFF1_CMAP0; 664 scr->cmap_finish_register = NGLE_REG_1; 665 break; 666 667 case STI_DD_ARTIST: 668 scr->setupfb = ngle_artist_setupfb; 669 scr->putcmap = ngle_putcmap; 670 671 scr->reg10_value = 0x13601000; 672 scr->reg12_value = NGLE_ARTIST_CMAP0; 673 scr->cmap_finish_register = NGLE_REG_26; 674 break; 675 676 case STI_DD_EG: 677 scr->setupfb = ngle_artist_setupfb; 678 scr->putcmap = ngle_putcmap; 679 680 scr->reg10_value = 0x13601000; 681 if (scr->scr_bpp > 8) { 682 scr->reg12_value = NGLE_BUFF1_CMAP3; 683 scr->cmap_finish_register = NGLE_REG_1; 684 } else { 685 scr->reg12_value = NGLE_ARTIST_CMAP0; 686 scr->cmap_finish_register = NGLE_REG_26; 687 } 688 break; 689 690 case STI_DD_HCRX: 691 scr->setupfb = ngle_elk_setupfb; 692 scr->putcmap = ngle_hcrx_putcmap; 693 694 if (scr->scr_bpp > 8) { 695 scr->reg12_value = NGLE_BUFF1_CMAP3; 696 scr->reg10_value = 0xBBA0A000; 697 } else { 698 scr->reg12_value = NGLE_BUFF1_CMAP0; 699 scr->reg10_value = 0x13602000; 700 } 701 scr->cmap_finish_register = NGLE_REG_38; 702 break; 703 704 case STI_DD_SUMMIT: 705 case STI_DD_LEGO: 706 scr->setupfb = summit_setupfb; 707 scr->putcmap = summit_putcmap; 708 scr->scr_bpp = 8; /* for now */ 709 break; 710 711 case STI_DD_GRX: 712 case STI_DD_CRX24: 713 case STI_DD_EVRX: 714 case STI_DD_3X2V: 715 case STI_DD_DUAL_CRX: 716 case STI_DD_PINNACLE: 717 default: 718 scr->setupfb = NULL; 719 scr->putcmap = 720 rom->scment == NULL ? NULL : ngle_default_putcmap; 721 break; 722 } 723 #endif 724 725 return 0; 726 727 fail: 728 /* XXX free resources */ 729 if (scr->scr_ecfg.addr != NULL) { 730 free(scr->scr_ecfg.addr, M_DEVBUF); 731 scr->scr_ecfg.addr = NULL; 732 } 733 734 return ENXIO; 735 } 736 737 void 738 sti_describe_screen(struct sti_softc *sc, struct sti_screen *scr) 739 { 740 struct sti_font *fp = &scr->scr_curfont; 741 742 aprint_normal("%s: %s, %dx%d frame buffer, %dx%dx%d display\n", 743 device_xname(sc->sc_dev), scr->name, scr->fbwidth, scr->fbheight, 744 scr->scr_cfg.scr_width, scr->scr_cfg.scr_height, scr->scr_bpp); 745 746 aprint_normal("%s: %dx%d font type %d, %d bpc, charset %d-%d\n", 747 device_xname(sc->sc_dev), fp->width, fp->height, 748 fp->type, fp->bpc, fp->first, fp->last); 749 } 750 751 void 752 sti_describe(struct sti_softc *sc) 753 { 754 struct sti_rom *rom = sc->sc_rom; 755 struct sti_dd *dd = &rom->rom_dd; 756 757 aprint_normal(": rev %d.%02d;%d, ID 0x%08X%08X\n", 758 dd->dd_grrev >> 4, dd->dd_grrev & 0xf, 759 dd->dd_lrrev, dd->dd_grid[0], dd->dd_grid[1]); 760 761 if (sc->sc_scr != NULL) 762 sti_describe_screen(sc, sc->sc_scr); 763 } 764 765 /* 766 * Final part of attachment. On hppa where we use the PDC console 767 * during autoconf, this has to be postponed until autoconf has 768 * completed. 769 */ 770 void 771 sti_end_attach(struct sti_softc *sc) 772 { 773 struct sti_screen *scr = sc->sc_scr; 774 775 if (scr == NULL) 776 return; 777 #if NWSDISPLAY > 0 778 else { 779 struct wsemuldisplaydev_attach_args waa; 780 scr->scr_wsmode = WSDISPLAYIO_MODE_EMUL; 781 782 waa.console = sc->sc_flags & STI_CONSOLE ? 1 : 0; 783 waa.scrdata = &scr->scr_screenlist; 784 waa.accessops = &sti_accessops; 785 waa.accesscookie = scr; 786 787 /* attach as console if required */ 788 if (waa.console && !ISSET(sc->sc_flags, STI_ATTACHED)) { 789 long defattr; 790 791 sti_alloc_attr(scr, 0, 0, 0, &defattr); 792 wsdisplay_cnattach(&scr->scr_wsd, scr, 793 0, scr->scr_wsd.nrows - 1, defattr); 794 sc->sc_flags |= STI_ATTACHED; 795 } 796 797 config_found(sc->sc_dev, &waa, wsemuldisplaydevprint, 798 CFARGS_NONE); 799 } 800 #endif 801 } 802 803 u_int 804 sti_rom_size(bus_space_tag_t memt, bus_space_handle_t romh) 805 { 806 int devtype; 807 u_int romend; 808 809 devtype = bus_space_read_1(memt, romh, 3); 810 if (devtype == STI_DEVTYPE4) { 811 bus_space_read_region_stream_4(memt, romh, STI_DEV4_DD_ROMEND, 812 (uint32_t *)&romend, 1); 813 } else { 814 romend = parseword(STI_DEV1_DD_ROMEND); 815 } 816 817 DPRINTF(("%s: %08x (%08x)\n", __func__, romend, round_page(romend))); 818 819 return round_page(romend); 820 } 821 822 int 823 sti_fetchfonts(struct sti_screen *scr, struct sti_inqconfout *cfg, 824 uint32_t baseaddr, u_int fontindex) 825 { 826 struct sti_rom *rom = scr->scr_rom; 827 bus_space_tag_t memt = rom->memt; 828 bus_space_handle_t romh = rom->romh; 829 struct sti_font *fp = &scr->scr_curfont; 830 uint32_t addr; 831 int size; 832 #ifdef notyet 833 int uc; 834 struct { 835 struct sti_unpmvflags flags; 836 struct sti_unpmvin in; 837 struct sti_unpmvout out; 838 } a; 839 #endif 840 841 /* 842 * Get the first PROM font in memory 843 */ 844 845 STI_ENABLE_ROM(rom->rom_softc); 846 847 rescan: 848 addr = baseaddr; 849 do { 850 if (rom->rom_devtype == STI_DEVTYPE1) { 851 fp->first = parseshort(addr + 0x00); 852 fp->last = parseshort(addr + 0x08); 853 fp->width = bus_space_read_1(memt, romh, addr + 0x13); 854 fp->height = bus_space_read_1(memt, romh, addr + 0x17); 855 fp->type = bus_space_read_1(memt, romh, addr + 0x1b); 856 fp->bpc = bus_space_read_1(memt, romh, addr + 0x1f); 857 fp->next = parseword(addr + 0x20); 858 fp->uheight= bus_space_read_1(memt, romh, addr + 0x33); 859 fp->uoffset= bus_space_read_1(memt, romh, addr + 0x37); 860 } else { /* STI_DEVTYPE4 */ 861 bus_space_read_region_stream_4(memt, romh, addr, 862 (uint32_t *)fp, sizeof(struct sti_font) / 4); 863 } 864 865 #ifdef STIDEBUG 866 STI_DISABLE_ROM(rom->rom_softc); 867 DPRINTF(("%s: %dx%d font type %d, %d bpc, charset %d-%d\n", 868 device_xname(scr->scr_rom->rom_softc->sc_dev), fp->width, 869 fp->height, fp->type, fp->bpc, fp->first, fp->last)); 870 STI_ENABLE_ROM(rom->rom_softc); 871 #endif 872 873 if (fontindex == 0) { 874 size = sizeof(struct sti_font) + 875 (fp->last - fp->first + 1) * fp->bpc; 876 if (rom->rom_devtype == STI_DEVTYPE1) 877 size *= 4; 878 scr->scr_romfont = malloc(size, M_DEVBUF, M_WAITOK); 879 880 bus_space_read_region_stream_4(memt, romh, addr, 881 (uint32_t *)scr->scr_romfont, size / 4); 882 break; 883 } 884 885 addr = baseaddr + fp->next; 886 fontindex--; 887 } while (fp->next != 0); 888 889 /* 890 * If our font index was bogus, we did not find the expected font. 891 * In this case, pick the first one and be done with it. 892 */ 893 if (fp->next == 0 && scr->scr_romfont == NULL) { 894 fontindex = 0; 895 goto rescan; 896 } 897 898 STI_DISABLE_ROM(rom->rom_softc); 899 900 #ifdef notyet 901 /* 902 * If there is enough room in the off-screen framebuffer memory, 903 * display all the characters there in order to display them 904 * faster with blkmv operations rather than unpmv later on. 905 */ 906 if (size <= cfg->fbheight * 907 (cfg->fbwidth - cfg->width - cfg->owidth)) { 908 memset(&a, 0, sizeof(a)); 909 a.flags.flags = STI_UNPMVF_WAIT; 910 a.in.fg_colour = STI_COLOUR_WHITE; 911 a.in.bg_colour = STI_COLOUR_BLACK; 912 a.in.font_addr = scr->scr_romfont; 913 914 scr->scr_fontmaxcol = cfg->fbheight / fp->height; 915 scr->scr_fontbase = cfg->width + cfg->owidth; 916 for (uc = fp->first; uc <= fp->last; uc++) { 917 a.in.x = ((uc - fp->first) / scr->scr_fontmaxcol) * 918 fp->width + scr->scr_fontbase; 919 a.in.y = ((uc - fp->first) % scr->scr_fontmaxcol) * 920 fp->height; 921 a.in.index = uc; 922 923 (*scr->unpmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg); 924 if (a.out.errno) { 925 aprint_error_dev(sc->sc_dev, "unpmv %d " 926 "returned %d\n", uc, a.out.errno); 927 return 0; 928 } 929 } 930 931 free(scr->scr_romfont, M_DEVBUF); 932 scr->scr_romfont = NULL; 933 } 934 #endif 935 936 return 0; 937 } 938 939 /* 940 * Wrappers around STI code pointers 941 */ 942 943 int 944 sti_init(struct sti_screen *scr, int mode) 945 { 946 struct sti_rom *rom = scr->scr_rom; 947 struct { 948 struct sti_initflags flags; 949 struct sti_initin in; 950 struct sti_einitin ein; 951 struct sti_initout out; 952 } a; 953 954 KASSERT(rom != NULL); 955 memset(&a, 0, sizeof(a)); 956 957 a.flags.flags = STI_INITF_WAIT | STI_INITF_PBET | STI_INITF_PBETI; 958 if ((mode & STI_TEXTMODE) != 0) { 959 a.flags.flags |= STI_INITF_TEXT | STI_INITF_CMB | 960 STI_INITF_PBET | STI_INITF_PBETI | STI_INITF_ICMT; 961 a.in.text_planes = 1; 962 } else { 963 a.flags.flags |= STI_INITF_TEXT | STI_INITF_NTEXT; 964 /* 965 * Request as many text planes as STI will allow. 966 * The reason to do this - when switching to framebuffer mode 967 * for X we need access to all planes. In theory STI should do 968 * just that when we request access to both text and non-text 969 * planes as above. 970 * In reality though, at least on my PCI Visualize EG, some 971 * planes and/or colour registers remain inaccessible if we 972 * request only one text plane. 973 * Clearly we're missing a register write or two here, but so 974 * far I haven't found it. 975 */ 976 a.in.text_planes = 3; 977 } 978 if ((mode & STI_CLEARSCR) != 0) 979 a.flags.flags |= STI_INITF_CLEAR; 980 981 a.in.ext_in = &a.ein; 982 983 DPRINTF(("%s: init,%p(%x, %p, %p, %p)\n", 984 device_xname(rom->rom_softc->sc_dev), rom->init, a.flags.flags, 985 &a.in, &a.out, &scr->scr_cfg)); 986 987 (*rom->init)(&a.flags, &a.in, &a.out, &scr->scr_cfg); 988 989 if (a.out.text_planes != a.in.text_planes) 990 return -1; /* not colliding with sti errno values */ 991 return a.out.errno; 992 } 993 994 int 995 sti_inqcfg(struct sti_screen *scr, struct sti_inqconfout *out) 996 { 997 struct sti_rom *rom = scr->scr_rom; 998 struct { 999 struct sti_inqconfflags flags; 1000 struct sti_inqconfin in; 1001 } a; 1002 1003 memset(&a, 0, sizeof(a)); 1004 1005 a.flags.flags = STI_INQCONFF_WAIT; 1006 (*rom->inqconf)(&a.flags, &a.in, out, &scr->scr_cfg); 1007 1008 return out->errno; 1009 } 1010 1011 void 1012 sti_bmove(struct sti_screen *scr, int x1, int y1, int x2, int y2, int h, int w, 1013 enum sti_bmove_funcs f) 1014 { 1015 struct sti_rom *rom = scr->scr_rom; 1016 struct { 1017 struct sti_blkmvflags flags; 1018 struct sti_blkmvin in; 1019 struct sti_blkmvout out; 1020 } a; 1021 1022 memset(&a, 0, sizeof(a)); 1023 1024 a.flags.flags = STI_BLKMVF_WAIT; 1025 switch (f) { 1026 case bmf_clear: 1027 a.flags.flags |= STI_BLKMVF_CLR; 1028 a.in.bg_colour = STI_COLOUR_BLACK; 1029 break; 1030 case bmf_underline: 1031 case bmf_copy: 1032 a.in.fg_colour = STI_COLOUR_WHITE; 1033 a.in.bg_colour = STI_COLOUR_BLACK; 1034 break; 1035 case bmf_invert: 1036 a.flags.flags |= STI_BLKMVF_COLR; 1037 a.in.fg_colour = STI_COLOUR_BLACK; 1038 a.in.bg_colour = STI_COLOUR_WHITE; 1039 break; 1040 } 1041 a.in.srcx = x1; 1042 a.in.srcy = y1; 1043 a.in.dstx = x2; 1044 a.in.dsty = y2; 1045 a.in.height = h; 1046 a.in.width = w; 1047 1048 (*rom->blkmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg); 1049 #ifdef STIDEBUG 1050 if (a.out.errno) 1051 printf("%s: blkmv returned %d\n", 1052 device_xname(rom->rom_softc->sc_dev), a.out.errno); 1053 #endif 1054 } 1055 1056 int 1057 sti_setcment(struct sti_screen *scr, u_int i, u_char r, u_char g, u_char b) 1058 { 1059 struct sti_rom *rom = scr->scr_rom; 1060 struct { 1061 struct sti_scmentflags flags; 1062 struct sti_scmentin in; 1063 struct sti_scmentout out; 1064 } a; 1065 1066 memset(&a, 0, sizeof(a)); 1067 1068 a.flags.flags = STI_SCMENTF_WAIT; 1069 a.in.entry = i; 1070 a.in.value = (r << 16) | (g << 8) | b; 1071 1072 (*rom->scment)(&a.flags, &a.in, &a.out, &scr->scr_cfg); 1073 1074 return a.out.errno; 1075 } 1076 1077 /* 1078 * wsdisplay accessops 1079 */ 1080 int 1081 sti_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l) 1082 { 1083 struct sti_screen *scr = (struct sti_screen *)v; 1084 struct sti_rom *rom = scr->scr_rom; 1085 struct wsdisplay_fbinfo *wdf; 1086 struct wsdisplay_cmap *cmapp; 1087 u_int mode, idx, count; 1088 int ret; 1089 1090 ret = 0; 1091 switch (cmd) { 1092 case GCID: 1093 *(u_int *)data = rom->rom_dd.dd_grid[0]; 1094 break; 1095 1096 case WSDISPLAYIO_GMODE: 1097 *(u_int *)data = scr->scr_wsmode; 1098 break; 1099 1100 case WSDISPLAYIO_SMODE: 1101 mode = *(u_int *)data; 1102 switch (mode) { 1103 case WSDISPLAYIO_MODE_EMUL: 1104 if (scr->scr_wsmode != WSDISPLAYIO_MODE_EMUL) 1105 ret = sti_init(scr, STI_TEXTMODE); 1106 break; 1107 case WSDISPLAYIO_MODE_DUMBFB: 1108 if (scr->scr_wsmode != WSDISPLAYIO_MODE_DUMBFB) { 1109 ret = sti_init(scr, 0); 1110 if (scr->setupfb != NULL) 1111 scr->setupfb(scr); 1112 else 1113 #if 0 1114 ret = sti_init(scr, STI_FBMODE); 1115 #else 1116 ret = EINVAL; 1117 #endif 1118 } 1119 break; 1120 case WSDISPLAYIO_MODE_MAPPED: 1121 default: 1122 ret = EINVAL; 1123 break; 1124 } 1125 if (ret == 0) 1126 scr->scr_wsmode = mode; 1127 break; 1128 1129 case WSDISPLAYIO_GTYPE: 1130 *(u_int *)data = WSDISPLAY_TYPE_STI; 1131 break; 1132 1133 case WSDISPLAYIO_GINFO: 1134 wdf = (struct wsdisplay_fbinfo *)data; 1135 wdf->height = scr->scr_cfg.scr_height; 1136 wdf->width = scr->scr_cfg.scr_width; 1137 wdf->depth = scr->scr_bpp; 1138 if (scr->putcmap == NULL || scr->scr_bpp > 8) 1139 wdf->cmsize = 0; 1140 else 1141 wdf->cmsize = STI_NCMAP; 1142 break; 1143 1144 case WSDISPLAYIO_LINEBYTES: 1145 if (scr->scr_bpp > 8) 1146 *(u_int *)data = scr->scr_cfg.fb_width * 4; 1147 else 1148 *(u_int *)data = scr->scr_cfg.fb_width; 1149 break; 1150 1151 case WSDISPLAYIO_GETCMAP: 1152 if (scr->putcmap == NULL || scr->scr_bpp > 8) 1153 return ENODEV; 1154 cmapp = (struct wsdisplay_cmap *)data; 1155 idx = cmapp->index; 1156 count = cmapp->count; 1157 if (idx >= STI_NCMAP || count > STI_NCMAP - idx) 1158 return EINVAL; 1159 if ((ret = copyout(&scr->scr_rcmap[idx], cmapp->red, count))) 1160 break; 1161 if ((ret = copyout(&scr->scr_gcmap[idx], cmapp->green, count))) 1162 break; 1163 if ((ret = copyout(&scr->scr_bcmap[idx], cmapp->blue, count))) 1164 break; 1165 break; 1166 1167 case WSDISPLAYIO_PUTCMAP: 1168 if (scr->putcmap == NULL || scr->scr_bpp > 8) 1169 return ENODEV; 1170 if (scr->scr_wsmode == WSDISPLAYIO_MODE_EMUL) { 1171 /* 1172 * The hardware palette settings are handled by 1173 * the STI ROM in STI_TEXTMODE and changing cmap 1174 * could cause mangled text colors at least on CRX. 1175 * Updating CMAP in EMUL mode isn't expected anyway 1176 * so just ignore it. 1177 */ 1178 return 0; 1179 } 1180 cmapp = (struct wsdisplay_cmap *)data; 1181 idx = cmapp->index; 1182 count = cmapp->count; 1183 if (idx >= STI_NCMAP || count > STI_NCMAP - idx) 1184 return EINVAL; 1185 if ((ret = copyin(cmapp->red, &scr->scr_rcmap[idx], count))) 1186 break; 1187 if ((ret = copyin(cmapp->green, &scr->scr_gcmap[idx], count))) 1188 break; 1189 if ((ret = copyin(cmapp->blue, &scr->scr_bcmap[idx], count))) 1190 break; 1191 ret = scr->putcmap(scr, idx, count); 1192 break; 1193 1194 case WSDISPLAYIO_SVIDEO: 1195 case WSDISPLAYIO_GVIDEO: 1196 case WSDISPLAYIO_GCURPOS: 1197 case WSDISPLAYIO_SCURPOS: 1198 case WSDISPLAYIO_GCURMAX: 1199 case WSDISPLAYIO_GCURSOR: 1200 case WSDISPLAYIO_SCURSOR: 1201 default: 1202 return ENOTTY; /* not supported yet */ 1203 } 1204 1205 return ret; 1206 } 1207 1208 paddr_t 1209 sti_mmap(void *v, void *vs, off_t offset, int prot) 1210 { 1211 struct sti_screen *scr = (struct sti_screen *)v; 1212 struct sti_rom *rom = scr->scr_rom; 1213 paddr_t pa; 1214 1215 if ((offset & PAGE_MASK) != 0) 1216 return -1; 1217 1218 if (offset < 0 || offset >= scr->fblen) 1219 return -1; 1220 1221 if (scr->scr_wsmode != WSDISPLAYIO_MODE_DUMBFB) 1222 return -1; 1223 1224 pa = bus_space_mmap(rom->memt, scr->fbaddr, offset, prot, 1225 BUS_SPACE_MAP_LINEAR); 1226 1227 if (pa == -1) 1228 pa = scr->fbaddr + offset; 1229 1230 return pa; 1231 } 1232 1233 int 1234 sti_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep, 1235 int *cxp, int *cyp, long *defattr) 1236 { 1237 struct sti_screen *scr = (struct sti_screen *)v; 1238 1239 if (scr->scr_nscreens > 0) 1240 return ENOMEM; 1241 1242 *cookiep = scr; 1243 *cxp = 0; 1244 *cyp = 0; 1245 sti_alloc_attr(scr, 0, 0, 0, defattr); 1246 scr->scr_nscreens++; 1247 return 0; 1248 } 1249 1250 void 1251 sti_free_screen(void *v, void *cookie) 1252 { 1253 struct sti_screen *scr = (struct sti_screen *)v; 1254 1255 scr->scr_nscreens--; 1256 } 1257 1258 int 1259 sti_show_screen(void *v, void *cookie, int waitok, void (*cb)(void *, int, int), 1260 void *cbarg) 1261 { 1262 #if 0 1263 struct sti_screen *scr = (struct sti_screen *)v; 1264 #endif 1265 1266 return 0; 1267 } 1268 1269 int 1270 sti_load_font(void *v, void *cookie, struct wsdisplay_font *font) 1271 { 1272 #if 0 1273 struct sti_screen *scr = (struct sti_screen *)v; 1274 #endif 1275 1276 return -1; 1277 } 1278 1279 /* 1280 * wsdisplay emulops 1281 */ 1282 void 1283 sti_cursor(void *v, int on, int row, int col) 1284 { 1285 struct sti_screen *scr = (struct sti_screen *)v; 1286 struct sti_font *fp = &scr->scr_curfont; 1287 1288 sti_bmove(scr, 1289 col * fp->width, row * fp->height, 1290 col * fp->width, row * fp->height, 1291 fp->height, fp->width, bmf_invert); 1292 } 1293 1294 /* 1295 * ISO 8859-1 part of Unicode to HP Roman font index conversion array. 1296 */ 1297 const uint8_t 1298 sti_unitoroman[0x100 - 0xa0] = { 1299 0xa0, 0xb8, 0xbf, 0xbb, 0xba, 0xbc, 0, 0xbd, 1300 0xab, 0, 0xf9, 0xfb, 0, 0xf6, 0, 0xb0, 1301 1302 0xb3, 0xfe, 0, 0, 0xa8, 0xf3, 0xf4, 0xf2, 1303 0, 0, 0xfa, 0xfd, 0xf7, 0xf8, 0, 0xb9, 1304 1305 0xa1, 0xe0, 0xa2, 0xe1, 0xd8, 0xd0, 0xd3, 0xb4, 1306 0xa3, 0xdc, 0xa4, 0xa5, 0xe6, 0xe5, 0xa6, 0xa7, 1307 1308 0xe3, 0xb6, 0xe8, 0xe7, 0xdf, 0xe9, 0xda, 0, 1309 0xd2, 0xad, 0xed, 0xae, 0xdb, 0xb1, 0xf0, 0xde, 1310 1311 0xc8, 0xc4, 0xc0, 0xe2, 0xcc, 0xd4, 0xd7, 0xb5, 1312 0xc9, 0xc5, 0xc1, 0xcd, 0xd9, 0xd5, 0xd1, 0xdd, 1313 1314 0xe4, 0xb7, 0xca, 0xc6, 0xc2, 0xea, 0xce, 0, 1315 0xd6, 0xcb, 0xc7, 0xc3, 0xcf, 0xb2, 0xf1, 0xef 1316 }; 1317 1318 int 1319 sti_mapchar(void *v, int uni, u_int *index) 1320 { 1321 struct sti_screen *scr = (struct sti_screen *)v; 1322 struct sti_font *fp = &scr->scr_curfont; 1323 int c; 1324 1325 switch (fp->type) { 1326 case STI_FONT_HPROMAN8: 1327 if (uni >= 0x80 && uni < 0xa0) 1328 c = -1; 1329 else if (uni >= 0xa0 && uni < 0x100) { 1330 c = (int)sti_unitoroman[uni - 0xa0]; 1331 if (c == 0) 1332 c = -1; 1333 } else 1334 c = uni; 1335 break; 1336 default: 1337 c = uni; 1338 break; 1339 } 1340 1341 if (c == -1 || c < fp->first || c > fp->last) { 1342 *index = ' '; 1343 return 0; 1344 } 1345 1346 *index = c; 1347 return 5; 1348 } 1349 1350 void 1351 sti_putchar(void *v, int row, int col, u_int uc, long attr) 1352 { 1353 struct sti_screen *scr = (struct sti_screen *)v; 1354 struct sti_rom *rom = scr->scr_rom; 1355 struct sti_font *fp = &scr->scr_curfont; 1356 int bg, fg; 1357 1358 fg = WSATTR_UNPACK_FG(attr); 1359 bg = WSATTR_UNPACK_BG(attr); 1360 1361 if (scr->scr_romfont != NULL) { 1362 /* 1363 * Font is in memory, use unpmv 1364 */ 1365 struct { 1366 struct sti_unpmvflags flags; 1367 struct sti_unpmvin in; 1368 struct sti_unpmvout out; 1369 } a; 1370 1371 memset(&a, 0, sizeof(a)); 1372 1373 a.flags.flags = STI_UNPMVF_WAIT; 1374 a.in.fg_colour = fg; 1375 a.in.bg_colour = bg; 1376 a.in.x = col * fp->width; 1377 a.in.y = row * fp->height; 1378 a.in.font_addr = scr->scr_romfont; 1379 a.in.index = uc; 1380 1381 (*rom->unpmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg); 1382 } else { 1383 /* 1384 * Font is in frame buffer, use blkmv 1385 */ 1386 struct { 1387 struct sti_blkmvflags flags; 1388 struct sti_blkmvin in; 1389 struct sti_blkmvout out; 1390 } a; 1391 1392 memset(&a, 0, sizeof(a)); 1393 1394 a.flags.flags = STI_BLKMVF_WAIT; 1395 a.in.fg_colour = fg; 1396 a.in.bg_colour = bg; 1397 1398 a.in.srcx = ((uc - fp->first) / scr->scr_fontmaxcol) * 1399 fp->width + scr->scr_fontbase; 1400 a.in.srcy = ((uc - fp->first) % scr->scr_fontmaxcol) * 1401 fp->height; 1402 a.in.dstx = col * fp->width; 1403 a.in.dsty = row * fp->height; 1404 a.in.height = fp->height; 1405 a.in.width = fp->width; 1406 1407 (*rom->blkmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg); 1408 } 1409 } 1410 1411 void 1412 sti_copycols(void *v, int row, int srccol, int dstcol, int ncols) 1413 { 1414 struct sti_screen *scr = (struct sti_screen *)v; 1415 struct sti_font *fp = &scr->scr_curfont; 1416 1417 sti_bmove(scr, 1418 srccol * fp->width, row * fp->height, 1419 dstcol * fp->width, row * fp->height, 1420 fp->height, ncols * fp->width, bmf_copy); 1421 } 1422 1423 void 1424 sti_erasecols(void *v, int row, int startcol, int ncols, long attr) 1425 { 1426 struct sti_screen *scr = (struct sti_screen *)v; 1427 struct sti_font *fp = &scr->scr_curfont; 1428 1429 sti_bmove(scr, 1430 startcol * fp->width, row * fp->height, 1431 startcol * fp->width, row * fp->height, 1432 fp->height, ncols * fp->width, bmf_clear); 1433 } 1434 1435 void 1436 sti_copyrows(void *v, int srcrow, int dstrow, int nrows) 1437 { 1438 struct sti_screen *scr = (struct sti_screen *)v; 1439 struct sti_font *fp = &scr->scr_curfont; 1440 1441 sti_bmove(scr, 0, srcrow * fp->height, 0, dstrow * fp->height, 1442 nrows * fp->height, scr->scr_cfg.scr_width, bmf_copy); 1443 } 1444 1445 void 1446 sti_eraserows(void *v, int srcrow, int nrows, long attr) 1447 { 1448 struct sti_screen *scr = (struct sti_screen *)v; 1449 struct sti_font *fp = &scr->scr_curfont; 1450 1451 sti_bmove(scr, 0, srcrow * fp->height, 0, srcrow * fp->height, 1452 nrows * fp->height, scr->scr_cfg.scr_width, bmf_clear); 1453 } 1454 1455 int 1456 sti_alloc_attr(void *v, int fg, int bg, int flags, long *pattr) 1457 { 1458 #if 0 1459 struct sti_screen *scr = (struct sti_screen *)v; 1460 #endif 1461 1462 if ((flags & (WSATTR_HILIT | WSATTR_BLINK | 1463 WSATTR_UNDERLINE | WSATTR_WSCOLORS)) != 0) 1464 return EINVAL; 1465 if ((flags & WSATTR_REVERSE) != 0) { 1466 fg = STI_COLOUR_BLACK; 1467 bg = STI_COLOUR_WHITE; 1468 } else { 1469 fg = STI_COLOUR_WHITE; 1470 bg = STI_COLOUR_BLACK; 1471 } 1472 1473 *pattr = WSATTR_PACK(fg, bg, flags); 1474 return 0; 1475 } 1476 1477 /* 1478 * Early console support. Only used on hp300, currently 1479 */ 1480 int 1481 sti_cnattach(struct sti_rom *rom, struct sti_screen *scr, bus_space_tag_t memt, 1482 bus_addr_t *bases, u_int codebase) 1483 { 1484 bus_space_handle_t romh; 1485 u_int romend; 1486 int error; 1487 long defattr; 1488 1489 if ((error = bus_space_map(memt, bases[0], PAGE_SIZE, 0, &romh)) != 0) 1490 return error; 1491 1492 /* 1493 * Compute real PROM size 1494 */ 1495 romend = sti_rom_size(memt, romh); 1496 1497 bus_space_unmap(memt, romh, PAGE_SIZE); 1498 1499 if ((error = bus_space_map(memt, bases[0], romend, 0, &romh)) != 0) 1500 return error; 1501 1502 bases[0] = romh; 1503 if (sti_rom_setup(rom, memt, memt, romh, bases, codebase) != 0) 1504 return -1; 1505 scr->scr_rom = rom; 1506 if (sti_screen_setup(scr, STI_CLEARSCR) != 0) 1507 return -1; 1508 1509 sti_alloc_attr(scr, 0, 0, 0, &defattr); 1510 wsdisplay_cnattach(&scr->scr_wsd, scr, 0, 0, defattr); 1511 1512 return 0; 1513 } 1514 1515 int 1516 ngle_default_putcmap(struct sti_screen *scr, u_int idx, u_int count) 1517 { 1518 int i, ret; 1519 1520 for (i = idx + count - 1; i >= (int)idx; i--) 1521 if ((ret = sti_setcment(scr, i, scr->scr_rcmap[i], 1522 scr->scr_gcmap[i], scr->scr_bcmap[i]))) 1523 return EINVAL; 1524 1525 return 0; 1526 } 1527 1528 #ifndef SMALL_KERNEL 1529 1530 void ngle_setup_hw(bus_space_tag_t, bus_space_handle_t); 1531 void ngle_setup_fb(bus_space_tag_t, bus_space_handle_t, uint32_t); 1532 void ngle_setup_attr_planes(struct sti_screen *scr); 1533 void ngle_setup_bt458(struct sti_screen *scr); 1534 1535 #define ngle_bt458_write(memt, memh, r, v) \ 1536 bus_space_write_stream_4(memt, memh, NGLE_REG_RAMDAC + ((r) << 2), (v) << 24) 1537 1538 void 1539 ngle_artist_setupfb(struct sti_screen *scr) 1540 { 1541 struct sti_rom *rom = scr->scr_rom; 1542 bus_space_tag_t memt = rom->memt; 1543 bus_space_handle_t memh = rom->regh[2]; 1544 1545 ngle_setup_bt458(scr); 1546 1547 ngle_setup_hw(memt, memh); 1548 ngle_setup_fb(memt, memh, scr->reg10_value); 1549 1550 ngle_setup_attr_planes(scr); 1551 1552 ngle_setup_hw(memt, memh); 1553 bus_space_write_stream_4(memt, memh, NGLE_REG_21, 1554 bus_space_read_stream_4(memt, memh, NGLE_REG_21) | 0x0a000000); 1555 bus_space_write_stream_4(memt, memh, NGLE_REG_27, 1556 bus_space_read_stream_4(memt, memh, NGLE_REG_27) | 0x00800000); 1557 } 1558 1559 void 1560 ngle_elk_setupfb(struct sti_screen *scr) 1561 { 1562 struct sti_rom *rom = scr->scr_rom; 1563 bus_space_tag_t memt = rom->memt; 1564 bus_space_handle_t memh = rom->regh[2]; 1565 1566 ngle_setup_bt458(scr); 1567 1568 ngle_setup_hw(memt, memh); 1569 ngle_setup_fb(memt, memh, scr->reg10_value); 1570 1571 ngle_setup_attr_planes(scr); 1572 1573 ngle_setup_hw(memt, memh); 1574 /* enable overlay planes in Bt458 command register */ 1575 ngle_bt458_write(memt, memh, 0x0c, 0x06); 1576 ngle_bt458_write(memt, memh, 0x0e, 0x43); 1577 } 1578 1579 void 1580 ngle_timber_setupfb(struct sti_screen *scr) 1581 { 1582 struct sti_rom *rom = scr->scr_rom; 1583 bus_space_tag_t memt = rom->memt; 1584 bus_space_handle_t memh = rom->regh[2]; 1585 1586 ngle_setup_bt458(scr); 1587 1588 ngle_setup_hw(memt, memh); 1589 /* enable overlay planes in Bt458 command register */ 1590 ngle_bt458_write(memt, memh, 0x0c, 0x06); 1591 ngle_bt458_write(memt, memh, 0x0e, 0x43); 1592 } 1593 1594 static void 1595 summit_wait(struct sti_screen *scr) 1596 { 1597 struct sti_rom *rom = scr->scr_rom; 1598 bus_space_tag_t memt = rom->memt; 1599 bus_space_handle_t memh = rom->regh[0]; 1600 1601 while (bus_space_read_stream_4(memt, memh, VISFX_STATUS) != 0) 1602 continue; 1603 } 1604 1605 void 1606 summit_setupfb(struct sti_screen *scr) 1607 { 1608 struct sti_rom *rom = scr->scr_rom; 1609 bus_space_tag_t memt = rom->memt; 1610 bus_space_handle_t memh = rom->regh[0]; 1611 1612 summit_wait(scr); 1613 bus_space_write_stream_4(memt, memh, 0xb08044, 0x1b); 1614 bus_space_write_stream_4(memt, memh, 0xb08048, 0x1b); 1615 bus_space_write_stream_4(memt, memh, 0x920860, 0xe4); 1616 bus_space_write_stream_4(memt, memh, 0xa00818, 0); 1617 bus_space_write_stream_4(memt, memh, 0xa00404, 0); 1618 bus_space_write_stream_4(memt, memh, 0x921110, 0); 1619 bus_space_write_stream_4(memt, memh, 0x9211d8, 0); 1620 bus_space_write_stream_4(memt, memh, 0xa0086c, 0); 1621 bus_space_write_stream_4(memt, memh, 0x921114, 0); 1622 bus_space_write_stream_4(memt, memh, 0xac1050, 0); 1623 1624 bus_space_write_stream_4(memt, memh, VISFX_APERTURE_ACCESS, 1625 VISFX_DEPTH_8); 1626 1627 bus_space_write_stream_4(memt, memh, VISFX_PIXEL_MASK, 0xffffffff); 1628 bus_space_write_stream_4(memt, memh, VISFX_PLANE_MASK, 0xffffffff); 1629 bus_space_write_stream_4(memt, memh, VISFX_VRAM_WRITE_MODE, 1630 VISFX_WRITE_MODE_PLAIN); 1631 bus_space_write_stream_4(memt, memh, VISFX_VRAM_READ_MODE, 1632 VISFX_READ_MODE_COPY); 1633 } 1634 1635 void 1636 ngle_setup_bt458(struct sti_screen *scr) 1637 { 1638 struct sti_rom *rom = scr->scr_rom; 1639 bus_space_tag_t memt = rom->memt; 1640 bus_space_handle_t memh = rom->regh[2]; 1641 1642 ngle_setup_hw(memt, memh); 1643 /* set Bt458 read mask register to all planes */ 1644 ngle_bt458_write(memt, memh, 0x08, 0x04); 1645 ngle_bt458_write(memt, memh, 0x0a, 0xff); 1646 } 1647 1648 void 1649 ngle_setup_attr_planes(struct sti_screen *scr) 1650 { 1651 struct sti_rom *rom = scr->scr_rom; 1652 bus_space_tag_t memt = rom->memt; 1653 bus_space_handle_t memh = rom->regh[2]; 1654 1655 ngle_setup_hw(memt, memh); 1656 bus_space_write_stream_4(memt, memh, NGLE_REG_11, 0x2ea0d000); 1657 bus_space_write_stream_4(memt, memh, NGLE_REG_14, 0x23000302); 1658 bus_space_write_stream_4(memt, memh, NGLE_REG_12, scr->reg12_value); 1659 bus_space_write_stream_4(memt, memh, NGLE_REG_8, 0xffffffff); 1660 1661 bus_space_write_stream_4(memt, memh, NGLE_REG_6, 0x00000000); 1662 bus_space_write_stream_4(memt, memh, NGLE_REG_9, 1663 (scr->scr_cfg.scr_width << 16) | scr->scr_cfg.scr_height); 1664 bus_space_write_stream_4(memt, memh, NGLE_REG_6, 0x05000000); 1665 bus_space_write_stream_4(memt, memh, NGLE_REG_9, 0x00040001); 1666 1667 ngle_setup_hw(memt, memh); 1668 bus_space_write_stream_4(memt, memh, NGLE_REG_12, 0x00000000); 1669 1670 ngle_setup_fb(memt, memh, scr->reg10_value); 1671 } 1672 1673 int 1674 ngle_putcmap(struct sti_screen *scr, u_int idx, u_int count) 1675 { 1676 struct sti_rom *rom = scr->scr_rom; 1677 bus_space_tag_t memt = rom->memt; 1678 bus_space_handle_t memh = rom->regh[2]; 1679 uint8_t *r, *g, *b; 1680 uint32_t cmap_finish; 1681 1682 if (scr->scr_bpp > 8) 1683 cmap_finish = 0x83000100; 1684 else 1685 cmap_finish = 0x80000100; 1686 1687 r = scr->scr_rcmap + idx; 1688 g = scr->scr_gcmap + idx; 1689 b = scr->scr_bcmap + idx; 1690 1691 ngle_setup_hw(memt, memh); 1692 bus_space_write_stream_4(memt, memh, NGLE_REG_10, 0xbbe0f000); 1693 bus_space_write_stream_4(memt, memh, NGLE_REG_14, 0x03000300); 1694 bus_space_write_stream_4(memt, memh, NGLE_REG_13, 0xffffffff); 1695 1696 while (count-- != 0) { 1697 ngle_setup_hw(memt, memh); 1698 bus_space_write_stream_4(memt, memh, NGLE_REG_3, 1699 0x400 | (idx << 2)); 1700 bus_space_write_stream_4(memt, memh, NGLE_REG_4, 1701 (*r << 16) | (*g << 8) | *b); 1702 1703 idx++; 1704 r++, g++, b++; 1705 } 1706 1707 1708 bus_space_write_stream_4(memt, memh, NGLE_REG_2, 0x400); 1709 bus_space_write_stream_4(memt, memh, scr->cmap_finish_register, 1710 cmap_finish); 1711 ngle_setup_fb(memt, memh, scr->reg10_value); 1712 1713 1714 return 0; 1715 } 1716 1717 int 1718 ngle_hcrx_putcmap(struct sti_screen *scr, u_int idx, u_int count) 1719 { 1720 struct sti_rom *rom = scr->scr_rom; 1721 bus_space_tag_t memt = rom->memt; 1722 bus_space_handle_t memh = rom->regh[2]; 1723 uint8_t *r, *g, *b; 1724 uint32_t cmap_finish; 1725 1726 if (scr->scr_bpp > 8) 1727 cmap_finish = 0x80000100; 1728 else 1729 cmap_finish = 0x82000100; 1730 1731 r = scr->scr_rcmap + idx; 1732 g = scr->scr_gcmap + idx; 1733 b = scr->scr_bcmap + idx; 1734 1735 ngle_setup_hw(memt, memh); 1736 bus_space_write_stream_4(memt, memh, NGLE_REG_10, 0xbbe0f000); 1737 bus_space_write_stream_4(memt, memh, NGLE_REG_14, 0x03000300); 1738 bus_space_write_stream_4(memt, memh, NGLE_REG_13, 0xffffffff); 1739 1740 while (count-- != 0) { 1741 ngle_setup_hw(memt, memh); 1742 bus_space_write_stream_4(memt, memh, NGLE_REG_3, 1743 0x400 | (idx << 2)); 1744 bus_space_write_stream_4(memt, memh, NGLE_REG_4, 1745 (*r << 16) | (*g << 8) | *b); 1746 1747 idx++; 1748 r++, g++, b++; 1749 } 1750 1751 1752 bus_space_write_stream_4(memt, memh, NGLE_REG_2, 0x400); 1753 bus_space_write_stream_4(memt, memh, NGLE_REG_38, cmap_finish); 1754 ngle_setup_fb(memt, memh, scr->reg10_value); 1755 1756 1757 return 0; 1758 } 1759 1760 int 1761 summit_putcmap(struct sti_screen *scr, u_int idx, u_int count) 1762 { 1763 struct sti_rom *rom = scr->scr_rom; 1764 bus_space_tag_t memt = rom->memt; 1765 bus_space_handle_t memh = rom->regh[0]; 1766 uint8_t *r, *g, *b; 1767 1768 r = scr->scr_rcmap + idx; 1769 g = scr->scr_gcmap + idx; 1770 b = scr->scr_bcmap + idx; 1771 1772 if (rom->rom_dd.dd_grid[0] == STI_DD_LEGO) { 1773 bus_space_write_stream_4(memt, memh, VISFX_COLOR_INDEX, idx); 1774 } else 1775 bus_space_write_stream_4(memt, memh, VISFX_COLOR_INDEX, 1776 0xc0005100 + idx); 1777 1778 while (count-- != 0) { 1779 bus_space_write_stream_4(memt, memh, 1780 VISFX_COLOR_VALUE, (*r << 16) | (*g << 8) | *b); 1781 r++, g++, b++; 1782 } 1783 bus_space_write_stream_4(memt, memh, VISFX_COLOR_MASK, 0xff); 1784 bus_space_write_stream_4(memt, memh, 0x80004c, 0xc); 1785 bus_space_write_stream_4(memt, memh, 0x800000, 0); 1786 1787 return 0; 1788 } 1789 1790 void 1791 ngle_setup_hw(bus_space_tag_t memt, bus_space_handle_t memh) 1792 { 1793 uint8_t stat; 1794 1795 do { 1796 stat = bus_space_read_1(memt, memh, NGLE_REG_15b0); 1797 if (stat == 0) 1798 stat = bus_space_read_1(memt, memh, NGLE_REG_15b0); 1799 } while (stat != 0); 1800 } 1801 1802 void 1803 ngle_setup_fb(bus_space_tag_t memt, bus_space_handle_t memh, uint32_t reg10) 1804 { 1805 1806 ngle_setup_hw(memt, memh); 1807 bus_space_write_stream_4(memt, memh, NGLE_REG_10, reg10); 1808 bus_space_write_stream_4(memt, memh, NGLE_REG_14, 0x83000300); 1809 ngle_setup_hw(memt, memh); 1810 bus_space_write_1(memt, memh, NGLE_REG_16b1, 1); 1811 } 1812 #endif /* SMALL_KERNEL */ 1813