sti.c revision 1.16 1 /* $NetBSD: sti.c,v 1.16 2011/07/11 02:30:49 matt 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.16 2011/07/11 02:30:49 matt 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 = scr->scr_scrlist;
644
645 return 0;
646
647 fail:
648 /* XXX free resources */
649 if (scr->scr_ecfg.addr != NULL) {
650 free(scr->scr_ecfg.addr, M_DEVBUF);
651 scr->scr_ecfg.addr = NULL;
652 }
653
654 return ENXIO;
655 }
656
657 void
658 sti_describe_screen(struct sti_softc *sc, struct sti_screen *scr)
659 {
660 struct sti_font *fp = &scr->scr_curfont;
661
662 aprint_normal("%s: %s, %dx%d frame buffer, %dx%dx%d display\n",
663 device_xname(sc->sc_dev), scr->name, scr->fbwidth, scr->fbheight,
664 scr->scr_cfg.scr_width, scr->scr_cfg.scr_height, scr->scr_bpp);
665
666 aprint_normal("%s: %dx%d font type %d, %d bpc, charset %d-%d\n",
667 device_xname(sc->sc_dev), fp->width, fp->height,
668 fp->type, fp->bpc, fp->first, fp->last);
669 }
670
671 void
672 sti_describe(struct sti_softc *sc)
673 {
674 struct sti_rom *rom = sc->sc_rom;
675 struct sti_dd *dd = &rom->rom_dd;
676
677 aprint_normal(": rev %d.%02d;%d, ID 0x%08X%08X\n",
678 dd->dd_grrev >> 4, dd->dd_grrev & 0xf,
679 dd->dd_lrrev, dd->dd_grid[0], dd->dd_grid[1]);
680
681 if (sc->sc_scr != NULL)
682 sti_describe_screen(sc, sc->sc_scr);
683 }
684
685 void
686 sti_end_attach(struct sti_softc *sc)
687 {
688 struct sti_screen *scr = sc->sc_scr;
689
690 if (scr == NULL)
691 return;
692 #if NWSDISPLAY > 0
693 else {
694 struct wsemuldisplaydev_attach_args waa;
695 scr->scr_wsmode = WSDISPLAYIO_MODE_EMUL;
696
697 waa.console = sc->sc_flags & STI_CONSOLE ? 1 : 0;
698 waa.scrdata = &scr->scr_screenlist;
699 waa.accessops = &sti_accessops;
700 waa.accesscookie = scr;
701
702 /* attach as console if required */
703 if (waa.console && !ISSET(sc->sc_flags, STI_ATTACHED)) {
704 long defattr;
705
706 sti_alloc_attr(scr, 0, 0, 0, &defattr);
707 wsdisplay_cnattach(&scr->scr_wsd, scr,
708 0, scr->scr_wsd.nrows - 1, defattr);
709 sc->sc_flags |= STI_ATTACHED;
710 }
711
712 config_found(sc->sc_dev, &waa, wsemuldisplaydevprint);
713 }
714 #endif
715 }
716
717 u_int
718 sti_rom_size(bus_space_tag_t memt, bus_space_handle_t romh)
719 {
720 int devtype;
721 u_int romend;
722
723 devtype = bus_space_read_1(memt, romh, 3);
724 if (devtype == STI_DEVTYPE4) {
725 bus_space_read_region_stream_4(memt, romh, STI_DEV4_DD_ROMEND,
726 (uint32_t *)&romend, 1);
727 } else {
728 romend = parseword(STI_DEV1_DD_ROMEND);
729 }
730
731 DPRINTF(("%s: %08x (%08x)\n", __func__, romend, round_page(romend)));
732
733 return round_page(romend);
734 }
735
736 int
737 sti_fetchfonts(struct sti_screen *scr, struct sti_inqconfout *cfg,
738 uint32_t baseaddr, u_int fontindex)
739 {
740 struct sti_rom *rom = scr->scr_rom;
741 bus_space_tag_t memt = rom->memt;
742 bus_space_handle_t romh = rom->romh;
743 struct sti_font *fp = &scr->scr_curfont;
744 uint32_t addr;
745 int size;
746 #ifdef notyet
747 int uc;
748 struct {
749 struct sti_unpmvflags flags;
750 struct sti_unpmvin in;
751 struct sti_unpmvout out;
752 } a;
753 #endif
754
755 /*
756 * Get the first PROM font in memory
757 */
758
759 STI_ENABLE_ROM(rom->rom_softc);
760
761 rescan:
762 addr = baseaddr;
763 do {
764 if (rom->rom_devtype == STI_DEVTYPE1) {
765 fp->first = parseshort(addr + 0x00);
766 fp->last = parseshort(addr + 0x08);
767 fp->width = bus_space_read_1(memt, romh, addr + 0x13);
768 fp->height = bus_space_read_1(memt, romh, addr + 0x17);
769 fp->type = bus_space_read_1(memt, romh, addr + 0x1b);
770 fp->bpc = bus_space_read_1(memt, romh, addr + 0x1f);
771 fp->next = parseword(addr + 0x20);
772 fp->uheight= bus_space_read_1(memt, romh, addr + 0x33);
773 fp->uoffset= bus_space_read_1(memt, romh, addr + 0x37);
774 } else { /* STI_DEVTYPE4 */
775 bus_space_read_region_stream_4(memt, romh, addr,
776 (uint32_t *)fp, sizeof(struct sti_font) / 4);
777 }
778
779 #ifdef STIDEBUG
780 STI_DISABLE_ROM(rom->rom_softc);
781 DPRINTF(("%s: %dx%d font type %d, %d bpc, charset %d-%d\n",
782 device_xname(scr->scr_rom->rom_softc->sc_dev), fp->width,
783 fp->height, fp->type, fp->bpc, fp->first, fp->last));
784 STI_ENABLE_ROM(rom->rom_softc);
785 #endif
786
787 if (fontindex == 0) {
788 size = sizeof(struct sti_font) +
789 (fp->last - fp->first + 1) * fp->bpc;
790 if (rom->rom_devtype == STI_DEVTYPE1)
791 size *= 4;
792 scr->scr_romfont = malloc(size, M_DEVBUF, M_NOWAIT);
793 if (scr->scr_romfont == NULL)
794 return ENOMEM;
795
796 bus_space_read_region_stream_4(memt, romh, addr,
797 (uint32_t *)scr->scr_romfont, size / 4);
798 break;
799 }
800
801 addr = baseaddr + fp->next;
802 fontindex--;
803 } while (fp->next != 0);
804
805 /*
806 * If our font index was bogus, we did not find the expected font.
807 * In this case, pick the first one and be done with it.
808 */
809 if (fp->next == 0 && scr->scr_romfont == NULL) {
810 fontindex = 0;
811 goto rescan;
812 }
813
814 STI_DISABLE_ROM(rom->rom_softc);
815
816 #ifdef notyet
817 /*
818 * If there is enough room in the off-screen framebuffer memory,
819 * display all the characters there in order to display them
820 * faster with blkmv operations rather than unpmv later on.
821 */
822 if (size <= cfg->fbheight *
823 (cfg->fbwidth - cfg->width - cfg->owidth)) {
824 memset(&a, 0, sizeof(a));
825 a.flags.flags = STI_UNPMVF_WAIT;
826 a.in.fg_colour = STI_COLOUR_WHITE;
827 a.in.bg_colour = STI_COLOUR_BLACK;
828 a.in.font_addr = scr->scr_romfont;
829
830 scr->scr_fontmaxcol = cfg->fbheight / fp->height;
831 scr->scr_fontbase = cfg->width + cfg->owidth;
832 for (uc = fp->first; uc <= fp->last; uc++) {
833 a.in.x = ((uc - fp->first) / scr->scr_fontmaxcol) *
834 fp->width + scr->scr_fontbase;
835 a.in.y = ((uc - fp->first) % scr->scr_fontmaxcol) *
836 fp->height;
837 a.in.index = uc;
838
839 (*scr->unpmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
840 if (a.out.errno) {
841 aprint_error_dev(sc->sc_dev, "unpmv %d "
842 "returned %d\n", uc, a.out.errno);
843 return 0;
844 }
845 }
846
847 free(scr->scr_romfont, M_DEVBUF);
848 scr->scr_romfont = NULL;
849 }
850 #endif
851
852 return 0;
853 }
854
855 /*
856 * Wrappers around STI code pointers
857 */
858 int
859 sti_init(struct sti_screen *scr, int mode)
860 {
861 struct sti_rom *rom = scr->scr_rom;
862 struct {
863 struct sti_initflags flags;
864 struct sti_initin in;
865 struct sti_einitin ein;
866 struct sti_initout out;
867 } a;
868
869 KASSERT(rom != NULL);
870 memset(&a, 0, sizeof(a));
871
872 a.flags.flags = STI_INITF_WAIT | STI_INITF_CMB | STI_INITF_EBET |
873 (mode & STI_TEXTMODE ? STI_INITF_TEXT | STI_INITF_PBET |
874 STI_INITF_PBETI | STI_INITF_ICMT : 0) |
875 (mode & STI_CLEARSCR ? STI_INITF_CLEAR : 0);
876 a.in.text_planes = 1;
877 a.in.ext_in = &a.ein;
878
879 DPRINTF(("%s: init,%p(%x, %p, %p, %p)\n",
880 device_xname(rom->rom_softc->sc_dev), rom->init, a.flags.flags,
881 &a.in, &a.out, &scr->scr_cfg));
882
883 (*rom->init)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
884
885 if (a.out.text_planes != a.in.text_planes)
886 return -1; /* not colliding with sti errno values */
887 return a.out.errno;
888 }
889
890 int
891 sti_inqcfg(struct sti_screen *scr, struct sti_inqconfout *out)
892 {
893 struct sti_rom *rom = scr->scr_rom;
894 struct {
895 struct sti_inqconfflags flags;
896 struct sti_inqconfin in;
897 } a;
898
899 memset(&a, 0, sizeof(a));
900
901 a.flags.flags = STI_INQCONFF_WAIT;
902 (*rom->inqconf)(&a.flags, &a.in, out, &scr->scr_cfg);
903
904 return out->errno;
905 }
906
907 void
908 sti_bmove(struct sti_screen *scr, int x1, int y1, int x2, int y2, int h, int w,
909 enum sti_bmove_funcs f)
910 {
911 struct sti_rom *rom = scr->scr_rom;
912 struct {
913 struct sti_blkmvflags flags;
914 struct sti_blkmvin in;
915 struct sti_blkmvout out;
916 } a;
917
918 memset(&a, 0, sizeof(a));
919
920 a.flags.flags = STI_BLKMVF_WAIT;
921 switch (f) {
922 case bmf_clear:
923 a.flags.flags |= STI_BLKMVF_CLR;
924 a.in.bg_colour = STI_COLOUR_BLACK;
925 break;
926 case bmf_underline:
927 case bmf_copy:
928 a.in.fg_colour = STI_COLOUR_WHITE;
929 a.in.bg_colour = STI_COLOUR_BLACK;
930 break;
931 case bmf_invert:
932 a.flags.flags |= STI_BLKMVF_COLR;
933 a.in.fg_colour = STI_COLOUR_BLACK;
934 a.in.bg_colour = STI_COLOUR_WHITE;
935 break;
936 }
937 a.in.srcx = x1;
938 a.in.srcy = y1;
939 a.in.dstx = x2;
940 a.in.dsty = y2;
941 a.in.height = h;
942 a.in.width = w;
943
944 (*rom->blkmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
945 #ifdef STIDEBUG
946 if (a.out.errno)
947 printf("%s: blkmv returned %d\n",
948 device_xname(rom->rom_softc->sc_dev), a.out.errno);
949 #endif
950 }
951
952 int
953 sti_setcment(struct sti_screen *scr, u_int i, u_char r, u_char g, u_char b)
954 {
955 struct sti_rom *rom = scr->scr_rom;
956 struct {
957 struct sti_scmentflags flags;
958 struct sti_scmentin in;
959 struct sti_scmentout out;
960 } a;
961
962 memset(&a, 0, sizeof(a));
963
964 a.flags.flags = STI_SCMENTF_WAIT;
965 a.in.entry = i;
966 a.in.value = (r << 16) | (g << 8) | b;
967
968 (*rom->scment)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
969
970 return a.out.errno;
971 }
972
973 /*
974 * wsdisplay accessops
975 */
976 int
977 sti_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l)
978 {
979 struct sti_screen *scr = (struct sti_screen *)v;
980 struct sti_rom *rom = scr->scr_rom;
981 struct wsdisplay_fbinfo *wdf;
982 struct wsdisplay_cmap *cmapp;
983 u_int mode, idx, count;
984 int i, ret;
985
986 ret = 0;
987 switch (cmd) {
988 case WSDISPLAYIO_GMODE:
989 *(u_int *)data = scr->scr_wsmode;
990 break;
991
992 case WSDISPLAYIO_SMODE:
993 mode = *(u_int *)data;
994 if (scr->scr_wsmode == WSDISPLAYIO_MODE_EMUL &&
995 mode == WSDISPLAYIO_MODE_DUMBFB)
996 ret = sti_init(scr, 0);
997 else if (scr->scr_wsmode == WSDISPLAYIO_MODE_DUMBFB &&
998 mode == WSDISPLAYIO_MODE_EMUL)
999 ret = sti_init(scr, STI_TEXTMODE);
1000 scr->scr_wsmode = mode;
1001 break;
1002
1003 case WSDISPLAYIO_GTYPE:
1004 *(u_int *)data = WSDISPLAY_TYPE_STI;
1005 break;
1006
1007 case WSDISPLAYIO_GINFO:
1008 wdf = (struct wsdisplay_fbinfo *)data;
1009 wdf->height = scr->scr_cfg.scr_height;
1010 wdf->width = scr->scr_cfg.scr_width;
1011 wdf->depth = scr->scr_bpp;
1012 if (rom->scment == NULL)
1013 wdf->cmsize = 0;
1014 else
1015 wdf->cmsize = STI_NCMAP;
1016 break;
1017
1018 case WSDISPLAYIO_LINEBYTES:
1019 *(u_int *)data = scr->scr_cfg.fb_width;
1020 break;
1021
1022 case WSDISPLAYIO_GETCMAP:
1023 if (rom->scment == NULL)
1024 return ENOTTY;
1025 cmapp = (struct wsdisplay_cmap *)data;
1026 idx = cmapp->index;
1027 count = cmapp->count;
1028 if (idx >= STI_NCMAP || idx + count > STI_NCMAP)
1029 return EINVAL;
1030 if ((ret = copyout(&scr->scr_rcmap[idx], cmapp->red, count)))
1031 break;
1032 if ((ret = copyout(&scr->scr_gcmap[idx], cmapp->green, count)))
1033 break;
1034 if ((ret = copyout(&scr->scr_bcmap[idx], cmapp->blue, count)))
1035 break;
1036 break;
1037
1038 case WSDISPLAYIO_PUTCMAP:
1039 if (rom->scment == NULL)
1040 return ENOTTY;
1041 cmapp = (struct wsdisplay_cmap *)data;
1042 idx = cmapp->index;
1043 count = cmapp->count;
1044 if (idx >= STI_NCMAP || idx + count > STI_NCMAP)
1045 return EINVAL;
1046 if ((ret = copyin(cmapp->red, &scr->scr_rcmap[idx], count)))
1047 break;
1048 if ((ret = copyin(cmapp->green, &scr->scr_gcmap[idx], count)))
1049 break;
1050 if ((ret = copyin(cmapp->blue, &scr->scr_bcmap[idx], count)))
1051 break;
1052 for (i = idx + count - 1; i >= idx; i--)
1053 if ((ret = sti_setcment(scr, i, scr->scr_rcmap[i],
1054 scr->scr_gcmap[i], scr->scr_bcmap[i]))) {
1055
1056 DPRINTF(("sti_ioctl: "
1057 "sti_setcment(%d, %u, %u, %u): %%d\n", i,
1058 (u_int)scr->scr_rcmap[i],
1059 (u_int)scr->scr_gcmap[i],
1060 (u_int)scr->scr_bcmap[i]));
1061
1062 ret = EINVAL;
1063 break;
1064 }
1065 break;
1066
1067 case WSDISPLAYIO_SVIDEO:
1068 case WSDISPLAYIO_GVIDEO:
1069 case WSDISPLAYIO_GCURPOS:
1070 case WSDISPLAYIO_SCURPOS:
1071 case WSDISPLAYIO_GCURMAX:
1072 case WSDISPLAYIO_GCURSOR:
1073 case WSDISPLAYIO_SCURSOR:
1074 default:
1075 return ENOTTY; /* not supported yet */
1076 }
1077
1078 return ret;
1079 }
1080
1081 paddr_t
1082 sti_mmap(void *v, void *vs, off_t offset, int prot)
1083 {
1084 #if 0
1085 struct sti_screen *scr = (struct sti_screen *)v;
1086 #endif
1087 /* XXX not finished */
1088 return -1;
1089 }
1090
1091 int
1092 sti_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
1093 int *cxp, int *cyp, long *defattr)
1094 {
1095 struct sti_screen *scr = (struct sti_screen *)v;
1096
1097 if (scr->scr_nscreens > 0)
1098 return ENOMEM;
1099
1100 *cookiep = scr;
1101 *cxp = 0;
1102 *cyp = 0;
1103 sti_alloc_attr(scr, 0, 0, 0, defattr);
1104 scr->scr_nscreens++;
1105
1106 return 0;
1107 }
1108
1109 void
1110 sti_free_screen(void *v, void *cookie)
1111 {
1112 struct sti_screen *scr = (struct sti_screen *)v;
1113
1114 scr->scr_nscreens--;
1115 }
1116
1117 int
1118 sti_show_screen(void *v, void *cookie, int waitok, void (*cb)(void *, int, int),
1119 void *cbarg)
1120 {
1121 #if 0
1122 struct sti_screen *scr = (struct sti_screen *)v;
1123 #endif
1124
1125 return 0;
1126 }
1127
1128 int
1129 sti_load_font(void *v, void *cookie, struct wsdisplay_font *font)
1130 {
1131 #if 0
1132 struct sti_screen *scr = (struct sti_screen *)v;
1133 #endif
1134
1135 return -1;
1136 }
1137
1138 /*
1139 * wsdisplay emulops
1140 */
1141 void
1142 sti_cursor(void *v, int on, int row, int col)
1143 {
1144 struct sti_screen *scr = (struct sti_screen *)v;
1145 struct sti_font *fp = &scr->scr_curfont;
1146
1147 sti_bmove(scr, col * fp->width, row * fp->height, col * fp->width,
1148 row * fp->height, fp->height, fp->width, bmf_invert);
1149 }
1150
1151 /*
1152 * ISO 8859-1 part of Unicode to HP Roman font index conversion array.
1153 */
1154 static const uint8_t
1155 sti_unitoroman[0x100 - 0xa0] = {
1156 0xa0, 0xb8, 0xbf, 0xbb, 0xba, 0xbc, 0, 0xbd,
1157 0xab, 0, 0xf9, 0xfb, 0, 0xf6, 0, 0xb0,
1158
1159 0xb3, 0xfe, 0, 0, 0xa8, 0xf3, 0xf4, 0xf2,
1160 0, 0, 0xfa, 0xfd, 0xf7, 0xf8, 0, 0xb9,
1161
1162 0xa1, 0xe0, 0xa2, 0xe1, 0xd8, 0xd0, 0xd3, 0xb4,
1163 0xa3, 0xdc, 0xa4, 0xa5, 0xe6, 0xe5, 0xa6, 0xa7,
1164
1165 0xe3, 0xb6, 0xe8, 0xe7, 0xdf, 0xe9, 0xda, 0,
1166 0xd2, 0xad, 0xed, 0xae, 0xdb, 0xb1, 0xf0, 0xde,
1167
1168 0xc8, 0xc4, 0xc0, 0xe2, 0xcc, 0xd4, 0xd7, 0xb5,
1169 0xc9, 0xc5, 0xc1, 0xcd, 0xd9, 0xd5, 0xd1, 0xdd,
1170
1171 0xe4, 0xb7, 0xca, 0xc6, 0xc2, 0xea, 0xce, 0,
1172 0xd6, 0xcb, 0xc7, 0xc3, 0xcf, 0xb2, 0xf1, 0xef
1173 };
1174
1175 int
1176 sti_mapchar(void *v, int uni, u_int *index)
1177 {
1178 struct sti_screen *scr = (struct sti_screen *)v;
1179 struct sti_font *fp = &scr->scr_curfont;
1180 int c;
1181
1182 switch (fp->type) {
1183 case STI_FONT_HPROMAN8:
1184 if (uni >= 0x80 && uni < 0xa0)
1185 c = -1;
1186 else if (uni >= 0xa0 && uni < 0x100) {
1187 c = (int)sti_unitoroman[uni - 0xa0];
1188 if (c == 0)
1189 c = -1;
1190 } else
1191 c = uni;
1192 break;
1193 default:
1194 c = uni;
1195 break;
1196 }
1197
1198 if (c == -1 || c < fp->first || c > fp->last) {
1199 *index = ' ';
1200 return 0;
1201 }
1202
1203 *index = c;
1204 return 5;
1205 }
1206
1207 void
1208 sti_putchar(void *v, int row, int col, u_int uc, long attr)
1209 {
1210 struct sti_screen *scr = (struct sti_screen *)v;
1211 struct sti_rom *rom = scr->scr_rom;
1212 struct sti_font *fp = &scr->scr_curfont;
1213
1214 if (scr->scr_romfont != NULL) {
1215 /*
1216 * Font is in memory, use unpmv
1217 */
1218 struct {
1219 struct sti_unpmvflags flags;
1220 struct sti_unpmvin in;
1221 struct sti_unpmvout out;
1222 } a;
1223
1224 memset(&a, 0, sizeof(a));
1225
1226 a.flags.flags = STI_UNPMVF_WAIT;
1227 /* XXX does not handle text attributes */
1228 a.in.fg_colour = STI_COLOUR_WHITE;
1229 a.in.bg_colour = STI_COLOUR_BLACK;
1230 a.in.x = col * fp->width;
1231 a.in.y = row * fp->height;
1232 a.in.font_addr = scr->scr_romfont;
1233 a.in.index = uc;
1234
1235 (*rom->unpmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
1236 } else {
1237 /*
1238 * Font is in frame buffer, use blkmv
1239 */
1240 struct {
1241 struct sti_blkmvflags flags;
1242 struct sti_blkmvin in;
1243 struct sti_blkmvout out;
1244 } a;
1245
1246 memset(&a, 0, sizeof(a));
1247
1248 a.flags.flags = STI_BLKMVF_WAIT;
1249 /* XXX does not handle text attributes */
1250 a.in.fg_colour = STI_COLOUR_WHITE;
1251 a.in.bg_colour = STI_COLOUR_BLACK;
1252
1253 a.in.srcx = ((uc - fp->first) / scr->scr_fontmaxcol) *
1254 fp->width + scr->scr_fontbase;
1255 a.in.srcy = ((uc - fp->first) % scr->scr_fontmaxcol) *
1256 fp->height;
1257 a.in.dstx = col * fp->width;
1258 a.in.dsty = row * fp->height;
1259 a.in.height = fp->height;
1260 a.in.width = fp->width;
1261
1262 (*rom->blkmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
1263 }
1264 }
1265
1266 void
1267 sti_copycols(void *v, int row, int srccol, int dstcol, int ncols)
1268 {
1269 struct sti_screen *scr = (struct sti_screen *)v;
1270 struct sti_font *fp = &scr->scr_curfont;
1271
1272 sti_bmove(scr, srccol * fp->width, row * fp->height, dstcol * fp->width,
1273 row * fp->height, fp->height, ncols * fp->width, bmf_copy);
1274 }
1275
1276 void
1277 sti_erasecols(void *v, int row, int startcol, int ncols, long attr)
1278 {
1279 struct sti_screen *scr = (struct sti_screen *)v;
1280 struct sti_font *fp = &scr->scr_curfont;
1281
1282 sti_bmove(scr, startcol * fp->width, row * fp->height,
1283 startcol * fp->width, row * fp->height, fp->height,
1284 ncols * fp->width, bmf_clear);
1285 }
1286
1287 void
1288 sti_copyrows(void *v, int srcrow, int dstrow, int nrows)
1289 {
1290 struct sti_screen *scr = (struct sti_screen *)v;
1291 struct sti_font *fp = &scr->scr_curfont;
1292
1293 sti_bmove(scr, 0, srcrow * fp->height, 0, dstrow * fp->height,
1294 nrows * fp->height, scr->scr_cfg.scr_width, bmf_copy);
1295 }
1296
1297 void
1298 sti_eraserows(void *v, int srcrow, int nrows, long attr)
1299 {
1300 struct sti_screen *scr = (struct sti_screen *)v;
1301 struct sti_font *fp = &scr->scr_curfont;
1302
1303 sti_bmove(scr, 0, srcrow * fp->height, 0, srcrow * fp->height,
1304 nrows * fp->height, scr->scr_cfg.scr_width, bmf_clear);
1305 }
1306
1307 int
1308 sti_alloc_attr(void *v, int fg, int bg, int flags, long *pattr)
1309 {
1310 #if 0
1311 struct sti_screen *scr = (struct sti_screen *)v;
1312 #endif
1313
1314 *pattr = 0;
1315
1316 return 0;
1317 }
1318