1 /*	$OpenBSD: sti.c,v 1.47 2006/11/29 19:08:22 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 "wsdisplay.h"
36 
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/device.h>
40 #include <sys/malloc.h>
41 
42 #include <uvm/uvm.h>
43 
44 #include <machine/bus.h>
45 
46 #include <dev/wscons/wsdisplayvar.h>
47 #include <dev/wscons/wsconsio.h>
48 
49 #include <dev/ic/stireg.h>
50 #include <dev/ic/stivar.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 struct wsscreen_descr sti_default_screen = {
97 	"default", 0, 0,
98 	&sti_emulops,
99 	0, 0,
100 	0
101 };
102 
103 const struct wsscreen_descr *sti_default_scrlist[] = {
104 	&sti_default_screen
105 };
106 
107 struct wsscreen_list sti_default_screenlist = {
108 	sizeof(sti_default_scrlist) / sizeof(sti_default_scrlist[0]),
109 	sti_default_scrlist
110 };
111 
112 enum sti_bmove_funcs {
113 	bmf_clear, bmf_copy, bmf_invert, bmf_underline
114 };
115 
116 int sti_init(struct sti_softc *sc, int mode);
117 int sti_inqcfg(struct sti_softc *sc, struct sti_inqconfout *out);
118 void sti_bmove(struct sti_softc *sc, int, int, int, int, int, int,
119     enum sti_bmove_funcs);
120 int sti_setcment(struct sti_softc *sc, u_int i, u_char r, u_char g, u_char b);
121 int sti_fetchfonts(struct sti_softc *sc, struct sti_inqconfout *cfg,
122     u_int32_t addr);
123 void sti_attach_deferred(void *);
124 
125 void
sti_attach_common(sc)126 sti_attach_common(sc)
127 	struct sti_softc *sc;
128 {
129 	struct sti_inqconfout cfg;
130 	struct sti_einqconfout ecfg;
131 	bus_space_handle_t fbh;
132 	struct sti_dd *dd;
133 	struct sti_cfg *cc;
134 	int error, size, i;
135 
136 	/* { extern int pmapdebug; pmapdebug = 0xfffff; } */
137 	dd = &sc->sc_dd;
138 	if (sc->sc_devtype == STI_DEVTYPE1) {
139 #define	parseshort(o) \
140 	((bus_space_read_1(sc->memt, sc->romh, (o) + 3) <<  8) | \
141 	 (bus_space_read_1(sc->memt, sc->romh, (o) + 7)))
142 #define	parseword(o) \
143 	((bus_space_read_1(sc->memt, sc->romh, (o) +  3) << 24) | \
144 	 (bus_space_read_1(sc->memt, sc->romh, (o) +  7) << 16) | \
145 	 (bus_space_read_1(sc->memt, sc->romh, (o) + 11) <<  8) | \
146 	 (bus_space_read_1(sc->memt, sc->romh, (o) + 15)))
147 
148 		dd->dd_type  = bus_space_read_1(sc->memt, sc->romh, 0x03);
149 		dd->dd_nmon  = bus_space_read_1(sc->memt, sc->romh, 0x07);
150 		dd->dd_grrev = bus_space_read_1(sc->memt, sc->romh, 0x0b);
151 		dd->dd_lrrev = bus_space_read_1(sc->memt, sc->romh, 0x0f);
152 		dd->dd_grid[0] = parseword(0x10);
153 		dd->dd_grid[1] = parseword(0x20);
154 		dd->dd_fntaddr = parseword(0x30) & ~3;
155 		dd->dd_maxst   = parseword(0x40);
156 		dd->dd_romend  = parseword(0x50) & ~3;
157 		dd->dd_reglst  = parseword(0x60) & ~3;
158 		dd->dd_maxreent= parseshort(0x70);
159 		dd->dd_maxtimo = parseshort(0x78);
160 		dd->dd_montbl  = parseword(0x80) & ~3;
161 		dd->dd_udaddr  = parseword(0x90) & ~3;
162 		dd->dd_stimemreq=parseword(0xa0);
163 		dd->dd_udsize  = parseword(0xb0);
164 		dd->dd_pwruse  = parseshort(0xc0);
165 		dd->dd_bussup  = bus_space_read_1(sc->memt, sc->romh, 0xcb);
166 		dd->dd_ebussup = bus_space_read_1(sc->memt, sc->romh, 0xcf);
167 		dd->dd_altcodet= bus_space_read_1(sc->memt, sc->romh, 0xd3);
168 		dd->dd_eddst[0]= bus_space_read_1(sc->memt, sc->romh, 0xd7);
169 		dd->dd_eddst[1]= bus_space_read_1(sc->memt, sc->romh, 0xdb);
170 		dd->dd_eddst[2]= bus_space_read_1(sc->memt, sc->romh, 0xdf);
171 		dd->dd_cfbaddr = parseword(0xe0) & ~3;
172 
173 		dd->dd_pacode[0x0] = parseword(0x100) & ~3;
174 		dd->dd_pacode[0x1] = parseword(0x110) & ~3;
175 		dd->dd_pacode[0x2] = parseword(0x120) & ~3;
176 		dd->dd_pacode[0x3] = parseword(0x130) & ~3;
177 		dd->dd_pacode[0x4] = parseword(0x140) & ~3;
178 		dd->dd_pacode[0x5] = parseword(0x150) & ~3;
179 		dd->dd_pacode[0x6] = parseword(0x160) & ~3;
180 		dd->dd_pacode[0x7] = parseword(0x170) & ~3;
181 		dd->dd_pacode[0x8] = parseword(0x180) & ~3;
182 		dd->dd_pacode[0x9] = parseword(0x190) & ~3;
183 		dd->dd_pacode[0xa] = parseword(0x1a0) & ~3;
184 		dd->dd_pacode[0xb] = parseword(0x1b0) & ~3;
185 		dd->dd_pacode[0xc] = parseword(0x1c0) & ~3;
186 		dd->dd_pacode[0xd] = parseword(0x1d0) & ~3;
187 		dd->dd_pacode[0xe] = parseword(0x1e0) & ~3;
188 		dd->dd_pacode[0xf] = parseword(0x1f0) & ~3;
189 	} else	/* STI_DEVTYPE4 */
190 		bus_space_read_region_4(sc->memt, sc->romh, 0, (u_int32_t *)dd,
191 		    sizeof(*dd) / 4);
192 
193 #ifdef STIDEBUG
194 	printf("dd:\n"
195 	    "devtype=%x, rev=%x;%d, altt=%x, gid=%016llx, font=%x, mss=%x\n"
196 	    "end=%x, regions=%x, msto=%x, timo=%d, mont=%x, user=%x[%x]\n"
197 	    "memrq=%x, pwr=%d, bus=%x, ebus=%x, cfb=%x\n"
198 	    "code=",
199 	    dd->dd_type & 0xff, dd->dd_grrev, dd->dd_lrrev, dd->dd_altcodet,
200 	    *(u_int64_t *)dd->dd_grid, dd->dd_fntaddr, dd->dd_maxst,
201 	    dd->dd_romend, dd->dd_reglst, dd->dd_maxreent, dd->dd_maxtimo,
202 	    dd->dd_montbl, dd->dd_udaddr, dd->dd_udsize, dd->dd_stimemreq,
203 	    dd->dd_pwruse, dd->dd_bussup, dd->dd_ebussup, dd->dd_cfbaddr);
204 	printf("%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x\n",
205 	    dd->dd_pacode[0x0], dd->dd_pacode[0x1], dd->dd_pacode[0x2],
206 	    dd->dd_pacode[0x3], dd->dd_pacode[0x4], dd->dd_pacode[0x5],
207 	    dd->dd_pacode[0x6], dd->dd_pacode[0x7], dd->dd_pacode[0x8],
208 	    dd->dd_pacode[0x9], dd->dd_pacode[0xa], dd->dd_pacode[0xb],
209 	    dd->dd_pacode[0xc], dd->dd_pacode[0xd], dd->dd_pacode[0xe],
210 	    dd->dd_pacode[0xf]);
211 #endif
212 	/* divise code size, could be less than STI_END entries */
213 	for (i = STI_END; !dd->dd_pacode[i]; i--);
214 	size = dd->dd_pacode[i] - dd->dd_pacode[STI_BEGIN];
215 	if (sc->sc_devtype == STI_DEVTYPE1)
216 		size = (size + 3) / 4;
217 	if (!(sc->sc_code = uvm_km_alloc1(kernel_map, round_page(size), 0))) {
218 		printf(": cannot allocate %u bytes for code\n", size);
219 		return;
220 	}
221 #ifdef STIDEBUG
222 	printf("code=0x%x[%x]\n", sc->sc_code, size);
223 #endif
224 
225 	/* copy code into memory */
226 	if (sc->sc_devtype == STI_DEVTYPE1) {
227 		u_int8_t *p = (u_int8_t *)sc->sc_code;
228 		u_int32_t addr, eaddr;
229 
230 		for (addr = dd->dd_pacode[STI_BEGIN], eaddr = addr + size * 4;
231 		    addr < eaddr; addr += 4 )
232 			*p++ = bus_space_read_4(sc->memt, sc->romh, addr) & 0xff;
233 
234 	} else	/* STI_DEVTYPE4 */
235 		bus_space_read_region_4(sc->memt, sc->romh,
236 		    dd->dd_pacode[STI_BEGIN], (u_int32_t *)sc->sc_code,
237 		    size / 4);
238 
239 #define	O(i)	(dd->dd_pacode[(i)]? (sc->sc_code + \
240 	(dd->dd_pacode[(i)] - dd->dd_pacode[0]) / \
241 	(sc->sc_devtype == STI_DEVTYPE1? 4 : 1)) : NULL)
242 	sc->init	= (sti_init_t)	O(STI_INIT_GRAPH);
243 	sc->mgmt	= (sti_mgmt_t)	O(STI_STATE_MGMT);
244 	sc->unpmv	= (sti_unpmv_t)	O(STI_FONT_UNPMV);
245 	sc->blkmv	= (sti_blkmv_t)	O(STI_BLOCK_MOVE);
246 	sc->test	= (sti_test_t)	O(STI_SELF_TEST);
247 	sc->exhdl	= (sti_exhdl_t)	O(STI_EXCEP_HDLR);
248 	sc->inqconf	= (sti_inqconf_t)O(STI_INQ_CONF);
249 	sc->scment	= (sti_scment_t)O(STI_SCM_ENT);
250 	sc->dmac	= (sti_dmac_t)	O(STI_DMA_CTRL);
251 	sc->flowc	= (sti_flowc_t)	O(STI_FLOW_CTRL);
252 	sc->utiming	= (sti_utiming_t)O(STI_UTIMING);
253 	sc->pmgr	= (sti_pmgr_t)	O(STI_PROC_MGR);
254 	sc->util	= (sti_util_t)	O(STI_UTIL);
255 
256 	if ((error = uvm_map_protect(kernel_map, sc->sc_code,
257 	    sc->sc_code + round_page(size), UVM_PROT_RX, FALSE))) {
258 		printf(": uvm_map_protect failed (%d)\n", error);
259 		uvm_km_free(kernel_map, sc->sc_code, round_page(size));
260 		return;
261 	}
262 
263 	cc = &sc->sc_cfg;
264 	bzero(cc, sizeof (*cc));
265 	{
266 		int i = dd->dd_reglst;
267 		u_int32_t *p;
268 		struct sti_region r;
269 
270 #ifdef STIDEBUG
271 		printf("stiregions @%p:\n", i);
272 #endif
273 		r.last = 0;
274 		for (p = cc->regions; !r.last &&
275 		     p < &cc->regions[STI_REGION_MAX]; p++) {
276 
277 			if (sc->sc_devtype == STI_DEVTYPE1)
278 				*(u_int *)&r = parseword(i), i+= 16;
279 			else
280 				*(u_int *)&r = bus_space_read_4(sc->memt, sc->romh, i), i += 4;
281 
282 			*p = (p == cc->regions? sc->romh : sc->base) +
283 			    (r.offset << PGSHIFT);
284 #ifdef STIDEBUG
285 			printf("%x @ 0x%x%s%s%s%s\n",
286 			    r.length << PGSHIFT, *p, r.sys_only? " sys" : "",
287 			    r.cache? " cache" : "", r.btlb? " btlb" : "",
288 			    r.last? " last" : "");
289 #endif
290 
291 			/* rom has already been mapped */
292 			if (p != cc->regions) {
293 				if (bus_space_map(sc->memt, *p,
294 				    r.length << PGSHIFT, 0, &fbh)) {
295 #ifdef STIDEBUG
296 					printf("already mapped region\n");
297 #endif
298 				} else {
299 					if (p - cc->regions == 1) {
300 						sc->fbaddr = *p;
301 						sc->fblen = r.length << PGSHIFT;
302 					}
303 					*p = fbh;
304 				}
305 			}
306 		}
307 	}
308 
309 	if ((error = sti_init(sc, 0))) {
310 		printf(": can not initialize (%d)\n", error);
311 		return;
312 	}
313 
314 	bzero(&cfg, sizeof(cfg));
315 	bzero(&ecfg, sizeof(ecfg));
316 	cfg.ext = &ecfg;
317 	if ((error = sti_inqcfg(sc, &cfg))) {
318 		printf(": error %d inquiring config\n", error);
319 		return;
320 	}
321 
322 	if ((error = sti_init(sc, STI_TEXTMODE))) {
323 		printf(": can not initialize (%d)\n", error);
324 		return;
325 	}
326 
327 #ifdef STIDEBUG
328 	printf("conf: bpp=%d planes=%d attr=%b\n"
329 	    "crt=0x%x:0x%x:0x%x hw=0x%x:0x%x:0x%x\n", cfg.bpp,
330 	    cfg.planes, cfg.attributes, STI_INQCONF_BITS,
331 	    ecfg.crt_config[0], ecfg.crt_config[1], ecfg.crt_config[2],
332 	    ecfg.crt_hw[0], ecfg.crt_hw[1], ecfg.crt_hw[2]);
333 #endif
334 	sc->sc_wsmode = WSDISPLAYIO_MODE_EMUL;
335 	sc->sc_bpp = cfg.bppu;
336 	printf(": %s rev %d.%02d;%d, ID 0x%016llX\n"
337 	    "%s: %dx%d frame buffer, %dx%dx%d display, offset %dx%d\n",
338 	    cfg.name, dd->dd_grrev >> 4, dd->dd_grrev & 0xf, dd->dd_lrrev,
339 	    *(u_int64_t *)dd->dd_grid,
340 	    sc->sc_dev.dv_xname, cfg.fbwidth, cfg.fbheight,
341 	    cfg.width, cfg.height, cfg.bppu, cfg.owidth, cfg.oheight);
342 
343 	if ((error = sti_fetchfonts(sc, &cfg, dd->dd_fntaddr))) {
344 		printf("%s: cannot fetch fonts (%d)\n",
345 		    sc->sc_dev.dv_xname, error);
346 		return;
347 	}
348 
349 	/*
350 	 * parse screen descriptions:
351 	 *	figure number of fonts supported;
352 	 *	allocate wscons structures;
353 	 *	calculate dimensions.
354 	 */
355 
356 	sti_default_screen.ncols = cfg.width / sc->sc_curfont.width;
357 	sti_default_screen.nrows = cfg.height / sc->sc_curfont.height;
358 	sti_default_screen.fontwidth = sc->sc_curfont.width;
359 	sti_default_screen.fontheight = sc->sc_curfont.height;
360 
361 #if NWSDISPLAY > 0
362 	startuphook_establish(sti_attach_deferred, sc);
363 #endif
364 
365 	/* { extern int pmapdebug; pmapdebug = 0; } */
366 }
367 
368 void
sti_attach_deferred(void * v)369 sti_attach_deferred(void *v)
370 {
371 	struct sti_softc *sc = v;
372 	struct wsemuldisplaydev_attach_args waa;
373 
374 	waa.console = sc->sc_flags & STI_CONSOLE? 1 : 0;
375 	waa.scrdata = &sti_default_screenlist;
376 	waa.accessops = &sti_accessops;
377 	waa.accesscookie = sc;
378 	waa.defaultscreens = 0;
379 
380 	/* attach as console if required */
381 	if (waa.console) {
382 		long defattr;
383 
384 		sti_alloc_attr(sc, 0, 0, 0, &defattr);
385 		wsdisplay_cnattach(&sti_default_screen, sc,
386 		    0, sti_default_screen.nrows - 1, defattr);
387 	}
388 
389 	config_found(&sc->sc_dev, &waa, wsemuldisplaydevprint);
390 }
391 
392 int
sti_fetchfonts(struct sti_softc * sc,struct sti_inqconfout * cfg,u_int32_t addr)393 sti_fetchfonts(struct sti_softc *sc, struct sti_inqconfout *cfg, u_int32_t addr)
394 {
395 	struct sti_font *fp = &sc->sc_curfont;
396 	int size;
397 #ifdef notyet
398 	int uc;
399 	struct {
400 		struct sti_unpmvflags flags;
401 		struct sti_unpmvin in;
402 		struct sti_unpmvout out;
403 	} a;
404 #endif
405 
406 	/*
407 	 * Get the first PROM font in memory
408 	 */
409 	do {
410 		if (sc->sc_devtype == STI_DEVTYPE1) {
411 			fp->first  = parseshort(addr + 0x00);
412 			fp->last   = parseshort(addr + 0x08);
413 			fp->width  = bus_space_read_1(sc->memt, sc->romh,
414 			    addr + 0x13);
415 			fp->height = bus_space_read_1(sc->memt, sc->romh,
416 			    addr + 0x17);
417 			fp->type   = bus_space_read_1(sc->memt, sc->romh,
418 			    addr + 0x1b);
419 			fp->bpc    = bus_space_read_1(sc->memt, sc->romh,
420 			    addr + 0x1f);
421 			fp->next   = parseword(addr + 0x23);
422 			fp->uheight= bus_space_read_1(sc->memt, sc->romh,
423 			    addr + 0x33);
424 			fp->uoffset= bus_space_read_1(sc->memt, sc->romh,
425 			    addr + 0x37);
426 		} else	/* STI_DEVTYPE4 */
427 			bus_space_read_region_4(sc->memt, sc->romh, addr,
428 			    (u_int32_t *)fp, sizeof(struct sti_font) / 4);
429 
430 		printf("%s: %dx%d font type %d, %d bpc, charset %d-%d\n",
431 		    sc->sc_dev.dv_xname, fp->width, fp->height,
432 		    fp->type,  fp->bpc, fp->first, fp->last);
433 
434 		size = sizeof(struct sti_font) +
435 		    (fp->last - fp->first + 1) * fp->bpc;
436 		if (sc->sc_devtype == STI_DEVTYPE1)
437 			size *= 4;
438 		sc->sc_romfont = malloc(size, M_DEVBUF, M_NOWAIT);
439 		if (sc->sc_romfont == NULL)
440 			return (ENOMEM);
441 
442 		bus_space_read_region_4(sc->memt, sc->romh, addr,
443 		    (u_int32_t *)sc->sc_romfont, size / 4);
444 
445 		addr = NULL; /* fp->next */
446 	} while (addr);
447 
448 #ifdef notyet
449 	/*
450 	 * If there is enough room in the off-screen framebuffer memory,
451 	 * display all the characters there in order to display them
452 	 * faster with blkmv operations rather than unpmv later on.
453 	 */
454 	if (size <= cfg->fbheight *
455 	    (cfg->fbwidth - cfg->width - cfg->owidth)) {
456 		bzero(&a, sizeof(a));
457 		a.flags.flags = STI_UNPMVF_WAIT;
458 		a.in.fg_colour = STI_COLOUR_WHITE;
459 		a.in.bg_colour = STI_COLOUR_BLACK;
460 		a.in.font_addr = sc->sc_romfont;
461 
462 		sc->sc_fontmaxcol = cfg->fbheight / fp->height;
463 		sc->sc_fontbase = cfg->width + cfg->owidth;
464 		for (uc = fp->first; uc <= fp->last; uc++) {
465 			a.in.x = ((uc - fp->first) / sc->sc_fontmaxcol) *
466 			    fp->width + sc->sc_fontbase;
467 			a.in.y = ((uc - fp->first) % sc->sc_fontmaxcol) *
468 			    fp->height;
469 			a.in.index = uc;
470 
471 			(*sc->unpmv)(&a.flags, &a.in, &a.out, &sc->sc_cfg);
472 			if (a.out.errno) {
473 				printf("%s: unpmv %d returned %d\n",
474 				    sc->sc_dev.dv_xname, uc, a.out.errno);
475 				return (0);
476 			}
477 		}
478 
479 		free(sc->sc_romfont, M_DEVBUF);
480 		sc->sc_romfont = NULL;
481 	}
482 #endif
483 
484 	return (0);
485 }
486 
487 int
sti_init(sc,mode)488 sti_init(sc, mode)
489 	struct sti_softc *sc;
490 	int mode;
491 {
492 	struct {
493 		struct sti_initflags flags;
494 		struct sti_initin in;
495 		struct sti_initout out;
496 	} a;
497 
498 	bzero(&a,  sizeof(a));
499 
500 	a.flags.flags = STI_INITF_WAIT | STI_INITF_CMB | STI_INITF_EBET |
501 	    (mode & STI_TEXTMODE? STI_INITF_TEXT | STI_INITF_PBET |
502 	     STI_INITF_PBETI | STI_INITF_ICMT : 0);
503 	a.in.text_planes = 1;
504 #ifdef STIDEBUG
505 	printf("%s: init,%p(%x, %p, %p, %p)\n", sc->sc_dev.dv_xname,
506 	    sc->init, a.flags.flags, &a.in, &a.out, &sc->sc_cfg);
507 #endif
508 	(*sc->init)(&a.flags, &a.in, &a.out, &sc->sc_cfg);
509 	return (a.out.text_planes != a.in.text_planes || a.out.errno);
510 }
511 
512 int
sti_inqcfg(sc,out)513 sti_inqcfg(sc, out)
514 	struct sti_softc *sc;
515 	struct sti_inqconfout *out;
516 {
517 	struct {
518 		struct sti_inqconfflags flags;
519 		struct sti_inqconfin in;
520 	} a;
521 
522 	bzero(&a,  sizeof(a));
523 
524 	a.flags.flags = STI_INQCONFF_WAIT;
525 	(*sc->inqconf)(&a.flags, &a.in, out, &sc->sc_cfg);
526 
527 	return out->errno;
528 }
529 
530 void
sti_bmove(sc,x1,y1,x2,y2,h,w,f)531 sti_bmove(sc, x1, y1, x2, y2, h, w, f)
532 	struct sti_softc *sc;
533 	int x1, y1, x2, y2, h, w;
534 	enum sti_bmove_funcs f;
535 {
536 	struct {
537 		struct sti_blkmvflags flags;
538 		struct sti_blkmvin in;
539 		struct sti_blkmvout out;
540 	} a;
541 
542 	bzero(&a, sizeof(a));
543 
544 	a.flags.flags = STI_BLKMVF_WAIT;
545 	switch (f) {
546 	case bmf_clear:
547 		a.flags.flags |= STI_BLKMVF_CLR;
548 		a.in.bg_colour = STI_COLOUR_BLACK;
549 		break;
550 	case bmf_underline:
551 	case bmf_copy:
552 		a.in.fg_colour = STI_COLOUR_WHITE;
553 		a.in.bg_colour = STI_COLOUR_BLACK;
554 		break;
555 	case bmf_invert:
556 		a.flags.flags |= STI_BLKMVF_COLR;
557 		a.in.fg_colour = STI_COLOUR_BLACK;
558 		a.in.bg_colour = STI_COLOUR_WHITE;
559 		break;
560 	}
561 	a.in.srcx = x1;
562 	a.in.srcy = y1;
563 	a.in.dstx = x2;
564 	a.in.dsty = y2;
565 	a.in.height = h;
566 	a.in.width = w;
567 
568 	(*sc->blkmv)(&a.flags, &a.in, &a.out, &sc->sc_cfg);
569 #ifdef STIDEBUG
570 	if (a.out.errno)
571 		printf("%s: blkmv returned %d\n",
572 		    sc->sc_dev.dv_xname, a.out.errno);
573 #endif
574 }
575 
576 int
sti_setcment(struct sti_softc * sc,u_int i,u_char r,u_char g,u_char b)577 sti_setcment(struct sti_softc *sc, u_int i, u_char r, u_char g, u_char b)
578 {
579 	struct {
580 		struct sti_scmentflags flags;
581 		struct sti_scmentin in;
582 		struct sti_scmentout out;
583 	} a;
584 
585 	bzero(&a, sizeof(a));
586 
587 	a.flags.flags = STI_SCMENTF_WAIT;
588 	a.in.entry = i;
589 	a.in.value = (r << 16) | (g << 8) | b;
590 
591 	(*sc->scment)(&a.flags, &a.in, &a.out, &sc->sc_cfg);
592 
593 	return a.out.errno;
594 }
595 
596 int
sti_ioctl(v,cmd,data,flag,p)597 sti_ioctl(v, cmd, data, flag, p)
598 	void *v;
599 	u_long cmd;
600 	caddr_t data;
601 	int flag;
602 	struct proc *p;
603 {
604 	struct sti_softc *sc = v;
605 	struct wsdisplay_fbinfo *wdf;
606 	struct wsdisplay_cmap *cmapp;
607 	u_int mode, idx, count;
608 	int i, ret;
609 
610 	ret = 0;
611 	switch (cmd) {
612 	case WSDISPLAYIO_GMODE:
613 		*(u_int *)data = sc->sc_wsmode;
614 		break;
615 
616 	case WSDISPLAYIO_SMODE:
617 		mode = *(u_int *)data;
618 		if (sc->sc_wsmode == WSDISPLAYIO_MODE_EMUL &&
619 		    mode == WSDISPLAYIO_MODE_DUMBFB)
620 			ret = sti_init(sc, 0);
621 		else if (sc->sc_wsmode == WSDISPLAYIO_MODE_DUMBFB &&
622 		    mode == WSDISPLAYIO_MODE_EMUL)
623 			ret = sti_init(sc, STI_TEXTMODE);
624 		sc->sc_wsmode = mode;
625 		break;
626 
627 	case WSDISPLAYIO_GTYPE:
628 		*(u_int *)data = WSDISPLAY_TYPE_STI;
629 		break;
630 
631 	case WSDISPLAYIO_GINFO:
632 		wdf = (struct wsdisplay_fbinfo *)data;
633 		wdf->height = sc->sc_cfg.scr_height;
634 		wdf->width  = sc->sc_cfg.scr_width;
635 		wdf->depth  = sc->sc_bpp;
636 		wdf->cmsize = STI_NCMAP;
637 		break;
638 
639 	case WSDISPLAYIO_LINEBYTES:
640 		*(u_int *)data = sc->sc_cfg.fb_width;
641 		break;
642 
643 	case WSDISPLAYIO_GETCMAP:
644 		if (sc->scment == NULL)
645 			return ENOTTY;
646 		cmapp = (struct wsdisplay_cmap *)data;
647 		idx = cmapp->index;
648 		count = cmapp->count;
649 		if (idx > STI_NCMAP || idx + count >= STI_NCMAP)
650 			return EINVAL;
651 		if ((ret = copyout(&sc->sc_rcmap[idx], cmapp->red, count)))
652 			break;
653 		if ((ret = copyout(&sc->sc_gcmap[idx], cmapp->green, count)))
654 			break;
655 		if ((ret = copyout(&sc->sc_bcmap[idx], cmapp->blue, count)))
656 			break;
657 		break;
658 
659 	case WSDISPLAYIO_PUTCMAP:
660 		if (sc->scment == NULL)
661 			return ENOTTY;
662 		cmapp = (struct wsdisplay_cmap *)data;
663 		idx = cmapp->index;
664 		count = cmapp->count;
665 		if (idx > STI_NCMAP || idx + count >= STI_NCMAP)
666 			return EINVAL;
667 		if ((ret = copyin(cmapp->red, &sc->sc_rcmap[idx], count)))
668 			break;
669 		if ((ret = copyin(cmapp->green, &sc->sc_gcmap[idx], count)))
670 			break;
671 		if ((ret = copyin(cmapp->blue, &sc->sc_bcmap[idx], count)))
672 			break;
673 		for (i = idx + count - 1; i >= idx; i--)
674 			if ((ret = sti_setcment(sc, i, sc->sc_rcmap[i],
675 			    sc->sc_gcmap[i], sc->sc_bcmap[i]))) {
676 #ifdef STIDEBUG
677 				printf("sti_ioctl: "
678 				    "sti_setcment(%d, %u, %u, %u): %d\n", i,
679 				    (u_int)sc->sc_rcmap[i],
680 				    (u_int)sc->sc_gcmap[i],
681 				    (u_int)sc->sc_bcmap[i]);
682 #endif
683 				ret = EINVAL;
684 				break;
685 			}
686 		break;
687 
688 	case WSDISPLAYIO_SVIDEO:
689 	case WSDISPLAYIO_GVIDEO:
690 	case WSDISPLAYIO_GCURPOS:
691 	case WSDISPLAYIO_SCURPOS:
692 	case WSDISPLAYIO_GCURMAX:
693 	case WSDISPLAYIO_GCURSOR:
694 	case WSDISPLAYIO_SCURSOR:
695 	default:
696 		return (ENOTTY);	/* not supported yet */
697 	}
698 
699 	return (ret);
700 }
701 
702 paddr_t
sti_mmap(v,offset,prot)703 sti_mmap(v, offset, prot)
704 	void *v;
705 	off_t offset;
706 	int prot;
707 {
708 	/* XXX not finished */
709 	return -1;
710 }
711 
712 int
sti_alloc_screen(v,type,cookiep,cxp,cyp,defattr)713 sti_alloc_screen(v, type, cookiep, cxp, cyp, defattr)
714 	void *v;
715 	const struct wsscreen_descr *type;
716 	void **cookiep;
717 	int *cxp, *cyp;
718 	long *defattr;
719 {
720 	struct sti_softc *sc = v;
721 
722 	if (sc->sc_nscreens > 0)
723 		return ENOMEM;
724 
725 	*cookiep = sc;
726 	*cxp = 0;
727 	*cyp = 0;
728 	sti_alloc_attr(sc, 0, 0, 0, defattr);
729 	sc->sc_nscreens++;
730 	return 0;
731 }
732 
733 void
sti_free_screen(v,cookie)734 sti_free_screen(v, cookie)
735 	void *v;
736 	void *cookie;
737 {
738 	struct sti_softc *sc = v;
739 
740 	sc->sc_nscreens--;
741 }
742 
743 int
sti_show_screen(v,cookie,waitok,cb,cbarg)744 sti_show_screen(v, cookie, waitok, cb, cbarg)
745 	void *v;
746 	void *cookie;
747 	int waitok;
748 	void (*cb)(void *, int, int);
749 	void *cbarg;
750 {
751 	return 0;
752 }
753 
754 int
sti_load_font(v,cookie,font)755 sti_load_font(v, cookie, font)
756 	void *v;
757 	void *cookie;
758 	struct wsdisplay_font *font;
759 {
760 	return -1;
761 }
762 
763 void
sti_cursor(v,on,row,col)764 sti_cursor(v, on, row, col)
765 	void *v;
766 	int on, row, col;
767 {
768 	struct sti_softc *sc = v;
769 	struct sti_font *fp = &sc->sc_curfont;
770 
771 	sti_bmove(sc,
772 	    col * fp->width, row * fp->height,
773 	    col * fp->width, row * fp->height,
774 	    fp->height, fp->width, bmf_invert);
775 }
776 
777 int
sti_mapchar(v,uni,index)778 sti_mapchar(v, uni, index)
779 	void *v;
780 	int uni;
781 	u_int *index;
782 {
783 	if (uni < 256)
784 		*index = uni;
785 
786 	return 1;
787 }
788 
789 void
sti_putchar(v,row,col,uc,attr)790 sti_putchar(v, row, col, uc, attr)
791 	void *v;
792 	int row, col;
793 	u_int uc;
794 	long attr;
795 {
796 	struct sti_softc *sc = v;
797 	struct sti_font *fp = &sc->sc_curfont;
798 
799 	if (sc->sc_romfont != NULL) {
800 		/*
801 		 * Font is in memory, use unpmv
802 		 */
803 		struct {
804 			struct sti_unpmvflags flags;
805 			struct sti_unpmvin in;
806 			struct sti_unpmvout out;
807 		} a;
808 
809 		bzero(&a, sizeof(a));
810 
811 		a.flags.flags = STI_UNPMVF_WAIT;
812 		/* XXX does not handle text attributes */
813 		a.in.fg_colour = STI_COLOUR_WHITE;
814 		a.in.bg_colour = STI_COLOUR_BLACK;
815 		a.in.x = col * fp->width;
816 		a.in.y = row * fp->height;
817 		a.in.font_addr = sc->sc_romfont;
818 		a.in.index = uc;
819 
820 		(*sc->unpmv)(&a.flags, &a.in, &a.out, &sc->sc_cfg);
821 	} else {
822 		/*
823 		 * Font is in frame buffer, use blkmv
824 		 */
825 		struct {
826 			struct sti_blkmvflags flags;
827 			struct sti_blkmvin in;
828 			struct sti_blkmvout out;
829 		} a;
830 
831 		bzero(&a, sizeof(a));
832 
833 		a.flags.flags = STI_BLKMVF_WAIT;
834 		/* XXX does not handle text attributes */
835 		a.in.fg_colour = STI_COLOUR_WHITE;
836 		a.in.bg_colour = STI_COLOUR_BLACK;
837 
838 		a.in.srcx = ((uc - fp->first) / sc->sc_fontmaxcol) *
839 		    fp->width + sc->sc_fontbase;
840 		a.in.srcy = ((uc - fp->first) % sc->sc_fontmaxcol) *
841 		    fp->height;
842 		a.in.dstx = col * fp->width;
843 		a.in.dsty = row * fp->height;
844 		a.in.height = fp->height;
845 		a.in.width = fp->width;
846 
847 		(*sc->blkmv)(&a.flags, &a.in, &a.out, &sc->sc_cfg);
848 	}
849 }
850 
851 void
sti_copycols(v,row,srccol,dstcol,ncols)852 sti_copycols(v, row, srccol, dstcol, ncols)
853 	void *v;
854 	int row, srccol, dstcol, ncols;
855 {
856 	struct sti_softc *sc = v;
857 	struct sti_font *fp = &sc->sc_curfont;
858 
859 	sti_bmove(sc,
860 	    srccol * fp->width, row * fp->height,
861 	    dstcol * fp->width, row * fp->height,
862 	    fp->height, ncols * fp->width, bmf_copy);
863 }
864 
865 void
sti_erasecols(v,row,startcol,ncols,attr)866 sti_erasecols(v, row, startcol, ncols, attr)
867 	void *v;
868 	int row, startcol, ncols;
869 	long attr;
870 {
871 	struct sti_softc *sc = v;
872 	struct sti_font *fp = &sc->sc_curfont;
873 
874 	sti_bmove(sc,
875 	    startcol * fp->width, row * fp->height,
876 	    startcol * fp->width, row * fp->height,
877 	    fp->height, ncols * fp->width, bmf_clear);
878 }
879 
880 void
sti_copyrows(v,srcrow,dstrow,nrows)881 sti_copyrows(v, srcrow, dstrow, nrows)
882 	void *v;
883 	int srcrow, dstrow, nrows;
884 {
885 	struct sti_softc *sc = v;
886 	struct sti_font *fp = &sc->sc_curfont;
887 
888 	sti_bmove(sc, sc->sc_cfg.oscr_width, srcrow * fp->height,
889 	    sc->sc_cfg.oscr_width, dstrow * fp->height,
890 	    nrows * fp->height, sc->sc_cfg.scr_width, bmf_copy);
891 }
892 
893 void
sti_eraserows(v,srcrow,nrows,attr)894 sti_eraserows(v, srcrow, nrows, attr)
895 	void *v;
896 	int srcrow, nrows;
897 	long attr;
898 {
899 	struct sti_softc *sc = v;
900 	struct sti_font *fp = &sc->sc_curfont;
901 
902 	sti_bmove(sc, sc->sc_cfg.oscr_width, srcrow * fp->height,
903 	    sc->sc_cfg.oscr_width, srcrow * fp->height,
904 	    nrows * fp->height, sc->sc_cfg.scr_width, bmf_clear);
905 }
906 
907 int
sti_alloc_attr(v,fg,bg,flags,pattr)908 sti_alloc_attr(v, fg, bg, flags, pattr)
909 	void *v;
910 	int fg, bg, flags;
911 	long *pattr;
912 {
913 	/* struct sti_softc *sc = v; */
914 
915 	*pattr = 0;
916 
917 	return 0;
918 }
919 
920 void
sti_unpack_attr(void * v,long attr,int * fg,int * bg,int * ul)921 sti_unpack_attr(void *v, long attr, int *fg, int *bg, int *ul)
922 {
923 	*fg = WSCOL_WHITE;
924 	*bg = WSCOL_BLACK;
925 	if (ul != NULL)
926 		*ul = 0;
927 }
928 
929