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