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