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