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