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