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