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