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