1 /* $OpenBSD: sti.c,v 1.81 2021/04/29 15:12:14 kettenis 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->putcmap == NULL || scr->scr_bpp > 8) 1118 wdf->cmsize = 0; 1119 else 1120 wdf->cmsize = STI_NCMAP; 1121 break; 1122 1123 case WSDISPLAYIO_LINEBYTES: 1124 if (scr->scr_bpp > 8) 1125 *(u_int *)data = scr->scr_cfg.fb_width * 4; 1126 else 1127 *(u_int *)data = scr->scr_cfg.fb_width; 1128 break; 1129 1130 case WSDISPLAYIO_GETSUPPORTEDDEPTH: 1131 if (scr->scr_bpp > 8) 1132 *(u_int *)data = WSDISPLAYIO_DEPTH_24_32; 1133 else 1134 *(u_int *)data = WSDISPLAYIO_DEPTH_8; 1135 break; 1136 1137 case WSDISPLAYIO_GETCMAP: 1138 if (scr->putcmap == NULL || scr->scr_bpp > 8) 1139 return ENODEV; 1140 cmapp = (struct wsdisplay_cmap *)data; 1141 idx = cmapp->index; 1142 count = cmapp->count; 1143 if (idx >= STI_NCMAP || count > STI_NCMAP - idx) 1144 return EINVAL; 1145 if ((ret = copyout(&scr->scr_rcmap[idx], cmapp->red, count))) 1146 break; 1147 if ((ret = copyout(&scr->scr_gcmap[idx], cmapp->green, count))) 1148 break; 1149 if ((ret = copyout(&scr->scr_bcmap[idx], cmapp->blue, count))) 1150 break; 1151 break; 1152 1153 case WSDISPLAYIO_PUTCMAP: 1154 if (scr->putcmap == NULL || scr->scr_bpp > 8) 1155 return ENODEV; 1156 cmapp = (struct wsdisplay_cmap *)data; 1157 idx = cmapp->index; 1158 count = cmapp->count; 1159 if (idx >= STI_NCMAP || count > STI_NCMAP - idx) 1160 return EINVAL; 1161 if ((ret = copyin(cmapp->red, &scr->scr_rcmap[idx], count))) 1162 break; 1163 if ((ret = copyin(cmapp->green, &scr->scr_gcmap[idx], count))) 1164 break; 1165 if ((ret = copyin(cmapp->blue, &scr->scr_bcmap[idx], count))) 1166 break; 1167 ret = scr->putcmap(scr, idx, count); 1168 break; 1169 1170 case WSDISPLAYIO_SVIDEO: 1171 case WSDISPLAYIO_GVIDEO: 1172 break; 1173 1174 default: 1175 return (-1); /* not supported yet */ 1176 } 1177 1178 return (ret); 1179 } 1180 1181 paddr_t 1182 sti_mmap(void *v, off_t offset, int prot) 1183 { 1184 struct sti_screen *scr = (struct sti_screen *)v; 1185 #if 0 1186 struct sti_rom *rom = scr->scr_rom; 1187 #endif 1188 paddr_t pa; 1189 1190 if ((offset & PAGE_MASK) != 0) 1191 return -1; 1192 1193 if (offset < 0 || offset >= scr->fblen) 1194 return -1; 1195 1196 #if 0 /* XXX not all platforms provide bus_space_mmap() yet */ 1197 pa = bus_space_mmap(rom->memt, scr->fbaddr, offset, prot, 1198 BUS_SPACE_MAP_LINEAR); 1199 #else 1200 pa = scr->fbaddr + offset; 1201 #endif 1202 1203 return pa; 1204 } 1205 1206 int 1207 sti_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep, 1208 int *cxp, int *cyp, uint32_t *defattr) 1209 { 1210 struct sti_screen *scr = (struct sti_screen *)v; 1211 1212 if (scr->scr_nscreens > 0) 1213 return ENOMEM; 1214 1215 *cookiep = scr; 1216 *cxp = 0; 1217 *cyp = 0; 1218 sti_pack_attr(scr, 0, 0, 0, defattr); 1219 scr->scr_nscreens++; 1220 return 0; 1221 } 1222 1223 void 1224 sti_free_screen(void *v, void *cookie) 1225 { 1226 struct sti_screen *scr = (struct sti_screen *)v; 1227 1228 scr->scr_nscreens--; 1229 } 1230 1231 int 1232 sti_show_screen(void *v, void *cookie, int waitok, 1233 void (*cb)(void *, int, int), void *cbarg) 1234 { 1235 #if 0 1236 struct sti_screen *scr = (struct sti_screen *)v; 1237 #endif 1238 1239 return 0; 1240 } 1241 1242 /* 1243 * wsdisplay emulops 1244 */ 1245 1246 int 1247 sti_cursor(void *v, int on, int row, int col) 1248 { 1249 struct sti_screen *scr = (struct sti_screen *)v; 1250 struct sti_font *fp = &scr->scr_curfont; 1251 1252 sti_bmove(scr, 1253 col * fp->width, row * fp->height, 1254 col * fp->width, row * fp->height, 1255 fp->height, fp->width, bmf_invert); 1256 1257 return 0; 1258 } 1259 1260 /* 1261 * ISO 8859-1 part of Unicode to HP Roman font index conversion array. 1262 */ 1263 static const u_int8_t 1264 sti_unitoroman[0x100 - 0xa0] = { 1265 0xa0, 0xb8, 0xbf, 0xbb, 0xba, 0xbc, 0, 0xbd, 1266 0xab, 0, 0xf9, 0xfb, 0, 0xf6, 0, 0xb0, 1267 1268 0xb3, 0xfe, 0, 0, 0xa8, 0xf3, 0xf4, 0xf2, 1269 0, 0, 0xfa, 0xfd, 0xf7, 0xf8, 0, 0xb9, 1270 1271 0xa1, 0xe0, 0xa2, 0xe1, 0xd8, 0xd0, 0xd3, 0xb4, 1272 0xa3, 0xdc, 0xa4, 0xa5, 0xe6, 0xe5, 0xa6, 0xa7, 1273 1274 0xe3, 0xb6, 0xe8, 0xe7, 0xdf, 0xe9, 0xda, 0, 1275 0xd2, 0xad, 0xed, 0xae, 0xdb, 0xb1, 0xf0, 0xde, 1276 1277 0xc8, 0xc4, 0xc0, 0xe2, 0xcc, 0xd4, 0xd7, 0xb5, 1278 0xc9, 0xc5, 0xc1, 0xcd, 0xd9, 0xd5, 0xd1, 0xdd, 1279 1280 0xe4, 0xb7, 0xca, 0xc6, 0xc2, 0xea, 0xce, 0, 1281 0xd6, 0xcb, 0xc7, 0xc3, 0xcf, 0xb2, 0xf1, 0xef 1282 }; 1283 1284 int 1285 sti_mapchar(void *v, int uni, u_int *index) 1286 { 1287 struct sti_screen *scr = (struct sti_screen *)v; 1288 struct sti_font *fp = &scr->scr_curfont; 1289 int c; 1290 1291 switch (fp->type) { 1292 case STI_FONT_HPROMAN8: 1293 if (uni >= 0x80 && uni < 0xa0) 1294 c = -1; 1295 else if (uni >= 0xa0 && uni < 0x100) { 1296 c = (int)sti_unitoroman[uni - 0xa0]; 1297 if (c == 0) 1298 c = -1; 1299 } else 1300 c = uni; 1301 break; 1302 default: 1303 c = uni; 1304 break; 1305 } 1306 1307 if (c == -1 || c < fp->first || c > fp->last) { 1308 *index = '?'; 1309 return (0); 1310 } 1311 1312 *index = c; 1313 return (5); 1314 } 1315 1316 int 1317 sti_putchar(void *v, int row, int col, u_int uc, uint32_t attr) 1318 { 1319 struct sti_screen *scr = (struct sti_screen *)v; 1320 struct sti_rom *rom = scr->scr_rom; 1321 struct sti_font *fp = &scr->scr_curfont; 1322 int bg, fg; 1323 1324 sti_unpack_attr(scr, attr, &fg, &bg, NULL); 1325 1326 if (scr->scr_romfont != NULL) { 1327 /* 1328 * Font is in memory, use unpmv 1329 */ 1330 struct { 1331 struct sti_unpmvflags flags; 1332 struct sti_unpmvin in; 1333 struct sti_unpmvout out; 1334 } a; 1335 1336 bzero(&a, sizeof(a)); 1337 1338 a.flags.flags = STI_UNPMVF_WAIT; 1339 a.in.fg_colour = fg; 1340 a.in.bg_colour = bg; 1341 1342 a.in.x = col * fp->width; 1343 a.in.y = row * fp->height; 1344 a.in.font_addr = scr->scr_romfont; 1345 a.in.index = uc; 1346 1347 (*rom->unpmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg); 1348 } else { 1349 /* 1350 * Font is in frame buffer, use blkmv 1351 */ 1352 struct { 1353 struct sti_blkmvflags flags; 1354 struct sti_blkmvin in; 1355 struct sti_blkmvout out; 1356 } a; 1357 1358 bzero(&a, sizeof(a)); 1359 1360 a.flags.flags = STI_BLKMVF_WAIT; 1361 a.in.fg_colour = fg; 1362 a.in.bg_colour = bg; 1363 1364 a.in.srcx = ((uc - fp->first) / scr->scr_fontmaxcol) * 1365 fp->width + scr->scr_fontbase; 1366 a.in.srcy = ((uc - fp->first) % scr->scr_fontmaxcol) * 1367 fp->height; 1368 a.in.dstx = col * fp->width; 1369 a.in.dsty = row * fp->height; 1370 a.in.height = fp->height; 1371 a.in.width = fp->width; 1372 1373 (*rom->blkmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg); 1374 } 1375 1376 return 0; 1377 } 1378 1379 int 1380 sti_copycols(void *v, int row, int srccol, int dstcol, int ncols) 1381 { 1382 struct sti_screen *scr = (struct sti_screen *)v; 1383 struct sti_font *fp = &scr->scr_curfont; 1384 1385 sti_bmove(scr, 1386 srccol * fp->width, row * fp->height, 1387 dstcol * fp->width, row * fp->height, 1388 fp->height, ncols * fp->width, bmf_copy); 1389 1390 return 0; 1391 } 1392 1393 int 1394 sti_erasecols(void *v, int row, int startcol, int ncols, uint32_t attr) 1395 { 1396 struct sti_screen *scr = (struct sti_screen *)v; 1397 struct sti_font *fp = &scr->scr_curfont; 1398 1399 sti_bmove(scr, 1400 startcol * fp->width, row * fp->height, 1401 startcol * fp->width, row * fp->height, 1402 fp->height, ncols * fp->width, bmf_clear); 1403 1404 return 0; 1405 } 1406 1407 int 1408 sti_copyrows(void *v, int srcrow, int dstrow, int nrows) 1409 { 1410 struct sti_screen *scr = (struct sti_screen *)v; 1411 struct sti_font *fp = &scr->scr_curfont; 1412 1413 sti_bmove(scr, 0, srcrow * fp->height, 0, dstrow * fp->height, 1414 nrows * fp->height, scr->scr_cfg.scr_width, bmf_copy); 1415 1416 return 0; 1417 } 1418 1419 int 1420 sti_eraserows(void *v, int srcrow, int nrows, uint32_t attr) 1421 { 1422 struct sti_screen *scr = (struct sti_screen *)v; 1423 struct sti_font *fp = &scr->scr_curfont; 1424 1425 sti_bmove(scr, 0, srcrow * fp->height, 0, srcrow * fp->height, 1426 nrows * fp->height, scr->scr_cfg.scr_width, bmf_clear); 1427 1428 return 0; 1429 } 1430 1431 int 1432 sti_pack_attr(void *v, int fg, int bg, int flags, uint32_t *pattr) 1433 { 1434 #if 0 1435 struct sti_screen *scr = (struct sti_screen *)v; 1436 #endif 1437 1438 *pattr = flags & WSATTR_REVERSE; 1439 return 0; 1440 } 1441 1442 void 1443 sti_unpack_attr(void *v, uint32_t attr, int *fg, int *bg, int *ul) 1444 { 1445 #if 0 1446 struct sti_screen *scr = (struct sti_screen *)v; 1447 #endif 1448 1449 if (attr & WSATTR_REVERSE) { 1450 *fg = STI_COLOUR_BLACK; 1451 *bg = STI_COLOUR_WHITE; 1452 } else { 1453 *fg = STI_COLOUR_WHITE; 1454 *bg = STI_COLOUR_BLACK; 1455 } 1456 if (ul != NULL) 1457 *ul = 0; 1458 } 1459 1460 int 1461 ngle_default_putcmap(struct sti_screen *scr, u_int idx, u_int count) 1462 { 1463 int i, ret; 1464 1465 for (i = idx + count - 1; i >= (int)idx; i--) 1466 if ((ret = sti_setcment(scr, i, scr->scr_rcmap[i], 1467 scr->scr_gcmap[i], scr->scr_bcmap[i]))) 1468 return EINVAL; 1469 1470 return 0; 1471 } 1472 1473 #ifndef SMALL_KERNEL 1474 1475 void ngle_setup_hw(bus_space_tag_t, bus_space_handle_t); 1476 void ngle_setup_fb(bus_space_tag_t, bus_space_handle_t, uint32_t); 1477 void ngle_setup_attr_planes(struct sti_screen *scr); 1478 void ngle_setup_bt458(struct sti_screen *scr); 1479 1480 #define ngle_bt458_write(memt, memh, r, v) \ 1481 bus_space_write_4(memt, memh, NGLE_REG_RAMDAC + ((r) << 2), (v) << 24) 1482 1483 void 1484 ngle_artist_setupfb(struct sti_screen *scr) 1485 { 1486 struct sti_rom *rom = scr->scr_rom; 1487 bus_space_tag_t memt = rom->memt; 1488 bus_space_handle_t memh = rom->regh[2]; 1489 1490 ngle_setup_bt458(scr); 1491 1492 ngle_setup_hw(memt, memh); 1493 ngle_setup_fb(memt, memh, scr->reg10_value); 1494 1495 ngle_setup_attr_planes(scr); 1496 1497 ngle_setup_hw(memt, memh); 1498 bus_space_write_4(memt, memh, NGLE_REG_21, 1499 bus_space_read_4(memt, memh, NGLE_REG_21) | 0x0a000000); 1500 bus_space_write_4(memt, memh, NGLE_REG_27, 1501 bus_space_read_4(memt, memh, NGLE_REG_27) | 0x00800000); 1502 } 1503 1504 void 1505 ngle_elk_setupfb(struct sti_screen *scr) 1506 { 1507 struct sti_rom *rom = scr->scr_rom; 1508 bus_space_tag_t memt = rom->memt; 1509 bus_space_handle_t memh = rom->regh[2]; 1510 1511 ngle_setup_bt458(scr); 1512 1513 ngle_setup_hw(memt, memh); 1514 ngle_setup_fb(memt, memh, scr->reg10_value); 1515 1516 ngle_setup_attr_planes(scr); 1517 1518 ngle_setup_hw(memt, memh); 1519 /* enable overlay planes in Bt458 command register */ 1520 ngle_bt458_write(memt, memh, 0x0c, 0x06); 1521 ngle_bt458_write(memt, memh, 0x0e, 0x43); 1522 } 1523 1524 void 1525 ngle_timber_setupfb(struct sti_screen *scr) 1526 { 1527 struct sti_rom *rom = scr->scr_rom; 1528 bus_space_tag_t memt = rom->memt; 1529 bus_space_handle_t memh = rom->regh[2]; 1530 1531 ngle_setup_bt458(scr); 1532 1533 ngle_setup_hw(memt, memh); 1534 /* enable overlay planes in Bt458 command register */ 1535 ngle_bt458_write(memt, memh, 0x0c, 0x06); 1536 ngle_bt458_write(memt, memh, 0x0e, 0x43); 1537 } 1538 1539 void 1540 ngle_setup_bt458(struct sti_screen *scr) 1541 { 1542 struct sti_rom *rom = scr->scr_rom; 1543 bus_space_tag_t memt = rom->memt; 1544 bus_space_handle_t memh = rom->regh[2]; 1545 1546 ngle_setup_hw(memt, memh); 1547 /* set Bt458 read mask register to all planes */ 1548 ngle_bt458_write(memt, memh, 0x08, 0x04); 1549 ngle_bt458_write(memt, memh, 0x0a, 0xff); 1550 } 1551 1552 void 1553 ngle_setup_attr_planes(struct sti_screen *scr) 1554 { 1555 struct sti_rom *rom = scr->scr_rom; 1556 bus_space_tag_t memt = rom->memt; 1557 bus_space_handle_t memh = rom->regh[2]; 1558 1559 ngle_setup_hw(memt, memh); 1560 bus_space_write_4(memt, memh, NGLE_REG_11, 0x2ea0d000); 1561 bus_space_write_4(memt, memh, NGLE_REG_14, 0x23000302); 1562 bus_space_write_4(memt, memh, NGLE_REG_12, scr->reg12_value); 1563 bus_space_write_4(memt, memh, NGLE_REG_8, 0xffffffff); 1564 1565 bus_space_write_4(memt, memh, NGLE_REG_6, 0x00000000); 1566 bus_space_write_4(memt, memh, NGLE_REG_9, 1567 (scr->scr_cfg.scr_width << 16) | scr->scr_cfg.scr_height); 1568 bus_space_write_4(memt, memh, NGLE_REG_6, 0x05000000); 1569 bus_space_write_4(memt, memh, NGLE_REG_9, 0x00040001); 1570 1571 ngle_setup_hw(memt, memh); 1572 bus_space_write_4(memt, memh, NGLE_REG_12, 0x00000000); 1573 1574 ngle_setup_fb(memt, memh, scr->reg10_value); 1575 } 1576 1577 int 1578 ngle_putcmap(struct sti_screen *scr, u_int idx, u_int count) 1579 { 1580 struct sti_rom *rom = scr->scr_rom; 1581 bus_space_tag_t memt = rom->memt; 1582 bus_space_handle_t memh = rom->regh[2]; 1583 uint8_t *r, *g, *b; 1584 uint32_t cmap_finish; 1585 1586 if (scr->scr_bpp > 8) 1587 cmap_finish = 0x83000100; 1588 else 1589 cmap_finish = 0x80000100; 1590 1591 r = scr->scr_rcmap + idx; 1592 g = scr->scr_gcmap + idx; 1593 b = scr->scr_bcmap + idx; 1594 1595 ngle_setup_hw(memt, memh); 1596 bus_space_write_4(memt, memh, NGLE_REG_10, 0xbbe0f000); 1597 bus_space_write_4(memt, memh, NGLE_REG_14, 0x03000300); 1598 bus_space_write_4(memt, memh, NGLE_REG_13, 0xffffffff); 1599 1600 while (count-- != 0) { 1601 ngle_setup_hw(memt, memh); 1602 bus_space_write_4(memt, memh, NGLE_REG_3, 0x400 | (idx << 2)); 1603 bus_space_write_4(memt, memh, NGLE_REG_4, 1604 (*r << 16) | (*g << 8) | *b); 1605 1606 idx++; 1607 r++, g++, b++; 1608 } 1609 1610 bus_space_write_4(memt, memh, NGLE_REG_2, 0x400); 1611 bus_space_write_4(memt, memh, scr->cmap_finish_register, cmap_finish); 1612 ngle_setup_fb(memt, memh, scr->reg10_value); 1613 1614 1615 return 0; 1616 } 1617 1618 void 1619 ngle_setup_hw(bus_space_tag_t memt, bus_space_handle_t memh) 1620 { 1621 uint8_t stat; 1622 1623 do { 1624 stat = bus_space_read_1(memt, memh, NGLE_REG_15b0); 1625 if (stat == 0) 1626 stat = bus_space_read_1(memt, memh, NGLE_REG_15b0); 1627 } while (stat != 0); 1628 } 1629 1630 void 1631 ngle_setup_fb(bus_space_tag_t memt, bus_space_handle_t memh, uint32_t reg10) 1632 { 1633 ngle_setup_hw(memt, memh); 1634 bus_space_write_4(memt, memh, NGLE_REG_10, reg10); 1635 bus_space_write_4(memt, memh, NGLE_REG_14, 0x83000300); 1636 ngle_setup_hw(memt, memh); 1637 bus_space_write_1(memt, memh, NGLE_REG_16b1, 1); 1638 } 1639 #endif /* SMALL_KERNEL */ 1640