Annotation of sys/dev/ic/sti.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: sti.c,v 1.55 2007/06/17 13:59:08 miod 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.
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.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: void sti_cursor(void *v, int on, int row, int col);
57: int sti_mapchar(void *v, int uni, u_int *index);
58: void sti_putchar(void *v, int row, int col, u_int uc, long attr);
59: void sti_copycols(void *v, int row, int srccol, int dstcol, int ncols);
60: void sti_erasecols(void *v, int row, int startcol, int ncols, long attr);
61: void sti_copyrows(void *v, int srcrow, int dstrow, int nrows);
62: void sti_eraserows(void *v, int row, int nrows, long attr);
63: int sti_alloc_attr(void *v, int fg, int bg, int flags, long *pattr);
64: void sti_unpack_attr(void *v, long attr, int *fg, int *bg, int *ul);
65:
66: struct wsdisplay_emulops sti_emulops = {
67: sti_cursor,
68: sti_mapchar,
69: sti_putchar,
70: sti_copycols,
71: sti_erasecols,
72: sti_copyrows,
73: sti_eraserows,
74: sti_alloc_attr,
75: sti_unpack_attr
76: };
77:
78: int sti_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p);
79: paddr_t sti_mmap(void *v, off_t offset, int prot);
80: int sti_alloc_screen(void *v, const struct wsscreen_descr *type,
81: void **cookiep, int *cxp, int *cyp, long *defattr);
82: void sti_free_screen(void *v, void *cookie);
83: int sti_show_screen(void *v, void *cookie, int waitok,
84: void (*cb)(void *, int, int), void *cbarg);
85: int sti_load_font(void *v, void *cookie, struct wsdisplay_font *);
86:
87: const struct wsdisplay_accessops sti_accessops = {
88: sti_ioctl,
89: sti_mmap,
90: sti_alloc_screen,
91: sti_free_screen,
92: sti_show_screen,
93: sti_load_font
94: };
95:
96: enum sti_bmove_funcs {
97: bmf_clear, bmf_copy, bmf_invert, bmf_underline
98: };
99:
100: int sti_init(struct sti_screen *scr, int mode);
101: int sti_inqcfg(struct sti_screen *scr, struct sti_inqconfout *out);
102: void sti_bmove(struct sti_screen *scr, int, int, int, int, int, int,
103: enum sti_bmove_funcs);
104: int sti_setcment(struct sti_screen *scr, u_int i, u_char r, u_char g, u_char b);
105: int sti_fetchfonts(struct sti_screen *scr, struct sti_inqconfout *cfg,
106: u_int32_t addr);
107: int sti_screen_setup(struct sti_screen *scr, bus_space_tag_t iot,
108: bus_space_tag_t memt, bus_space_handle_t romh, bus_addr_t *bases,
109: u_int codebase);
110:
111: #if NSTI_PCI > 0
112: #define STI_ENABLE_ROM(sc) \
113: do { \
114: if ((sc) != NULL && (sc)->sc_enable_rom != NULL) \
115: (*(sc)->sc_enable_rom)(sc); \
116: } while (0)
117: #define STI_DISABLE_ROM(sc) \
118: do { \
119: if ((sc) != NULL && (sc)->sc_disable_rom != NULL) \
120: (*(sc)->sc_disable_rom)(sc); \
121: } while (0)
122: #else
123: #define STI_ENABLE_ROM(sc) do { /* nothing */ } while (0)
124: #define STI_DISABLE_ROM(sc) do { /* nothing */ } while (0)
125: #endif
126:
127: int
128: sti_attach_common(sc, codebase)
129: struct sti_softc *sc;
130: u_int codebase;
131: {
132: struct sti_screen *scr;
133: int rc;
134:
135: scr = malloc(sizeof(struct sti_screen), M_DEVBUF, M_NOWAIT);
136: if (scr == NULL) {
137: printf("cannot allocate screen data\n");
138: return (ENOMEM);
139: }
140:
141: bzero(scr, sizeof(struct sti_screen));
142: sc->sc_scr = scr;
143: scr->scr_main = sc;
144:
145: if ((rc = sti_screen_setup(scr, sc->iot, sc->memt, sc->romh, sc->bases,
146: codebase)) != 0) {
147: free(scr, M_DEVBUF);
148: sc->sc_scr = NULL;
149: return (rc);
150: }
151:
152: sti_describe(sc);
153: return (0);
154: }
155:
156: int
157: sti_screen_setup(struct sti_screen *scr, bus_space_tag_t iot,
158: bus_space_tag_t memt, bus_space_handle_t romh, bus_addr_t *bases,
159: u_int codebase)
160: {
161: struct sti_inqconfout cfg;
162: struct sti_einqconfout ecfg;
163: bus_space_handle_t fbh;
164: struct sti_dd *dd;
165: struct sti_cfg *cc;
166: int error, size, i;
167: int geometry_kluge = 0;
168:
169: STI_ENABLE_ROM(scr->scr_main);
170:
171: scr->iot = iot;
172: scr->memt = memt;
173: scr->romh = romh;
174: scr->bases = bases;
175: scr->scr_devtype = bus_space_read_1(memt, romh, 3);
176:
177: /* { extern int pmapdebug; pmapdebug = 0xfffff; } */
178: dd = &scr->scr_dd;
179: if (scr->scr_devtype == STI_DEVTYPE1) {
180: #define parseshort(o) \
181: ((bus_space_read_1(memt, romh, (o) + 3) << 8) | \
182: (bus_space_read_1(memt, romh, (o) + 7)))
183: #define parseword(o) \
184: ((bus_space_read_1(memt, romh, (o) + 3) << 24) | \
185: (bus_space_read_1(memt, romh, (o) + 7) << 16) | \
186: (bus_space_read_1(memt, romh, (o) + 11) << 8) | \
187: (bus_space_read_1(memt, romh, (o) + 15)))
188:
189: dd->dd_type = bus_space_read_1(memt, romh, 0x03);
190: dd->dd_nmon = bus_space_read_1(memt, romh, 0x07);
191: dd->dd_grrev = bus_space_read_1(memt, romh, 0x0b);
192: dd->dd_lrrev = bus_space_read_1(memt, romh, 0x0f);
193: dd->dd_grid[0] = parseword(0x10);
194: dd->dd_grid[1] = parseword(0x20);
195: dd->dd_fntaddr = parseword(0x30) & ~3;
196: dd->dd_maxst = parseword(0x40);
197: dd->dd_romend = parseword(0x50) & ~3;
198: dd->dd_reglst = parseword(0x60) & ~3;
199: dd->dd_maxreent= parseshort(0x70);
200: dd->dd_maxtimo = parseshort(0x78);
201: dd->dd_montbl = parseword(0x80) & ~3;
202: dd->dd_udaddr = parseword(0x90) & ~3;
203: dd->dd_stimemreq=parseword(0xa0);
204: dd->dd_udsize = parseword(0xb0);
205: dd->dd_pwruse = parseshort(0xc0);
206: dd->dd_bussup = bus_space_read_1(memt, romh, 0xcb);
207: dd->dd_ebussup = bus_space_read_1(memt, romh, 0xcf);
208: dd->dd_altcodet= bus_space_read_1(memt, romh, 0xd3);
209: dd->dd_eddst[0]= bus_space_read_1(memt, romh, 0xd7);
210: dd->dd_eddst[1]= bus_space_read_1(memt, romh, 0xdb);
211: dd->dd_eddst[2]= bus_space_read_1(memt, romh, 0xdf);
212: dd->dd_cfbaddr = parseword(0xe0) & ~3;
213:
214: codebase <<= 2;
215: dd->dd_pacode[0x0] = parseword(codebase + 0x000) & ~3;
216: dd->dd_pacode[0x1] = parseword(codebase + 0x010) & ~3;
217: dd->dd_pacode[0x2] = parseword(codebase + 0x020) & ~3;
218: dd->dd_pacode[0x3] = parseword(codebase + 0x030) & ~3;
219: dd->dd_pacode[0x4] = parseword(codebase + 0x040) & ~3;
220: dd->dd_pacode[0x5] = parseword(codebase + 0x050) & ~3;
221: dd->dd_pacode[0x6] = parseword(codebase + 0x060) & ~3;
222: dd->dd_pacode[0x7] = parseword(codebase + 0x070) & ~3;
223: dd->dd_pacode[0x8] = parseword(codebase + 0x080) & ~3;
224: dd->dd_pacode[0x9] = parseword(codebase + 0x090) & ~3;
225: dd->dd_pacode[0xa] = parseword(codebase + 0x0a0) & ~3;
226: dd->dd_pacode[0xb] = parseword(codebase + 0x0b0) & ~3;
227: dd->dd_pacode[0xc] = parseword(codebase + 0x0c0) & ~3;
228: dd->dd_pacode[0xd] = parseword(codebase + 0x0d0) & ~3;
229: dd->dd_pacode[0xe] = parseword(codebase + 0x0e0) & ~3;
230: dd->dd_pacode[0xf] = parseword(codebase + 0x0f0) & ~3;
231: } else { /* STI_DEVTYPE4 */
232: bus_space_read_raw_region_4(memt, romh, 0, (u_int8_t *)dd,
233: sizeof(*dd));
234: /* fix pacode... */
235: bus_space_read_raw_region_4(memt, romh, codebase,
236: (u_int8_t *)dd->dd_pacode, sizeof(dd->dd_pacode));
237: }
238:
239: STI_DISABLE_ROM(scr->scr_main);
240:
241: #ifdef STIDEBUG
242: printf("dd:\n"
243: "devtype=%x, rev=%x;%d, altt=%x, gid=%016llx, font=%x, mss=%x\n"
244: "end=%x, regions=%x, msto=%x, timo=%d, mont=%x, user=%x[%x]\n"
245: "memrq=%x, pwr=%d, bus=%x, ebus=%x, cfb=%x\n"
246: "code=",
247: dd->dd_type & 0xff, dd->dd_grrev, dd->dd_lrrev, dd->dd_altcodet,
248: *(u_int64_t *)dd->dd_grid, dd->dd_fntaddr, dd->dd_maxst,
249: dd->dd_romend, dd->dd_reglst, dd->dd_maxreent, dd->dd_maxtimo,
250: dd->dd_montbl, dd->dd_udaddr, dd->dd_udsize, dd->dd_stimemreq,
251: dd->dd_pwruse, dd->dd_bussup, dd->dd_ebussup, dd->dd_cfbaddr);
252: printf("%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x\n",
253: dd->dd_pacode[0x0], dd->dd_pacode[0x1], dd->dd_pacode[0x2],
254: dd->dd_pacode[0x3], dd->dd_pacode[0x4], dd->dd_pacode[0x5],
255: dd->dd_pacode[0x6], dd->dd_pacode[0x7], dd->dd_pacode[0x8],
256: dd->dd_pacode[0x9], dd->dd_pacode[0xa], dd->dd_pacode[0xb],
257: dd->dd_pacode[0xc], dd->dd_pacode[0xd], dd->dd_pacode[0xe],
258: dd->dd_pacode[0xf]);
259: #endif
260: /* divise code size, could be less than STI_END entries */
261: for (i = STI_END; !dd->dd_pacode[i]; i--);
262: size = dd->dd_pacode[i] - dd->dd_pacode[STI_BEGIN];
263: if (scr->scr_devtype == STI_DEVTYPE1)
264: size = (size + 3) / 4;
265: if (size == 0) {
266: printf(": no code for the requested platform\n");
267: return (EINVAL);
268: }
269: if (!(scr->scr_code = uvm_km_alloc(kernel_map, round_page(size)))) {
270: printf(": cannot allocate %u bytes for code\n", size);
271: return (ENOMEM);
272: }
273: #ifdef STIDEBUG
274: printf("code=0x%x[%x]\n", scr->scr_code, size);
275: #endif
276:
277: STI_ENABLE_ROM(scr->scr_main);
278:
279: /* copy code into memory */
280: if (scr->scr_devtype == STI_DEVTYPE1) {
281: u_int8_t *p = (u_int8_t *)scr->scr_code;
282: u_int32_t addr, eaddr;
283:
284: for (addr = dd->dd_pacode[STI_BEGIN], eaddr = addr + size * 4;
285: addr < eaddr; addr += 4 )
286: *p++ = bus_space_read_4(memt, romh, addr) & 0xff;
287:
288: } else /* STI_DEVTYPE4 */
289: bus_space_read_raw_region_4(memt, romh,
290: dd->dd_pacode[STI_BEGIN], (u_int8_t *)scr->scr_code,
291: size);
292:
293: STI_DISABLE_ROM(scr->scr_main);
294:
295: #define O(i) (dd->dd_pacode[(i)]? (scr->scr_code + \
296: (dd->dd_pacode[(i)] - dd->dd_pacode[0]) / \
297: (scr->scr_devtype == STI_DEVTYPE1? 4 : 1)) : NULL)
298:
299: scr->init = (sti_init_t) O(STI_INIT_GRAPH);
300: scr->mgmt = (sti_mgmt_t) O(STI_STATE_MGMT);
301: scr->unpmv = (sti_unpmv_t) O(STI_FONT_UNPMV);
302: scr->blkmv = (sti_blkmv_t) O(STI_BLOCK_MOVE);
303: scr->test = (sti_test_t) O(STI_SELF_TEST);
304: scr->exhdl = (sti_exhdl_t) O(STI_EXCEP_HDLR);
305: scr->inqconf = (sti_inqconf_t)O(STI_INQ_CONF);
306: scr->scment = (sti_scment_t)O(STI_SCM_ENT);
307: scr->dmac = (sti_dmac_t) O(STI_DMA_CTRL);
308: scr->flowc = (sti_flowc_t) O(STI_FLOW_CTRL);
309: scr->utiming = (sti_utiming_t)O(STI_UTIMING);
310: scr->pmgr = (sti_pmgr_t) O(STI_PROC_MGR);
311: scr->util = (sti_util_t) O(STI_UTIL);
312:
313: /*
314: * Set colormap entry is not implemented until 8.04, so force
315: * a NULL pointer here.
316: */
317: if (dd->dd_grrev < STI_REVISION(8,4)) {
318: scr->scment = NULL;
319: }
320:
321: if ((error = uvm_map_protect(kernel_map, scr->scr_code,
322: scr->scr_code + round_page(size), UVM_PROT_RX, FALSE))) {
323: printf(": uvm_map_protect failed (%d)\n", error);
324: uvm_km_free(kernel_map, scr->scr_code, round_page(size));
325: return (error);
326: }
327:
328: cc = &scr->scr_cfg;
329: bzero(cc, sizeof (*cc));
330: cc->ext_cfg = &scr->scr_ecfg;
331: bzero(cc->ext_cfg, sizeof(*cc->ext_cfg));
332: if (dd->dd_stimemreq) {
333: scr->scr_ecfg.addr =
334: malloc(dd->dd_stimemreq, M_DEVBUF, M_NOWAIT);
335: if (!scr->scr_ecfg.addr) {
336: printf("cannot allocate %d bytes for STI\n",
337: dd->dd_stimemreq);
338: uvm_km_free(kernel_map, scr->scr_code,
339: round_page(size));
340: return (ENOMEM);
341: }
342: }
343: {
344: int i = dd->dd_reglst;
345: u_int32_t *p;
346: struct sti_region r;
347:
348: #ifdef STIDEBUG
349: printf("stiregions @%p:\n", i);
350: #endif
351:
352: STI_ENABLE_ROM(scr->scr_main);
353:
354: r.last = 0;
355: for (p = cc->regions; !r.last &&
356: p < &cc->regions[STI_REGION_MAX]; p++) {
357:
358: if (scr->scr_devtype == STI_DEVTYPE1)
359: *(u_int *)&r = parseword(i), i+= 16;
360: else {
361: bus_space_read_raw_region_4(memt, romh, i,
362: (u_int8_t *)&r, 4);
363: i += 4;
364: }
365:
366: *p = bases[p - cc->regions] + (r.offset << PGSHIFT);
367: #ifdef STIDEBUG
368: STI_DISABLE_ROM(scr->scr_main);
369: printf("%08x @ 0x%08x%s%s%s%s\n",
370: r.length << PGSHIFT, *p, r.sys_only? " sys" : "",
371: r.cache? " cache" : "", r.btlb? " btlb" : "",
372: r.last? " last" : "");
373: STI_ENABLE_ROM(scr->scr_main);
374: #endif
375:
376: /* skip rom if it has already been mapped */
377: if (p == cc->regions && romh == bases[0])
378: continue;
379:
380: if (bus_space_map(memt, *p, r.length << PGSHIFT,
381: r.cache ? BUS_SPACE_MAP_CACHEABLE : 0, &fbh)) {
382: #ifdef STIDEBUG
383: STI_DISABLE_ROM(scr->scr_main);
384: printf("already mapped region\n");
385: STI_ENABLE_ROM(scr->scr_main);
386: #endif
387: } else {
388: if (p - cc->regions == 1) {
389: scr->fbaddr = *p;
390: scr->fblen = r.length << PGSHIFT;
391: }
392: *p = fbh;
393: }
394: }
395:
396: STI_DISABLE_ROM(scr->scr_main);
397: }
398:
399: if ((error = sti_init(scr, 0))) {
400: printf(": can not initialize (%d)\n", error);
401: /* XXX free resources */
402: return (ENXIO);
403: }
404:
405: bzero(&cfg, sizeof(cfg));
406: bzero(&ecfg, sizeof(ecfg));
407: cfg.ext = &ecfg;
408: if ((error = sti_inqcfg(scr, &cfg))) {
409: printf(": error %d inquiring config\n", error);
410: /* XXX free resources */
411: return (ENXIO);
412: }
413:
414: /*
415: * Older (rev 8.02) boards report wrong offset values,
416: * similar to the displayable area size, at least in m68k mode.
417: * Attempt to detect this and adjust here.
418: */
419: if (cfg.owidth == cfg.width &&
420: cfg.oheight == cfg.height)
421: geometry_kluge = 1;
422:
423: if (geometry_kluge) {
424: scr->scr_cfg.oscr_width = cfg.owidth =
425: cfg.fbwidth - cfg.width;
426: scr->scr_cfg.oscr_height = cfg.oheight =
427: cfg.fbheight - cfg.height;
428: }
429:
430: /*
431: * Save a few fields for sti_describe() later
432: */
433: scr->fbheight = cfg.fbheight;
434: scr->fbwidth = cfg.fbwidth;
435: scr->oheight = cfg.oheight;
436: scr->owidth = cfg.owidth;
437: bcopy(cfg.name, scr->name, sizeof(scr->name));
438:
439: if ((error = sti_init(scr, STI_TEXTMODE))) {
440: printf(": can not initialize (%d)\n", error);
441: /* XXX free resources */
442: return (ENXIO);
443: }
444:
445: #ifdef STIDEBUG
446: printf("conf: bpp=%d planes=%d attr=%b\n"
447: "crt=0x%x:0x%x:0x%x hw=0x%x:0x%x:0x%x\n", cfg.bpp,
448: cfg.planes, cfg.attributes, STI_INQCONF_BITS,
449: ecfg.crt_config[0], ecfg.crt_config[1], ecfg.crt_config[2],
450: ecfg.crt_hw[0], ecfg.crt_hw[1], ecfg.crt_hw[2]);
451: #endif
452: scr->scr_bpp = cfg.bppu;
453:
454: if ((error = sti_fetchfonts(scr, &cfg, dd->dd_fntaddr))) {
455: printf(": cannot fetch fonts (%d)\n", error);
456: /* XXX free resources */
457: return (ENXIO);
458: }
459:
460: /*
461: * setup screen descriptions:
462: * figure number of fonts supported;
463: * allocate wscons structures;
464: * calculate dimensions.
465: */
466:
467: strlcpy(scr->scr_wsd.name, "std", sizeof(scr->scr_wsd.name));
468: scr->scr_wsd.ncols = cfg.width / scr->scr_curfont.width;
469: scr->scr_wsd.nrows = cfg.height / scr->scr_curfont.height;
470: scr->scr_wsd.textops = &sti_emulops;
471: scr->scr_wsd.fontwidth = scr->scr_curfont.width;
472: scr->scr_wsd.fontheight = scr->scr_curfont.height;
473: scr->scr_wsd.capabilities = 0;
474:
475: scr->scr_scrlist[0] = &scr->scr_wsd;
476: scr->scr_screenlist.nscreens = 1;
477: scr->scr_screenlist.screens =
478: (const struct wsscreen_descr **)scr->scr_scrlist;
479:
480: /* { extern int pmapdebug; pmapdebug = 0; } */
481:
482: return (0);
483: }
484:
485: void
486: sti_describe(struct sti_softc *sc)
487: {
488: struct sti_screen *scr = sc->sc_scr;
489: struct sti_dd *dd = &scr->scr_dd;
490: struct sti_font *fp = &scr->scr_curfont;
491:
492: printf(": %s rev %d.%02d;%d, ID 0x%016llX\n",
493: scr->name, dd->dd_grrev >> 4, dd->dd_grrev & 0xf,
494: dd->dd_lrrev, *(u_int64_t *)dd->dd_grid);
495:
496: printf("%s: %dx%d frame buffer, %dx%dx%d display, offset %dx%d\n",
497: sc->sc_dev.dv_xname, scr->fbwidth, scr->fbheight,
498: scr->scr_cfg.scr_width, scr->scr_cfg.scr_height, scr->scr_bpp,
499: scr->owidth, scr->oheight);
500:
501: printf("%s: %dx%d font type %d, %d bpc, charset %d-%d\n",
502: sc->sc_dev.dv_xname, fp->width, fp->height,
503: fp->type, fp->bpc, fp->first, fp->last);
504: }
505:
506: void
507: sti_end_attach(void *v)
508: {
509: struct sti_softc *sc = v;
510: struct wsemuldisplaydev_attach_args waa;
511:
512: sc->sc_wsmode = WSDISPLAYIO_MODE_EMUL;
513:
514: waa.console = sc->sc_flags & STI_CONSOLE ? 1 : 0;
515: waa.scrdata = &sc->sc_scr->scr_screenlist;
516: waa.accessops = &sti_accessops;
517: waa.accesscookie = sc;
518: waa.defaultscreens = 0;
519:
520: /* attach as console if required */
521: if (waa.console && !ISSET(sc->sc_flags, STI_ATTACHED)) {
522: long defattr;
523:
524: sti_alloc_attr(sc, 0, 0, 0, &defattr);
525: wsdisplay_cnattach(&sc->sc_scr->scr_wsd, sc->sc_scr,
526: 0, sc->sc_scr->scr_wsd.nrows - 1, defattr);
527: sc->sc_flags |= STI_ATTACHED;
528: }
529:
530: config_found(&sc->sc_dev, &waa, wsemuldisplaydevprint);
531: }
532:
533: u_int
534: sti_rom_size(bus_space_tag_t iot, bus_space_handle_t ioh)
535: {
536: int devtype;
537: u_int romend;
538:
539: devtype = bus_space_read_1(iot, ioh, 3);
540: if (devtype == STI_DEVTYPE4) {
541: bus_space_read_raw_region_4(iot, ioh, 0x18,
542: (u_int8_t *)&romend, 4);
543: } else {
544: romend =
545: (bus_space_read_1(iot, ioh, 0x50 + 3) << 24) |
546: (bus_space_read_1(iot, ioh, 0x50 + 7) << 16) |
547: (bus_space_read_1(iot, ioh, 0x50 + 11) << 8) |
548: (bus_space_read_1(iot, ioh, 0x50 + 15));
549: }
550:
551: return (round_page(romend));
552: }
553:
554: int
555: sti_fetchfonts(struct sti_screen *scr, struct sti_inqconfout *cfg,
556: u_int32_t addr)
557: {
558: struct sti_font *fp = &scr->scr_curfont;
559: int size;
560: bus_space_tag_t memt;
561: bus_space_handle_t romh;
562: #ifdef notyet
563: int uc;
564: struct {
565: struct sti_unpmvflags flags;
566: struct sti_unpmvin in;
567: struct sti_unpmvout out;
568: } a;
569: #endif
570:
571: memt = scr->memt;
572: romh = scr->romh;
573:
574: /*
575: * Get the first PROM font in memory
576: */
577:
578: STI_ENABLE_ROM(scr->scr_main);
579:
580: do {
581: if (scr->scr_devtype == STI_DEVTYPE1) {
582: fp->first = parseshort(addr + 0x00);
583: fp->last = parseshort(addr + 0x08);
584: fp->width = bus_space_read_1(memt, romh,
585: addr + 0x13);
586: fp->height = bus_space_read_1(memt, romh,
587: addr + 0x17);
588: fp->type = bus_space_read_1(memt, romh,
589: addr + 0x1b);
590: fp->bpc = bus_space_read_1(memt, romh,
591: addr + 0x1f);
592: fp->next = parseword(addr + 0x23);
593: fp->uheight= bus_space_read_1(memt, romh,
594: addr + 0x33);
595: fp->uoffset= bus_space_read_1(memt, romh,
596: addr + 0x37);
597: } else /* STI_DEVTYPE4 */
598: bus_space_read_raw_region_4(memt, romh, addr,
599: (u_int8_t *)fp, sizeof(struct sti_font));
600:
601: size = sizeof(struct sti_font) +
602: (fp->last - fp->first + 1) * fp->bpc;
603: if (scr->scr_devtype == STI_DEVTYPE1)
604: size *= 4;
605: scr->scr_romfont = malloc(size, M_DEVBUF, M_NOWAIT);
606: if (scr->scr_romfont == NULL)
607: return (ENOMEM);
608:
609: bus_space_read_raw_region_4(memt, romh, addr,
610: (u_int8_t *)scr->scr_romfont, size);
611:
612: addr = NULL; /* fp->next */
613: } while (addr);
614:
615: STI_DISABLE_ROM(scr->scr_main);
616:
617: #ifdef notyet
618: /*
619: * If there is enough room in the off-screen framebuffer memory,
620: * display all the characters there in order to display them
621: * faster with blkmv operations rather than unpmv later on.
622: */
623: if (size <= cfg->fbheight *
624: (cfg->fbwidth - cfg->width - cfg->owidth)) {
625: bzero(&a, sizeof(a));
626: a.flags.flags = STI_UNPMVF_WAIT;
627: a.in.fg_colour = STI_COLOUR_WHITE;
628: a.in.bg_colour = STI_COLOUR_BLACK;
629: a.in.font_addr = scr->scr_romfont;
630:
631: scr->scr_fontmaxcol = cfg->fbheight / fp->height;
632: scr->scr_fontbase = cfg->width + cfg->owidth;
633: for (uc = fp->first; uc <= fp->last; uc++) {
634: a.in.x = ((uc - fp->first) / scr->scr_fontmaxcol) *
635: fp->width + scr->scr_fontbase;
636: a.in.y = ((uc - fp->first) % scr->scr_fontmaxcol) *
637: fp->height;
638: a.in.index = uc;
639:
640: (*scr->unpmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
641: if (a.out.errno) {
642: #ifdef STIDEBUG
643: printf("sti_unpmv %d returned %d\n",
644: uc, a.out.errno);
645: #endif
646: return (0);
647: }
648: }
649:
650: free(scr->scr_romfont, M_DEVBUF);
651: scr->scr_romfont = NULL;
652: }
653: #endif
654:
655: return (0);
656: }
657:
658: int
659: sti_init(scr, mode)
660: struct sti_screen *scr;
661: int mode;
662: {
663: struct {
664: struct sti_initflags flags;
665: struct sti_initin in;
666: struct sti_einitin ein;
667: struct sti_initout out;
668: } a;
669:
670: bzero(&a, sizeof(a));
671:
672: a.flags.flags = STI_INITF_WAIT | STI_INITF_CMB | STI_INITF_EBET |
673: (mode & STI_TEXTMODE? STI_INITF_TEXT | STI_INITF_PBET |
674: STI_INITF_PBETI | STI_INITF_ICMT : 0);
675: a.in.text_planes = 1;
676: a.in.ext_in = &a.ein;
677: #ifdef STIDEBUG
678: printf("sti_init,%p(%x, %p, %p, %p)\n",
679: scr->init, a.flags.flags, &a.in, &a.out, &scr->scr_cfg);
680: #endif
681: (*scr->init)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
682: if (a.out.text_planes != a.in.text_planes)
683: return (-1); /* not colliding with sti errno values */
684: return (a.out.errno);
685: }
686:
687: int
688: sti_inqcfg(struct sti_screen *scr, struct sti_inqconfout *out)
689: {
690: struct {
691: struct sti_inqconfflags flags;
692: struct sti_inqconfin in;
693: } a;
694:
695: bzero(&a, sizeof(a));
696:
697: a.flags.flags = STI_INQCONFF_WAIT;
698: (*scr->inqconf)(&a.flags, &a.in, out, &scr->scr_cfg);
699:
700: return out->errno;
701: }
702:
703: void
704: sti_bmove(scr, x1, y1, x2, y2, h, w, f)
705: struct sti_screen *scr;
706: int x1, y1, x2, y2, h, w;
707: enum sti_bmove_funcs f;
708: {
709: struct {
710: struct sti_blkmvflags flags;
711: struct sti_blkmvin in;
712: struct sti_blkmvout out;
713: } a;
714:
715: bzero(&a, sizeof(a));
716:
717: a.flags.flags = STI_BLKMVF_WAIT;
718: switch (f) {
719: case bmf_clear:
720: a.flags.flags |= STI_BLKMVF_CLR;
721: a.in.bg_colour = STI_COLOUR_BLACK;
722: break;
723: case bmf_underline:
724: case bmf_copy:
725: a.in.fg_colour = STI_COLOUR_WHITE;
726: a.in.bg_colour = STI_COLOUR_BLACK;
727: break;
728: case bmf_invert:
729: a.flags.flags |= STI_BLKMVF_COLR;
730: a.in.fg_colour = STI_COLOUR_BLACK;
731: a.in.bg_colour = STI_COLOUR_WHITE;
732: break;
733: }
734: a.in.srcx = x1;
735: a.in.srcy = y1;
736: a.in.dstx = x2;
737: a.in.dsty = y2;
738: a.in.height = h;
739: a.in.width = w;
740:
741: (*scr->blkmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
742: #ifdef STIDEBUG
743: if (a.out.errno)
744: printf("sti_blkmv returned %d\n", a.out.errno);
745: #endif
746: }
747:
748: int
749: sti_setcment(struct sti_screen *scr, u_int i, u_char r, u_char g, u_char b)
750: {
751: struct {
752: struct sti_scmentflags flags;
753: struct sti_scmentin in;
754: struct sti_scmentout out;
755: } a;
756:
757: bzero(&a, sizeof(a));
758:
759: a.flags.flags = STI_SCMENTF_WAIT;
760: a.in.entry = i;
761: a.in.value = (r << 16) | (g << 8) | b;
762:
763: (*scr->scment)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
764:
765: return a.out.errno;
766: }
767:
768: int
769: sti_ioctl(v, cmd, data, flag, p)
770: void *v;
771: u_long cmd;
772: caddr_t data;
773: int flag;
774: struct proc *p;
775: {
776: struct sti_softc *sc = v;
777: struct sti_screen *scr = sc->sc_scr;
778: struct wsdisplay_fbinfo *wdf;
779: struct wsdisplay_cmap *cmapp;
780: u_int mode, idx, count;
781: int i, ret;
782:
783: ret = 0;
784: switch (cmd) {
785: case WSDISPLAYIO_GMODE:
786: *(u_int *)data = sc->sc_wsmode;
787: break;
788:
789: case WSDISPLAYIO_SMODE:
790: mode = *(u_int *)data;
791: if (sc->sc_wsmode == WSDISPLAYIO_MODE_EMUL &&
792: mode == WSDISPLAYIO_MODE_DUMBFB)
793: ret = sti_init(scr, 0);
794: else if (sc->sc_wsmode == WSDISPLAYIO_MODE_DUMBFB &&
795: mode == WSDISPLAYIO_MODE_EMUL)
796: ret = sti_init(scr, STI_TEXTMODE);
797: sc->sc_wsmode = mode;
798: break;
799:
800: case WSDISPLAYIO_GTYPE:
801: *(u_int *)data = WSDISPLAY_TYPE_STI;
802: break;
803:
804: case WSDISPLAYIO_GINFO:
805: wdf = (struct wsdisplay_fbinfo *)data;
806: wdf->height = scr->scr_cfg.scr_height;
807: wdf->width = scr->scr_cfg.scr_width;
808: wdf->depth = scr->scr_bpp;
809: if (scr->scment == NULL)
810: wdf->cmsize = 0;
811: else
812: wdf->cmsize = STI_NCMAP;
813: break;
814:
815: case WSDISPLAYIO_LINEBYTES:
816: *(u_int *)data = scr->scr_cfg.fb_width;
817: break;
818:
819: case WSDISPLAYIO_GETCMAP:
820: if (scr->scment == NULL)
821: return ENODEV;
822: cmapp = (struct wsdisplay_cmap *)data;
823: idx = cmapp->index;
824: count = cmapp->count;
825: if (idx >= STI_NCMAP || idx + count > STI_NCMAP)
826: return EINVAL;
827: if ((ret = copyout(&scr->scr_rcmap[idx], cmapp->red, count)))
828: break;
829: if ((ret = copyout(&scr->scr_gcmap[idx], cmapp->green, count)))
830: break;
831: if ((ret = copyout(&scr->scr_bcmap[idx], cmapp->blue, count)))
832: break;
833: break;
834:
835: case WSDISPLAYIO_PUTCMAP:
836: if (scr->scment == NULL)
837: return ENODEV;
838: cmapp = (struct wsdisplay_cmap *)data;
839: idx = cmapp->index;
840: count = cmapp->count;
841: if (idx >= STI_NCMAP || idx + count > STI_NCMAP)
842: return EINVAL;
843: if ((ret = copyin(cmapp->red, &scr->scr_rcmap[idx], count)))
844: break;
845: if ((ret = copyin(cmapp->green, &scr->scr_gcmap[idx], count)))
846: break;
847: if ((ret = copyin(cmapp->blue, &scr->scr_bcmap[idx], count)))
848: break;
849: for (i = idx + count - 1; i >= idx; i--)
850: if ((ret = sti_setcment(scr, i, scr->scr_rcmap[i],
851: scr->scr_gcmap[i], scr->scr_bcmap[i]))) {
852: #ifdef STIDEBUG
853: printf("sti_ioctl: "
854: "sti_setcment(%d, %u, %u, %u): %d\n", i,
855: (u_int)scr->scr_rcmap[i],
856: (u_int)scr->scr_gcmap[i],
857: (u_int)scr->scr_bcmap[i]);
858: #endif
859: ret = EINVAL;
860: break;
861: }
862: break;
863:
864: case WSDISPLAYIO_SVIDEO:
865: case WSDISPLAYIO_GVIDEO:
866: break;
867:
868: case WSDISPLAYIO_GCURPOS:
869: case WSDISPLAYIO_SCURPOS:
870: case WSDISPLAYIO_GCURMAX:
871: case WSDISPLAYIO_GCURSOR:
872: case WSDISPLAYIO_SCURSOR:
873: default:
874: return (-1); /* not supported yet */
875: }
876:
877: return (ret);
878: }
879:
880: paddr_t
881: sti_mmap(v, offset, prot)
882: void *v;
883: off_t offset;
884: int prot;
885: {
886: /* XXX not finished */
887: return -1;
888: }
889:
890: int
891: sti_alloc_screen(v, type, cookiep, cxp, cyp, defattr)
892: void *v;
893: const struct wsscreen_descr *type;
894: void **cookiep;
895: int *cxp, *cyp;
896: long *defattr;
897: {
898: struct sti_softc *sc = v;
899:
900: if (sc->sc_nscreens > 0)
901: return ENOMEM;
902:
903: *cookiep = sc->sc_scr;
904: *cxp = 0;
905: *cyp = 0;
906: sti_alloc_attr(sc, 0, 0, 0, defattr);
907: sc->sc_nscreens++;
908: return 0;
909: }
910:
911: void
912: sti_free_screen(v, cookie)
913: void *v;
914: void *cookie;
915: {
916: struct sti_softc *sc = v;
917:
918: sc->sc_nscreens--;
919: }
920:
921: int
922: sti_show_screen(v, cookie, waitok, cb, cbarg)
923: void *v;
924: void *cookie;
925: int waitok;
926: void (*cb)(void *, int, int);
927: void *cbarg;
928: {
929: return 0;
930: }
931:
932: int
933: sti_load_font(v, cookie, font)
934: void *v;
935: void *cookie;
936: struct wsdisplay_font *font;
937: {
938: return -1;
939: }
940:
941: void
942: sti_cursor(v, on, row, col)
943: void *v;
944: int on, row, col;
945: {
946: struct sti_screen *scr = v;
947: struct sti_font *fp = &scr->scr_curfont;
948:
949: sti_bmove(scr,
950: col * fp->width, row * fp->height,
951: col * fp->width, row * fp->height,
952: fp->height, fp->width, bmf_invert);
953: }
954:
955: /*
956: * ISO 8859-1 part of Unicode to HP Roman font index conversion array.
957: */
958: static const u_int8_t
959: sti_unitoroman[0x100 - 0xa0] = {
960: 0xa0, 0xb8, 0xbf, 0xbb, 0xba, 0xbc, 0, 0xbd,
961: 0xab, 0, 0xf9, 0xfb, 0, 0xf6, 0, 0xb0,
962:
963: 0xb3, 0xfe, 0, 0, 0xa8, 0xf3, 0xf4, 0xf2,
964: 0, 0, 0xfa, 0xfd, 0xf7, 0xf8, 0, 0xb9,
965:
966: 0xa1, 0xe0, 0xa2, 0xe1, 0xd8, 0xd0, 0xd3, 0xb4,
967: 0xa3, 0xdc, 0xa4, 0xa5, 0xe6, 0xe5, 0xa6, 0xa7,
968:
969: 0xe3, 0xb6, 0xe8, 0xe7, 0xdf, 0xe9, 0xda, 0,
970: 0xd2, 0xad, 0xed, 0xae, 0xdb, 0xb1, 0xf0, 0xde,
971:
972: 0xc8, 0xc4, 0xc0, 0xe2, 0xcc, 0xd4, 0xd7, 0xb5,
973: 0xc9, 0xc5, 0xc1, 0xcd, 0xd9, 0xd5, 0xd1, 0xdd,
974:
975: 0xe4, 0xb7, 0xca, 0xc6, 0xc2, 0xea, 0xce, 0,
976: 0xd6, 0xcb, 0xc7, 0xc3, 0xcf, 0xb2, 0xf1, 0xef
977: };
978:
979: int
980: sti_mapchar(v, uni, index)
981: void *v;
982: int uni;
983: u_int *index;
984: {
985: struct sti_screen *scr = v;
986: struct sti_font *fp = &scr->scr_curfont;
987: int c;
988:
989: switch (fp->type) {
990: case STI_FONT_HPROMAN8:
991: if (uni >= 0x80 && uni < 0xa0)
992: c = -1;
993: else if (uni >= 0xa0 && uni < 0x100) {
994: c = (int)sti_unitoroman[uni - 0xa0];
995: if (c == 0)
996: c = -1;
997: } else
998: c = uni;
999: break;
1000: default:
1001: c = uni;
1002: break;
1003: }
1004:
1005: if (c == -1 || c < fp->first || c > fp->last) {
1006: *index = ' ';
1007: return (0);
1008: }
1009:
1010: *index = c;
1011: return (5);
1012: }
1013:
1014: void
1015: sti_putchar(v, row, col, uc, attr)
1016: void *v;
1017: int row, col;
1018: u_int uc;
1019: long attr;
1020: {
1021: struct sti_screen *scr = v;
1022: struct sti_font *fp = &scr->scr_curfont;
1023:
1024: if (scr->scr_romfont != NULL) {
1025: /*
1026: * Font is in memory, use unpmv
1027: */
1028: struct {
1029: struct sti_unpmvflags flags;
1030: struct sti_unpmvin in;
1031: struct sti_unpmvout out;
1032: } a;
1033:
1034: bzero(&a, sizeof(a));
1035:
1036: a.flags.flags = STI_UNPMVF_WAIT;
1037: /* XXX does not handle text attributes */
1038: a.in.fg_colour = STI_COLOUR_WHITE;
1039: a.in.bg_colour = STI_COLOUR_BLACK;
1040: a.in.x = col * fp->width;
1041: a.in.y = row * fp->height;
1042: a.in.font_addr = scr->scr_romfont;
1043: a.in.index = uc;
1044:
1045: (*scr->unpmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
1046: } else {
1047: /*
1048: * Font is in frame buffer, use blkmv
1049: */
1050: struct {
1051: struct sti_blkmvflags flags;
1052: struct sti_blkmvin in;
1053: struct sti_blkmvout out;
1054: } a;
1055:
1056: bzero(&a, sizeof(a));
1057:
1058: a.flags.flags = STI_BLKMVF_WAIT;
1059: /* XXX does not handle text attributes */
1060: a.in.fg_colour = STI_COLOUR_WHITE;
1061: a.in.bg_colour = STI_COLOUR_BLACK;
1062:
1063: a.in.srcx = ((uc - fp->first) / scr->scr_fontmaxcol) *
1064: fp->width + scr->scr_fontbase;
1065: a.in.srcy = ((uc - fp->first) % scr->scr_fontmaxcol) *
1066: fp->height;
1067: a.in.dstx = col * fp->width;
1068: a.in.dsty = row * fp->height;
1069: a.in.height = fp->height;
1070: a.in.width = fp->width;
1071:
1072: (*scr->blkmv)(&a.flags, &a.in, &a.out, &scr->scr_cfg);
1073: }
1074: }
1075:
1076: void
1077: sti_copycols(v, row, srccol, dstcol, ncols)
1078: void *v;
1079: int row, srccol, dstcol, ncols;
1080: {
1081: struct sti_screen *scr = v;
1082: struct sti_font *fp = &scr->scr_curfont;
1083:
1084: sti_bmove(scr,
1085: srccol * fp->width, row * fp->height,
1086: dstcol * fp->width, row * fp->height,
1087: fp->height, ncols * fp->width, bmf_copy);
1088: }
1089:
1090: void
1091: sti_erasecols(v, row, startcol, ncols, attr)
1092: void *v;
1093: int row, startcol, ncols;
1094: long attr;
1095: {
1096: struct sti_screen *scr = v;
1097: struct sti_font *fp = &scr->scr_curfont;
1098:
1099: sti_bmove(scr,
1100: startcol * fp->width, row * fp->height,
1101: startcol * fp->width, row * fp->height,
1102: fp->height, ncols * fp->width, bmf_clear);
1103: }
1104:
1105: void
1106: sti_copyrows(v, srcrow, dstrow, nrows)
1107: void *v;
1108: int srcrow, dstrow, nrows;
1109: {
1110: struct sti_screen *scr = v;
1111: struct sti_font *fp = &scr->scr_curfont;
1112:
1113: sti_bmove(scr, 0, srcrow * fp->height, 0, dstrow * fp->height,
1114: nrows * fp->height, scr->scr_cfg.scr_width, bmf_copy);
1115: }
1116:
1117: void
1118: sti_eraserows(v, srcrow, nrows, attr)
1119: void *v;
1120: int srcrow, nrows;
1121: long attr;
1122: {
1123: struct sti_screen *scr = v;
1124: struct sti_font *fp = &scr->scr_curfont;
1125:
1126: sti_bmove(scr, 0, srcrow * fp->height, 0, srcrow * fp->height,
1127: nrows * fp->height, scr->scr_cfg.scr_width, bmf_clear);
1128: }
1129:
1130: int
1131: sti_alloc_attr(v, fg, bg, flags, pattr)
1132: void *v;
1133: int fg, bg, flags;
1134: long *pattr;
1135: {
1136: /* struct sti_screen *scr = v; */
1137:
1138: *pattr = 0;
1139:
1140: return 0;
1141: }
1142:
1143: void
1144: sti_unpack_attr(void *v, long attr, int *fg, int *bg, int *ul)
1145: {
1146: *fg = WSCOL_WHITE;
1147: *bg = WSCOL_BLACK;
1148: if (ul != NULL)
1149: *ul = 0;
1150: }
1151:
1152: #if NSTI_SGC > 0
1153:
1154: /*
1155: * Early console support
1156: */
1157:
1158: void
1159: sti_clear(struct sti_screen *scr)
1160: {
1161: sti_bmove(scr, 0, 0, 0, 0,
1162: scr->scr_cfg.scr_height, scr->scr_cfg.scr_width, bmf_clear);
1163: }
1164:
1165: int
1166: sti_cnattach(struct sti_screen *scr, bus_space_tag_t iot, bus_addr_t *bases,
1167: u_int codebase)
1168: {
1169: bus_space_handle_t ioh;
1170: u_int romend;
1171: int error;
1172: long defattr;
1173:
1174: if ((error = bus_space_map(iot, bases[0], PAGE_SIZE, 0, &ioh)) != 0)
1175: return (error);
1176:
1177: /*
1178: * Compute real PROM size
1179: */
1180: romend = sti_rom_size(iot, ioh);
1181:
1182: bus_space_unmap(iot, ioh, PAGE_SIZE);
1183:
1184: if ((error = bus_space_map(iot, bases[0], romend, 0, &ioh)) != 0)
1185: return (error);
1186:
1187: bases[0] = ioh;
1188: if (sti_screen_setup(scr, iot, iot, ioh, bases, codebase) != 0)
1189: panic(__func__);
1190:
1191: sti_alloc_attr(scr, 0, 0, 0, &defattr);
1192: wsdisplay_cnattach(&scr->scr_wsd, scr, 0, 0, defattr);
1193:
1194: return (0);
1195: }
1196:
1197: #endif /* NSTI_SGC > 0 */
CVSweb