sti.c revision 1.44 1 /* $NetBSD: sti.c,v 1.44 2025/05/25 16:41:27 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.44 2025/05/25 16:41:27 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 << PGSHIFT);
451 DPRINTF(("%08x @ 0x%08x%s%s%s%s",
452 r->length << PGSHIFT, (int)addr, r->sys_only ? " sys" : "",
453 r->cache ? " cache" : "", r->btlb ? " btlb" : "",
454 r->last ? " last" : ""));
455
456 /*
457 * Region #0 is always the rom, and it should have been
458 * mapped already.
459 * XXX This expects a 1:1 mapping...
460 */
461 if (regno == 0 && romh == bases[0]) {
462 cc->regions[0] = addr;
463 DPRINTF(("\n"));
464 continue;
465 }
466
467 if (bus_space_map(memt, addr, r->length << PGSHIFT,
468 BUS_SPACE_MAP_LINEAR | (r->cache ?
469 BUS_SPACE_MAP_CACHEABLE : 0), &rom->regh[regno]) != 0) {
470 rom->regh[regno] = romh; /* XXX */
471 DPRINTF((" - already mapped region\n"));
472 } else {
473 addr = (bus_addr_t)
474 bus_space_vaddr(memt, rom->regh[regno]);
475 if (regno == 1) {
476 DPRINTF((" - fb"));
477 scr->fbaddr = addr;
478 scr->fblen = r->length << PGSHIFT;
479 }
480 DPRINTF(("\n"));
481 }
482
483 cc->regions[regno] = addr;
484 }
485
486 #ifdef STIDEBUG
487 /*
488 * Make sure we'll trap accessing unmapped regions
489 */
490 for (regno = 0; regno < STI_REGION_MAX; regno++)
491 if (cc->regions[regno] == 0)
492 cc->regions[regno] = 0x81234567;
493 #endif
494 }
495
496 int
497 sti_screen_setup(struct sti_screen *scr, int flags)
498 {
499 struct sti_rom *rom = scr->scr_rom;
500 bus_space_tag_t memt = rom->memt;
501 bus_space_handle_t romh = rom->romh;
502 struct sti_dd *dd = &rom->rom_dd;
503 struct sti_cfg *cc = &scr->scr_cfg;
504 struct sti_inqconfout cfg;
505 struct sti_einqconfout ecfg;
506 #ifdef STIDEBUG
507 char buf[256];
508 #endif
509 int error, i;
510 int geometry_kluge = 0;
511 u_int fontindex = 0;
512
513 KASSERT(scr != NULL);
514 memset(cc, 0, sizeof(*cc));
515 cc->ext_cfg = &scr->scr_ecfg;
516 memset(cc->ext_cfg, 0, sizeof(*cc->ext_cfg));
517
518 if (dd->dd_stimemreq) {
519 scr->scr_ecfg.addr =
520 malloc(dd->dd_stimemreq, M_DEVBUF, M_WAITOK);
521 }
522
523 sti_region_setup(scr);
524
525 if ((error = sti_init(scr, 0))) {
526 aprint_error(": cannot initialize (%d)\n", error);
527 goto fail;
528 }
529
530 memset(&cfg, 0, sizeof(cfg));
531 memset(&ecfg, 0, sizeof(ecfg));
532 cfg.ext = &ecfg;
533 if ((error = sti_inqcfg(scr, &cfg))) {
534 aprint_error(": error %d inquiring config\n", error);
535 goto fail;
536 }
537
538 /*
539 * Older (rev 8.02) boards report wrong offset values,
540 * similar to the displayable area size, at least in m68k mode.
541 * Attempt to detect this and adjust here.
542 */
543 if (cfg.owidth == cfg.width &&
544 cfg.oheight == cfg.height)
545 geometry_kluge = 1;
546
547 if (geometry_kluge) {
548 scr->scr_cfg.oscr_width = cfg.owidth =
549 cfg.fbwidth - cfg.width;
550 scr->scr_cfg.oscr_height = cfg.oheight =
551 cfg.fbheight - cfg.height;
552 }
553
554 /*
555 * Save a few fields for sti_describe_screen() later
556 */
557 scr->fbheight = cfg.fbheight;
558 scr->fbwidth = cfg.fbwidth;
559 scr->oheight = cfg.oheight;
560 scr->owidth = cfg.owidth;
561 memcpy(scr->name, cfg.name, sizeof(scr->name));
562
563 if (flags & STI_FBMODE) {
564 /* we're done here */
565 sti_init(scr, STI_FBMODE);
566 return 0;
567 }
568
569 if ((error = sti_init(scr, STI_TEXTMODE | flags))) {
570 aprint_error(": cannot initialize (%d)\n", error);
571 goto fail;
572 }
573 #ifdef STIDEBUG
574 snprintb(buf, sizeof(buf), STI_INQCONF_BITS, cfg.attributes);
575 DPRINTF(("conf: bpp=%d planes=%d attr=%s\n"
576 "crt=0x%x:0x%x:0x%x hw=0x%x:0x%x:0x%x\n", cfg.bpp,
577 cfg.planes, buf,
578 ecfg.crt_config[0], ecfg.crt_config[1], ecfg.crt_config[2],
579 ecfg.crt_hw[0], ecfg.crt_hw[1], ecfg.crt_hw[2]));
580 #endif
581 scr->scr_bpp = cfg.bppu;
582
583 /*
584 * Although scr->scr_ecfg.current_monitor is not filled by
585 * sti_init() as expected, we can nevertheless walk the monitor
586 * list, if there is any, and if we find a mode matching our
587 * resolution, pick its font index.
588 */
589 if (dd->dd_montbl != 0) {
590 STI_ENABLE_ROM(rom->rom_softc);
591
592 for (i = 0; i < dd->dd_nmon; i++) {
593 u_int offs = dd->dd_montbl + 8 * i;
594 uint32_t m[2];
595 sti_mon_t mon = (void *)m;
596 if (rom->rom_devtype == STI_DEVTYPE1) {
597 m[0] = parseword(4 * offs);
598 m[1] = parseword(4 * (offs + 4));
599 } else {
600 bus_space_read_region_stream_4(memt, romh, offs,
601 (uint32_t *)mon, sizeof(*mon) / 4);
602 }
603
604 if (mon->width == scr->scr_cfg.scr_width &&
605 mon->height == scr->scr_cfg.scr_height) {
606 fontindex = mon->font;
607 break;
608 }
609 }
610
611 STI_DISABLE_ROM(rom->rom_softc);
612
613 DPRINTF(("font index: %d\n", fontindex));
614 }
615
616 if ((error = sti_fetchfonts(scr, &cfg, dd->dd_fntaddr, fontindex))) {
617 aprint_error(": cannot fetch fonts (%d)\n", error);
618 goto fail;
619 }
620
621 /*
622 * setup screen descriptions:
623 * figure number of fonts supported;
624 * allocate wscons structures;
625 * calculate dimensions.
626 */
627
628 scr->scr_wsd.name = "std";
629 scr->scr_wsd.ncols = cfg.width / scr->scr_curfont.width;
630 scr->scr_wsd.nrows = cfg.height / scr->scr_curfont.height;
631 scr->scr_wsd.textops = &sti_emulops;
632 scr->scr_wsd.fontwidth = scr->scr_curfont.width;
633 scr->scr_wsd.fontheight = scr->scr_curfont.height;
634 scr->scr_wsd.capabilities = WSSCREEN_REVERSE;
635
636 scr->scr_scrlist[0] = &scr->scr_wsd;
637 scr->scr_screenlist.nscreens = 1;
638 scr->scr_screenlist.screens = scr->scr_scrlist;
639
640 #ifndef SMALL_KERNEL
641 /*
642 * Decide which board-specific routines to use.
643 */
644
645 switch (dd->dd_grid[0]) {
646 case STI_DD_CRX:
647 scr->setupfb = ngle_elk_setupfb;
648 scr->putcmap = ngle_putcmap;
649
650 scr->reg10_value = 0x13601000;
651 if (scr->scr_bpp > 8)
652 scr->reg12_value = NGLE_BUFF1_CMAP3;
653 else
654 scr->reg12_value = NGLE_BUFF1_CMAP0;
655 scr->cmap_finish_register = NGLE_REG_1;
656 break;
657
658 case STI_DD_TIMBER:
659 scr->setupfb = ngle_timber_setupfb;
660 scr->putcmap = ngle_putcmap;
661
662 scr->reg10_value = 0x13602000;
663 scr->reg12_value = NGLE_BUFF1_CMAP0;
664 scr->cmap_finish_register = NGLE_REG_1;
665 break;
666
667 case STI_DD_ARTIST:
668 scr->setupfb = ngle_artist_setupfb;
669 scr->putcmap = ngle_putcmap;
670
671 scr->reg10_value = 0x13601000;
672 scr->reg12_value = NGLE_ARTIST_CMAP0;
673 scr->cmap_finish_register = NGLE_REG_26;
674 break;
675
676 case STI_DD_EG:
677 scr->setupfb = ngle_artist_setupfb;
678 scr->putcmap = ngle_putcmap;
679
680 scr->reg10_value = 0x13601000;
681 if (scr->scr_bpp > 8) {
682 scr->reg12_value = NGLE_BUFF1_CMAP3;
683 scr->cmap_finish_register = NGLE_REG_1;
684 } else {
685 scr->reg12_value = NGLE_ARTIST_CMAP0;
686 scr->cmap_finish_register = NGLE_REG_26;
687 }
688 break;
689
690 case STI_DD_HCRX:
691 scr->setupfb = ngle_elk_setupfb;
692 scr->putcmap = ngle_hcrx_putcmap;
693
694 if (scr->scr_bpp > 8) {
695 scr->reg12_value = NGLE_BUFF1_CMAP3;
696 scr->reg10_value = 0xBBA0A000;
697 } else {
698 scr->reg12_value = NGLE_BUFF1_CMAP0;
699 scr->reg10_value = 0x13602000;
700 }
701 scr->cmap_finish_register = NGLE_REG_38;
702 break;
703
704 case STI_DD_SUMMIT:
705 case STI_DD_LEGO:
706 scr->setupfb = summit_setupfb;
707 scr->putcmap = summit_putcmap;
708 scr->scr_bpp = 8; /* for now */
709 break;
710
711 case STI_DD_EVRX:
712 case STI_DD_382C:
713 case STI_DD_3X2V:
714 /*
715 * EVRX, 382C, and 3X2V are available only on hp300 models
716 * and board specific routines are handled by MD
717 * sti_machdep_attach() in arch/hp300/dev/sti_machdep.c.
718 */
719 break;
720
721 case STI_DD_GRX:
722 case STI_DD_CRX24:
723 case STI_DD_DUAL_CRX:
724 case STI_DD_PINNACLE:
725 default:
726 scr->setupfb = NULL;
727 scr->putcmap =
728 rom->scment == NULL ? NULL : ngle_default_putcmap;
729 break;
730 }
731 #endif
732
733 return 0;
734
735 fail:
736 /* XXX free resources */
737 if (scr->scr_ecfg.addr != NULL) {
738 free(scr->scr_ecfg.addr, M_DEVBUF);
739 scr->scr_ecfg.addr = NULL;
740 }
741
742 return ENXIO;
743 }
744
745 void
746 sti_describe_screen(struct sti_softc *sc, struct sti_screen *scr)
747 {
748 struct sti_font *fp = &scr->scr_curfont;
749
750 aprint_normal("%s: %s, %dx%d frame buffer, %dx%dx%d display\n",
751 device_xname(sc->sc_dev), scr->name, scr->fbwidth, scr->fbheight,
752 scr->scr_cfg.scr_width, scr->scr_cfg.scr_height, scr->scr_bpp);
753
754 aprint_normal("%s: %dx%d font type %d, %d bpc, charset %d-%d\n",
755 device_xname(sc->sc_dev), fp->width, fp->height,
756 fp->type, fp->bpc, fp->first, fp->last);
757 }
758
759 void
760 sti_describe(struct sti_softc *sc)
761 {
762 struct sti_rom *rom = sc->sc_rom;
763 struct sti_dd *dd = &rom->rom_dd;
764
765 aprint_normal(": rev %d.%02d;%d, ID 0x%08X%08X\n",
766 dd->dd_grrev >> 4, dd->dd_grrev & 0xf,
767 dd->dd_lrrev, dd->dd_grid[0], dd->dd_grid[1]);
768
769 if (sc->sc_scr != NULL)
770 sti_describe_screen(sc, sc->sc_scr);
771 }
772
773 /*
774 * Final part of attachment. On hppa where we use the PDC console
775 * during autoconf, this has to be postponed until autoconf has
776 * completed.
777 */
778 void
779 sti_end_attach(struct sti_softc *sc)
780 {
781 struct sti_screen *scr = sc->sc_scr;
782
783 if (scr == NULL)
784 return;
785 #if NWSDISPLAY > 0
786 else {
787 struct wsemuldisplaydev_attach_args waa;
788 scr->scr_wsmode = WSDISPLAYIO_MODE_EMUL;
789
790 waa.console = sc->sc_flags & STI_CONSOLE ? 1 : 0;
791 waa.scrdata = &scr->scr_screenlist;
792 waa.accessops = &sti_accessops;
793 waa.accesscookie = scr;
794
795 /* attach as console if required */
796 if (waa.console && !ISSET(sc->sc_flags, STI_ATTACHED)) {
797 long defattr;
798
799 sti_alloc_attr(scr, 0, 0, 0, &defattr);
800 wsdisplay_cnattach(&scr->scr_wsd, scr,
801 0, scr->scr_wsd.nrows - 1, defattr);
802 sc->sc_flags |= STI_ATTACHED;
803 }
804
805 config_found(sc->sc_dev, &waa, wsemuldisplaydevprint,
806 CFARGS_NONE);
807 }
808 #endif
809 }
810
811 u_int
812 sti_rom_size(bus_space_tag_t memt, bus_space_handle_t romh)
813 {
814 int devtype;
815 u_int romend;
816
817 devtype = bus_space_read_1(memt, romh, 3);
818 if (devtype == STI_DEVTYPE4) {
819 bus_space_read_region_stream_4(memt, romh, STI_DEV4_DD_ROMEND,
820 (uint32_t *)&romend, 1);
821 } else {
822 romend = parseword(STI_DEV1_DD_ROMEND);
823 }
824
825 DPRINTF(("%s: %08x (%08x)\n", __func__, romend, round_page(romend)));
826
827 return round_page(romend);
828 }
829
830 int
831 sti_fetchfonts(struct sti_screen *scr, struct sti_inqconfout *cfg,
832 uint32_t baseaddr, u_int fontindex)
833 {
834 struct sti_rom *rom = scr->scr_rom;
835 bus_space_tag_t memt = rom->memt;
836 bus_space_handle_t romh = rom->romh;
837 struct sti_font *fp = &scr->scr_curfont;
838 uint32_t addr;
839 int size;
840 #ifdef notyet
841 int uc;
842 struct {
843 struct sti_unpmvflags flags;
844 struct sti_unpmvin in;
845 struct sti_unpmvout out;
846 } a;
847 #endif
848
849 /*
850 * Get the first PROM font in memory
851 */
852
853 STI_ENABLE_ROM(rom->rom_softc);
854
855 rescan:
856 addr = baseaddr;
857 do {
858 if (rom->rom_devtype == STI_DEVTYPE1) {
859 fp->first = parseshort(addr + 0x00);
860 fp->last = parseshort(addr + 0x08);
861 fp->width = bus_space_read_1(memt, romh, addr + 0x13);
862 fp->height = bus_space_read_1(memt, romh, addr + 0x17);
863 fp->type = bus_space_read_1(memt, romh, addr + 0x1b);
864 fp->bpc = bus_space_read_1(memt, romh, addr + 0x1f);
865 fp->next = parseword(addr + 0x20);
866 fp->uheight= bus_space_read_1(memt, romh, addr + 0x33);
867 fp->uoffset= bus_space_read_1(memt, romh, addr + 0x37);
868 } else { /* STI_DEVTYPE4 */
869 bus_space_read_region_stream_4(memt, romh, addr,
870 (uint32_t *)fp, sizeof(struct sti_font) / 4);
871 }
872
873 #ifdef STIDEBUG
874 STI_DISABLE_ROM(rom->rom_softc);
875 DPRINTF(("%s: %dx%d font type %d, %d bpc, charset %d-%d\n",
876 device_xname(scr->scr_rom->rom_softc->sc_dev), fp->width,
877 fp->height, fp->type, fp->bpc, fp->first, fp->last));
878 STI_ENABLE_ROM(rom->rom_softc);
879 #endif
880
881 if (fontindex == 0) {
882 size = sizeof(struct sti_font) +
883 (fp->last - fp->first + 1) * fp->bpc;
884 if (rom->rom_devtype == STI_DEVTYPE1)
885 size *= 4;
886 scr->scr_romfont = malloc(size, M_DEVBUF, M_WAITOK);
887
888 bus_space_read_region_stream_4(memt, romh, addr,
889 (uint32_t *)scr->scr_romfont, size / 4);
890 break;
891 }
892
893 addr = baseaddr + fp->next;
894 fontindex--;
895 } while (fp->next != 0);
896
897 /*
898 * If our font index was bogus, we did not find the expected font.
899 * In this case, pick the first one and be done with it.
900 */
901 if (fp->next == 0 && scr->scr_romfont == NULL) {
902 fontindex = 0;
903 goto rescan;
904 }
905
906 STI_DISABLE_ROM(rom->rom_softc);
907
908 #ifdef notyet
909 /*
910 * If there is enough room in the off-screen framebuffer memory,
911 * display all the characters there in order to display them
912 * faster with blkmv operations rather than unpmv later on.
913 */
914 if (size <= cfg->fbheight *
915 (cfg->fbwidth - cfg->width - cfg->owidth)) {
916 memset(&a, 0, sizeof(a));
917 a.flags.flags = STI_UNPMVF_WAIT;
918 a.in.fg_colour = STI_COLOUR_WHITE;
919 a.in.bg_colour = STI_COLOUR_BLACK;
920 a.in.font_addr = scr->scr_romfont;
921
922 scr->scr_fontmaxcol = cfg->fbheight / fp->height;
923 scr->scr_fontbase = cfg->width + cfg->owidth;
924 for (uc = fp->first; uc <= fp->last; uc++) {
925 a.in.x = ((uc - fp->first) / scr->scr_fontmaxcol) *
926 fp->width + scr->scr_fontbase;
927 a.in.y = ((uc - fp->first) % scr->scr_fontmaxcol) *
928 fp->height;
929 a.in.index = uc;
930
931 (*scr->unpmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
932 if (a.out.errno) {
933 aprint_error_dev(sc->sc_dev, "unpmv %d "
934 "returned %d\n", uc, a.out.errno);
935 return 0;
936 }
937 }
938
939 free(scr->scr_romfont, M_DEVBUF);
940 scr->scr_romfont = NULL;
941 }
942 #endif
943
944 return 0;
945 }
946
947 /*
948 * Wrappers around STI code pointers
949 */
950
951 int
952 sti_init(struct sti_screen *scr, int mode)
953 {
954 struct sti_rom *rom = scr->scr_rom;
955 struct {
956 struct sti_initflags flags;
957 struct sti_initin in;
958 struct sti_einitin ein;
959 struct sti_initout out;
960 } a;
961
962 KASSERT(rom != NULL);
963 memset(&a, 0, sizeof(a));
964
965 a.flags.flags = STI_INITF_WAIT | STI_INITF_PBET | STI_INITF_PBETI;
966 if ((mode & STI_TEXTMODE) != 0) {
967 a.flags.flags |= STI_INITF_TEXT | STI_INITF_CMB |
968 STI_INITF_PBET | STI_INITF_PBETI | STI_INITF_ICMT;
969 a.in.text_planes = 1;
970 } else {
971 a.flags.flags |= STI_INITF_TEXT | STI_INITF_NTEXT;
972 /*
973 * Request as many text planes as STI will allow.
974 * The reason to do this - when switching to framebuffer mode
975 * for X we need access to all planes. In theory STI should do
976 * just that when we request access to both text and non-text
977 * planes as above.
978 * In reality though, at least on my PCI Visualize EG, some
979 * planes and/or colour registers remain inaccessible if we
980 * request only one text plane.
981 * Clearly we're missing a register write or two here, but so
982 * far I haven't found it.
983 */
984 a.in.text_planes = 3;
985 }
986 if ((mode & STI_CLEARSCR) != 0)
987 a.flags.flags |= STI_INITF_CLEAR;
988
989 a.in.ext_in = &a.ein;
990
991 DPRINTF(("%s: init,%p(%x, %p, %p, %p)\n",
992 device_xname(rom->rom_softc->sc_dev), rom->init, a.flags.flags,
993 &a.in, &a.out, &scr->scr_cfg));
994
995 (*rom->init)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
996
997 if (a.out.text_planes != a.in.text_planes)
998 return -1; /* not colliding with sti errno values */
999 return a.out.errno;
1000 }
1001
1002 int
1003 sti_inqcfg(struct sti_screen *scr, struct sti_inqconfout *out)
1004 {
1005 struct sti_rom *rom = scr->scr_rom;
1006 struct {
1007 struct sti_inqconfflags flags;
1008 struct sti_inqconfin in;
1009 } a;
1010
1011 memset(&a, 0, sizeof(a));
1012
1013 a.flags.flags = STI_INQCONFF_WAIT;
1014 (*rom->inqconf)(&a.flags, &a.in, out, &scr->scr_cfg);
1015
1016 return out->errno;
1017 }
1018
1019 void
1020 sti_bmove(struct sti_screen *scr, int x1, int y1, int x2, int y2, int h, int w,
1021 enum sti_bmove_funcs f)
1022 {
1023 struct sti_rom *rom = scr->scr_rom;
1024 struct {
1025 struct sti_blkmvflags flags;
1026 struct sti_blkmvin in;
1027 struct sti_blkmvout out;
1028 } a;
1029
1030 memset(&a, 0, sizeof(a));
1031
1032 a.flags.flags = STI_BLKMVF_WAIT;
1033 switch (f) {
1034 case bmf_clear:
1035 a.flags.flags |= STI_BLKMVF_CLR;
1036 a.in.bg_colour = STI_COLOUR_BLACK;
1037 break;
1038 case bmf_underline:
1039 case bmf_copy:
1040 a.in.fg_colour = STI_COLOUR_WHITE;
1041 a.in.bg_colour = STI_COLOUR_BLACK;
1042 break;
1043 case bmf_invert:
1044 a.flags.flags |= STI_BLKMVF_COLR;
1045 a.in.fg_colour = STI_COLOUR_BLACK;
1046 a.in.bg_colour = STI_COLOUR_WHITE;
1047 break;
1048 }
1049 a.in.srcx = x1;
1050 a.in.srcy = y1;
1051 a.in.dstx = x2;
1052 a.in.dsty = y2;
1053 a.in.height = h;
1054 a.in.width = w;
1055
1056 (*rom->blkmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
1057 #ifdef STIDEBUG
1058 if (a.out.errno)
1059 printf("%s: blkmv returned %d\n",
1060 device_xname(rom->rom_softc->sc_dev), a.out.errno);
1061 #endif
1062 }
1063
1064 int
1065 sti_setcment(struct sti_screen *scr, u_int i, u_char r, u_char g, u_char b)
1066 {
1067 struct sti_rom *rom = scr->scr_rom;
1068 struct {
1069 struct sti_scmentflags flags;
1070 struct sti_scmentin in;
1071 struct sti_scmentout out;
1072 } a;
1073
1074 memset(&a, 0, sizeof(a));
1075
1076 a.flags.flags = STI_SCMENTF_WAIT;
1077 a.in.entry = i;
1078 a.in.value = (r << 16) | (g << 8) | b;
1079
1080 (*rom->scment)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
1081
1082 return a.out.errno;
1083 }
1084
1085 /*
1086 * wsdisplay accessops
1087 */
1088 int
1089 sti_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l)
1090 {
1091 struct sti_screen *scr = (struct sti_screen *)v;
1092 struct sti_rom *rom = scr->scr_rom;
1093 struct wsdisplay_fbinfo *wdf;
1094 struct wsdisplay_cmap *cmapp;
1095 u_int mode, idx, count;
1096 int ret;
1097
1098 ret = 0;
1099 switch (cmd) {
1100 case GCID:
1101 *(u_int *)data = rom->rom_dd.dd_grid[0];
1102 break;
1103
1104 case WSDISPLAYIO_GMODE:
1105 *(u_int *)data = scr->scr_wsmode;
1106 break;
1107
1108 case WSDISPLAYIO_SMODE:
1109 mode = *(u_int *)data;
1110 switch (mode) {
1111 case WSDISPLAYIO_MODE_EMUL:
1112 if (scr->scr_wsmode != WSDISPLAYIO_MODE_EMUL)
1113 ret = sti_init(scr, STI_TEXTMODE);
1114 break;
1115 case WSDISPLAYIO_MODE_DUMBFB:
1116 if (scr->scr_wsmode != WSDISPLAYIO_MODE_DUMBFB) {
1117 ret = sti_init(scr, 0);
1118 if (scr->setupfb != NULL)
1119 scr->setupfb(scr);
1120 else
1121 #if 0
1122 ret = sti_init(scr, STI_FBMODE);
1123 #else
1124 ret = EINVAL;
1125 #endif
1126 }
1127 break;
1128 case WSDISPLAYIO_MODE_MAPPED:
1129 default:
1130 ret = EINVAL;
1131 break;
1132 }
1133 if (ret == 0)
1134 scr->scr_wsmode = mode;
1135 break;
1136
1137 case WSDISPLAYIO_GTYPE:
1138 *(u_int *)data = WSDISPLAY_TYPE_STI;
1139 break;
1140
1141 case WSDISPLAYIO_GINFO:
1142 wdf = (struct wsdisplay_fbinfo *)data;
1143 wdf->height = scr->scr_cfg.scr_height;
1144 wdf->width = scr->scr_cfg.scr_width;
1145 wdf->depth = scr->scr_bpp;
1146 if (scr->putcmap == NULL || scr->scr_bpp > 8)
1147 wdf->cmsize = 0;
1148 else
1149 wdf->cmsize = STI_NCMAP;
1150 break;
1151
1152 case WSDISPLAYIO_LINEBYTES:
1153 if (scr->scr_bpp > 8)
1154 *(u_int *)data = scr->scr_cfg.fb_width * 4;
1155 else
1156 *(u_int *)data = scr->scr_cfg.fb_width;
1157 break;
1158
1159 case WSDISPLAYIO_GETCMAP:
1160 if (scr->putcmap == NULL || scr->scr_bpp > 8)
1161 return ENODEV;
1162 cmapp = (struct wsdisplay_cmap *)data;
1163 idx = cmapp->index;
1164 count = cmapp->count;
1165 if (idx >= STI_NCMAP || count > STI_NCMAP - idx)
1166 return EINVAL;
1167 if ((ret = copyout(&scr->scr_rcmap[idx], cmapp->red, count)))
1168 break;
1169 if ((ret = copyout(&scr->scr_gcmap[idx], cmapp->green, count)))
1170 break;
1171 if ((ret = copyout(&scr->scr_bcmap[idx], cmapp->blue, count)))
1172 break;
1173 break;
1174
1175 case WSDISPLAYIO_PUTCMAP:
1176 if (scr->putcmap == NULL || scr->scr_bpp > 8)
1177 return ENODEV;
1178 if (scr->scr_wsmode == WSDISPLAYIO_MODE_EMUL) {
1179 /*
1180 * The hardware palette settings are handled by
1181 * the STI ROM in STI_TEXTMODE and changing cmap
1182 * could cause mangled text colors at least on CRX.
1183 * Updating CMAP in EMUL mode isn't expected anyway
1184 * so just ignore it.
1185 */
1186 return 0;
1187 }
1188 cmapp = (struct wsdisplay_cmap *)data;
1189 idx = cmapp->index;
1190 count = cmapp->count;
1191 if (idx >= STI_NCMAP || count > STI_NCMAP - idx)
1192 return EINVAL;
1193 if ((ret = copyin(cmapp->red, &scr->scr_rcmap[idx], count)))
1194 break;
1195 if ((ret = copyin(cmapp->green, &scr->scr_gcmap[idx], count)))
1196 break;
1197 if ((ret = copyin(cmapp->blue, &scr->scr_bcmap[idx], count)))
1198 break;
1199 ret = scr->putcmap(scr, idx, count);
1200 break;
1201
1202 case WSDISPLAYIO_SVIDEO:
1203 case WSDISPLAYIO_GVIDEO:
1204 case WSDISPLAYIO_GCURPOS:
1205 case WSDISPLAYIO_SCURPOS:
1206 case WSDISPLAYIO_GCURMAX:
1207 case WSDISPLAYIO_GCURSOR:
1208 case WSDISPLAYIO_SCURSOR:
1209 default:
1210 return ENOTTY; /* not supported yet */
1211 }
1212
1213 return ret;
1214 }
1215
1216 paddr_t
1217 sti_mmap(void *v, void *vs, off_t offset, int prot)
1218 {
1219 struct sti_screen *scr = (struct sti_screen *)v;
1220 struct sti_rom *rom = scr->scr_rom;
1221 paddr_t pa;
1222
1223 if ((offset & PAGE_MASK) != 0)
1224 return -1;
1225
1226 if (offset < 0 || offset >= scr->fblen)
1227 return -1;
1228
1229 if (scr->scr_wsmode != WSDISPLAYIO_MODE_DUMBFB)
1230 return -1;
1231
1232 pa = bus_space_mmap(rom->memt, scr->fbaddr, offset, prot,
1233 BUS_SPACE_MAP_LINEAR);
1234
1235 if (pa == -1)
1236 pa = scr->fbaddr + offset;
1237
1238 return pa;
1239 }
1240
1241 int
1242 sti_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
1243 int *cxp, int *cyp, long *defattr)
1244 {
1245 struct sti_screen *scr = (struct sti_screen *)v;
1246
1247 if (scr->scr_nscreens > 0)
1248 return ENOMEM;
1249
1250 *cookiep = scr;
1251 *cxp = 0;
1252 *cyp = 0;
1253 sti_alloc_attr(scr, 0, 0, 0, defattr);
1254 scr->scr_nscreens++;
1255 return 0;
1256 }
1257
1258 void
1259 sti_free_screen(void *v, void *cookie)
1260 {
1261 struct sti_screen *scr = (struct sti_screen *)v;
1262
1263 scr->scr_nscreens--;
1264 }
1265
1266 int
1267 sti_show_screen(void *v, void *cookie, int waitok, void (*cb)(void *, int, int),
1268 void *cbarg)
1269 {
1270 #if 0
1271 struct sti_screen *scr = (struct sti_screen *)v;
1272 #endif
1273
1274 return 0;
1275 }
1276
1277 int
1278 sti_load_font(void *v, void *cookie, struct wsdisplay_font *font)
1279 {
1280 #if 0
1281 struct sti_screen *scr = (struct sti_screen *)v;
1282 #endif
1283
1284 return -1;
1285 }
1286
1287 /*
1288 * wsdisplay emulops
1289 */
1290 void
1291 sti_cursor(void *v, int on, int row, int col)
1292 {
1293 struct sti_screen *scr = (struct sti_screen *)v;
1294 struct sti_font *fp = &scr->scr_curfont;
1295
1296 sti_bmove(scr,
1297 col * fp->width, row * fp->height,
1298 col * fp->width, row * fp->height,
1299 fp->height, fp->width, bmf_invert);
1300 }
1301
1302 /*
1303 * ISO 8859-1 part of Unicode to HP Roman font index conversion array.
1304 */
1305 const uint8_t
1306 sti_unitoroman[0x100 - 0xa0] = {
1307 0xa0, 0xb8, 0xbf, 0xbb, 0xba, 0xbc, 0, 0xbd,
1308 0xab, 0, 0xf9, 0xfb, 0, 0xf6, 0, 0xb0,
1309
1310 0xb3, 0xfe, 0, 0, 0xa8, 0xf3, 0xf4, 0xf2,
1311 0, 0, 0xfa, 0xfd, 0xf7, 0xf8, 0, 0xb9,
1312
1313 0xa1, 0xe0, 0xa2, 0xe1, 0xd8, 0xd0, 0xd3, 0xb4,
1314 0xa3, 0xdc, 0xa4, 0xa5, 0xe6, 0xe5, 0xa6, 0xa7,
1315
1316 0xe3, 0xb6, 0xe8, 0xe7, 0xdf, 0xe9, 0xda, 0,
1317 0xd2, 0xad, 0xed, 0xae, 0xdb, 0xb1, 0xf0, 0xde,
1318
1319 0xc8, 0xc4, 0xc0, 0xe2, 0xcc, 0xd4, 0xd7, 0xb5,
1320 0xc9, 0xc5, 0xc1, 0xcd, 0xd9, 0xd5, 0xd1, 0xdd,
1321
1322 0xe4, 0xb7, 0xca, 0xc6, 0xc2, 0xea, 0xce, 0,
1323 0xd6, 0xcb, 0xc7, 0xc3, 0xcf, 0xb2, 0xf1, 0xef
1324 };
1325
1326 int
1327 sti_mapchar(void *v, int uni, u_int *index)
1328 {
1329 struct sti_screen *scr = (struct sti_screen *)v;
1330 struct sti_font *fp = &scr->scr_curfont;
1331 int c;
1332
1333 switch (fp->type) {
1334 case STI_FONT_HPROMAN8:
1335 if (uni >= 0x80 && uni < 0xa0)
1336 c = -1;
1337 else if (uni >= 0xa0 && uni < 0x100) {
1338 c = (int)sti_unitoroman[uni - 0xa0];
1339 if (c == 0)
1340 c = -1;
1341 } else
1342 c = uni;
1343 break;
1344 default:
1345 c = uni;
1346 break;
1347 }
1348
1349 if (c == -1 || c < fp->first || c > fp->last) {
1350 *index = ' ';
1351 return 0;
1352 }
1353
1354 *index = c;
1355 return 5;
1356 }
1357
1358 void
1359 sti_putchar(void *v, int row, int col, u_int uc, long attr)
1360 {
1361 struct sti_screen *scr = (struct sti_screen *)v;
1362 struct sti_rom *rom = scr->scr_rom;
1363 struct sti_font *fp = &scr->scr_curfont;
1364 int bg, fg;
1365
1366 fg = WSATTR_UNPACK_FG(attr);
1367 bg = WSATTR_UNPACK_BG(attr);
1368
1369 if (scr->scr_romfont != NULL) {
1370 /*
1371 * Font is in memory, use unpmv
1372 */
1373 struct {
1374 struct sti_unpmvflags flags;
1375 struct sti_unpmvin in;
1376 struct sti_unpmvout out;
1377 } a;
1378
1379 memset(&a, 0, sizeof(a));
1380
1381 a.flags.flags = STI_UNPMVF_WAIT;
1382 a.in.fg_colour = fg;
1383 a.in.bg_colour = bg;
1384 a.in.x = col * fp->width;
1385 a.in.y = row * fp->height;
1386 a.in.font_addr = scr->scr_romfont;
1387 a.in.index = uc;
1388
1389 (*rom->unpmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
1390 } else {
1391 /*
1392 * Font is in frame buffer, use blkmv
1393 */
1394 struct {
1395 struct sti_blkmvflags flags;
1396 struct sti_blkmvin in;
1397 struct sti_blkmvout out;
1398 } a;
1399
1400 memset(&a, 0, sizeof(a));
1401
1402 a.flags.flags = STI_BLKMVF_WAIT;
1403 a.in.fg_colour = fg;
1404 a.in.bg_colour = bg;
1405
1406 a.in.srcx = ((uc - fp->first) / scr->scr_fontmaxcol) *
1407 fp->width + scr->scr_fontbase;
1408 a.in.srcy = ((uc - fp->first) % scr->scr_fontmaxcol) *
1409 fp->height;
1410 a.in.dstx = col * fp->width;
1411 a.in.dsty = row * fp->height;
1412 a.in.height = fp->height;
1413 a.in.width = fp->width;
1414
1415 (*rom->blkmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
1416 }
1417 }
1418
1419 void
1420 sti_copycols(void *v, int row, int srccol, int dstcol, int ncols)
1421 {
1422 struct sti_screen *scr = (struct sti_screen *)v;
1423 struct sti_font *fp = &scr->scr_curfont;
1424
1425 sti_bmove(scr,
1426 srccol * fp->width, row * fp->height,
1427 dstcol * fp->width, row * fp->height,
1428 fp->height, ncols * fp->width, bmf_copy);
1429 }
1430
1431 void
1432 sti_erasecols(void *v, int row, int startcol, int ncols, long attr)
1433 {
1434 struct sti_screen *scr = (struct sti_screen *)v;
1435 struct sti_font *fp = &scr->scr_curfont;
1436
1437 sti_bmove(scr,
1438 startcol * fp->width, row * fp->height,
1439 startcol * fp->width, row * fp->height,
1440 fp->height, ncols * fp->width, bmf_clear);
1441 }
1442
1443 void
1444 sti_copyrows(void *v, int srcrow, int dstrow, int nrows)
1445 {
1446 struct sti_screen *scr = (struct sti_screen *)v;
1447 struct sti_font *fp = &scr->scr_curfont;
1448
1449 sti_bmove(scr, 0, srcrow * fp->height, 0, dstrow * fp->height,
1450 nrows * fp->height, scr->scr_cfg.scr_width, bmf_copy);
1451 }
1452
1453 void
1454 sti_eraserows(void *v, int srcrow, int nrows, long attr)
1455 {
1456 struct sti_screen *scr = (struct sti_screen *)v;
1457 struct sti_font *fp = &scr->scr_curfont;
1458
1459 sti_bmove(scr, 0, srcrow * fp->height, 0, srcrow * fp->height,
1460 nrows * fp->height, scr->scr_cfg.scr_width, bmf_clear);
1461 }
1462
1463 int
1464 sti_alloc_attr(void *v, int fg, int bg, int flags, long *pattr)
1465 {
1466 #if 0
1467 struct sti_screen *scr = (struct sti_screen *)v;
1468 #endif
1469
1470 if ((flags & (WSATTR_HILIT | WSATTR_BLINK |
1471 WSATTR_UNDERLINE | WSATTR_WSCOLORS)) != 0)
1472 return EINVAL;
1473 if ((flags & WSATTR_REVERSE) != 0) {
1474 fg = STI_COLOUR_BLACK;
1475 bg = STI_COLOUR_WHITE;
1476 } else {
1477 fg = STI_COLOUR_WHITE;
1478 bg = STI_COLOUR_BLACK;
1479 }
1480
1481 *pattr = WSATTR_PACK(fg, bg, flags);
1482 return 0;
1483 }
1484
1485 /*
1486 * Early console support. Only used on hp300, currently
1487 */
1488 int
1489 sti_cnattach(struct sti_rom *rom, struct sti_screen *scr, bus_space_tag_t memt,
1490 bus_addr_t *bases, u_int codebase)
1491 {
1492 bus_space_handle_t romh;
1493 u_int romend;
1494 int error;
1495 long defattr;
1496
1497 if ((error = bus_space_map(memt, bases[0], PAGE_SIZE, 0, &romh)) != 0)
1498 return error;
1499
1500 /*
1501 * Compute real PROM size
1502 */
1503 romend = sti_rom_size(memt, romh);
1504
1505 bus_space_unmap(memt, romh, PAGE_SIZE);
1506
1507 if ((error = bus_space_map(memt, bases[0], romend, 0, &romh)) != 0)
1508 return error;
1509
1510 bases[0] = romh;
1511 if (sti_rom_setup(rom, memt, memt, romh, bases, codebase) != 0)
1512 return -1;
1513 scr->scr_rom = rom;
1514 if (sti_screen_setup(scr, STI_CLEARSCR) != 0)
1515 return -1;
1516
1517 sti_alloc_attr(scr, 0, 0, 0, &defattr);
1518 wsdisplay_cnattach(&scr->scr_wsd, scr, 0, 0, defattr);
1519
1520 return 0;
1521 }
1522
1523 int
1524 ngle_default_putcmap(struct sti_screen *scr, u_int idx, u_int count)
1525 {
1526 int i, ret;
1527
1528 for (i = idx + count - 1; i >= (int)idx; i--)
1529 if ((ret = sti_setcment(scr, i, scr->scr_rcmap[i],
1530 scr->scr_gcmap[i], scr->scr_bcmap[i])))
1531 return EINVAL;
1532
1533 return 0;
1534 }
1535
1536 #ifndef SMALL_KERNEL
1537
1538 void ngle_setup_hw(bus_space_tag_t, bus_space_handle_t);
1539 void ngle_setup_fb(bus_space_tag_t, bus_space_handle_t, uint32_t);
1540 void ngle_setup_attr_planes(struct sti_screen *scr);
1541 void ngle_setup_bt458(struct sti_screen *scr);
1542
1543 #define ngle_bt458_write(memt, memh, r, v) \
1544 bus_space_write_stream_4(memt, memh, NGLE_REG_RAMDAC + ((r) << 2), (v) << 24)
1545
1546 void
1547 ngle_artist_setupfb(struct sti_screen *scr)
1548 {
1549 struct sti_rom *rom = scr->scr_rom;
1550 bus_space_tag_t memt = rom->memt;
1551 bus_space_handle_t memh = rom->regh[2];
1552
1553 ngle_setup_bt458(scr);
1554
1555 ngle_setup_hw(memt, memh);
1556 ngle_setup_fb(memt, memh, scr->reg10_value);
1557
1558 ngle_setup_attr_planes(scr);
1559
1560 ngle_setup_hw(memt, memh);
1561 bus_space_write_stream_4(memt, memh, NGLE_REG_21,
1562 bus_space_read_stream_4(memt, memh, NGLE_REG_21) | 0x0a000000);
1563 bus_space_write_stream_4(memt, memh, NGLE_REG_27,
1564 bus_space_read_stream_4(memt, memh, NGLE_REG_27) | 0x00800000);
1565 }
1566
1567 void
1568 ngle_elk_setupfb(struct sti_screen *scr)
1569 {
1570 struct sti_rom *rom = scr->scr_rom;
1571 bus_space_tag_t memt = rom->memt;
1572 bus_space_handle_t memh = rom->regh[2];
1573
1574 ngle_setup_bt458(scr);
1575
1576 ngle_setup_hw(memt, memh);
1577 ngle_setup_fb(memt, memh, scr->reg10_value);
1578
1579 ngle_setup_attr_planes(scr);
1580
1581 ngle_setup_hw(memt, memh);
1582 /* enable overlay planes in Bt458 command register */
1583 ngle_bt458_write(memt, memh, 0x0c, 0x06);
1584 ngle_bt458_write(memt, memh, 0x0e, 0x43);
1585 }
1586
1587 void
1588 ngle_timber_setupfb(struct sti_screen *scr)
1589 {
1590 struct sti_rom *rom = scr->scr_rom;
1591 bus_space_tag_t memt = rom->memt;
1592 bus_space_handle_t memh = rom->regh[2];
1593
1594 ngle_setup_bt458(scr);
1595
1596 ngle_setup_hw(memt, memh);
1597 /* enable overlay planes in Bt458 command register */
1598 ngle_bt458_write(memt, memh, 0x0c, 0x06);
1599 ngle_bt458_write(memt, memh, 0x0e, 0x43);
1600 }
1601
1602 static void
1603 summit_wait(struct sti_screen *scr)
1604 {
1605 struct sti_rom *rom = scr->scr_rom;
1606 bus_space_tag_t memt = rom->memt;
1607 bus_space_handle_t memh = rom->regh[0];
1608
1609 while (bus_space_read_stream_4(memt, memh, VISFX_STATUS) != 0)
1610 continue;
1611 }
1612
1613 void
1614 summit_setupfb(struct sti_screen *scr)
1615 {
1616 struct sti_rom *rom = scr->scr_rom;
1617 bus_space_tag_t memt = rom->memt;
1618 bus_space_handle_t memh = rom->regh[0];
1619
1620 summit_wait(scr);
1621 bus_space_write_stream_4(memt, memh, 0xb08044, 0x1b);
1622 bus_space_write_stream_4(memt, memh, 0xb08048, 0x1b);
1623 bus_space_write_stream_4(memt, memh, 0x920860, 0xe4);
1624 bus_space_write_stream_4(memt, memh, 0xa00818, 0);
1625 bus_space_write_stream_4(memt, memh, 0xa00404, 0);
1626 bus_space_write_stream_4(memt, memh, 0x921110, 0);
1627 bus_space_write_stream_4(memt, memh, 0x9211d8, 0);
1628 bus_space_write_stream_4(memt, memh, 0xa0086c, 0);
1629 bus_space_write_stream_4(memt, memh, 0x921114, 0);
1630 bus_space_write_stream_4(memt, memh, 0xac1050, 0);
1631
1632 bus_space_write_stream_4(memt, memh, VISFX_APERTURE_ACCESS,
1633 VISFX_DEPTH_8);
1634
1635 bus_space_write_stream_4(memt, memh, VISFX_PIXEL_MASK, 0xffffffff);
1636 bus_space_write_stream_4(memt, memh, VISFX_PLANE_MASK, 0xffffffff);
1637 bus_space_write_stream_4(memt, memh, VISFX_VRAM_WRITE_MODE,
1638 VISFX_WRITE_MODE_PLAIN);
1639 bus_space_write_stream_4(memt, memh, VISFX_VRAM_READ_MODE,
1640 VISFX_READ_MODE_COPY);
1641 }
1642
1643 void
1644 ngle_setup_bt458(struct sti_screen *scr)
1645 {
1646 struct sti_rom *rom = scr->scr_rom;
1647 bus_space_tag_t memt = rom->memt;
1648 bus_space_handle_t memh = rom->regh[2];
1649
1650 ngle_setup_hw(memt, memh);
1651 /* set Bt458 read mask register to all planes */
1652 ngle_bt458_write(memt, memh, 0x08, 0x04);
1653 ngle_bt458_write(memt, memh, 0x0a, 0xff);
1654 }
1655
1656 void
1657 ngle_setup_attr_planes(struct sti_screen *scr)
1658 {
1659 struct sti_rom *rom = scr->scr_rom;
1660 bus_space_tag_t memt = rom->memt;
1661 bus_space_handle_t memh = rom->regh[2];
1662
1663 ngle_setup_hw(memt, memh);
1664 bus_space_write_stream_4(memt, memh, NGLE_REG_11, 0x2ea0d000);
1665 bus_space_write_stream_4(memt, memh, NGLE_REG_14, 0x23000302);
1666 bus_space_write_stream_4(memt, memh, NGLE_REG_12, scr->reg12_value);
1667 bus_space_write_stream_4(memt, memh, NGLE_REG_8, 0xffffffff);
1668
1669 bus_space_write_stream_4(memt, memh, NGLE_REG_6, 0x00000000);
1670 bus_space_write_stream_4(memt, memh, NGLE_REG_9,
1671 (scr->scr_cfg.scr_width << 16) | scr->scr_cfg.scr_height);
1672 bus_space_write_stream_4(memt, memh, NGLE_REG_6, 0x05000000);
1673 bus_space_write_stream_4(memt, memh, NGLE_REG_9, 0x00040001);
1674
1675 ngle_setup_hw(memt, memh);
1676 bus_space_write_stream_4(memt, memh, NGLE_REG_12, 0x00000000);
1677
1678 ngle_setup_fb(memt, memh, scr->reg10_value);
1679 }
1680
1681 int
1682 ngle_putcmap(struct sti_screen *scr, u_int idx, u_int count)
1683 {
1684 struct sti_rom *rom = scr->scr_rom;
1685 bus_space_tag_t memt = rom->memt;
1686 bus_space_handle_t memh = rom->regh[2];
1687 uint8_t *r, *g, *b;
1688 uint32_t cmap_finish;
1689
1690 if (scr->scr_bpp > 8)
1691 cmap_finish = 0x83000100;
1692 else
1693 cmap_finish = 0x80000100;
1694
1695 r = scr->scr_rcmap + idx;
1696 g = scr->scr_gcmap + idx;
1697 b = scr->scr_bcmap + idx;
1698
1699 ngle_setup_hw(memt, memh);
1700 bus_space_write_stream_4(memt, memh, NGLE_REG_10, 0xbbe0f000);
1701 bus_space_write_stream_4(memt, memh, NGLE_REG_14, 0x03000300);
1702 bus_space_write_stream_4(memt, memh, NGLE_REG_13, 0xffffffff);
1703
1704 while (count-- != 0) {
1705 ngle_setup_hw(memt, memh);
1706 bus_space_write_stream_4(memt, memh, NGLE_REG_3,
1707 0x400 | (idx << 2));
1708 bus_space_write_stream_4(memt, memh, NGLE_REG_4,
1709 (*r << 16) | (*g << 8) | *b);
1710
1711 idx++;
1712 r++, g++, b++;
1713 }
1714
1715
1716 bus_space_write_stream_4(memt, memh, NGLE_REG_2, 0x400);
1717 bus_space_write_stream_4(memt, memh, scr->cmap_finish_register,
1718 cmap_finish);
1719 ngle_setup_fb(memt, memh, scr->reg10_value);
1720
1721
1722 return 0;
1723 }
1724
1725 int
1726 ngle_hcrx_putcmap(struct sti_screen *scr, u_int idx, u_int count)
1727 {
1728 struct sti_rom *rom = scr->scr_rom;
1729 bus_space_tag_t memt = rom->memt;
1730 bus_space_handle_t memh = rom->regh[2];
1731 uint8_t *r, *g, *b;
1732 uint32_t cmap_finish;
1733
1734 if (scr->scr_bpp > 8)
1735 cmap_finish = 0x80000100;
1736 else
1737 cmap_finish = 0x82000100;
1738
1739 r = scr->scr_rcmap + idx;
1740 g = scr->scr_gcmap + idx;
1741 b = scr->scr_bcmap + idx;
1742
1743 ngle_setup_hw(memt, memh);
1744 bus_space_write_stream_4(memt, memh, NGLE_REG_10, 0xbbe0f000);
1745 bus_space_write_stream_4(memt, memh, NGLE_REG_14, 0x03000300);
1746 bus_space_write_stream_4(memt, memh, NGLE_REG_13, 0xffffffff);
1747
1748 while (count-- != 0) {
1749 ngle_setup_hw(memt, memh);
1750 bus_space_write_stream_4(memt, memh, NGLE_REG_3,
1751 0x400 | (idx << 2));
1752 bus_space_write_stream_4(memt, memh, NGLE_REG_4,
1753 (*r << 16) | (*g << 8) | *b);
1754
1755 idx++;
1756 r++, g++, b++;
1757 }
1758
1759
1760 bus_space_write_stream_4(memt, memh, NGLE_REG_2, 0x400);
1761 bus_space_write_stream_4(memt, memh, NGLE_REG_38, cmap_finish);
1762 ngle_setup_fb(memt, memh, scr->reg10_value);
1763
1764
1765 return 0;
1766 }
1767
1768 int
1769 summit_putcmap(struct sti_screen *scr, u_int idx, u_int count)
1770 {
1771 struct sti_rom *rom = scr->scr_rom;
1772 bus_space_tag_t memt = rom->memt;
1773 bus_space_handle_t memh = rom->regh[0];
1774 uint8_t *r, *g, *b;
1775
1776 r = scr->scr_rcmap + idx;
1777 g = scr->scr_gcmap + idx;
1778 b = scr->scr_bcmap + idx;
1779
1780 if (rom->rom_dd.dd_grid[0] == STI_DD_LEGO) {
1781 bus_space_write_stream_4(memt, memh, VISFX_COLOR_INDEX, idx);
1782 } else
1783 bus_space_write_stream_4(memt, memh, VISFX_COLOR_INDEX,
1784 0xc0005100 + idx);
1785
1786 while (count-- != 0) {
1787 bus_space_write_stream_4(memt, memh,
1788 VISFX_COLOR_VALUE, (*r << 16) | (*g << 8) | *b);
1789 r++, g++, b++;
1790 }
1791 bus_space_write_stream_4(memt, memh, VISFX_COLOR_MASK, 0xff);
1792 bus_space_write_stream_4(memt, memh, 0x80004c, 0xc);
1793 bus_space_write_stream_4(memt, memh, 0x800000, 0);
1794
1795 return 0;
1796 }
1797
1798 void
1799 ngle_setup_hw(bus_space_tag_t memt, bus_space_handle_t memh)
1800 {
1801 uint8_t stat;
1802
1803 do {
1804 stat = bus_space_read_1(memt, memh, NGLE_REG_15b0);
1805 if (stat == 0)
1806 stat = bus_space_read_1(memt, memh, NGLE_REG_15b0);
1807 } while (stat != 0);
1808 }
1809
1810 void
1811 ngle_setup_fb(bus_space_tag_t memt, bus_space_handle_t memh, uint32_t reg10)
1812 {
1813
1814 ngle_setup_hw(memt, memh);
1815 bus_space_write_stream_4(memt, memh, NGLE_REG_10, reg10);
1816 bus_space_write_stream_4(memt, memh, NGLE_REG_14, 0x83000300);
1817 ngle_setup_hw(memt, memh);
1818 bus_space_write_1(memt, memh, NGLE_REG_16b1, 1);
1819 }
1820 #endif /* SMALL_KERNEL */
1821