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