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