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