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