1 /* $NetBSD: sti.c,v 1.10 2009/05/07 15:34:50 skrll Exp $ */ 2 3 /* $OpenBSD: sti.c,v 1.35 2003/12/16 06:07:13 mickey Exp $ */ 4 5 /* 6 * Copyright (c) 2000-2003 Michael Shalayeff 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, 22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 27 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 28 * THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 /* 31 * TODO: 32 * call sti procs asynchronously; 33 * implement console scroll-back; 34 * X11 support. 35 */ 36 37 #include <sys/cdefs.h> 38 __KERNEL_RCSID(0, "$NetBSD: sti.c,v 1.10 2009/05/07 15:34:50 skrll Exp $"); 39 40 #include "wsdisplay.h" 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/device.h> 45 #include <sys/malloc.h> 46 47 #include <uvm/uvm.h> 48 49 #include <sys/bus.h> 50 51 #include <dev/wscons/wsdisplayvar.h> 52 #include <dev/wscons/wsconsio.h> 53 54 #include <dev/ic/stireg.h> 55 #include <dev/ic/stivar.h> 56 57 void sti_cursor(void *, int, int, int); 58 int sti_mapchar(void *, int, u_int *); 59 void sti_putchar(void *, int, int, u_int, long); 60 void sti_copycols(void *, int, int, int, int); 61 void sti_erasecols(void *, int, int, int, long); 62 void sti_copyrows(void *, int, int, int); 63 void sti_eraserows(void *, int, int, long); 64 int sti_alloc_attr(void *, int, int, int, long *); 65 66 struct wsdisplay_emulops sti_emulops = { 67 sti_cursor, 68 sti_mapchar, 69 sti_putchar, 70 sti_copycols, 71 sti_erasecols, 72 sti_copyrows, 73 sti_eraserows, 74 sti_alloc_attr 75 }; 76 77 int sti_ioctl(void *, void *, u_long, void *, int, struct lwp *); 78 paddr_t sti_mmap(void *, void *, off_t, int); 79 int sti_alloc_screen(void *, const struct wsscreen_descr *, 80 void **, int *, int *, long *); 81 void sti_free_screen(void *, void *); 82 int sti_show_screen(void *, void *, int, void (*cb)(void *, int, int), void *); 83 int sti_load_font(void *, void *, struct wsdisplay_font *); 84 85 const struct wsdisplay_accessops sti_accessops = { 86 sti_ioctl, 87 sti_mmap, 88 sti_alloc_screen, 89 sti_free_screen, 90 sti_show_screen, 91 sti_load_font 92 }; 93 94 struct wsscreen_descr sti_default_screen = { 95 "default", 0, 0, 96 &sti_emulops, 97 0, 0, 98 WSSCREEN_REVERSE | WSSCREEN_UNDERLINE 99 }; 100 101 const struct wsscreen_descr *sti_default_scrlist[] = { 102 &sti_default_screen 103 }; 104 105 struct wsscreen_list sti_default_screenlist = { 106 sizeof(sti_default_scrlist) / sizeof(sti_default_scrlist[0]), 107 sti_default_scrlist 108 }; 109 110 enum sti_bmove_funcs { 111 bmf_clear, bmf_copy, bmf_invert, bmf_underline 112 }; 113 114 int sti_init(struct sti_softc *, int); 115 int sti_inqcfg(struct sti_softc *, struct sti_inqconfout *); 116 void sti_bmove(struct sti_softc *, int, int, int, int, int, int, 117 enum sti_bmove_funcs); 118 int sti_setcment(struct sti_softc *, u_int, u_char, u_char, u_char); 119 int sti_fetchfonts(struct sti_softc *, struct sti_inqconfout *, u_int32_t); 120 void sti_attach_deferred(device_t); 121 122 void 123 sti_attach_common(struct sti_softc *sc) 124 { 125 struct sti_inqconfout cfg; 126 struct sti_einqconfout ecfg; 127 bus_space_handle_t fbh; 128 struct sti_dd *dd; 129 struct sti_cfg *cc; 130 int error, size, i; 131 u_int8_t *p = (u_int8_t *)sc->sc_code; 132 u_int32_t addr, eaddr; 133 struct sti_region r; 134 u_int32_t *q; 135 uint32_t tmp; 136 137 dd = &sc->sc_dd; 138 if (sc->sc_devtype == STI_DEVTYPE1) { 139 #define parseshort(o) \ 140 ((bus_space_read_1(sc->memt, sc->romh, (o) + 3) << 8) | \ 141 (bus_space_read_1(sc->memt, sc->romh, (o) + 7))) 142 #define parseword(o) \ 143 ((bus_space_read_1(sc->memt, sc->romh, (o) + 3) << 24) | \ 144 (bus_space_read_1(sc->memt, sc->romh, (o) + 7) << 16) | \ 145 (bus_space_read_1(sc->memt, sc->romh, (o) + 11) << 8) | \ 146 (bus_space_read_1(sc->memt, sc->romh, (o) + 15))) 147 148 dd->dd_type = bus_space_read_1(sc->memt, sc->romh, 0x03); 149 dd->dd_nmon = bus_space_read_1(sc->memt, sc->romh, 0x07); 150 dd->dd_grrev = bus_space_read_1(sc->memt, sc->romh, 0x0b); 151 dd->dd_lrrev = bus_space_read_1(sc->memt, sc->romh, 0x0f); 152 dd->dd_grid[0] = parseword(0x10); 153 dd->dd_grid[1] = parseword(0x20); 154 dd->dd_fntaddr = parseword(0x30) & ~3; 155 dd->dd_maxst = parseword(0x40); 156 dd->dd_romend = parseword(0x50) & ~3; 157 dd->dd_reglst = parseword(0x60) & ~3; 158 dd->dd_maxreent= parseshort(0x70); 159 dd->dd_maxtimo = parseshort(0x78); 160 dd->dd_montbl = parseword(0x80) & ~3; 161 dd->dd_udaddr = parseword(0x90) & ~3; 162 dd->dd_stimemreq=parseword(0xa0); 163 dd->dd_udsize = parseword(0xb0); 164 dd->dd_pwruse = parseshort(0xc0); 165 dd->dd_bussup = bus_space_read_1(sc->memt, sc->romh, 0xcb); 166 dd->dd_ebussup = bus_space_read_1(sc->memt, sc->romh, 0xcf); 167 dd->dd_altcodet= bus_space_read_1(sc->memt, sc->romh, 0xd3); 168 dd->dd_eddst[0]= bus_space_read_1(sc->memt, sc->romh, 0xd7); 169 dd->dd_eddst[1]= bus_space_read_1(sc->memt, sc->romh, 0xdb); 170 dd->dd_eddst[2]= bus_space_read_1(sc->memt, sc->romh, 0xdf); 171 dd->dd_cfbaddr = parseword(0xe0) & ~3; 172 173 dd->dd_pacode[0x0] = parseword(0x100) & ~3; 174 dd->dd_pacode[0x1] = parseword(0x110) & ~3; 175 dd->dd_pacode[0x2] = parseword(0x120) & ~3; 176 dd->dd_pacode[0x3] = parseword(0x130) & ~3; 177 dd->dd_pacode[0x4] = parseword(0x140) & ~3; 178 dd->dd_pacode[0x5] = parseword(0x150) & ~3; 179 dd->dd_pacode[0x6] = parseword(0x160) & ~3; 180 dd->dd_pacode[0x7] = parseword(0x170) & ~3; 181 dd->dd_pacode[0x8] = parseword(0x180) & ~3; 182 dd->dd_pacode[0x9] = parseword(0x190) & ~3; 183 dd->dd_pacode[0xa] = parseword(0x1a0) & ~3; 184 dd->dd_pacode[0xb] = parseword(0x1b0) & ~3; 185 dd->dd_pacode[0xc] = parseword(0x1c0) & ~3; 186 dd->dd_pacode[0xd] = parseword(0x1d0) & ~3; 187 dd->dd_pacode[0xe] = parseword(0x1e0) & ~3; 188 dd->dd_pacode[0xf] = parseword(0x1f0) & ~3; 189 } else /* STI_DEVTYPE4 */ 190 bus_space_read_region_4(sc->memt, sc->romh, 0, (u_int32_t *)dd, 191 sizeof(*dd) / 4); 192 193 #ifdef STIDEBUG 194 printf("dd:\n" 195 "devtype=%x, rev=%x;%d, altt=%x, gid=%016llx, font=%x, mss=%x\n" 196 "end=%x, regions=%x, msto=%x, timo=%d, mont=%x, user=%x[%x]\n" 197 "memrq=%x, pwr=%d, bus=%x, ebus=%x, cfb=%x\n" 198 "code=", 199 dd->dd_type & 0xff, dd->dd_grrev, dd->dd_lrrev, dd->dd_altcodet, 200 *(u_int64_t *)dd->dd_grid, dd->dd_fntaddr, dd->dd_maxst, 201 dd->dd_romend, dd->dd_reglst, dd->dd_maxreent, dd->dd_maxtimo, 202 dd->dd_montbl, dd->dd_udaddr, dd->dd_udsize, dd->dd_stimemreq, 203 dd->dd_pwruse, dd->dd_bussup, dd->dd_ebussup, dd->dd_cfbaddr); 204 printf("%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x\n", 205 dd->dd_pacode[0x0], dd->dd_pacode[0x1], dd->dd_pacode[0x2], 206 dd->dd_pacode[0x3], dd->dd_pacode[0x4], dd->dd_pacode[0x5], 207 dd->dd_pacode[0x6], dd->dd_pacode[0x7], dd->dd_pacode[0x8], 208 dd->dd_pacode[0x9], dd->dd_pacode[0xa], dd->dd_pacode[0xb], 209 dd->dd_pacode[0xc], dd->dd_pacode[0xd], dd->dd_pacode[0xe], 210 dd->dd_pacode[0xf]); 211 #endif 212 /* divise code size, could be less than STI_END entries */ 213 for (i = STI_END; !dd->dd_pacode[i]; i--); 214 size = dd->dd_pacode[i] - dd->dd_pacode[STI_BEGIN]; 215 if (sc->sc_devtype == STI_DEVTYPE1) 216 size = (size + 3) / 4; 217 if (!(sc->sc_code = uvm_km_alloc(kernel_map, round_page(size), 0, 218 UVM_KMF_WIRED))) { 219 printf(": cannot allocate %u bytes for code\n", size); 220 return; 221 } 222 #ifdef STIDEBUG 223 printf("code=0x%x[%x]\n", (uint)sc->sc_code, size); 224 #endif 225 226 /* copy code into memory */ 227 if (sc->sc_devtype == STI_DEVTYPE1) { 228 p = (u_int8_t *)sc->sc_code; 229 for (addr = dd->dd_pacode[STI_BEGIN], eaddr = addr + size * 4; 230 addr < eaddr; addr += 4 ) 231 *p++ = bus_space_read_4(sc->memt, sc->romh, addr) 232 & 0xff; 233 234 } else /* STI_DEVTYPE4 */ 235 bus_space_read_region_4(sc->memt, sc->romh, 236 dd->dd_pacode[STI_BEGIN], (u_int32_t *)sc->sc_code, 237 size / 4); 238 239 #define O(i) (dd->dd_pacode[(i)] ? (sc->sc_code + \ 240 (dd->dd_pacode[(i)] - dd->dd_pacode[0]) / \ 241 (sc->sc_devtype == STI_DEVTYPE1 ? 4 : 1)) : 0) 242 sc->init = (sti_init_t) O(STI_INIT_GRAPH); 243 sc->mgmt = (sti_mgmt_t) O(STI_STATE_MGMT); 244 sc->unpmv = (sti_unpmv_t) O(STI_FONT_UNPMV); 245 sc->blkmv = (sti_blkmv_t) O(STI_BLOCK_MOVE); 246 sc->test = (sti_test_t) O(STI_SELF_TEST); 247 sc->exhdl = (sti_exhdl_t) O(STI_EXCEP_HDLR); 248 sc->inqconf = (sti_inqconf_t)O(STI_INQ_CONF); 249 sc->scment = (sti_scment_t)O(STI_SCM_ENT); 250 sc->dmac = (sti_dmac_t) O(STI_DMA_CTRL); 251 sc->flowc = (sti_flowc_t) O(STI_FLOW_CTRL); 252 sc->utiming = (sti_utiming_t)O(STI_UTIMING); 253 sc->pmgr = (sti_pmgr_t) O(STI_PROC_MGR); 254 sc->util = (sti_util_t) O(STI_UTIL); 255 256 if ((error = uvm_map_protect(kernel_map, sc->sc_code, 257 sc->sc_code + round_page(size), UVM_PROT_RX, FALSE))) { 258 printf(": uvm_map_protect failed (%d)\n", error); 259 uvm_km_free(kernel_map, sc->sc_code, round_page(size), 260 UVM_KMF_WIRED); 261 return; 262 } 263 264 cc = &sc->sc_cfg; 265 memset(cc, 0, sizeof (*cc)); 266 i = dd->dd_reglst; 267 #ifdef STIDEBUG 268 printf("stiregions @%d:\n", i); 269 #endif 270 r.last = 0; 271 for (q = cc->regions; !r.last && 272 q < &cc->regions[STI_REGION_MAX]; q++) { 273 274 if (sc->sc_devtype == STI_DEVTYPE1) 275 tmp = parseword(i), i += 16; 276 else 277 tmp = bus_space_read_4(sc->memt, sc->romh, i), i += 4; 278 memcpy(&r, &tmp, sizeof (r)); 279 280 *q = (q == cc->regions ? sc->romh : sc->base) + 281 (r.offset << PGSHIFT); 282 #ifdef STIDEBUG 283 printf("%x @ 0x%x%s%s%s%s\n", 284 r.length << PGSHIFT, *q, r.sys_only ? " sys" : "", 285 r.cache ? " cache" : "", r.btlb ? " btlb" : "", 286 r.last ? " last" : ""); 287 #endif 288 289 /* rom has already been mapped */ 290 if (q != cc->regions) { 291 if (bus_space_map(sc->memt, *q, 292 r.length << PGSHIFT, 0, &fbh)) { 293 #ifdef STIDEBUG 294 printf("already mapped region\n"); 295 #endif 296 } else { 297 if (q - cc->regions == 1) { 298 sc->fbaddr = *q; 299 sc->fblen = r.length << PGSHIFT; 300 } 301 *q = fbh; 302 } 303 } 304 } 305 306 if ((error = sti_init(sc, 0))) { 307 printf(": can not initialize (%d)\n", error); 308 return; 309 } 310 311 memset(&cfg, 0, sizeof(cfg)); 312 memset(&ecfg, 0, sizeof(ecfg)); 313 cfg.ext = &ecfg; 314 if ((error = sti_inqcfg(sc, &cfg))) { 315 printf(": error %d inquiring config\n", error); 316 return; 317 } 318 319 if ((error = sti_init(sc, STI_TEXTMODE))) { 320 printf(": can not initialize (%d)\n", error); 321 return; 322 } 323 324 #ifdef STIDEBUG 325 printf("conf: bpp=%d planes=%d attr=%d\n" 326 "crt=0x%x:0x%x:0x%x hw=0x%x:0x%x:0x%x\n", 327 cfg.bpp, cfg.planes, cfg.attributes, 328 ecfg.crt_config[0], ecfg.crt_config[1], ecfg.crt_config[2], 329 ecfg.crt_hw[0], ecfg.crt_hw[1], ecfg.crt_hw[2]); 330 #endif 331 sc->sc_wsmode = WSDISPLAYIO_MODE_EMUL; 332 sc->sc_bpp = cfg.bppu; 333 printf(": %s rev %d.%02d;%d, ID 0x%016llX\n" 334 "%s: %dx%d frame buffer, %dx%dx%d display, offset %dx%d\n", 335 cfg.name, dd->dd_grrev >> 4, dd->dd_grrev & 0xf, dd->dd_lrrev, 336 *(u_int64_t *)dd->dd_grid, device_xname(sc->sc_dev), cfg.fbwidth, 337 cfg.fbheight, cfg.width, cfg.height, cfg.bppu, cfg.owidth, 338 cfg.oheight); 339 340 if ((error = sti_fetchfonts(sc, &cfg, dd->dd_fntaddr))) { 341 aprint_error_dev(sc->sc_dev, "cannot fetch fonts (%d)\n", 342 error); 343 return; 344 } 345 346 /* 347 * parse screen descriptions: 348 * figure number of fonts supported; 349 * allocate wscons structures; 350 * calculate dimensions. 351 */ 352 353 sti_default_screen.ncols = cfg.width / sc->sc_curfont.width; 354 sti_default_screen.nrows = cfg.height / sc->sc_curfont.height; 355 sti_default_screen.fontwidth = sc->sc_curfont.width; 356 sti_default_screen.fontheight = sc->sc_curfont.height; 357 358 #if NWSDISPLAY > 0 359 config_interrupts(sc->sc_dev, sti_attach_deferred); 360 #endif 361 362 } 363 364 void 365 sti_attach_deferred(device_t dev) 366 { 367 struct sti_softc *sc = device_private(dev); 368 struct wsemuldisplaydev_attach_args waa; 369 long defattr; 370 371 waa.console = sc->sc_flags & STI_CONSOLE ? 1 : 0; 372 waa.scrdata = &sti_default_screenlist; 373 waa.accessops = &sti_accessops; 374 waa.accesscookie = sc; 375 376 /* attach as console if required */ 377 if (waa.console) { 378 sti_alloc_attr(sc, 0, 0, 0, &defattr); 379 wsdisplay_cnattach(&sti_default_screen, sc, 380 0, sti_default_screen.nrows - 1, defattr); 381 } 382 383 config_found(sc->sc_dev, &waa, wsemuldisplaydevprint); 384 } 385 386 int 387 sti_fetchfonts(struct sti_softc *sc, struct sti_inqconfout *cfg, u_int32_t addr) 388 { 389 struct sti_font *fp = &sc->sc_curfont; 390 int size; 391 #ifdef notyet 392 int uc; 393 struct { 394 struct sti_unpmvflags flags; 395 struct sti_unpmvin in; 396 struct sti_unpmvout out; 397 } a; 398 #endif 399 400 /* 401 * Get the first PROM font in memory 402 */ 403 do { 404 if (sc->sc_devtype == STI_DEVTYPE1) { 405 fp->first = parseshort(addr + 0x00); 406 fp->last = parseshort(addr + 0x08); 407 fp->width = bus_space_read_1(sc->memt, sc->romh, 408 addr + 0x13); 409 fp->height = bus_space_read_1(sc->memt, sc->romh, 410 addr + 0x17); 411 fp->type = bus_space_read_1(sc->memt, sc->romh, 412 addr + 0x1b); 413 fp->bpc = bus_space_read_1(sc->memt, sc->romh, 414 addr + 0x1f); 415 fp->next = parseword(addr + 0x23); 416 fp->uheight= bus_space_read_1(sc->memt, sc->romh, 417 addr + 0x33); 418 fp->uoffset= bus_space_read_1(sc->memt, sc->romh, 419 addr + 0x37); 420 } else /* STI_DEVTYPE4 */ 421 bus_space_read_region_4(sc->memt, sc->romh, addr, 422 (u_int32_t *)fp, sizeof(struct sti_font) / 4); 423 424 printf("%s: %dx%d font type %d, %d bpc, charset %d-%d\n", 425 device_xname(sc->sc_dev), fp->width, fp->height, fp->type, 426 fp->bpc, fp->first, fp->last); 427 428 size = sizeof(struct sti_font) + 429 (fp->last - fp->first + 1) * fp->bpc; 430 if (sc->sc_devtype == STI_DEVTYPE1) 431 size *= 4; 432 sc->sc_romfont = malloc(size, M_DEVBUF, M_NOWAIT); 433 if (sc->sc_romfont == NULL) 434 return (ENOMEM); 435 436 bus_space_read_region_4(sc->memt, sc->romh, addr, 437 (u_int32_t *)sc->sc_romfont, size / 4); 438 439 addr = 0; /* fp->next */ 440 } while (addr); 441 442 #ifdef notyet 443 /* 444 * If there is enough room in the off-screen framebuffer memory, 445 * display all the characters there in order to display them 446 * faster with blkmv operations rather than unpmv later on. 447 */ 448 if (size <= cfg->fbheight * 449 (cfg->fbwidth - cfg->width - cfg->owidth)) { 450 memset(&a, 0, sizeof(a)); 451 a.flags.flags = STI_UNPMVF_WAIT; 452 a.in.fg_colour = STI_COLOUR_WHITE; 453 a.in.bg_colour = STI_COLOUR_BLACK; 454 a.in.font_addr = sc->sc_romfont; 455 456 sc->sc_fontmaxcol = cfg->fbheight / fp->height; 457 sc->sc_fontbase = cfg->width + cfg->owidth; 458 for (uc = fp->first; uc <= fp->last; uc++) { 459 a.in.x = ((uc - fp->first) / sc->sc_fontmaxcol) * 460 fp->width + sc->sc_fontbase; 461 a.in.y = ((uc - fp->first) % sc->sc_fontmaxcol) * 462 fp->height; 463 a.in.index = uc; 464 465 (*sc->unpmv)(&a.flags, &a.in, &a.out, &sc->sc_cfg); 466 if (a.out.errno) { 467 aprint_error_dev(sc->sc_dev, "unpmv %d returned %d\n", 468 uc, a.out.errno); 469 return (0); 470 } 471 } 472 473 free(sc->sc_romfont, M_DEVBUF); 474 sc->sc_romfont = NULL; 475 } 476 #endif 477 478 return (0); 479 } 480 481 int 482 sti_init(struct sti_softc *sc, int mode) 483 { 484 struct { 485 struct sti_initflags flags; 486 struct sti_initin in; 487 struct sti_initout out; 488 } a; 489 490 memset(&a, 0, sizeof(a)); 491 492 a.flags.flags = STI_INITF_WAIT | STI_INITF_CMB | STI_INITF_EBET | 493 (mode & STI_TEXTMODE ? STI_INITF_TEXT | STI_INITF_PBET | 494 STI_INITF_PBETI | STI_INITF_ICMT : 0); 495 a.in.text_planes = 1; 496 #ifdef STIDEBUG 497 printf("%s: init,%p(%x, %p, %p, %p)\n", device_xname(sc->sc_dev), 498 sc->init, a.flags.flags, &a.in, &a.out, &sc->sc_cfg); 499 #endif 500 (*sc->init)(&a.flags, &a.in, &a.out, &sc->sc_cfg); 501 return (a.out.text_planes != a.in.text_planes || a.out.errno); 502 } 503 504 int 505 sti_inqcfg(struct sti_softc *sc, struct sti_inqconfout *out) 506 { 507 struct { 508 struct sti_inqconfflags flags; 509 struct sti_inqconfin in; 510 } a; 511 512 memset(&a, 0, sizeof(a)); 513 514 a.flags.flags = STI_INQCONFF_WAIT; 515 (*sc->inqconf)(&a.flags, &a.in, out, &sc->sc_cfg); 516 517 return out->errno; 518 } 519 520 void 521 sti_bmove(struct sti_softc *sc, int x1, int y1, int x2, int y2, int h, int w, 522 enum sti_bmove_funcs f) 523 { 524 struct { 525 struct sti_blkmvflags flags; 526 struct sti_blkmvin in; 527 struct sti_blkmvout out; 528 } a; 529 530 memset(&a, 0, sizeof(a)); 531 532 a.flags.flags = STI_BLKMVF_WAIT; 533 switch (f) { 534 case bmf_clear: 535 a.flags.flags |= STI_BLKMVF_CLR; 536 a.in.bg_colour = STI_COLOUR_BLACK; 537 break; 538 case bmf_underline: 539 case bmf_copy: 540 a.in.fg_colour = STI_COLOUR_WHITE; 541 a.in.bg_colour = STI_COLOUR_BLACK; 542 break; 543 case bmf_invert: 544 a.flags.flags |= STI_BLKMVF_COLR; 545 a.in.fg_colour = STI_COLOUR_BLACK; 546 a.in.bg_colour = STI_COLOUR_WHITE; 547 break; 548 } 549 a.in.srcx = x1; 550 a.in.srcy = y1; 551 a.in.dstx = x2; 552 a.in.dsty = y2; 553 a.in.height = h; 554 a.in.width = w; 555 556 (*sc->blkmv)(&a.flags, &a.in, &a.out, &sc->sc_cfg); 557 #ifdef STIDEBUG 558 if (a.out.errno) 559 aprint_error_dev(sc->sc_dev, "blkmv returned %d\n", 560 a.out.errno); 561 #endif 562 } 563 564 int 565 sti_setcment(struct sti_softc *sc, u_int i, u_char r, u_char g, u_char b) 566 { 567 struct { 568 struct sti_scmentflags flags; 569 struct sti_scmentin in; 570 struct sti_scmentout out; 571 } a; 572 573 memset(&a, 0, sizeof(a)); 574 575 a.flags.flags = STI_SCMENTF_WAIT; 576 a.in.entry = i; 577 a.in.value = (r << 16) | (g << 8) | b; 578 579 (*sc->scment)(&a.flags, &a.in, &a.out, &sc->sc_cfg); 580 581 return a.out.errno; 582 } 583 584 int 585 sti_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l) 586 { 587 struct sti_softc *sc = v; 588 struct wsdisplay_fbinfo *wdf; 589 struct wsdisplay_cmap *cmapp; 590 u_int mode, idx, count; 591 int i, ret; 592 593 ret = 0; 594 switch (cmd) { 595 case WSDISPLAYIO_GMODE: 596 *(u_int *)data = sc->sc_wsmode; 597 break; 598 599 case WSDISPLAYIO_SMODE: 600 mode = *(u_int *)data; 601 if (sc->sc_wsmode == WSDISPLAYIO_MODE_EMUL && 602 mode == WSDISPLAYIO_MODE_DUMBFB) 603 ret = sti_init(sc, 0); 604 else if (sc->sc_wsmode == WSDISPLAYIO_MODE_DUMBFB && 605 mode == WSDISPLAYIO_MODE_EMUL) 606 ret = sti_init(sc, STI_TEXTMODE); 607 sc->sc_wsmode = mode; 608 break; 609 610 case WSDISPLAYIO_GTYPE: 611 *(u_int *)data = WSDISPLAY_TYPE_STI; 612 break; 613 614 case WSDISPLAYIO_GINFO: 615 wdf = (struct wsdisplay_fbinfo *)data; 616 wdf->height = sc->sc_cfg.scr_height; 617 wdf->width = sc->sc_cfg.scr_width; 618 wdf->depth = sc->sc_bpp; 619 wdf->cmsize = STI_NCMAP; 620 break; 621 622 case WSDISPLAYIO_LINEBYTES: 623 *(u_int *)data = sc->sc_cfg.fb_width; 624 break; 625 626 case WSDISPLAYIO_GETCMAP: 627 if (sc->scment == NULL) 628 return ENOTTY; 629 cmapp = (struct wsdisplay_cmap *)data; 630 idx = cmapp->index; 631 count = cmapp->count; 632 if (idx > STI_NCMAP || idx + count >= STI_NCMAP) 633 return EINVAL; 634 if ((ret = copyout(&sc->sc_rcmap[idx], cmapp->red, count))) 635 break; 636 if ((ret = copyout(&sc->sc_gcmap[idx], cmapp->green, count))) 637 break; 638 if ((ret = copyout(&sc->sc_bcmap[idx], cmapp->blue, count))) 639 break; 640 break; 641 642 case WSDISPLAYIO_PUTCMAP: 643 if (sc->scment == NULL) 644 return ENOTTY; 645 cmapp = (struct wsdisplay_cmap *)data; 646 idx = cmapp->index; 647 count = cmapp->count; 648 if (idx > STI_NCMAP || idx + count >= STI_NCMAP) 649 return EINVAL; 650 if ((ret = copyin(cmapp->red, &sc->sc_rcmap[idx], count))) 651 break; 652 if ((ret = copyin(cmapp->green, &sc->sc_gcmap[idx], count))) 653 break; 654 if ((ret = copyin(cmapp->blue, &sc->sc_bcmap[idx], count))) 655 break; 656 for (i = idx + count - 1; i >= idx; i--) 657 if ((ret = sti_setcment(sc, i, sc->sc_rcmap[i], 658 sc->sc_gcmap[i], sc->sc_bcmap[i]))) { 659 #ifdef STIDEBUG 660 printf("sti_ioctl: " 661 "sti_setcment(%d, %u, %u, %u): %%d\n", i, 662 (u_int)sc->sc_rcmap[i], 663 (u_int)sc->sc_gcmap[i], 664 (u_int)sc->sc_bcmap[i]); 665 #endif 666 ret = EINVAL; 667 break; 668 } 669 break; 670 671 case WSDISPLAYIO_SVIDEO: 672 case WSDISPLAYIO_GVIDEO: 673 case WSDISPLAYIO_GCURPOS: 674 case WSDISPLAYIO_SCURPOS: 675 case WSDISPLAYIO_GCURMAX: 676 case WSDISPLAYIO_GCURSOR: 677 case WSDISPLAYIO_SCURSOR: 678 default: 679 return (ENOTTY); /* not supported yet */ 680 } 681 682 return (ret); 683 } 684 685 paddr_t 686 sti_mmap(void *v, void *vs, off_t offset, int prot) 687 { 688 /* XXX not finished */ 689 return -1; 690 } 691 692 int 693 sti_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep, 694 int *cxp, int *cyp, long *defattr) 695 { 696 struct sti_softc *sc = v; 697 698 if (sc->sc_nscreens > 0) 699 return ENOMEM; 700 701 *cookiep = sc; 702 *cxp = 0; 703 *cyp = 0; 704 sti_alloc_attr(sc, 0, 0, 0, defattr); 705 sc->sc_nscreens++; 706 return 0; 707 } 708 709 void 710 sti_free_screen(void *v, void *cookie) 711 { 712 struct sti_softc *sc = v; 713 714 sc->sc_nscreens--; 715 } 716 717 int 718 sti_show_screen(void *v, void *cookie, int waitok, void (*cb)(void *, int, int), void *cbarg) 719 { 720 return 0; 721 } 722 723 int 724 sti_load_font(void *v, void *cookie, struct wsdisplay_font *font) 725 { 726 return -1; 727 } 728 729 void 730 sti_cursor(void *v, int on, int row, int col) 731 { 732 struct sti_softc *sc = v; 733 struct sti_font *fp = &sc->sc_curfont; 734 735 sti_bmove(sc, col * fp->width, row * fp->height, col * fp->width, 736 row * fp->height, fp->height, fp->width, bmf_invert); 737 } 738 739 int 740 sti_mapchar(void *v, int uni, u_int *index) 741 { 742 if (uni < 256) 743 *index = uni; 744 745 return 1; 746 } 747 748 void 749 sti_putchar(void *v, int row, int col, u_int uc, long attr) 750 { 751 struct sti_softc *sc = v; 752 struct sti_font *fp = &sc->sc_curfont; 753 754 if (sc->sc_romfont != NULL) { 755 /* 756 * Font is in memory, use unpmv 757 */ 758 struct { 759 struct sti_unpmvflags flags; 760 struct sti_unpmvin in; 761 struct sti_unpmvout out; 762 } a; 763 764 memset(&a, 0, sizeof(a)); 765 766 a.flags.flags = STI_UNPMVF_WAIT; 767 /* XXX does not handle text attributes */ 768 a.in.fg_colour = STI_COLOUR_WHITE; 769 a.in.bg_colour = STI_COLOUR_BLACK; 770 a.in.x = col * fp->width; 771 a.in.y = row * fp->height; 772 a.in.font_addr = sc->sc_romfont; 773 a.in.index = uc; 774 775 (*sc->unpmv)(&a.flags, &a.in, &a.out, &sc->sc_cfg); 776 } else { 777 /* 778 * Font is in frame buffer, use blkmv 779 */ 780 struct { 781 struct sti_blkmvflags flags; 782 struct sti_blkmvin in; 783 struct sti_blkmvout out; 784 } a; 785 786 memset(&a, 0, sizeof(a)); 787 788 a.flags.flags = STI_BLKMVF_WAIT; 789 /* XXX does not handle text attributes */ 790 a.in.fg_colour = STI_COLOUR_WHITE; 791 a.in.bg_colour = STI_COLOUR_BLACK; 792 793 a.in.srcx = ((uc - fp->first) / sc->sc_fontmaxcol) * 794 fp->width + sc->sc_fontbase; 795 a.in.srcy = ((uc - fp->first) % sc->sc_fontmaxcol) * 796 fp->height; 797 a.in.dstx = col * fp->width; 798 a.in.dsty = row * fp->height; 799 a.in.height = fp->height; 800 a.in.width = fp->width; 801 802 (*sc->blkmv)(&a.flags, &a.in, &a.out, &sc->sc_cfg); 803 } 804 } 805 806 void 807 sti_copycols(void *v, int row, int srccol, int dstcol, int ncols) 808 { 809 struct sti_softc *sc = v; 810 struct sti_font *fp = &sc->sc_curfont; 811 812 sti_bmove(sc, srccol * fp->width, row * fp->height, dstcol * fp->width, 813 row * fp->height, fp->height, ncols * fp->width, bmf_copy); 814 } 815 816 void 817 sti_erasecols(void *v, int row, int startcol, int ncols, long attr) 818 { 819 struct sti_softc *sc = v; 820 struct sti_font *fp = &sc->sc_curfont; 821 822 sti_bmove(sc, startcol * fp->width, row * fp->height, 823 startcol * fp->width, row * fp->height, fp->height, 824 ncols * fp->width, bmf_clear); 825 } 826 827 void 828 sti_copyrows(void *v, int srcrow, int dstrow, int nrows) 829 { 830 struct sti_softc *sc = v; 831 struct sti_font *fp = &sc->sc_curfont; 832 833 sti_bmove(sc, sc->sc_cfg.oscr_width, srcrow * fp->height, 834 sc->sc_cfg.oscr_width, dstrow * fp->height, 835 nrows * fp->height, sc->sc_cfg.scr_width, bmf_copy); 836 } 837 838 void 839 sti_eraserows(void *v, int srcrow, int nrows, long attr) 840 { 841 struct sti_softc *sc = v; 842 struct sti_font *fp = &sc->sc_curfont; 843 844 sti_bmove(sc, sc->sc_cfg.oscr_width, srcrow * fp->height, 845 sc->sc_cfg.oscr_width, srcrow * fp->height, 846 nrows * fp->height, sc->sc_cfg.scr_width, bmf_clear); 847 } 848 849 int 850 sti_alloc_attr(void *v, int fg, int bg, int flags, long *pattr) 851 { 852 /* struct sti_softc *sc = v; */ 853 854 *pattr = 0; 855 856 return 0; 857 } 858 859