sti.c revision 1.23 1 /* $NetBSD: sti.c,v 1.23 2020/12/23 08:34:35 tsutsui Exp $ */
2
3 /* $OpenBSD: sti.c,v 1.61 2009/09/05 14:09:35 miod Exp $ */
4
5 /*
6 * Copyright (c) 2000-2003 Michael Shalayeff
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
27 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28 * THE POSSIBILITY OF SUCH DAMAGE.
29 */
30 /*
31 * TODO:
32 * call sti procs asynchronously;
33 * implement console scroll-back;
34 * X11 support on more models.
35 */
36
37 #include <sys/cdefs.h>
38 __KERNEL_RCSID(0, "$NetBSD: sti.c,v 1.23 2020/12/23 08:34:35 tsutsui Exp $");
39
40 #include "wsdisplay.h"
41
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/device.h>
45 #include <sys/malloc.h>
46
47 #include <uvm/uvm_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 .cursor = sti_cursor,
84 .mapchar = sti_mapchar,
85 .putchar = sti_putchar,
86 .copycols = sti_copycols,
87 .erasecols = sti_erasecols,
88 .copyrows = sti_copyrows,
89 .eraserows = sti_eraserows,
90 .allocattr = sti_alloc_attr
91 };
92
93 const struct wsdisplay_accessops sti_accessops = {
94 .ioctl = sti_ioctl,
95 .mmap = sti_mmap,
96 .alloc_screen = sti_alloc_screen,
97 .free_screen = sti_free_screen,
98 .show_screen = sti_show_screen,
99 .load_font = sti_load_font
100 };
101
102 enum sti_bmove_funcs {
103 bmf_clear, bmf_copy, bmf_invert, bmf_underline
104 };
105
106 void sti_bmove(struct sti_screen *, int, int, int, int, int, int,
107 enum sti_bmove_funcs);
108 int sti_inqcfg(struct sti_screen *, struct sti_inqconfout *);
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 int ngle_default_putcmap(struct sti_screen *, u_int, u_int);
122
123 #ifndef SMALL_KERNEL
124 void ngle_artist_setupfb(struct sti_screen *);
125 void ngle_elk_setupfb(struct sti_screen *);
126 void ngle_timber_setupfb(struct sti_screen *);
127 int ngle_putcmap(struct sti_screen *, u_int, u_int);
128 #endif
129
130 #if NSTI_PCI > 0
131 #define STI_ENABLE_ROM(sc) \
132 do { \
133 if ((sc) != NULL && (sc)->sc_enable_rom != NULL) \
134 (*(sc)->sc_enable_rom)(sc); \
135 } while (0)
136 #define STI_DISABLE_ROM(sc) \
137 do { \
138 if ((sc) != NULL && (sc)->sc_disable_rom != NULL) \
139 (*(sc)->sc_disable_rom)(sc); \
140 } while (0)
141 #else
142 #define STI_ENABLE_ROM(sc) do { /* nothing */ } while (0)
143 #define STI_DISABLE_ROM(sc) do { /* nothing */ } while (0)
144 #endif
145
146 /* Macros to read larger than 8 bit values from byte roms */
147 #define parseshort(o) \
148 ((bus_space_read_1(memt, romh, (o) + 3) << 8) | \
149 (bus_space_read_1(memt, romh, (o) + 7)))
150 #define parseword(o) \
151 ((bus_space_read_1(memt, romh, (o) + 3) << 24) | \
152 (bus_space_read_1(memt, romh, (o) + 7) << 16) | \
153 (bus_space_read_1(memt, romh, (o) + 11) << 8) | \
154 (bus_space_read_1(memt, romh, (o) + 15)))
155
156 int
157 sti_attach_common(struct sti_softc *sc, bus_space_tag_t iot,
158 bus_space_tag_t memt, bus_space_handle_t romh, u_int codebase)
159 {
160 struct sti_rom *rom;
161 int rc;
162
163 rom = (struct sti_rom *)malloc(sizeof(*rom), M_DEVBUF,
164 M_WAITOK | M_ZERO);
165 rom->rom_softc = sc;
166 rc = sti_rom_setup(rom, iot, memt, romh, sc->bases, codebase);
167 if (rc != 0) {
168 free(rom, M_DEVBUF);
169 return rc;
170 }
171
172 sc->sc_rom = rom;
173
174 sti_describe(sc);
175
176 sc->sc_scr = sti_attach_screen(sc,
177 sc->sc_flags & STI_CONSOLE ? 0 : STI_CLEARSCR);
178 if (sc->sc_scr == NULL)
179 rc = ENOMEM;
180
181 return rc;
182 }
183
184 struct sti_screen *
185 sti_attach_screen(struct sti_softc *sc, int flags)
186 {
187 struct sti_screen *scr;
188 int rc;
189
190 scr = (struct sti_screen *)malloc(sizeof(*scr), M_DEVBUF,
191 M_WAITOK | M_ZERO);
192 scr->scr_rom = sc->sc_rom;
193 rc = sti_screen_setup(scr, flags);
194 if (rc != 0) {
195 free(scr, M_DEVBUF);
196 return NULL;
197 }
198
199 sti_describe_screen(sc, scr);
200
201 return scr;
202 }
203
204 int
205 sti_rom_setup(struct sti_rom *rom, bus_space_tag_t iot, bus_space_tag_t memt,
206 bus_space_handle_t romh, bus_addr_t *bases, u_int codebase)
207 {
208 struct sti_dd *dd;
209 int error, size, i;
210
211 KASSERT(rom != NULL);
212 STI_ENABLE_ROM(rom->rom_softc);
213
214 rom->iot = iot;
215 rom->memt = memt;
216 rom->romh = romh;
217 rom->bases = bases;
218
219 /*
220 * Get ROM header and code function pointers.
221 */
222
223 dd = &rom->rom_dd;
224 rom->rom_devtype = bus_space_read_1(memt, romh, 3);
225 if (rom->rom_devtype == STI_DEVTYPE1) {
226 dd->dd_type = bus_space_read_1(memt, romh, 0x03);
227 dd->dd_nmon = bus_space_read_1(memt, romh, 0x07);
228 dd->dd_grrev = bus_space_read_1(memt, romh, 0x0b);
229 dd->dd_lrrev = bus_space_read_1(memt, romh, 0x0f);
230 dd->dd_grid[0] = parseword(0x10);
231 dd->dd_grid[1] = parseword(0x20);
232 dd->dd_fntaddr = parseword(0x30) & ~3;
233 dd->dd_maxst = parseword(0x40);
234 dd->dd_romend = parseword(0x50) & ~3;
235 dd->dd_reglst = parseword(0x60) & ~3;
236 dd->dd_maxreent = parseshort(0x70);
237 dd->dd_maxtimo = parseshort(0x78);
238 dd->dd_montbl = parseword(0x80) & ~3;
239 dd->dd_udaddr = parseword(0x90) & ~3;
240 dd->dd_stimemreq = parseword(0xa0);
241 dd->dd_udsize = parseword(0xb0);
242 dd->dd_pwruse = parseshort(0xc0);
243 dd->dd_bussup = bus_space_read_1(memt, romh, 0xcb);
244 dd->dd_ebussup = bus_space_read_1(memt, romh, 0xcf);
245 dd->dd_altcodet = bus_space_read_1(memt, romh, 0xd3);
246 dd->dd_eddst[0] = bus_space_read_1(memt, romh, 0xd7);
247 dd->dd_eddst[1] = bus_space_read_1(memt, romh, 0xdb);
248 dd->dd_eddst[2] = bus_space_read_1(memt, romh, 0xdf);
249 dd->dd_cfbaddr = parseword(0xe0) & ~3;
250
251 codebase <<= 2;
252 dd->dd_pacode[0x0] = parseword(codebase + 0x000) & ~3;
253 dd->dd_pacode[0x1] = parseword(codebase + 0x010) & ~3;
254 dd->dd_pacode[0x2] = parseword(codebase + 0x020) & ~3;
255 dd->dd_pacode[0x3] = parseword(codebase + 0x030) & ~3;
256 dd->dd_pacode[0x4] = parseword(codebase + 0x040) & ~3;
257 dd->dd_pacode[0x5] = parseword(codebase + 0x050) & ~3;
258 dd->dd_pacode[0x6] = parseword(codebase + 0x060) & ~3;
259 dd->dd_pacode[0x7] = parseword(codebase + 0x070) & ~3;
260 dd->dd_pacode[0x8] = parseword(codebase + 0x080) & ~3;
261 dd->dd_pacode[0x9] = parseword(codebase + 0x090) & ~3;
262 dd->dd_pacode[0xa] = parseword(codebase + 0x0a0) & ~3;
263 dd->dd_pacode[0xb] = parseword(codebase + 0x0b0) & ~3;
264 dd->dd_pacode[0xc] = parseword(codebase + 0x0c0) & ~3;
265 dd->dd_pacode[0xd] = parseword(codebase + 0x0d0) & ~3;
266 dd->dd_pacode[0xe] = parseword(codebase + 0x0e0) & ~3;
267 dd->dd_pacode[0xf] = parseword(codebase + 0x0f0) & ~3;
268 } else { /* STI_DEVTYPE4 */
269 bus_space_read_region_stream_4(memt, romh, 0, (uint32_t *)dd,
270 sizeof(*dd) / 4);
271 /* fix pacode... */
272 bus_space_read_region_stream_4(memt, romh, codebase,
273 (uint32_t *)dd->dd_pacode, sizeof(dd->dd_pacode) / 4);
274 }
275
276 STI_DISABLE_ROM(rom->rom_softc);
277
278 DPRINTF(("dd:\n"
279 "devtype=%x, rev=%x;%d, altt=%x, gid=%08x%08x, font=%x, mss=%x\n"
280 "end=%x, regions=%x, msto=%x, timo=%d, mont=%x, user=%x[%x]\n"
281 "memrq=%x, pwr=%d, bus=%x, ebus=%x, cfb=%x\n"
282 "code=",
283 dd->dd_type & 0xff, dd->dd_grrev, dd->dd_lrrev, dd->dd_altcodet,
284 dd->dd_grid[0], dd->dd_grid[1], dd->dd_fntaddr, dd->dd_maxst,
285 dd->dd_romend, dd->dd_reglst, dd->dd_maxreent, dd->dd_maxtimo,
286 dd->dd_montbl, dd->dd_udaddr, dd->dd_udsize, dd->dd_stimemreq,
287 dd->dd_pwruse, dd->dd_bussup, dd->dd_ebussup, dd->dd_cfbaddr));
288 DPRINTF(("%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x\n",
289 dd->dd_pacode[0x0], dd->dd_pacode[0x1], dd->dd_pacode[0x2],
290 dd->dd_pacode[0x3], dd->dd_pacode[0x4], dd->dd_pacode[0x5],
291 dd->dd_pacode[0x6], dd->dd_pacode[0x7], dd->dd_pacode[0x8],
292 dd->dd_pacode[0x9], dd->dd_pacode[0xa], dd->dd_pacode[0xb],
293 dd->dd_pacode[0xc], dd->dd_pacode[0xd], dd->dd_pacode[0xe],
294 dd->dd_pacode[0xf]));
295
296 /*
297 * Figure out how many bytes we need for the STI code.
298 * Note there could be fewer than STI_END pointer entries
299 * populated, especially on older devices.
300 */
301 for (i = STI_END; dd->dd_pacode[i] == 0; i--)
302 ;
303
304 size = dd->dd_pacode[i] - dd->dd_pacode[STI_BEGIN];
305
306 if (rom->rom_devtype == STI_DEVTYPE1)
307 size = (size + 3) / 4;
308 if (size == 0) {
309 aprint_error(": no code for the requested platform\n");
310 return EINVAL;
311 }
312
313 if (!(rom->rom_code = uvm_km_alloc(kernel_map, round_page(size), 0,
314 UVM_KMF_WIRED))) {
315 aprint_error(": cannot allocate %u bytes for code\n", size);
316 return ENOMEM;
317 }
318 DPRINTF(("code=0x%lx[%x]\n", rom->rom_code, size));
319
320 /*
321 * Copy code into memory and make it executable.
322 */
323
324 STI_ENABLE_ROM(rom->rom_softc);
325
326 if (rom->rom_devtype == STI_DEVTYPE1) {
327 uint8_t *p;
328 uint32_t addr, eaddr;
329
330 p = (uint8_t *)rom->rom_code;
331
332 for (addr = dd->dd_pacode[STI_BEGIN], eaddr = addr + size * 4;
333 addr < eaddr; addr += 4 ) {
334 *p++ = bus_space_read_4(memt, romh, addr) & 0xff;
335 }
336 } else { /* STI_DEVTYPE4 */
337 bus_space_read_region_stream_4(memt, romh,
338 dd->dd_pacode[STI_BEGIN], (uint32_t *)rom->rom_code,
339 size / 4);
340 }
341
342 STI_DISABLE_ROM(rom->rom_softc);
343
344 if ((error = uvm_map_protect(kernel_map, rom->rom_code,
345 rom->rom_code + round_page(size), UVM_PROT_RX, FALSE))) {
346 aprint_error(": uvm_map_protect failed (%d)\n", error);
347 uvm_km_free(kernel_map, rom->rom_code, round_page(size),
348 UVM_KMF_WIRED);
349 return error;
350 }
351
352 /*
353 * Setup code function pointers.
354 */
355
356 #define O(i) \
357 (dd->dd_pacode[(i)] == 0 ? 0 : \
358 (rom->rom_code + (dd->dd_pacode[(i)] - dd->dd_pacode[0]) / \
359 (rom->rom_devtype == STI_DEVTYPE1 ? 4 : 1)))
360
361 rom->init = (sti_init_t)O(STI_INIT_GRAPH);
362 rom->mgmt = (sti_mgmt_t)O(STI_STATE_MGMT);
363 rom->unpmv = (sti_unpmv_t)O(STI_FONT_UNPMV);
364 rom->blkmv = (sti_blkmv_t)O(STI_BLOCK_MOVE);
365 rom->test = (sti_test_t)O(STI_SELF_TEST);
366 rom->exhdl = (sti_exhdl_t)O(STI_EXCEP_HDLR);
367 rom->inqconf = (sti_inqconf_t)O(STI_INQ_CONF);
368 rom->scment = (sti_scment_t)O(STI_SCM_ENT);
369 rom->dmac = (sti_dmac_t)O(STI_DMA_CTRL);
370 rom->flowc = (sti_flowc_t)O(STI_FLOW_CTRL);
371 rom->utiming = (sti_utiming_t)O(STI_UTIMING);
372 rom->pmgr = (sti_pmgr_t)O(STI_PROC_MGR);
373 rom->util = (sti_util_t)O(STI_UTIL);
374
375 #undef O
376
377 /*
378 * Set colormap entry is not implemented until 8.04, so force
379 * a NULL pointer here.
380 */
381 if (dd->dd_grrev < STI_REVISION(8, 4)) {
382 rom->scment = NULL;
383 }
384
385 return 0;
386 }
387
388 /*
389 * Map all regions.
390 */
391 void
392 sti_region_setup(struct sti_screen *scr)
393 {
394 struct sti_rom *rom = scr->scr_rom;
395 bus_space_tag_t memt = rom->memt;
396 bus_space_handle_t romh = rom->romh;
397 bus_addr_t *bases = rom->bases;
398 struct sti_dd *dd = &rom->rom_dd;
399 struct sti_cfg *cc = &scr->scr_cfg;
400 struct sti_region regions[STI_REGION_MAX], *r;
401 u_int regno, regcnt;
402 bus_addr_t addr;
403
404 DPRINTF(("stiregions @ %x:\n", dd->dd_reglst));
405
406 /*
407 * Read the region information.
408 */
409
410 STI_ENABLE_ROM(rom->rom_softc);
411
412 if (rom->rom_devtype == STI_DEVTYPE1) {
413 for (regno = 0; regno < STI_REGION_MAX; regno++)
414 *(u_int *)(regions + regno) =
415 parseword(dd->dd_reglst + regno * 0x10);
416 } else {
417 bus_space_read_region_stream_4(memt, romh, dd->dd_reglst,
418 (uint32_t *)regions, sizeof(regions) / 4);
419 }
420
421 STI_DISABLE_ROM(rom->rom_softc);
422
423 /*
424 * Count them.
425 */
426
427 for (regcnt = 0, r = regions; regcnt < STI_REGION_MAX; regcnt++, r++)
428 if (r->last)
429 break;
430 regcnt++;
431
432 /*
433 * Map them.
434 */
435
436 for (regno = 0, r = regions; regno < regcnt; regno++, r++) {
437 if (r->length == 0)
438 continue;
439
440 /*
441 * Assume an existing mapping exists.
442 */
443 addr = bases[regno] + (r->offset << PGSHIFT);
444 DPRINTF(("%08x @ 0x%08x%s%s%s%s",
445 r->length << PGSHIFT, (int)addr, r->sys_only ? " sys" : "",
446 r->cache ? " cache" : "", r->btlb ? " btlb" : "",
447 r->last ? " last" : ""));
448
449 /*
450 * Region #0 is always the rom, and it should have been
451 * mapped already.
452 * XXX This expects a 1:1 mapping...
453 */
454 if (regno == 0 && romh == bases[0]) {
455 cc->regions[0] = addr;
456 DPRINTF(("\n"));
457 continue;
458 }
459
460 if (bus_space_map(memt, addr, r->length << PGSHIFT,
461 BUS_SPACE_MAP_LINEAR | (r->cache ?
462 BUS_SPACE_MAP_CACHEABLE : 0), &rom->regh[regno]) != 0) {
463 rom->regh[regno] = romh; /* XXX */
464 DPRINTF((" - already mapped region\n"));
465 } else {
466 addr = (bus_addr_t)
467 bus_space_vaddr(memt, rom->regh[regno]);
468 if (regno == 1) {
469 DPRINTF((" - fb"));
470 scr->fbaddr = addr;
471 scr->fblen = r->length << PGSHIFT;
472 }
473 DPRINTF(("\n"));
474 }
475
476 cc->regions[regno] = addr;
477 }
478
479 #ifdef STIDEBUG
480 /*
481 * Make sure we'll trap accessing unmapped regions
482 */
483 for (regno = 0; regno < STI_REGION_MAX; regno++)
484 if (cc->regions[regno] == 0)
485 cc->regions[regno] = 0x81234567;
486 #endif
487 }
488
489 int
490 sti_screen_setup(struct sti_screen *scr, int flags)
491 {
492 struct sti_rom *rom = scr->scr_rom;
493 bus_space_tag_t memt = rom->memt;
494 bus_space_handle_t romh = rom->romh;
495 struct sti_dd *dd = &rom->rom_dd;
496 struct sti_cfg *cc = &scr->scr_cfg;
497 struct sti_inqconfout cfg;
498 struct sti_einqconfout ecfg;
499 #ifdef STIDEBUG
500 char buf[256];
501 #endif
502 int error, i;
503 int geometry_kluge = 0;
504 u_int fontindex = 0;
505
506 KASSERT(scr != NULL);
507 memset(cc, 0, sizeof(*cc));
508 cc->ext_cfg = &scr->scr_ecfg;
509 memset(cc->ext_cfg, 0, sizeof(*cc->ext_cfg));
510
511 if (dd->dd_stimemreq) {
512 scr->scr_ecfg.addr =
513 malloc(dd->dd_stimemreq, M_DEVBUF, M_WAITOK);
514 }
515
516 sti_region_setup(scr);
517
518 if ((error = sti_init(scr, 0))) {
519 aprint_error(": cannot initialize (%d)\n", error);
520 goto fail;
521 }
522
523 memset(&cfg, 0, sizeof(cfg));
524 memset(&ecfg, 0, sizeof(ecfg));
525 cfg.ext = &ecfg;
526 if ((error = sti_inqcfg(scr, &cfg))) {
527 aprint_error(": error %d inquiring config\n", error);
528 goto fail;
529 }
530
531 /*
532 * Older (rev 8.02) boards report wrong offset values,
533 * similar to the displayable area size, at least in m68k mode.
534 * Attempt to detect this and adjust here.
535 */
536 if (cfg.owidth == cfg.width &&
537 cfg.oheight == cfg.height)
538 geometry_kluge = 1;
539
540 if (geometry_kluge) {
541 scr->scr_cfg.oscr_width = cfg.owidth =
542 cfg.fbwidth - cfg.width;
543 scr->scr_cfg.oscr_height = cfg.oheight =
544 cfg.fbheight - cfg.height;
545 }
546
547 /*
548 * Save a few fields for sti_describe_screen() later
549 */
550 scr->fbheight = cfg.fbheight;
551 scr->fbwidth = cfg.fbwidth;
552 scr->oheight = cfg.oheight;
553 scr->owidth = cfg.owidth;
554 memcpy(scr->name, cfg.name, sizeof(scr->name));
555
556 if ((error = sti_init(scr, STI_TEXTMODE | flags))) {
557 aprint_error(": cannot initialize (%d)\n", error);
558 goto fail;
559 }
560 #ifdef STIDEBUG
561 snprintb(buf, sizeof(buf), STI_INQCONF_BITS, cfg.attributes);
562 DPRINTF(("conf: bpp=%d planes=%d attr=%s\n"
563 "crt=0x%x:0x%x:0x%x hw=0x%x:0x%x:0x%x\n", cfg.bpp,
564 cfg.planes, buf,
565 ecfg.crt_config[0], ecfg.crt_config[1], ecfg.crt_config[2],
566 ecfg.crt_hw[0], ecfg.crt_hw[1], ecfg.crt_hw[2]));
567 #endif
568 scr->scr_bpp = cfg.bppu;
569
570 /*
571 * Although scr->scr_ecfg.current_monitor is not filled by
572 * sti_init() as expected, we can nevertheless walk the monitor
573 * list, if there is any, and if we find a mode matching our
574 * resolution, pick its font index.
575 */
576 if (dd->dd_montbl != 0) {
577 STI_ENABLE_ROM(rom->rom_softc);
578
579 for (i = 0; i < dd->dd_nmon; i++) {
580 u_int offs = dd->dd_montbl + 8 * i;
581 uint32_t m[2];
582 sti_mon_t mon = (void *)m;
583 if (rom->rom_devtype == STI_DEVTYPE1) {
584 m[0] = parseword(4 * offs);
585 m[1] = parseword(4 * (offs + 4));
586 } else {
587 bus_space_read_region_stream_4(memt, romh, offs,
588 (uint32_t *)mon, sizeof(*mon) / 4);
589 }
590
591 if (mon->width == scr->scr_cfg.scr_width &&
592 mon->height == scr->scr_cfg.scr_height) {
593 fontindex = mon->font;
594 break;
595 }
596 }
597
598 STI_DISABLE_ROM(rom->rom_softc);
599
600 DPRINTF(("font index: %d\n", fontindex));
601 }
602
603 if ((error = sti_fetchfonts(scr, &cfg, dd->dd_fntaddr, fontindex))) {
604 aprint_error(": cannot fetch fonts (%d)\n", error);
605 goto fail;
606 }
607
608 /*
609 * setup screen descriptions:
610 * figure number of fonts supported;
611 * allocate wscons structures;
612 * calculate dimensions.
613 */
614
615 scr->scr_wsd.name = "std";
616 scr->scr_wsd.ncols = cfg.width / scr->scr_curfont.width;
617 scr->scr_wsd.nrows = cfg.height / scr->scr_curfont.height;
618 scr->scr_wsd.textops = &sti_emulops;
619 scr->scr_wsd.fontwidth = scr->scr_curfont.width;
620 scr->scr_wsd.fontheight = scr->scr_curfont.height;
621 scr->scr_wsd.capabilities = WSSCREEN_REVERSE | WSSCREEN_UNDERLINE;
622
623 scr->scr_scrlist[0] = &scr->scr_wsd;
624 scr->scr_screenlist.nscreens = 1;
625 scr->scr_screenlist.screens = scr->scr_scrlist;
626
627 #ifndef SMALL_KERNEL
628 /*
629 * Decide which board-specific routines to use.
630 */
631
632 switch (dd->dd_grid[0]) {
633 case STI_DD_CRX:
634 scr->setupfb = ngle_elk_setupfb;
635 scr->putcmap = ngle_putcmap;
636
637 scr->reg10_value = 0x13601000;
638 if (scr->scr_bpp > 8)
639 scr->reg12_value = NGLE_BUFF1_CMAP3;
640 else
641 scr->reg12_value = NGLE_BUFF1_CMAP0;
642 scr->cmap_finish_register = NGLE_REG_1;
643 break;
644
645 case STI_DD_TIMBER:
646 scr->setupfb = ngle_timber_setupfb;
647 scr->putcmap = ngle_putcmap;
648
649 scr->reg10_value = 0x13602000;
650 scr->reg12_value = NGLE_BUFF1_CMAP0;
651 scr->cmap_finish_register = NGLE_REG_1;
652 break;
653
654 case STI_DD_ARTIST:
655 scr->setupfb = ngle_artist_setupfb;
656 scr->putcmap = ngle_putcmap;
657
658 scr->reg10_value = 0x13601000;
659 scr->reg12_value = NGLE_ARTIST_CMAP0;
660 scr->cmap_finish_register = NGLE_REG_26;
661 break;
662
663 case STI_DD_EG:
664 scr->setupfb = ngle_artist_setupfb;
665 scr->putcmap = ngle_putcmap;
666
667 scr->reg10_value = 0x13601000;
668 if (scr->scr_bpp > 8) {
669 scr->reg12_value = NGLE_BUFF1_CMAP3;
670 scr->cmap_finish_register = NGLE_REG_1;
671 } else {
672 scr->reg12_value = NGLE_ARTIST_CMAP0;
673 scr->cmap_finish_register = NGLE_REG_26;
674 }
675 break;
676
677 case STI_DD_GRX:
678 case STI_DD_CRX24:
679 case STI_DD_EVRX:
680 case STI_DD_3X2V:
681 case STI_DD_DUAL_CRX:
682 case STI_DD_HCRX:
683 case STI_DD_LEGO:
684 case STI_DD_SUMMIT:
685 case STI_DD_PINNACLE:
686 default:
687 scr->setupfb = NULL;
688 scr->putcmap =
689 rom->scment == NULL ? NULL : ngle_default_putcmap;
690 break;
691 }
692 #endif
693
694 return 0;
695
696 fail:
697 /* XXX free resources */
698 if (scr->scr_ecfg.addr != NULL) {
699 free(scr->scr_ecfg.addr, M_DEVBUF);
700 scr->scr_ecfg.addr = NULL;
701 }
702
703 return ENXIO;
704 }
705
706 void
707 sti_describe_screen(struct sti_softc *sc, struct sti_screen *scr)
708 {
709 struct sti_font *fp = &scr->scr_curfont;
710
711 aprint_normal("%s: %s, %dx%d frame buffer, %dx%dx%d display\n",
712 device_xname(sc->sc_dev), scr->name, scr->fbwidth, scr->fbheight,
713 scr->scr_cfg.scr_width, scr->scr_cfg.scr_height, scr->scr_bpp);
714
715 aprint_normal("%s: %dx%d font type %d, %d bpc, charset %d-%d\n",
716 device_xname(sc->sc_dev), fp->width, fp->height,
717 fp->type, fp->bpc, fp->first, fp->last);
718 }
719
720 void
721 sti_describe(struct sti_softc *sc)
722 {
723 struct sti_rom *rom = sc->sc_rom;
724 struct sti_dd *dd = &rom->rom_dd;
725
726 aprint_normal(": rev %d.%02d;%d, ID 0x%08X%08X\n",
727 dd->dd_grrev >> 4, dd->dd_grrev & 0xf,
728 dd->dd_lrrev, dd->dd_grid[0], dd->dd_grid[1]);
729
730 if (sc->sc_scr != NULL)
731 sti_describe_screen(sc, sc->sc_scr);
732 }
733
734 /*
735 * Final part of attachment. On hppa where we use the PDC console
736 * during autoconf, this has to be postponed until autoconf has
737 * completed.
738 */
739 void
740 sti_end_attach(struct sti_softc *sc)
741 {
742 struct sti_screen *scr = sc->sc_scr;
743
744 if (scr == NULL)
745 return;
746 #if NWSDISPLAY > 0
747 else {
748 struct wsemuldisplaydev_attach_args waa;
749 scr->scr_wsmode = WSDISPLAYIO_MODE_EMUL;
750
751 waa.console = sc->sc_flags & STI_CONSOLE ? 1 : 0;
752 waa.scrdata = &scr->scr_screenlist;
753 waa.accessops = &sti_accessops;
754 waa.accesscookie = scr;
755
756 /* attach as console if required */
757 if (waa.console && !ISSET(sc->sc_flags, STI_ATTACHED)) {
758 long defattr;
759
760 sti_alloc_attr(scr, 0, 0, 0, &defattr);
761 wsdisplay_cnattach(&scr->scr_wsd, scr,
762 0, scr->scr_wsd.nrows - 1, defattr);
763 sc->sc_flags |= STI_ATTACHED;
764 }
765
766 config_found(sc->sc_dev, &waa, wsemuldisplaydevprint);
767 }
768 #endif
769 }
770
771 u_int
772 sti_rom_size(bus_space_tag_t memt, bus_space_handle_t romh)
773 {
774 int devtype;
775 u_int romend;
776
777 devtype = bus_space_read_1(memt, romh, 3);
778 if (devtype == STI_DEVTYPE4) {
779 bus_space_read_region_stream_4(memt, romh, STI_DEV4_DD_ROMEND,
780 (uint32_t *)&romend, 1);
781 } else {
782 romend = parseword(STI_DEV1_DD_ROMEND);
783 }
784
785 DPRINTF(("%s: %08x (%08x)\n", __func__, romend, round_page(romend)));
786
787 return round_page(romend);
788 }
789
790 int
791 sti_fetchfonts(struct sti_screen *scr, struct sti_inqconfout *cfg,
792 uint32_t baseaddr, u_int fontindex)
793 {
794 struct sti_rom *rom = scr->scr_rom;
795 bus_space_tag_t memt = rom->memt;
796 bus_space_handle_t romh = rom->romh;
797 struct sti_font *fp = &scr->scr_curfont;
798 uint32_t addr;
799 int size;
800 #ifdef notyet
801 int uc;
802 struct {
803 struct sti_unpmvflags flags;
804 struct sti_unpmvin in;
805 struct sti_unpmvout out;
806 } a;
807 #endif
808
809 /*
810 * Get the first PROM font in memory
811 */
812
813 STI_ENABLE_ROM(rom->rom_softc);
814
815 rescan:
816 addr = baseaddr;
817 do {
818 if (rom->rom_devtype == STI_DEVTYPE1) {
819 fp->first = parseshort(addr + 0x00);
820 fp->last = parseshort(addr + 0x08);
821 fp->width = bus_space_read_1(memt, romh, addr + 0x13);
822 fp->height = bus_space_read_1(memt, romh, addr + 0x17);
823 fp->type = bus_space_read_1(memt, romh, addr + 0x1b);
824 fp->bpc = bus_space_read_1(memt, romh, addr + 0x1f);
825 fp->next = parseword(addr + 0x20);
826 fp->uheight= bus_space_read_1(memt, romh, addr + 0x33);
827 fp->uoffset= bus_space_read_1(memt, romh, addr + 0x37);
828 } else { /* STI_DEVTYPE4 */
829 bus_space_read_region_stream_4(memt, romh, addr,
830 (uint32_t *)fp, sizeof(struct sti_font) / 4);
831 }
832
833 #ifdef STIDEBUG
834 STI_DISABLE_ROM(rom->rom_softc);
835 DPRINTF(("%s: %dx%d font type %d, %d bpc, charset %d-%d\n",
836 device_xname(scr->scr_rom->rom_softc->sc_dev), fp->width,
837 fp->height, fp->type, fp->bpc, fp->first, fp->last));
838 STI_ENABLE_ROM(rom->rom_softc);
839 #endif
840
841 if (fontindex == 0) {
842 size = sizeof(struct sti_font) +
843 (fp->last - fp->first + 1) * fp->bpc;
844 if (rom->rom_devtype == STI_DEVTYPE1)
845 size *= 4;
846 scr->scr_romfont = malloc(size, M_DEVBUF, M_WAITOK);
847
848 bus_space_read_region_stream_4(memt, romh, addr,
849 (uint32_t *)scr->scr_romfont, size / 4);
850 break;
851 }
852
853 addr = baseaddr + fp->next;
854 fontindex--;
855 } while (fp->next != 0);
856
857 /*
858 * If our font index was bogus, we did not find the expected font.
859 * In this case, pick the first one and be done with it.
860 */
861 if (fp->next == 0 && scr->scr_romfont == NULL) {
862 fontindex = 0;
863 goto rescan;
864 }
865
866 STI_DISABLE_ROM(rom->rom_softc);
867
868 #ifdef notyet
869 /*
870 * If there is enough room in the off-screen framebuffer memory,
871 * display all the characters there in order to display them
872 * faster with blkmv operations rather than unpmv later on.
873 */
874 if (size <= cfg->fbheight *
875 (cfg->fbwidth - cfg->width - cfg->owidth)) {
876 memset(&a, 0, sizeof(a));
877 a.flags.flags = STI_UNPMVF_WAIT;
878 a.in.fg_colour = STI_COLOUR_WHITE;
879 a.in.bg_colour = STI_COLOUR_BLACK;
880 a.in.font_addr = scr->scr_romfont;
881
882 scr->scr_fontmaxcol = cfg->fbheight / fp->height;
883 scr->scr_fontbase = cfg->width + cfg->owidth;
884 for (uc = fp->first; uc <= fp->last; uc++) {
885 a.in.x = ((uc - fp->first) / scr->scr_fontmaxcol) *
886 fp->width + scr->scr_fontbase;
887 a.in.y = ((uc - fp->first) % scr->scr_fontmaxcol) *
888 fp->height;
889 a.in.index = uc;
890
891 (*scr->unpmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
892 if (a.out.errno) {
893 aprint_error_dev(sc->sc_dev, "unpmv %d "
894 "returned %d\n", uc, a.out.errno);
895 return 0;
896 }
897 }
898
899 free(scr->scr_romfont, M_DEVBUF);
900 scr->scr_romfont = NULL;
901 }
902 #endif
903
904 return 0;
905 }
906
907 /*
908 * Wrappers around STI code pointers
909 */
910
911 int
912 sti_init(struct sti_screen *scr, int mode)
913 {
914 struct sti_rom *rom = scr->scr_rom;
915 struct {
916 struct sti_initflags flags;
917 struct sti_initin in;
918 struct sti_einitin ein;
919 struct sti_initout out;
920 } a;
921
922 KASSERT(rom != NULL);
923 memset(&a, 0, sizeof(a));
924
925 a.flags.flags = STI_INITF_WAIT | STI_INITF_EBET;
926 if ((mode & STI_TEXTMODE) != 0) {
927 a.flags.flags |= STI_INITF_TEXT | STI_INITF_CMB |
928 STI_INITF_PBET | STI_INITF_PBETI | STI_INITF_ICMT;
929 } else {
930 a.flags.flags |= STI_INITF_NTEXT;
931 }
932 if ((mode & STI_CLEARSCR) != 0)
933 a.flags.flags |= STI_INITF_CLEAR;
934
935 a.in.text_planes = 1;
936 a.in.ext_in = &a.ein;
937
938 DPRINTF(("%s: init,%p(%x, %p, %p, %p)\n",
939 device_xname(rom->rom_softc->sc_dev), rom->init, a.flags.flags,
940 &a.in, &a.out, &scr->scr_cfg));
941
942 (*rom->init)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
943
944 if (a.out.text_planes != a.in.text_planes)
945 return -1; /* not colliding with sti errno values */
946 return a.out.errno;
947 }
948
949 int
950 sti_inqcfg(struct sti_screen *scr, struct sti_inqconfout *out)
951 {
952 struct sti_rom *rom = scr->scr_rom;
953 struct {
954 struct sti_inqconfflags flags;
955 struct sti_inqconfin in;
956 } a;
957
958 memset(&a, 0, sizeof(a));
959
960 a.flags.flags = STI_INQCONFF_WAIT;
961 (*rom->inqconf)(&a.flags, &a.in, out, &scr->scr_cfg);
962
963 return out->errno;
964 }
965
966 void
967 sti_bmove(struct sti_screen *scr, int x1, int y1, int x2, int y2, int h, int w,
968 enum sti_bmove_funcs f)
969 {
970 struct sti_rom *rom = scr->scr_rom;
971 struct {
972 struct sti_blkmvflags flags;
973 struct sti_blkmvin in;
974 struct sti_blkmvout out;
975 } a;
976
977 memset(&a, 0, sizeof(a));
978
979 a.flags.flags = STI_BLKMVF_WAIT;
980 switch (f) {
981 case bmf_clear:
982 a.flags.flags |= STI_BLKMVF_CLR;
983 a.in.bg_colour = STI_COLOUR_BLACK;
984 break;
985 case bmf_underline:
986 case bmf_copy:
987 a.in.fg_colour = STI_COLOUR_WHITE;
988 a.in.bg_colour = STI_COLOUR_BLACK;
989 break;
990 case bmf_invert:
991 a.flags.flags |= STI_BLKMVF_COLR;
992 a.in.fg_colour = STI_COLOUR_BLACK;
993 a.in.bg_colour = STI_COLOUR_WHITE;
994 break;
995 }
996 a.in.srcx = x1;
997 a.in.srcy = y1;
998 a.in.dstx = x2;
999 a.in.dsty = y2;
1000 a.in.height = h;
1001 a.in.width = w;
1002
1003 (*rom->blkmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
1004 #ifdef STIDEBUG
1005 if (a.out.errno)
1006 printf("%s: blkmv returned %d\n",
1007 device_xname(rom->rom_softc->sc_dev), a.out.errno);
1008 #endif
1009 }
1010
1011 int
1012 sti_setcment(struct sti_screen *scr, u_int i, u_char r, u_char g, u_char b)
1013 {
1014 struct sti_rom *rom = scr->scr_rom;
1015 struct {
1016 struct sti_scmentflags flags;
1017 struct sti_scmentin in;
1018 struct sti_scmentout out;
1019 } a;
1020
1021 memset(&a, 0, sizeof(a));
1022
1023 a.flags.flags = STI_SCMENTF_WAIT;
1024 a.in.entry = i;
1025 a.in.value = (r << 16) | (g << 8) | b;
1026
1027 (*rom->scment)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
1028
1029 return a.out.errno;
1030 }
1031
1032 /*
1033 * wsdisplay accessops
1034 */
1035 int
1036 sti_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l)
1037 {
1038 struct sti_screen *scr = (struct sti_screen *)v;
1039 struct wsdisplay_fbinfo *wdf;
1040 struct wsdisplay_cmap *cmapp;
1041 u_int mode, idx, count;
1042 int ret;
1043
1044 ret = 0;
1045 switch (cmd) {
1046 case WSDISPLAYIO_GMODE:
1047 *(u_int *)data = scr->scr_wsmode;
1048 break;
1049
1050 case WSDISPLAYIO_SMODE:
1051 mode = *(u_int *)data;
1052 switch (mode) {
1053 case WSDISPLAYIO_MODE_EMUL:
1054 if (scr->scr_wsmode != WSDISPLAYIO_MODE_EMUL)
1055 ret = sti_init(scr, STI_TEXTMODE);
1056 break;
1057 case WSDISPLAYIO_MODE_DUMBFB:
1058 if (scr->scr_wsmode != WSDISPLAYIO_MODE_DUMBFB) {
1059 sti_init(scr, 0);
1060 if (scr->setupfb != NULL)
1061 scr->setupfb(scr);
1062 else
1063 #if 0
1064 ret = sti_init(scr, STI_FBMODE);
1065 #else
1066 ret = EINVAL;
1067 #endif
1068 }
1069 break;
1070 case WSDISPLAYIO_MODE_MAPPED:
1071 default:
1072 ret = EINVAL;
1073 break;
1074 }
1075 if (ret == 0)
1076 scr->scr_wsmode = mode;
1077 break;
1078
1079 case WSDISPLAYIO_GTYPE:
1080 *(u_int *)data = WSDISPLAY_TYPE_STI;
1081 break;
1082
1083 case WSDISPLAYIO_GINFO:
1084 wdf = (struct wsdisplay_fbinfo *)data;
1085 wdf->height = scr->scr_cfg.scr_height;
1086 wdf->width = scr->scr_cfg.scr_width;
1087 wdf->depth = scr->scr_bpp;
1088 if (scr->putcmap == NULL || scr->scr_bpp > 8)
1089 wdf->cmsize = 0;
1090 else
1091 wdf->cmsize = STI_NCMAP;
1092 break;
1093
1094 case WSDISPLAYIO_LINEBYTES:
1095 if (scr->scr_bpp > 8)
1096 *(u_int *)data = scr->scr_cfg.fb_width * 4;
1097 else
1098 *(u_int *)data = scr->scr_cfg.fb_width;
1099 break;
1100
1101 case WSDISPLAYIO_GETCMAP:
1102 if (scr->putcmap == NULL || scr->scr_bpp > 8)
1103 return ENODEV;
1104 cmapp = (struct wsdisplay_cmap *)data;
1105 idx = cmapp->index;
1106 count = cmapp->count;
1107 if (idx >= STI_NCMAP || count > STI_NCMAP - idx)
1108 return EINVAL;
1109 if ((ret = copyout(&scr->scr_rcmap[idx], cmapp->red, count)))
1110 break;
1111 if ((ret = copyout(&scr->scr_gcmap[idx], cmapp->green, count)))
1112 break;
1113 if ((ret = copyout(&scr->scr_bcmap[idx], cmapp->blue, count)))
1114 break;
1115 break;
1116
1117 case WSDISPLAYIO_PUTCMAP:
1118 if (scr->putcmap == NULL || scr->scr_bpp > 8)
1119 return ENODEV;
1120 cmapp = (struct wsdisplay_cmap *)data;
1121 idx = cmapp->index;
1122 count = cmapp->count;
1123 if (idx >= STI_NCMAP || count > STI_NCMAP - idx)
1124 return EINVAL;
1125 if ((ret = copyin(cmapp->red, &scr->scr_rcmap[idx], count)))
1126 break;
1127 if ((ret = copyin(cmapp->green, &scr->scr_gcmap[idx], count)))
1128 break;
1129 if ((ret = copyin(cmapp->blue, &scr->scr_bcmap[idx], count)))
1130 break;
1131 ret = scr->putcmap(scr, idx, count);
1132 break;
1133
1134 case WSDISPLAYIO_SVIDEO:
1135 case WSDISPLAYIO_GVIDEO:
1136 case WSDISPLAYIO_GCURPOS:
1137 case WSDISPLAYIO_SCURPOS:
1138 case WSDISPLAYIO_GCURMAX:
1139 case WSDISPLAYIO_GCURSOR:
1140 case WSDISPLAYIO_SCURSOR:
1141 default:
1142 return ENOTTY; /* not supported yet */
1143 }
1144
1145 return ret;
1146 }
1147
1148 paddr_t
1149 sti_mmap(void *v, void *vs, off_t offset, int prot)
1150 {
1151 struct sti_screen *scr = (struct sti_screen *)v;
1152 #if 0
1153 struct sti_rom *rom = scr->scr_rom;
1154 #endif
1155 paddr_t pa;
1156
1157 if ((offset & PAGE_MASK) != 0)
1158 return -1;
1159
1160 if (offset < 0 || offset >= scr->fblen)
1161 return -1;
1162
1163 #if 0 /* XXX not all platforms provide bus_space_mmap() yet */
1164 pa = bus_space_mmap(rom->memt, scr->fbaddr, offset, prot,
1165 BUS_SPACE_MAP_LINEAR);
1166 #else
1167 pa = scr->fbaddr + offset;
1168 #endif
1169
1170 return pa;
1171 }
1172
1173 int
1174 sti_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
1175 int *cxp, int *cyp, long *defattr)
1176 {
1177 struct sti_screen *scr = (struct sti_screen *)v;
1178
1179 if (scr->scr_nscreens > 0)
1180 return ENOMEM;
1181
1182 *cookiep = scr;
1183 *cxp = 0;
1184 *cyp = 0;
1185 sti_alloc_attr(scr, 0, 0, 0, defattr);
1186 scr->scr_nscreens++;
1187 return 0;
1188 }
1189
1190 void
1191 sti_free_screen(void *v, void *cookie)
1192 {
1193 struct sti_screen *scr = (struct sti_screen *)v;
1194
1195 scr->scr_nscreens--;
1196 }
1197
1198 int
1199 sti_show_screen(void *v, void *cookie, int waitok, void (*cb)(void *, int, int),
1200 void *cbarg)
1201 {
1202 #if 0
1203 struct sti_screen *scr = (struct sti_screen *)v;
1204 #endif
1205
1206 return 0;
1207 }
1208
1209 int
1210 sti_load_font(void *v, void *cookie, struct wsdisplay_font *font)
1211 {
1212 #if 0
1213 struct sti_screen *scr = (struct sti_screen *)v;
1214 #endif
1215
1216 return -1;
1217 }
1218
1219 /*
1220 * wsdisplay emulops
1221 */
1222 void
1223 sti_cursor(void *v, int on, int row, int col)
1224 {
1225 struct sti_screen *scr = (struct sti_screen *)v;
1226 struct sti_font *fp = &scr->scr_curfont;
1227
1228 sti_bmove(scr,
1229 col * fp->width, row * fp->height,
1230 col * fp->width, row * fp->height,
1231 fp->height, fp->width, bmf_invert);
1232 }
1233
1234 /*
1235 * ISO 8859-1 part of Unicode to HP Roman font index conversion array.
1236 */
1237 static const uint8_t
1238 sti_unitoroman[0x100 - 0xa0] = {
1239 0xa0, 0xb8, 0xbf, 0xbb, 0xba, 0xbc, 0, 0xbd,
1240 0xab, 0, 0xf9, 0xfb, 0, 0xf6, 0, 0xb0,
1241
1242 0xb3, 0xfe, 0, 0, 0xa8, 0xf3, 0xf4, 0xf2,
1243 0, 0, 0xfa, 0xfd, 0xf7, 0xf8, 0, 0xb9,
1244
1245 0xa1, 0xe0, 0xa2, 0xe1, 0xd8, 0xd0, 0xd3, 0xb4,
1246 0xa3, 0xdc, 0xa4, 0xa5, 0xe6, 0xe5, 0xa6, 0xa7,
1247
1248 0xe3, 0xb6, 0xe8, 0xe7, 0xdf, 0xe9, 0xda, 0,
1249 0xd2, 0xad, 0xed, 0xae, 0xdb, 0xb1, 0xf0, 0xde,
1250
1251 0xc8, 0xc4, 0xc0, 0xe2, 0xcc, 0xd4, 0xd7, 0xb5,
1252 0xc9, 0xc5, 0xc1, 0xcd, 0xd9, 0xd5, 0xd1, 0xdd,
1253
1254 0xe4, 0xb7, 0xca, 0xc6, 0xc2, 0xea, 0xce, 0,
1255 0xd6, 0xcb, 0xc7, 0xc3, 0xcf, 0xb2, 0xf1, 0xef
1256 };
1257
1258 int
1259 sti_mapchar(void *v, int uni, u_int *index)
1260 {
1261 struct sti_screen *scr = (struct sti_screen *)v;
1262 struct sti_font *fp = &scr->scr_curfont;
1263 int c;
1264
1265 switch (fp->type) {
1266 case STI_FONT_HPROMAN8:
1267 if (uni >= 0x80 && uni < 0xa0)
1268 c = -1;
1269 else if (uni >= 0xa0 && uni < 0x100) {
1270 c = (int)sti_unitoroman[uni - 0xa0];
1271 if (c == 0)
1272 c = -1;
1273 } else
1274 c = uni;
1275 break;
1276 default:
1277 c = uni;
1278 break;
1279 }
1280
1281 if (c == -1 || c < fp->first || c > fp->last) {
1282 *index = ' ';
1283 return 0;
1284 }
1285
1286 *index = c;
1287 return 5;
1288 }
1289
1290 void
1291 sti_putchar(void *v, int row, int col, u_int uc, long attr)
1292 {
1293 struct sti_screen *scr = (struct sti_screen *)v;
1294 struct sti_rom *rom = scr->scr_rom;
1295 struct sti_font *fp = &scr->scr_curfont;
1296
1297 if (scr->scr_romfont != NULL) {
1298 /*
1299 * Font is in memory, use unpmv
1300 */
1301 struct {
1302 struct sti_unpmvflags flags;
1303 struct sti_unpmvin in;
1304 struct sti_unpmvout out;
1305 } a;
1306
1307 memset(&a, 0, sizeof(a));
1308
1309 a.flags.flags = STI_UNPMVF_WAIT;
1310 /* XXX does not handle text attributes */
1311 a.in.fg_colour = STI_COLOUR_WHITE;
1312 a.in.bg_colour = STI_COLOUR_BLACK;
1313 a.in.x = col * fp->width;
1314 a.in.y = row * fp->height;
1315 a.in.font_addr = scr->scr_romfont;
1316 a.in.index = uc;
1317
1318 (*rom->unpmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
1319 } else {
1320 /*
1321 * Font is in frame buffer, use blkmv
1322 */
1323 struct {
1324 struct sti_blkmvflags flags;
1325 struct sti_blkmvin in;
1326 struct sti_blkmvout out;
1327 } a;
1328
1329 memset(&a, 0, sizeof(a));
1330
1331 a.flags.flags = STI_BLKMVF_WAIT;
1332 /* XXX does not handle text attributes */
1333 a.in.fg_colour = STI_COLOUR_WHITE;
1334 a.in.bg_colour = STI_COLOUR_BLACK;
1335
1336 a.in.srcx = ((uc - fp->first) / scr->scr_fontmaxcol) *
1337 fp->width + scr->scr_fontbase;
1338 a.in.srcy = ((uc - fp->first) % scr->scr_fontmaxcol) *
1339 fp->height;
1340 a.in.dstx = col * fp->width;
1341 a.in.dsty = row * fp->height;
1342 a.in.height = fp->height;
1343 a.in.width = fp->width;
1344
1345 (*rom->blkmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
1346 }
1347 }
1348
1349 void
1350 sti_copycols(void *v, int row, int srccol, int dstcol, int ncols)
1351 {
1352 struct sti_screen *scr = (struct sti_screen *)v;
1353 struct sti_font *fp = &scr->scr_curfont;
1354
1355 sti_bmove(scr,
1356 srccol * fp->width, row * fp->height,
1357 dstcol * fp->width, row * fp->height,
1358 fp->height, ncols * fp->width, bmf_copy);
1359 }
1360
1361 void
1362 sti_erasecols(void *v, int row, int startcol, int ncols, long attr)
1363 {
1364 struct sti_screen *scr = (struct sti_screen *)v;
1365 struct sti_font *fp = &scr->scr_curfont;
1366
1367 sti_bmove(scr,
1368 startcol * fp->width, row * fp->height,
1369 startcol * fp->width, row * fp->height,
1370 fp->height, ncols * fp->width, bmf_clear);
1371 }
1372
1373 void
1374 sti_copyrows(void *v, int srcrow, int dstrow, int nrows)
1375 {
1376 struct sti_screen *scr = (struct sti_screen *)v;
1377 struct sti_font *fp = &scr->scr_curfont;
1378
1379 sti_bmove(scr, 0, srcrow * fp->height, 0, dstrow * fp->height,
1380 nrows * fp->height, scr->scr_cfg.scr_width, bmf_copy);
1381 }
1382
1383 void
1384 sti_eraserows(void *v, int srcrow, int nrows, long attr)
1385 {
1386 struct sti_screen *scr = (struct sti_screen *)v;
1387 struct sti_font *fp = &scr->scr_curfont;
1388
1389 sti_bmove(scr, 0, srcrow * fp->height, 0, srcrow * fp->height,
1390 nrows * fp->height, scr->scr_cfg.scr_width, bmf_clear);
1391 }
1392
1393 int
1394 sti_alloc_attr(void *v, int fg, int bg, int flags, long *pattr)
1395 {
1396 #if 0
1397 struct sti_screen *scr = (struct sti_screen *)v;
1398 #endif
1399
1400 *pattr = 0;
1401
1402 return 0;
1403 }
1404
1405 #ifdef hp300 /* XXX */
1406 /*
1407 * Early console support. Only used on hp300.
1408 */
1409 int
1410 sti_cnattach(struct sti_rom *rom, struct sti_screen *scr, bus_space_tag_t memt,
1411 bus_addr_t *bases, u_int codebase)
1412 {
1413 bus_space_handle_t romh;
1414 u_int romend;
1415 int error;
1416 long defattr;
1417
1418 if ((error = bus_space_map(memt, bases[0], PAGE_SIZE, 0, &romh)) != 0)
1419 return error;
1420
1421 /*
1422 * Compute real PROM size
1423 */
1424 romend = sti_rom_size(memt, romh);
1425
1426 bus_space_unmap(memt, romh, PAGE_SIZE);
1427
1428 if ((error = bus_space_map(memt, bases[0], romend, 0, &romh)) != 0)
1429 return error;
1430
1431 bases[0] = romh;
1432 if (sti_rom_setup(rom, memt, memt, romh, bases, codebase) != 0)
1433 return -1;
1434 scr->scr_rom = rom;
1435 if (sti_screen_setup(scr, STI_CLEARSCR) != 0)
1436 return -1;
1437
1438 sti_alloc_attr(scr, 0, 0, 0, &defattr);
1439 wsdisplay_cnattach(&scr->scr_wsd, scr, 0, 0, defattr);
1440
1441 return 0;
1442 }
1443 #endif
1444
1445 int
1446 ngle_default_putcmap(struct sti_screen *scr, u_int idx, u_int count)
1447 {
1448 int i, ret;
1449
1450 for (i = idx + count - 1; i >= (int)idx; i--)
1451 if ((ret = sti_setcment(scr, i, scr->scr_rcmap[i],
1452 scr->scr_gcmap[i], scr->scr_bcmap[i])))
1453 return EINVAL;
1454
1455 return 0;
1456 }
1457
1458 #ifndef SMALL_KERNEL
1459
1460 void ngle_setup_hw(bus_space_tag_t, bus_space_handle_t);
1461 void ngle_setup_fb(bus_space_tag_t, bus_space_handle_t, uint32_t);
1462 void ngle_setup_attr_planes(struct sti_screen *scr);
1463 void ngle_setup_bt458(struct sti_screen *scr);
1464
1465 #define ngle_bt458_write(memt, memh, r, v) \
1466 bus_space_write_4(memt, memh, NGLE_REG_RAMDAC + ((r) << 2), (v) << 24)
1467
1468 void
1469 ngle_artist_setupfb(struct sti_screen *scr)
1470 {
1471 struct sti_rom *rom = scr->scr_rom;
1472 bus_space_tag_t memt = rom->memt;
1473 bus_space_handle_t memh = rom->regh[2];
1474
1475 ngle_setup_bt458(scr);
1476
1477 ngle_setup_hw(memt, memh);
1478 ngle_setup_fb(memt, memh, scr->reg10_value);
1479
1480 ngle_setup_attr_planes(scr);
1481
1482 ngle_setup_hw(memt, memh);
1483 bus_space_write_4(memt, memh, NGLE_REG_21,
1484 bus_space_read_4(memt, memh, NGLE_REG_21) | 0x0a000000);
1485 bus_space_write_4(memt, memh, NGLE_REG_27,
1486 bus_space_read_4(memt, memh, NGLE_REG_27) | 0x00800000);
1487 }
1488
1489 void
1490 ngle_elk_setupfb(struct sti_screen *scr)
1491 {
1492 struct sti_rom *rom = scr->scr_rom;
1493 bus_space_tag_t memt = rom->memt;
1494 bus_space_handle_t memh = rom->regh[2];
1495
1496 ngle_setup_bt458(scr);
1497
1498 ngle_setup_hw(memt, memh);
1499 ngle_setup_fb(memt, memh, scr->reg10_value);
1500
1501 ngle_setup_attr_planes(scr);
1502
1503 ngle_setup_hw(memt, memh);
1504 /* enable overlay planes in Bt458 command register */
1505 ngle_bt458_write(memt, memh, 0x0c, 0x06);
1506 ngle_bt458_write(memt, memh, 0x0e, 0x43);
1507 }
1508
1509 void
1510 ngle_timber_setupfb(struct sti_screen *scr)
1511 {
1512 struct sti_rom *rom = scr->scr_rom;
1513 bus_space_tag_t memt = rom->memt;
1514 bus_space_handle_t memh = rom->regh[2];
1515
1516 ngle_setup_bt458(scr);
1517
1518 ngle_setup_hw(memt, memh);
1519 /* enable overlay planes in Bt458 command register */
1520 ngle_bt458_write(memt, memh, 0x0c, 0x06);
1521 ngle_bt458_write(memt, memh, 0x0e, 0x43);
1522 }
1523
1524 void
1525 ngle_setup_bt458(struct sti_screen *scr)
1526 {
1527 struct sti_rom *rom = scr->scr_rom;
1528 bus_space_tag_t memt = rom->memt;
1529 bus_space_handle_t memh = rom->regh[2];
1530
1531 ngle_setup_hw(memt, memh);
1532 /* set Bt458 read mask register to all planes */
1533 ngle_bt458_write(memt, memh, 0x08, 0x04);
1534 ngle_bt458_write(memt, memh, 0x0a, 0xff);
1535 }
1536
1537 void
1538 ngle_setup_attr_planes(struct sti_screen *scr)
1539 {
1540 struct sti_rom *rom = scr->scr_rom;
1541 bus_space_tag_t memt = rom->memt;
1542 bus_space_handle_t memh = rom->regh[2];
1543
1544 ngle_setup_hw(memt, memh);
1545 bus_space_write_4(memt, memh, NGLE_REG_11, 0x2ea0d000);
1546 bus_space_write_4(memt, memh, NGLE_REG_14, 0x23000302);
1547 bus_space_write_4(memt, memh, NGLE_REG_12, scr->reg12_value);
1548 bus_space_write_4(memt, memh, NGLE_REG_8, 0xffffffff);
1549
1550 bus_space_write_4(memt, memh, NGLE_REG_6, 0x00000000);
1551 bus_space_write_4(memt, memh, NGLE_REG_9,
1552 (scr->scr_cfg.scr_width << 16) | scr->scr_cfg.scr_height);
1553 bus_space_write_4(memt, memh, NGLE_REG_6, 0x05000000);
1554 bus_space_write_4(memt, memh, NGLE_REG_9, 0x00040001);
1555
1556 ngle_setup_hw(memt, memh);
1557 bus_space_write_4(memt, memh, NGLE_REG_12, 0x00000000);
1558
1559 ngle_setup_fb(memt, memh, scr->reg10_value);
1560 }
1561
1562 int
1563 ngle_putcmap(struct sti_screen *scr, u_int idx, u_int count)
1564 {
1565 struct sti_rom *rom = scr->scr_rom;
1566 bus_space_tag_t memt = rom->memt;
1567 bus_space_handle_t memh = rom->regh[2];
1568 uint8_t *r, *g, *b;
1569 uint32_t cmap_finish;
1570
1571 if (scr->scr_bpp > 8)
1572 cmap_finish = 0x83000100;
1573 else
1574 cmap_finish = 0x80000100;
1575
1576 r = scr->scr_rcmap + idx;
1577 g = scr->scr_gcmap + idx;
1578 b = scr->scr_bcmap + idx;
1579
1580 ngle_setup_hw(memt, memh);
1581 bus_space_write_4(memt, memh, NGLE_REG_10, 0xbbe0f000);
1582 bus_space_write_4(memt, memh, NGLE_REG_14, 0x03000300);
1583 bus_space_write_4(memt, memh, NGLE_REG_13, 0xffffffff);
1584
1585 while (count-- != 0) {
1586 ngle_setup_hw(memt, memh);
1587 bus_space_write_4(memt, memh, NGLE_REG_3, 0x400 | (idx << 2));
1588 bus_space_write_4(memt, memh, NGLE_REG_4,
1589 (*r << 16) | (*g << 8) | *b);
1590
1591 idx++;
1592 r++, g++, b++;
1593 }
1594
1595 bus_space_write_4(memt, memh, NGLE_REG_2, 0x400);
1596 bus_space_write_4(memt, memh, scr->cmap_finish_register, cmap_finish);
1597 ngle_setup_fb(memt, memh, scr->reg10_value);
1598
1599
1600 return 0;
1601 }
1602
1603 void
1604 ngle_setup_hw(bus_space_tag_t memt, bus_space_handle_t memh)
1605 {
1606 uint8_t stat;
1607
1608 do {
1609 stat = bus_space_read_1(memt, memh, NGLE_REG_15b0);
1610 if (stat == 0)
1611 stat = bus_space_read_1(memt, memh, NGLE_REG_15b0);
1612 } while (stat != 0);
1613 }
1614
1615 void
1616 ngle_setup_fb(bus_space_tag_t memt, bus_space_handle_t memh, uint32_t reg10)
1617 {
1618
1619 ngle_setup_hw(memt, memh);
1620 bus_space_write_4(memt, memh, NGLE_REG_10, reg10);
1621 bus_space_write_4(memt, memh, NGLE_REG_14, 0x83000300);
1622 ngle_setup_hw(memt, memh);
1623 bus_space_write_1(memt, memh, NGLE_REG_16b1, 1);
1624 }
1625 #endif /* SMALL_KERNEL */
1626