sti.c revision 1.15 1 /* $NetBSD: sti.c,v 1.15 2011/05/21 12:02:55 tsutsui Exp $ */
2
3 /* $OpenBSD: sti.c,v 1.61 2009/09/05 14:09:35 miod 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.15 2011/05/21 12:02:55 tsutsui 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 #ifndef hp300 /* XXX */
58 #include "sti_pci.h"
59 #endif
60
61 #ifdef STIDEBUG
62
63 #define DPRINTF(s) do { \
64 if (stidebug) \
65 printf s; \
66 } while(0)
67
68 int stidebug = 1;
69 #else
70 #define DPRINTF(s) /* */
71 #endif
72
73 void sti_cursor(void *, int, int, int);
74 int sti_mapchar(void *, int, u_int *);
75 void sti_putchar(void *, int, int, u_int, long);
76 void sti_copycols(void *, int, int, int, int);
77 void sti_erasecols(void *, int, int, int, long);
78 void sti_copyrows(void *, int, int, int);
79 void sti_eraserows(void *, int, int, long);
80 int sti_alloc_attr(void *, int, int, int, long *);
81
82 struct wsdisplay_emulops sti_emulops = {
83 sti_cursor,
84 sti_mapchar,
85 sti_putchar,
86 sti_copycols,
87 sti_erasecols,
88 sti_copyrows,
89 sti_eraserows,
90 sti_alloc_attr
91 };
92
93 int sti_ioctl(void *, void *, u_long, void *, int, struct lwp *);
94 paddr_t sti_mmap(void *, void *, off_t, int);
95 int sti_alloc_screen(void *, const struct wsscreen_descr *,
96 void **, int *, int *, long *);
97 void sti_free_screen(void *, void *);
98 int sti_show_screen(void *, void *, int, void (*cb)(void *, int, int), void *);
99 int sti_load_font(void *, void *, struct wsdisplay_font *);
100
101 const struct wsdisplay_accessops sti_accessops = {
102 sti_ioctl,
103 sti_mmap,
104 sti_alloc_screen,
105 sti_free_screen,
106 sti_show_screen,
107 sti_load_font
108 };
109
110 enum sti_bmove_funcs {
111 bmf_clear, bmf_copy, bmf_invert, bmf_underline
112 };
113
114 int sti_init(struct sti_screen *, int);
115 #define STI_TEXTMODE 0x01
116 #define STI_CLEARSCR 0x02
117 int sti_inqcfg(struct sti_screen *, struct sti_inqconfout *);
118 void sti_bmove(struct sti_screen *, int, int, int, int, int, int,
119 enum sti_bmove_funcs);
120 int sti_setcment(struct sti_screen *, u_int, u_char, u_char, u_char);
121
122 struct sti_screen *sti_attach_screen(struct sti_softc *, int);
123 void sti_describe_screen(struct sti_softc *, struct sti_screen *);
124
125 int sti_fetchfonts(struct sti_screen *, struct sti_inqconfout *, uint32_t,
126 u_int);
127 void sti_region_setup(struct sti_screen *);
128 int sti_rom_setup(struct sti_rom *, bus_space_tag_t, bus_space_tag_t,
129 bus_space_handle_t, bus_addr_t *, u_int);
130 int sti_screen_setup(struct sti_screen *, int);
131
132 #if NSTI_PCI > 0
133 #define STI_ENABLE_ROM(sc) \
134 do { \
135 if ((sc) != NULL && (sc)->sc_enable_rom != NULL) \
136 (*(sc)->sc_enable_rom)(sc); \
137 } while (0)
138 #define STI_DISABLE_ROM(sc) \
139 do { \
140 if ((sc) != NULL && (sc)->sc_disable_rom != NULL) \
141 (*(sc)->sc_disable_rom)(sc); \
142 } while (0)
143 #else
144 #define STI_ENABLE_ROM(sc) do { /* nothing */ } while (0)
145 #define STI_DISABLE_ROM(sc) do { /* nothing */ } while (0)
146 #endif
147
148 /* Macros to read larger than 8 bit values from byte roms */
149 #define parseshort(o) \
150 ((bus_space_read_1(memt, romh, (o) + 3) << 8) | \
151 (bus_space_read_1(memt, romh, (o) + 7)))
152 #define parseword(o) \
153 ((bus_space_read_1(memt, romh, (o) + 3) << 24) | \
154 (bus_space_read_1(memt, romh, (o) + 7) << 16) | \
155 (bus_space_read_1(memt, romh, (o) + 11) << 8) | \
156 (bus_space_read_1(memt, romh, (o) + 15)))
157
158 int
159 sti_attach_common(struct sti_softc *sc, bus_space_tag_t iot,
160 bus_space_tag_t memt, bus_space_handle_t romh, u_int codebase)
161 {
162 struct sti_rom *rom;
163 int rc;
164
165 rom = (struct sti_rom *)malloc(sizeof(*rom), M_DEVBUF,
166 M_NOWAIT | M_ZERO);
167 if (rom == NULL) {
168 aprint_error("cannot allocate rom data\n");
169 return ENOMEM;
170 }
171
172 rom->rom_softc = sc;
173 rc = sti_rom_setup(rom, iot, memt, romh, sc->bases, codebase);
174 if (rc != 0) {
175 free(rom, M_DEVBUF);
176 return rc;
177 }
178
179 sc->sc_rom = rom;
180
181 sti_describe(sc);
182
183 sc->sc_scr = sti_attach_screen(sc,
184 sc->sc_flags & STI_CONSOLE ? 0 : STI_CLEARSCR);
185 if (sc->sc_scr == NULL)
186 rc = ENOMEM;
187
188 return rc;
189 }
190
191 struct sti_screen *
192 sti_attach_screen(struct sti_softc *sc, int flags)
193 {
194 struct sti_screen *scr;
195 int rc;
196
197 scr = (struct sti_screen *)malloc(sizeof(*scr), M_DEVBUF,
198 M_NOWAIT | M_ZERO);
199 if (scr == NULL) {
200 aprint_error("cannot allocate screen data\n");
201 return NULL;
202 }
203
204 scr->scr_rom = sc->sc_rom;
205 rc = sti_screen_setup(scr, flags);
206 if (rc != 0) {
207 free(scr, M_DEVBUF);
208 return NULL;
209 }
210
211 sti_describe_screen(sc, scr);
212
213 return scr;
214 }
215
216 int
217 sti_rom_setup(struct sti_rom *rom, bus_space_tag_t iot, bus_space_tag_t memt,
218 bus_space_handle_t romh, bus_addr_t *bases, u_int codebase)
219 {
220 struct sti_dd *dd;
221 int error, size, i;
222
223 KASSERT(rom != NULL);
224 STI_ENABLE_ROM(rom->rom_softc);
225
226 rom->iot = iot;
227 rom->memt = memt;
228 rom->romh = romh;
229 rom->bases = bases;
230
231 /*
232 * Get ROM header and code function pointers.
233 */
234 dd = &rom->rom_dd;
235 rom->rom_devtype = bus_space_read_1(memt, romh, 3);
236 if (rom->rom_devtype == STI_DEVTYPE1) {
237 dd->dd_type = bus_space_read_1(memt, romh, 0x03);
238 dd->dd_nmon = bus_space_read_1(memt, romh, 0x07);
239 dd->dd_grrev = bus_space_read_1(memt, romh, 0x0b);
240 dd->dd_lrrev = bus_space_read_1(memt, romh, 0x0f);
241 dd->dd_grid[0] = parseword(0x10);
242 dd->dd_grid[1] = parseword(0x20);
243 dd->dd_fntaddr = parseword(0x30) & ~3;
244 dd->dd_maxst = parseword(0x40);
245 dd->dd_romend = parseword(0x50) & ~3;
246 dd->dd_reglst = parseword(0x60) & ~3;
247 dd->dd_maxreent= parseshort(0x70);
248 dd->dd_maxtimo = parseshort(0x78);
249 dd->dd_montbl = parseword(0x80) & ~3;
250 dd->dd_udaddr = parseword(0x90) & ~3;
251 dd->dd_stimemreq=parseword(0xa0);
252 dd->dd_udsize = parseword(0xb0);
253 dd->dd_pwruse = parseshort(0xc0);
254 dd->dd_bussup = bus_space_read_1(memt, romh, 0xcb);
255 dd->dd_ebussup = bus_space_read_1(memt, romh, 0xcf);
256 dd->dd_altcodet= bus_space_read_1(memt, romh, 0xd3);
257 dd->dd_eddst[0]= bus_space_read_1(memt, romh, 0xd7);
258 dd->dd_eddst[1]= bus_space_read_1(memt, romh, 0xdb);
259 dd->dd_eddst[2]= bus_space_read_1(memt, romh, 0xdf);
260 dd->dd_cfbaddr = parseword(0xe0) & ~3;
261
262 codebase <<= 2;
263 dd->dd_pacode[0x0] = parseword(codebase + 0x00) & ~3;
264 dd->dd_pacode[0x1] = parseword(codebase + 0x10) & ~3;
265 dd->dd_pacode[0x2] = parseword(codebase + 0x20) & ~3;
266 dd->dd_pacode[0x3] = parseword(codebase + 0x30) & ~3;
267 dd->dd_pacode[0x4] = parseword(codebase + 0x40) & ~3;
268 dd->dd_pacode[0x5] = parseword(codebase + 0x50) & ~3;
269 dd->dd_pacode[0x6] = parseword(codebase + 0x60) & ~3;
270 dd->dd_pacode[0x7] = parseword(codebase + 0x70) & ~3;
271 dd->dd_pacode[0x8] = parseword(codebase + 0x80) & ~3;
272 dd->dd_pacode[0x9] = parseword(codebase + 0x90) & ~3;
273 dd->dd_pacode[0xa] = parseword(codebase + 0xa0) & ~3;
274 dd->dd_pacode[0xb] = parseword(codebase + 0xb0) & ~3;
275 dd->dd_pacode[0xc] = parseword(codebase + 0xc0) & ~3;
276 dd->dd_pacode[0xd] = parseword(codebase + 0xd0) & ~3;
277 dd->dd_pacode[0xe] = parseword(codebase + 0xe0) & ~3;
278 dd->dd_pacode[0xf] = parseword(codebase + 0xf0) & ~3;
279 } else { /* STI_DEVTYPE4 */
280 bus_space_read_region_stream_4(memt, romh, 0, (uint32_t *)dd,
281 sizeof(*dd) / 4);
282 /* fix pacode... */
283 bus_space_read_region_stream_4(memt, romh, codebase,
284 (uint32_t *)dd->dd_pacode, sizeof(dd->dd_pacode) / 4);
285 }
286
287 STI_DISABLE_ROM(rom->rom_softc);
288
289 DPRINTF(("dd:\n"
290 "devtype=%x, rev=%x;%d, altt=%x, gid=%08x%08x, font=%x, mss=%x\n"
291 "end=%x, regions=%x, msto=%x, timo=%d, mont=%x, user=%x[%x]\n"
292 "memrq=%x, pwr=%d, bus=%x, ebus=%x, cfb=%x\n"
293 "code=",
294 dd->dd_type & 0xff, dd->dd_grrev, dd->dd_lrrev, dd->dd_altcodet,
295 dd->dd_grid[0], dd->dd_grid[1], dd->dd_fntaddr, dd->dd_maxst,
296 dd->dd_romend, dd->dd_reglst, dd->dd_maxreent, dd->dd_maxtimo,
297 dd->dd_montbl, dd->dd_udaddr, dd->dd_udsize, dd->dd_stimemreq,
298 dd->dd_pwruse, dd->dd_bussup, dd->dd_ebussup, dd->dd_cfbaddr));
299 DPRINTF(("%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x\n",
300 dd->dd_pacode[0x0], dd->dd_pacode[0x1], dd->dd_pacode[0x2],
301 dd->dd_pacode[0x3], dd->dd_pacode[0x4], dd->dd_pacode[0x5],
302 dd->dd_pacode[0x6], dd->dd_pacode[0x7], dd->dd_pacode[0x8],
303 dd->dd_pacode[0x9], dd->dd_pacode[0xa], dd->dd_pacode[0xb],
304 dd->dd_pacode[0xc], dd->dd_pacode[0xd], dd->dd_pacode[0xe],
305 dd->dd_pacode[0xf]));
306
307 /*
308 * Figure out how many bytes we need for the STI code.
309 * Note there could be fewer than STI_END pointer entries
310 * populated, especially on older devices.
311 */
312 for (i = STI_END; !dd->dd_pacode[i]; i--)
313 ;
314
315 size = dd->dd_pacode[i] - dd->dd_pacode[STI_BEGIN];
316
317 if (rom->rom_devtype == STI_DEVTYPE1)
318 size = (size + 3) / 4;
319 if (size == 0) {
320 aprint_error(": no code for the requested platform\n");
321 return EINVAL;
322 }
323
324 DPRINTF(("code size %x/%x\n", size, round_page(size)));
325
326 if (!(rom->rom_code = uvm_km_alloc(kernel_map, round_page(size), 0,
327 UVM_KMF_WIRED))) {
328 aprint_error(": cannot allocate %u bytes for code\n", size);
329 return ENOMEM;
330 }
331
332 /*
333 * Copy code into memory and make it executable.
334 */
335
336 STI_ENABLE_ROM(rom->rom_softc);
337
338 if (rom->rom_devtype == STI_DEVTYPE1) {
339 uint8_t *p;
340 uint32_t addr, eaddr;
341
342 p = (uint8_t *)rom->rom_code;
343
344 for (addr = dd->dd_pacode[STI_BEGIN], eaddr = addr + size * 4;
345 addr < eaddr; addr += 4 ) {
346 *p++ = bus_space_read_4(memt, romh, addr)
347 & 0xff;
348 }
349 } else { /* STI_DEVTYPE4 */
350 bus_space_read_region_stream_4(memt, romh,
351 dd->dd_pacode[STI_BEGIN], (uint32_t *)rom->rom_code,
352 size / 4);
353 }
354
355 STI_DISABLE_ROM(rom->rom_softc);
356
357 if ((error = uvm_map_protect(kernel_map, rom->rom_code,
358 rom->rom_code + round_page(size), UVM_PROT_RX, FALSE))) {
359 aprint_error(": uvm_map_protect failed (%d)\n", error);
360 uvm_km_free(kernel_map, rom->rom_code, round_page(size),
361 UVM_KMF_WIRED);
362 return error;
363 }
364
365 /*
366 * Setup code function pointers.
367 */
368
369 #define O(i) \
370 (dd->dd_pacode[(i)] == 0 ? 0 : \
371 (rom->rom_code + (dd->dd_pacode[(i)] - dd->dd_pacode[0]) / \
372 (rom->rom_devtype == STI_DEVTYPE1 ? 4 : 1)))
373 rom->init = (sti_init_t) O(STI_INIT_GRAPH);
374 rom->mgmt = (sti_mgmt_t) O(STI_STATE_MGMT);
375 rom->unpmv = (sti_unpmv_t) O(STI_FONT_UNPMV);
376 rom->blkmv = (sti_blkmv_t) O(STI_BLOCK_MOVE);
377 rom->test = (sti_test_t) O(STI_SELF_TEST);
378 rom->exhdl = (sti_exhdl_t) O(STI_EXCEP_HDLR);
379 rom->inqconf = (sti_inqconf_t)O(STI_INQ_CONF);
380 rom->scment = (sti_scment_t)O(STI_SCM_ENT);
381 rom->dmac = (sti_dmac_t) O(STI_DMA_CTRL);
382 rom->flowc = (sti_flowc_t) O(STI_FLOW_CTRL);
383 rom->utiming = (sti_utiming_t)O(STI_UTIMING);
384 rom->pmgr = (sti_pmgr_t) O(STI_PROC_MGR);
385 rom->util = (sti_util_t) O(STI_UTIL);
386
387 #undef O
388 /*
389 * Set colormap entry is not implemented until 8.04, so force
390 * a NULL pointer here.
391 */
392
393 if (dd->dd_grrev < STI_REVISION(8, 4)) {
394 rom->scment = NULL;
395 }
396
397 return 0;
398 }
399
400 /*
401 * Map all regions.
402 */
403 void
404 sti_region_setup(struct sti_screen *scr)
405 {
406 struct sti_rom *rom = scr->scr_rom;
407 bus_space_tag_t memt = rom->memt;
408 bus_space_handle_t romh = rom->romh;
409 bus_addr_t *bases = rom->bases;
410 struct sti_dd *dd = &rom->rom_dd;
411 struct sti_cfg *cc = &scr->scr_cfg;
412 bus_space_handle_t bh;
413 struct sti_region regions[STI_REGION_MAX], *r;
414 u_int regno, regcnt;
415 bus_addr_t addr;
416
417 DPRINTF(("stiregions @ %x:\n", dd->dd_reglst));
418
419 /*
420 * Read the region information.
421 */
422
423 STI_ENABLE_ROM(rom->rom_softc);
424
425 if (rom->rom_devtype == STI_DEVTYPE1) {
426 for (regno = 0; regno < STI_REGION_MAX; regno++)
427 *(u_int *)(regions + regno) =
428 parseword(dd->dd_reglst + regno * 0x10);
429 } else {
430 bus_space_read_region_stream_4(memt, romh, dd->dd_reglst,
431 (uint32_t *)regions, sizeof(regions) / 4);
432 }
433
434 STI_DISABLE_ROM(rom->rom_softc);
435
436 /*
437 * Count them.
438 */
439
440 for (regcnt = 0, r = regions; regcnt < STI_REGION_MAX; regcnt++, r++)
441 if (r->last)
442 break;
443 regcnt++;
444
445 /*
446 * Map them.
447 */
448
449 for (regno = 0, r = regions; regno < regcnt; regno++, r++) {
450 if (r->length == 0)
451 continue;
452
453 /*
454 * Assume an existing mapping exists.
455 */
456 addr = bases[regno] + (r->offset << PGSHIFT);
457 DPRINTF(("%08x @ 0x%08x%s%s%s%s",
458 r->length << PGSHIFT, (int)addr, r->sys_only ? " sys" : "",
459 r->cache ? " cache" : "", r->btlb ? " btlb" : "",
460 r->last ? " last" : ""));
461
462 /*
463 * Region #0 is always the rom, and it should have been
464 * mapped already.
465 * XXX This expects a 1:1 mapping...
466 */
467 if (regno == 0 && romh == bases[0]) {
468 cc->regions[0] = addr;
469 DPRINTF(("\n"));
470 continue;
471 }
472
473 /* XXXNH BUS_SPACE_MAP_CACHEABLE */
474 if (bus_space_map(memt, addr, r->length << PGSHIFT,
475 r->cache ? BUS_SPACE_MAP_CACHEABLE : 0, &bh)) {
476 DPRINTF((" - already mapped region\n"));
477 } else {
478
479 /* XXX should use bus_space_vaddr */
480 addr = (bus_addr_t)bh;
481 if (regno == 1) {
482 DPRINTF((" - fb"));
483 scr->fbaddr = addr;
484 scr->fblen = r->length << PGSHIFT;
485 }
486 DPRINTF(("\n"));
487 }
488
489 cc->regions[regno] = addr;
490 }
491
492 #ifdef STIDEBUG
493 /*
494 * Make sure we'll trap accessing unmapped regions
495 */
496 for (regno = 0; regno < STI_REGION_MAX; regno++)
497 if (cc->regions[regno] == 0)
498 cc->regions[regno] = 0x81234567;
499 #endif
500 }
501
502 int
503 sti_screen_setup(struct sti_screen *scr, int flags)
504 {
505 struct sti_rom *rom = scr->scr_rom;
506 bus_space_tag_t memt = rom->memt;
507 bus_space_handle_t romh = rom->romh;
508 struct sti_dd *dd = &rom->rom_dd;
509 struct sti_cfg *cc = &scr->scr_cfg;
510 struct sti_inqconfout cfg;
511 struct sti_einqconfout ecfg;
512 #ifdef STIDEBUG
513 char buf[256];
514 #endif
515 int error, i;
516 int geometry_kluge = 0;
517 u_int fontindex = 0;
518
519 KASSERT(scr != NULL);
520 memset(cc, 0, sizeof(*cc));
521 cc->ext_cfg = &scr->scr_ecfg;
522 memset(cc->ext_cfg, 0, sizeof(*cc->ext_cfg));
523
524 if (dd->dd_stimemreq) {
525 scr->scr_ecfg.addr =
526 malloc(dd->dd_stimemreq, M_DEVBUF, M_NOWAIT);
527 if (!scr->scr_ecfg.addr) {
528 aprint_error("cannot allocate %d bytes for STI\n",
529 dd->dd_stimemreq);
530 return ENOMEM;
531 }
532 }
533
534 sti_region_setup(scr);
535
536 if ((error = sti_init(scr, 0))) {
537 aprint_error(": cannot initialize (%d)\n", error);
538 goto fail;
539 }
540
541 memset(&cfg, 0, sizeof(cfg));
542 memset(&ecfg, 0, sizeof(ecfg));
543 cfg.ext = &ecfg;
544 if ((error = sti_inqcfg(scr, &cfg))) {
545 aprint_error(": error %d inquiring config\n", error);
546 goto fail;
547 }
548
549 /*
550 * Older (rev 8.02) boards report wrong offset values,
551 * similar to the displayable area size, at least in m68k mode.
552 * Attempt to detect this and adjust here.
553 */
554 if (cfg.owidth == cfg.width &&
555 cfg.oheight == cfg.height)
556 geometry_kluge = 1;
557
558 if (geometry_kluge) {
559 scr->scr_cfg.oscr_width = cfg.owidth =
560 cfg.fbwidth - cfg.width;
561 scr->scr_cfg.oscr_height = cfg.oheight =
562 cfg.fbheight - cfg.height;
563 }
564
565 /*
566 * Save a few fields for sti_describe_screen() later
567 */
568 scr->fbheight = cfg.fbheight;
569 scr->fbwidth = cfg.fbwidth;
570 scr->oheight = cfg.oheight;
571 scr->owidth = cfg.owidth;
572 memcpy(scr->name, cfg.name, sizeof(scr->name));
573
574 if ((error = sti_init(scr, STI_TEXTMODE | flags))) {
575 aprint_error(": cannot initialize (%d)\n", error);
576 goto fail;
577 }
578 #ifdef STIDEBUG
579 snprintb(buf, sizeof(buf), STI_INQCONF_BITS, cfg.attributes);
580 DPRINTF(("conf: bpp=%d planes=%d attr=%s\n"
581 "crt=0x%x:0x%x:0x%x hw=0x%x:0x%x:0x%x\n", cfg.bpp,
582 cfg.planes, buf,
583 ecfg.crt_config[0], ecfg.crt_config[1], ecfg.crt_config[2],
584 ecfg.crt_hw[0], ecfg.crt_hw[1], ecfg.crt_hw[2]));
585 #endif
586 scr->scr_bpp = cfg.bppu;
587
588 /*
589 * Although scr->scr_ecfg.current_monitor is not filled by
590 * sti_init() as expected, we can nevertheless walk the monitor
591 * list, if there is any, and if we find a mode matching our
592 * resolution, pick its font index.
593 */
594 if (dd->dd_montbl != 0) {
595 STI_ENABLE_ROM(rom->rom_softc);
596
597 for (i = 0; i < dd->dd_nmon; i++) {
598 u_int offs = dd->dd_montbl + 8 * i;
599 uint32_t m[2];
600 sti_mon_t mon = (void *)m;
601 if (rom->rom_devtype == STI_DEVTYPE1) {
602 m[0] = parseword(4 * offs);
603 m[1] = parseword(4 * (offs + 4));
604 } else {
605 bus_space_read_region_stream_4(memt, romh, offs,
606 (uint32_t *)mon, sizeof(*mon) / 4);
607 }
608
609 if (mon->width == scr->scr_cfg.scr_width &&
610 mon->height == scr->scr_cfg.scr_height) {
611 fontindex = mon->font;
612 break;
613 }
614 }
615
616 STI_DISABLE_ROM(rom->rom_softc);
617
618 DPRINTF(("font index: %d\n", fontindex));
619 }
620
621 if ((error = sti_fetchfonts(scr, &cfg, dd->dd_fntaddr, fontindex))) {
622 aprint_error(": cannot fetch fonts (%d)\n", error);
623 goto fail;
624 }
625
626 /*
627 * setup screen descriptions:
628 * figure number of fonts supported;
629 * allocate wscons structures;
630 * calculate dimensions.
631 */
632
633 scr->scr_wsd.name = "std";
634 scr->scr_wsd.ncols = cfg.width / scr->scr_curfont.width;
635 scr->scr_wsd.nrows = cfg.height / scr->scr_curfont.height;
636 scr->scr_wsd.textops = &sti_emulops;
637 scr->scr_wsd.fontwidth = scr->scr_curfont.width;
638 scr->scr_wsd.fontheight = scr->scr_curfont.height;
639 scr->scr_wsd.capabilities = WSSCREEN_REVERSE | WSSCREEN_UNDERLINE;
640
641 scr->scr_scrlist[0] = &scr->scr_wsd;
642 scr->scr_screenlist.nscreens = 1;
643 scr->scr_screenlist.screens =
644 (const struct wsscreen_descr **)scr->scr_scrlist;
645
646 return 0;
647
648 fail:
649 /* XXX free resources */
650 if (scr->scr_ecfg.addr != NULL) {
651 free(scr->scr_ecfg.addr, M_DEVBUF);
652 scr->scr_ecfg.addr = NULL;
653 }
654
655 return ENXIO;
656 }
657
658 void
659 sti_describe_screen(struct sti_softc *sc, struct sti_screen *scr)
660 {
661 struct sti_font *fp = &scr->scr_curfont;
662
663 aprint_normal("%s: %s, %dx%d frame buffer, %dx%dx%d display\n",
664 device_xname(sc->sc_dev), scr->name, scr->fbwidth, scr->fbheight,
665 scr->scr_cfg.scr_width, scr->scr_cfg.scr_height, scr->scr_bpp);
666
667 aprint_normal("%s: %dx%d font type %d, %d bpc, charset %d-%d\n",
668 device_xname(sc->sc_dev), fp->width, fp->height,
669 fp->type, fp->bpc, fp->first, fp->last);
670 }
671
672 void
673 sti_describe(struct sti_softc *sc)
674 {
675 struct sti_rom *rom = sc->sc_rom;
676 struct sti_dd *dd = &rom->rom_dd;
677
678 aprint_normal(": rev %d.%02d;%d, ID 0x%08X%08X\n",
679 dd->dd_grrev >> 4, dd->dd_grrev & 0xf,
680 dd->dd_lrrev, dd->dd_grid[0], dd->dd_grid[1]);
681
682 if (sc->sc_scr != NULL)
683 sti_describe_screen(sc, sc->sc_scr);
684 }
685
686 void
687 sti_end_attach(struct sti_softc *sc)
688 {
689 struct sti_screen *scr = sc->sc_scr;
690
691 if (scr == NULL)
692 return;
693 #if NWSDISPLAY > 0
694 else {
695 struct wsemuldisplaydev_attach_args waa;
696 scr->scr_wsmode = WSDISPLAYIO_MODE_EMUL;
697
698 waa.console = sc->sc_flags & STI_CONSOLE ? 1 : 0;
699 waa.scrdata = &scr->scr_screenlist;
700 waa.accessops = &sti_accessops;
701 waa.accesscookie = scr;
702
703 /* attach as console if required */
704 if (waa.console && !ISSET(sc->sc_flags, STI_ATTACHED)) {
705 long defattr;
706
707 sti_alloc_attr(scr, 0, 0, 0, &defattr);
708 wsdisplay_cnattach(&scr->scr_wsd, scr,
709 0, scr->scr_wsd.nrows - 1, defattr);
710 sc->sc_flags |= STI_ATTACHED;
711 }
712
713 config_found(sc->sc_dev, &waa, wsemuldisplaydevprint);
714 }
715 #endif
716 }
717
718 u_int
719 sti_rom_size(bus_space_tag_t memt, bus_space_handle_t romh)
720 {
721 int devtype;
722 u_int romend;
723
724 devtype = bus_space_read_1(memt, romh, 3);
725 if (devtype == STI_DEVTYPE4) {
726 bus_space_read_region_stream_4(memt, romh, STI_DEV4_DD_ROMEND,
727 (uint32_t *)&romend, 1);
728 } else {
729 romend = parseword(STI_DEV1_DD_ROMEND);
730 }
731
732 DPRINTF(("%s: %08x (%08x)\n", __func__, romend, round_page(romend)));
733
734 return round_page(romend);
735 }
736
737 int
738 sti_fetchfonts(struct sti_screen *scr, struct sti_inqconfout *cfg,
739 uint32_t baseaddr, u_int fontindex)
740 {
741 struct sti_rom *rom = scr->scr_rom;
742 bus_space_tag_t memt = rom->memt;
743 bus_space_handle_t romh = rom->romh;
744 struct sti_font *fp = &scr->scr_curfont;
745 uint32_t addr;
746 int size;
747 #ifdef notyet
748 int uc;
749 struct {
750 struct sti_unpmvflags flags;
751 struct sti_unpmvin in;
752 struct sti_unpmvout out;
753 } a;
754 #endif
755
756 /*
757 * Get the first PROM font in memory
758 */
759
760 STI_ENABLE_ROM(rom->rom_softc);
761
762 rescan:
763 addr = baseaddr;
764 do {
765 if (rom->rom_devtype == STI_DEVTYPE1) {
766 fp->first = parseshort(addr + 0x00);
767 fp->last = parseshort(addr + 0x08);
768 fp->width = bus_space_read_1(memt, romh, addr + 0x13);
769 fp->height = bus_space_read_1(memt, romh, addr + 0x17);
770 fp->type = bus_space_read_1(memt, romh, addr + 0x1b);
771 fp->bpc = bus_space_read_1(memt, romh, addr + 0x1f);
772 fp->next = parseword(addr + 0x20);
773 fp->uheight= bus_space_read_1(memt, romh, addr + 0x33);
774 fp->uoffset= bus_space_read_1(memt, romh, addr + 0x37);
775 } else { /* STI_DEVTYPE4 */
776 bus_space_read_region_stream_4(memt, romh, addr,
777 (uint32_t *)fp, sizeof(struct sti_font) / 4);
778 }
779
780 #ifdef STIDEBUG
781 STI_DISABLE_ROM(rom->rom_softc);
782 DPRINTF(("%s: %dx%d font type %d, %d bpc, charset %d-%d\n",
783 device_xname(scr->scr_rom->rom_softc->sc_dev), fp->width,
784 fp->height, fp->type, fp->bpc, fp->first, fp->last));
785 STI_ENABLE_ROM(rom->rom_softc);
786 #endif
787
788 if (fontindex == 0) {
789 size = sizeof(struct sti_font) +
790 (fp->last - fp->first + 1) * fp->bpc;
791 if (rom->rom_devtype == STI_DEVTYPE1)
792 size *= 4;
793 scr->scr_romfont = malloc(size, M_DEVBUF, M_NOWAIT);
794 if (scr->scr_romfont == NULL)
795 return ENOMEM;
796
797 bus_space_read_region_stream_4(memt, romh, addr,
798 (uint32_t *)scr->scr_romfont, size / 4);
799 break;
800 }
801
802 addr = baseaddr + fp->next;
803 fontindex--;
804 } while (fp->next != 0);
805
806 /*
807 * If our font index was bogus, we did not find the expected font.
808 * In this case, pick the first one and be done with it.
809 */
810 if (fp->next == 0 && scr->scr_romfont == NULL) {
811 fontindex = 0;
812 goto rescan;
813 }
814
815 STI_DISABLE_ROM(rom->rom_softc);
816
817 #ifdef notyet
818 /*
819 * If there is enough room in the off-screen framebuffer memory,
820 * display all the characters there in order to display them
821 * faster with blkmv operations rather than unpmv later on.
822 */
823 if (size <= cfg->fbheight *
824 (cfg->fbwidth - cfg->width - cfg->owidth)) {
825 memset(&a, 0, sizeof(a));
826 a.flags.flags = STI_UNPMVF_WAIT;
827 a.in.fg_colour = STI_COLOUR_WHITE;
828 a.in.bg_colour = STI_COLOUR_BLACK;
829 a.in.font_addr = scr->scr_romfont;
830
831 scr->scr_fontmaxcol = cfg->fbheight / fp->height;
832 scr->scr_fontbase = cfg->width + cfg->owidth;
833 for (uc = fp->first; uc <= fp->last; uc++) {
834 a.in.x = ((uc - fp->first) / scr->scr_fontmaxcol) *
835 fp->width + scr->scr_fontbase;
836 a.in.y = ((uc - fp->first) % scr->scr_fontmaxcol) *
837 fp->height;
838 a.in.index = uc;
839
840 (*scr->unpmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
841 if (a.out.errno) {
842 aprint_error_dev(sc->sc_dev, "unpmv %d "
843 "returned %d\n", uc, a.out.errno);
844 return 0;
845 }
846 }
847
848 free(scr->scr_romfont, M_DEVBUF);
849 scr->scr_romfont = NULL;
850 }
851 #endif
852
853 return 0;
854 }
855
856 /*
857 * Wrappers around STI code pointers
858 */
859 int
860 sti_init(struct sti_screen *scr, int mode)
861 {
862 struct sti_rom *rom = scr->scr_rom;
863 struct {
864 struct sti_initflags flags;
865 struct sti_initin in;
866 struct sti_einitin ein;
867 struct sti_initout out;
868 } a;
869
870 KASSERT(rom != NULL);
871 memset(&a, 0, sizeof(a));
872
873 a.flags.flags = STI_INITF_WAIT | STI_INITF_CMB | STI_INITF_EBET |
874 (mode & STI_TEXTMODE ? STI_INITF_TEXT | STI_INITF_PBET |
875 STI_INITF_PBETI | STI_INITF_ICMT : 0) |
876 (mode & STI_CLEARSCR ? STI_INITF_CLEAR : 0);
877 a.in.text_planes = 1;
878 a.in.ext_in = &a.ein;
879
880 DPRINTF(("%s: init,%p(%x, %p, %p, %p)\n",
881 device_xname(rom->rom_softc->sc_dev), rom->init, a.flags.flags,
882 &a.in, &a.out, &scr->scr_cfg));
883
884 (*rom->init)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
885
886 if (a.out.text_planes != a.in.text_planes)
887 return -1; /* not colliding with sti errno values */
888 return a.out.errno;
889 }
890
891 int
892 sti_inqcfg(struct sti_screen *scr, struct sti_inqconfout *out)
893 {
894 struct sti_rom *rom = scr->scr_rom;
895 struct {
896 struct sti_inqconfflags flags;
897 struct sti_inqconfin in;
898 } a;
899
900 memset(&a, 0, sizeof(a));
901
902 a.flags.flags = STI_INQCONFF_WAIT;
903 (*rom->inqconf)(&a.flags, &a.in, out, &scr->scr_cfg);
904
905 return out->errno;
906 }
907
908 void
909 sti_bmove(struct sti_screen *scr, int x1, int y1, int x2, int y2, int h, int w,
910 enum sti_bmove_funcs f)
911 {
912 struct sti_rom *rom = scr->scr_rom;
913 struct {
914 struct sti_blkmvflags flags;
915 struct sti_blkmvin in;
916 struct sti_blkmvout out;
917 } a;
918
919 memset(&a, 0, sizeof(a));
920
921 a.flags.flags = STI_BLKMVF_WAIT;
922 switch (f) {
923 case bmf_clear:
924 a.flags.flags |= STI_BLKMVF_CLR;
925 a.in.bg_colour = STI_COLOUR_BLACK;
926 break;
927 case bmf_underline:
928 case bmf_copy:
929 a.in.fg_colour = STI_COLOUR_WHITE;
930 a.in.bg_colour = STI_COLOUR_BLACK;
931 break;
932 case bmf_invert:
933 a.flags.flags |= STI_BLKMVF_COLR;
934 a.in.fg_colour = STI_COLOUR_BLACK;
935 a.in.bg_colour = STI_COLOUR_WHITE;
936 break;
937 }
938 a.in.srcx = x1;
939 a.in.srcy = y1;
940 a.in.dstx = x2;
941 a.in.dsty = y2;
942 a.in.height = h;
943 a.in.width = w;
944
945 (*rom->blkmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
946 #ifdef STIDEBUG
947 if (a.out.errno)
948 printf("%s: blkmv returned %d\n",
949 device_xname(rom->rom_softc->sc_dev), a.out.errno);
950 #endif
951 }
952
953 int
954 sti_setcment(struct sti_screen *scr, u_int i, u_char r, u_char g, u_char b)
955 {
956 struct sti_rom *rom = scr->scr_rom;
957 struct {
958 struct sti_scmentflags flags;
959 struct sti_scmentin in;
960 struct sti_scmentout out;
961 } a;
962
963 memset(&a, 0, sizeof(a));
964
965 a.flags.flags = STI_SCMENTF_WAIT;
966 a.in.entry = i;
967 a.in.value = (r << 16) | (g << 8) | b;
968
969 (*rom->scment)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
970
971 return a.out.errno;
972 }
973
974 /*
975 * wsdisplay accessops
976 */
977 int
978 sti_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l)
979 {
980 struct sti_screen *scr = (struct sti_screen *)v;
981 struct sti_rom *rom = scr->scr_rom;
982 struct wsdisplay_fbinfo *wdf;
983 struct wsdisplay_cmap *cmapp;
984 u_int mode, idx, count;
985 int i, ret;
986
987 ret = 0;
988 switch (cmd) {
989 case WSDISPLAYIO_GMODE:
990 *(u_int *)data = scr->scr_wsmode;
991 break;
992
993 case WSDISPLAYIO_SMODE:
994 mode = *(u_int *)data;
995 if (scr->scr_wsmode == WSDISPLAYIO_MODE_EMUL &&
996 mode == WSDISPLAYIO_MODE_DUMBFB)
997 ret = sti_init(scr, 0);
998 else if (scr->scr_wsmode == WSDISPLAYIO_MODE_DUMBFB &&
999 mode == WSDISPLAYIO_MODE_EMUL)
1000 ret = sti_init(scr, STI_TEXTMODE);
1001 scr->scr_wsmode = mode;
1002 break;
1003
1004 case WSDISPLAYIO_GTYPE:
1005 *(u_int *)data = WSDISPLAY_TYPE_STI;
1006 break;
1007
1008 case WSDISPLAYIO_GINFO:
1009 wdf = (struct wsdisplay_fbinfo *)data;
1010 wdf->height = scr->scr_cfg.scr_height;
1011 wdf->width = scr->scr_cfg.scr_width;
1012 wdf->depth = scr->scr_bpp;
1013 if (rom->scment == NULL)
1014 wdf->cmsize = 0;
1015 else
1016 wdf->cmsize = STI_NCMAP;
1017 break;
1018
1019 case WSDISPLAYIO_LINEBYTES:
1020 *(u_int *)data = scr->scr_cfg.fb_width;
1021 break;
1022
1023 case WSDISPLAYIO_GETCMAP:
1024 if (rom->scment == NULL)
1025 return ENOTTY;
1026 cmapp = (struct wsdisplay_cmap *)data;
1027 idx = cmapp->index;
1028 count = cmapp->count;
1029 if (idx >= STI_NCMAP || idx + count > STI_NCMAP)
1030 return EINVAL;
1031 if ((ret = copyout(&scr->scr_rcmap[idx], cmapp->red, count)))
1032 break;
1033 if ((ret = copyout(&scr->scr_gcmap[idx], cmapp->green, count)))
1034 break;
1035 if ((ret = copyout(&scr->scr_bcmap[idx], cmapp->blue, count)))
1036 break;
1037 break;
1038
1039 case WSDISPLAYIO_PUTCMAP:
1040 if (rom->scment == NULL)
1041 return ENOTTY;
1042 cmapp = (struct wsdisplay_cmap *)data;
1043 idx = cmapp->index;
1044 count = cmapp->count;
1045 if (idx >= STI_NCMAP || idx + count > STI_NCMAP)
1046 return EINVAL;
1047 if ((ret = copyin(cmapp->red, &scr->scr_rcmap[idx], count)))
1048 break;
1049 if ((ret = copyin(cmapp->green, &scr->scr_gcmap[idx], count)))
1050 break;
1051 if ((ret = copyin(cmapp->blue, &scr->scr_bcmap[idx], count)))
1052 break;
1053 for (i = idx + count - 1; i >= idx; i--)
1054 if ((ret = sti_setcment(scr, i, scr->scr_rcmap[i],
1055 scr->scr_gcmap[i], scr->scr_bcmap[i]))) {
1056
1057 DPRINTF(("sti_ioctl: "
1058 "sti_setcment(%d, %u, %u, %u): %%d\n", i,
1059 (u_int)scr->scr_rcmap[i],
1060 (u_int)scr->scr_gcmap[i],
1061 (u_int)scr->scr_bcmap[i]));
1062
1063 ret = EINVAL;
1064 break;
1065 }
1066 break;
1067
1068 case WSDISPLAYIO_SVIDEO:
1069 case WSDISPLAYIO_GVIDEO:
1070 case WSDISPLAYIO_GCURPOS:
1071 case WSDISPLAYIO_SCURPOS:
1072 case WSDISPLAYIO_GCURMAX:
1073 case WSDISPLAYIO_GCURSOR:
1074 case WSDISPLAYIO_SCURSOR:
1075 default:
1076 return ENOTTY; /* not supported yet */
1077 }
1078
1079 return ret;
1080 }
1081
1082 paddr_t
1083 sti_mmap(void *v, void *vs, off_t offset, int prot)
1084 {
1085 #if 0
1086 struct sti_screen *scr = (struct sti_screen *)v;
1087 #endif
1088 /* XXX not finished */
1089 return -1;
1090 }
1091
1092 int
1093 sti_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
1094 int *cxp, int *cyp, long *defattr)
1095 {
1096 struct sti_screen *scr = (struct sti_screen *)v;
1097
1098 if (scr->scr_nscreens > 0)
1099 return ENOMEM;
1100
1101 *cookiep = scr;
1102 *cxp = 0;
1103 *cyp = 0;
1104 sti_alloc_attr(scr, 0, 0, 0, defattr);
1105 scr->scr_nscreens++;
1106
1107 return 0;
1108 }
1109
1110 void
1111 sti_free_screen(void *v, void *cookie)
1112 {
1113 struct sti_screen *scr = (struct sti_screen *)v;
1114
1115 scr->scr_nscreens--;
1116 }
1117
1118 int
1119 sti_show_screen(void *v, void *cookie, int waitok, void (*cb)(void *, int, int),
1120 void *cbarg)
1121 {
1122 #if 0
1123 struct sti_screen *scr = (struct sti_screen *)v;
1124 #endif
1125
1126 return 0;
1127 }
1128
1129 int
1130 sti_load_font(void *v, void *cookie, struct wsdisplay_font *font)
1131 {
1132 #if 0
1133 struct sti_screen *scr = (struct sti_screen *)v;
1134 #endif
1135
1136 return -1;
1137 }
1138
1139 /*
1140 * wsdisplay emulops
1141 */
1142 void
1143 sti_cursor(void *v, int on, int row, int col)
1144 {
1145 struct sti_screen *scr = (struct sti_screen *)v;
1146 struct sti_font *fp = &scr->scr_curfont;
1147
1148 sti_bmove(scr, col * fp->width, row * fp->height, col * fp->width,
1149 row * fp->height, fp->height, fp->width, bmf_invert);
1150 }
1151
1152 /*
1153 * ISO 8859-1 part of Unicode to HP Roman font index conversion array.
1154 */
1155 static const uint8_t
1156 sti_unitoroman[0x100 - 0xa0] = {
1157 0xa0, 0xb8, 0xbf, 0xbb, 0xba, 0xbc, 0, 0xbd,
1158 0xab, 0, 0xf9, 0xfb, 0, 0xf6, 0, 0xb0,
1159
1160 0xb3, 0xfe, 0, 0, 0xa8, 0xf3, 0xf4, 0xf2,
1161 0, 0, 0xfa, 0xfd, 0xf7, 0xf8, 0, 0xb9,
1162
1163 0xa1, 0xe0, 0xa2, 0xe1, 0xd8, 0xd0, 0xd3, 0xb4,
1164 0xa3, 0xdc, 0xa4, 0xa5, 0xe6, 0xe5, 0xa6, 0xa7,
1165
1166 0xe3, 0xb6, 0xe8, 0xe7, 0xdf, 0xe9, 0xda, 0,
1167 0xd2, 0xad, 0xed, 0xae, 0xdb, 0xb1, 0xf0, 0xde,
1168
1169 0xc8, 0xc4, 0xc0, 0xe2, 0xcc, 0xd4, 0xd7, 0xb5,
1170 0xc9, 0xc5, 0xc1, 0xcd, 0xd9, 0xd5, 0xd1, 0xdd,
1171
1172 0xe4, 0xb7, 0xca, 0xc6, 0xc2, 0xea, 0xce, 0,
1173 0xd6, 0xcb, 0xc7, 0xc3, 0xcf, 0xb2, 0xf1, 0xef
1174 };
1175
1176 int
1177 sti_mapchar(void *v, int uni, u_int *index)
1178 {
1179 struct sti_screen *scr = (struct sti_screen *)v;
1180 struct sti_font *fp = &scr->scr_curfont;
1181 int c;
1182
1183 switch (fp->type) {
1184 case STI_FONT_HPROMAN8:
1185 if (uni >= 0x80 && uni < 0xa0)
1186 c = -1;
1187 else if (uni >= 0xa0 && uni < 0x100) {
1188 c = (int)sti_unitoroman[uni - 0xa0];
1189 if (c == 0)
1190 c = -1;
1191 } else
1192 c = uni;
1193 break;
1194 default:
1195 c = uni;
1196 break;
1197 }
1198
1199 if (c == -1 || c < fp->first || c > fp->last) {
1200 *index = ' ';
1201 return 0;
1202 }
1203
1204 *index = c;
1205 return 5;
1206 }
1207
1208 void
1209 sti_putchar(void *v, int row, int col, u_int uc, long attr)
1210 {
1211 struct sti_screen *scr = (struct sti_screen *)v;
1212 struct sti_rom *rom = scr->scr_rom;
1213 struct sti_font *fp = &scr->scr_curfont;
1214
1215 if (scr->scr_romfont != NULL) {
1216 /*
1217 * Font is in memory, use unpmv
1218 */
1219 struct {
1220 struct sti_unpmvflags flags;
1221 struct sti_unpmvin in;
1222 struct sti_unpmvout out;
1223 } a;
1224
1225 memset(&a, 0, sizeof(a));
1226
1227 a.flags.flags = STI_UNPMVF_WAIT;
1228 /* XXX does not handle text attributes */
1229 a.in.fg_colour = STI_COLOUR_WHITE;
1230 a.in.bg_colour = STI_COLOUR_BLACK;
1231 a.in.x = col * fp->width;
1232 a.in.y = row * fp->height;
1233 a.in.font_addr = scr->scr_romfont;
1234 a.in.index = uc;
1235
1236 (*rom->unpmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
1237 } else {
1238 /*
1239 * Font is in frame buffer, use blkmv
1240 */
1241 struct {
1242 struct sti_blkmvflags flags;
1243 struct sti_blkmvin in;
1244 struct sti_blkmvout out;
1245 } a;
1246
1247 memset(&a, 0, sizeof(a));
1248
1249 a.flags.flags = STI_BLKMVF_WAIT;
1250 /* XXX does not handle text attributes */
1251 a.in.fg_colour = STI_COLOUR_WHITE;
1252 a.in.bg_colour = STI_COLOUR_BLACK;
1253
1254 a.in.srcx = ((uc - fp->first) / scr->scr_fontmaxcol) *
1255 fp->width + scr->scr_fontbase;
1256 a.in.srcy = ((uc - fp->first) % scr->scr_fontmaxcol) *
1257 fp->height;
1258 a.in.dstx = col * fp->width;
1259 a.in.dsty = row * fp->height;
1260 a.in.height = fp->height;
1261 a.in.width = fp->width;
1262
1263 (*rom->blkmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
1264 }
1265 }
1266
1267 void
1268 sti_copycols(void *v, int row, int srccol, int dstcol, int ncols)
1269 {
1270 struct sti_screen *scr = (struct sti_screen *)v;
1271 struct sti_font *fp = &scr->scr_curfont;
1272
1273 sti_bmove(scr, srccol * fp->width, row * fp->height, dstcol * fp->width,
1274 row * fp->height, fp->height, ncols * fp->width, bmf_copy);
1275 }
1276
1277 void
1278 sti_erasecols(void *v, int row, int startcol, int ncols, long attr)
1279 {
1280 struct sti_screen *scr = (struct sti_screen *)v;
1281 struct sti_font *fp = &scr->scr_curfont;
1282
1283 sti_bmove(scr, startcol * fp->width, row * fp->height,
1284 startcol * fp->width, row * fp->height, fp->height,
1285 ncols * fp->width, bmf_clear);
1286 }
1287
1288 void
1289 sti_copyrows(void *v, int srcrow, int dstrow, int nrows)
1290 {
1291 struct sti_screen *scr = (struct sti_screen *)v;
1292 struct sti_font *fp = &scr->scr_curfont;
1293
1294 sti_bmove(scr, 0, srcrow * fp->height, 0, dstrow * fp->height,
1295 nrows * fp->height, scr->scr_cfg.scr_width, bmf_copy);
1296 }
1297
1298 void
1299 sti_eraserows(void *v, int srcrow, int nrows, long attr)
1300 {
1301 struct sti_screen *scr = (struct sti_screen *)v;
1302 struct sti_font *fp = &scr->scr_curfont;
1303
1304 sti_bmove(scr, 0, srcrow * fp->height, 0, srcrow * fp->height,
1305 nrows * fp->height, scr->scr_cfg.scr_width, bmf_clear);
1306 }
1307
1308 int
1309 sti_alloc_attr(void *v, int fg, int bg, int flags, long *pattr)
1310 {
1311 #if 0
1312 struct sti_screen *scr = (struct sti_screen *)v;
1313 #endif
1314
1315 *pattr = 0;
1316
1317 return 0;
1318 }
1319