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