xref: /openbsd-src/sys/dev/ic/sti.c (revision b2ea75c1b17e1a9a339660e7ed45cd24946b230e)
1 /*	$OpenBSD: sti.c,v 1.5 2001/03/20 08:32:20 mickey Exp $	*/
2 
3 /*
4  * Copyright (c) 2000-2001 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  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *      This product includes software developed by Michael Shalayeff.
18  * 4. The name of the author may not be used to endorse or promote products
19  *    derived from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24  * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
25  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27  * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
30  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
31  * THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 /*
34  * TODO:
35  *	call sti procs asynchronously;
36  *	implement console scroll-back;
37  *	X11 support.
38  */
39 
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/device.h>
43 #include <sys/malloc.h>
44 
45 #include <vm/vm.h>
46 #include <vm/vm_kern.h>
47 #include <uvm/uvm.h>
48 
49 #include <machine/bus.h>
50 
51 #include <dev/wscons/wsdisplayvar.h>
52 #include <dev/wscons/wsconsio.h>
53 
54 #include <hppa/dev/cpudevs.h>
55 
56 #include <dev/ic/stireg.h>
57 #include <dev/ic/stivar.h>
58 
59 struct cfdriver sti_cd = {
60 	NULL, "sti", DV_DULL
61 };
62 
63 void sti_cursor __P((void *v, int on, int row, int col));
64 int  sti_mapchar __P((void *v, int uni, u_int *index));
65 void sti_putchar __P((void *v, int row, int col, u_int uc, long attr));
66 void sti_copycols __P((void *v, int row, int srccol, int dstcol, int ncols));
67 void sti_erasecols __P((void *v, int row, int startcol, int ncols, long attr));
68 void sti_copyrows __P((void *v, int srcrow, int dstrow, int nrows));
69 void sti_eraserows __P((void *v, int row, int nrows, long attr));
70 int  sti_alloc_attr __P((void *v, int fg, int bg, int flags, long *));
71 
72 struct wsdisplay_emulops sti_emulops = {
73 	sti_cursor,
74 	sti_mapchar,
75 	sti_putchar,
76 	sti_copycols,
77 	sti_erasecols,
78 	sti_copyrows,
79 	sti_eraserows,
80 	sti_alloc_attr
81 };
82 
83 int sti_ioctl __P((void *v, u_long cmd, caddr_t data, int flag, struct proc *p));
84 paddr_t sti_mmap __P((void *v, off_t offset, int prot));
85 int sti_alloc_screen __P((void *v, const struct wsscreen_descr *type,
86 	void **cookiep, int *cxp, int *cyp, long *defattr));
87 	void sti_free_screen __P((void *v, void *cookie));
88 int sti_show_screen __P((void *v, void *cookie, int waitok,
89 	void (*cb) __P((void *, int, int)), void *cbarg));
90 int sti_load_font __P((void *v, void *cookie, struct wsdisplay_font *));
91 
92 const struct wsdisplay_accessops sti_accessops = {
93 	sti_ioctl,
94 	sti_mmap,
95 	sti_alloc_screen,
96 	sti_free_screen,
97 	sti_show_screen,
98 	sti_load_font
99 };
100 
101 struct wsscreen_descr sti_default_screen = {
102 	"default", 0, 0,
103 	&sti_emulops,
104 	0, 0,
105 	WSSCREEN_REVERSE | WSSCREEN_UNDERLINE
106 };
107 
108 const struct wsscreen_descr *sti_default_scrlist[] = {
109 	&sti_default_screen
110 };
111 
112 struct wsscreen_list sti_default_screenlist = {
113 	sizeof(sti_default_scrlist) / sizeof(sti_default_scrlist[0]),
114 	sti_default_scrlist
115 };
116 
117 enum sti_bmove_funcs {
118 	bmf_clear, bmf_copy, bmf_invert, bmf_underline
119 };
120 
121 int sti_init __P((struct sti_softc *sc, int mode));
122 int sti_inqcfg __P((struct sti_softc *sc, struct sti_inqconfout *out));
123 void sti_bmove __P((struct sti_softc *sc, int, int, int, int, int, int,
124 	enum sti_bmove_funcs));
125 
126 void
127 sti_attach_common(sc)
128 	struct sti_softc *sc;
129 {
130 	struct sti_inqconfout cfg;
131 	bus_space_handle_t fbh;
132 	struct wsemuldisplaydev_attach_args waa;
133 	struct sti_dd *dd;
134 	struct sti_cfg *cc;
135 	struct sti_fontcfg *ff;
136 	int error, size, i;
137 
138 	dd = &sc->sc_dd;
139 	if (sc->sc_devtype == STI_DEVTYPE1) {
140 #define	parseshort(o) \
141 	((bus_space_read_1(sc->memt, sc->romh, (o) + 3) <<  8) | \
142 	 (bus_space_read_1(sc->memt, sc->romh, (o) + 7)))
143 #define	parseword(o) \
144 	((bus_space_read_1(sc->memt, sc->romh, (o) +  3) << 24) | \
145 	 (bus_space_read_1(sc->memt, sc->romh, (o) +  7) << 16) | \
146 	 (bus_space_read_1(sc->memt, sc->romh, (o) + 11) <<  8) | \
147 	 (bus_space_read_1(sc->memt, sc->romh, (o) + 15)))
148 
149 		dd->dd_type  = bus_space_read_1(sc->memt, sc->romh, 3);
150 		dd->dd_nmon  = bus_space_read_1(sc->memt, sc->romh, 7);
151 		dd->dd_grrev = bus_space_read_1(sc->memt, sc->romh, 11);
152 		dd->dd_lrrev = bus_space_read_1(sc->memt, sc->romh, 15);
153 		dd->dd_grid[0] = parseword(0x10);
154 		dd->dd_grid[1] = parseword(0x20);
155 		dd->dd_fntaddr = parseword(0x30) & ~3;
156 		dd->dd_maxst   = parseword(0x40);
157 		dd->dd_romend  = parseword(0x50) & ~3;
158 		dd->dd_reglst  = parseword(0x60) & ~3;
159 		dd->dd_maxreent= parseshort(0x70);
160 		dd->dd_maxtimo = parseshort(0x78);
161 				/* what happened to 0x80 ? */
162 		dd->dd_montbl  = parseword(0x90);
163 		dd->dd_udaddr  = parseword(0xa0) & ~3;
164 		dd->dd_stimemreq=parseword(0xb0);
165 		dd->dd_udsize  = parseword(0xc0);
166 		dd->dd_pwruse  = parseshort(0xd0);
167 		dd->dd_bussup  = bus_space_read_1(sc->memt, sc->romh, 0xdb);
168 		dd->dd_ebussup = bus_space_read_1(sc->memt, sc->romh, 0xdf);
169 		dd->dd_altcodet= bus_space_read_1(sc->memt, sc->romh, 0xe3);
170 		dd->dd_cfbaddr = parseword(0xf0) & ~3;
171 
172 		dd->dd_pacode[0x0] = parseword(0x100) & ~3;
173 		dd->dd_pacode[0x1] = parseword(0x110) & ~3;
174 		dd->dd_pacode[0x2] = parseword(0x120) & ~3;
175 		dd->dd_pacode[0x3] = parseword(0x130) & ~3;
176 		dd->dd_pacode[0x4] = parseword(0x140) & ~3;
177 		dd->dd_pacode[0x5] = parseword(0x150) & ~3;
178 		dd->dd_pacode[0x6] = parseword(0x160) & ~3;
179 		dd->dd_pacode[0x7] = parseword(0x170) & ~3;
180 		dd->dd_pacode[0x8] = parseword(0x180) & ~3;
181 		dd->dd_pacode[0x9] = parseword(0x190) & ~3;
182 		dd->dd_pacode[0xa] = parseword(0x1a0) & ~3;
183 		dd->dd_pacode[0xb] = parseword(0x1b0) & ~3;
184 		dd->dd_pacode[0xc] = parseword(0x1c0) & ~3;
185 		dd->dd_pacode[0xd] = parseword(0x1d0) & ~3;
186 		dd->dd_pacode[0xe] = parseword(0x1e0) & ~3;
187 		dd->dd_pacode[0xf] = parseword(0x1f0) & ~3;
188 	} else	/* STI_DEVTYPE4 */
189 		bus_space_read_region_4(sc->memt, sc->romh, 0, (u_int32_t *)dd,
190 		    sizeof(*dd) / 4);
191 
192 #ifdef STIDEBUG
193 	printf("dd:\n"
194 	    "devtype=%x, rev=%x;%d, gid=%x%x, font=%x, mss=%x\n"
195 	    "end=%x, mmap=%x, msto=%x, timo=%d, mont=%x, ua=%x\n"
196 	    "memrq=%x, pwr=%d, bus=%x, ebus=%x, altt=%x, cfb=%x\n"
197 	    "code=",
198 	    dd->dd_type, dd->dd_grrev, dd->dd_lrrev,
199 	    dd->dd_grid[0], dd->dd_grid[1],
200 	    dd->dd_fntaddr, dd->dd_maxst, dd->dd_romend,
201 	    dd->dd_reglst, dd->dd_maxreent,
202 	    dd->dd_maxtimo, dd->dd_montbl, dd->dd_udaddr,
203 	    dd->dd_stimemreq, dd->dd_udsize, dd->dd_pwruse,
204 	    dd->dd_bussup, dd->dd_altcodet, dd->dd_cfbaddr);
205 	printf("%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x\n",
206 	    dd->dd_pacode[0x0], dd->dd_pacode[0x1], dd->dd_pacode[0x2],
207 	    dd->dd_pacode[0x3], dd->dd_pacode[0x4], dd->dd_pacode[0x5],
208 	    dd->dd_pacode[0x6], dd->dd_pacode[0x7], dd->dd_pacode[0x8],
209 	    dd->dd_pacode[0x9], dd->dd_pacode[0xa], dd->dd_pacode[0xb],
210 	    dd->dd_pacode[0xc], dd->dd_pacode[0xd], dd->dd_pacode[0xe],
211 	    dd->dd_pacode[0xf]);
212 #endif
213 	/* divine code size, could be less than STI_END entries */
214 	for (i = STI_END; !dd->dd_pacode[i]; i--);
215 	size = dd->dd_pacode[i] - dd->dd_pacode[STI_BEGIN];
216 	if (sc->sc_devtype == STI_DEVTYPE1)
217 		size = (size + 3) / 4;
218 	if (!(sc->sc_code = uvm_km_kmemalloc(kernel_map,
219 	    uvm.kernel_object, round_page(size), UVM_KMF_NOWAIT))) {
220 		printf(": cannot allocate %u bytes for code\n", size);
221 		return;
222 	}
223 
224 	/* copy code into memory */
225 	if (sc->sc_devtype == STI_DEVTYPE1) {
226 		register u_int8_t *p = (u_int8_t *)sc->sc_code;
227 
228 		for (i = 0; i < size; i++)
229 			*p++ = bus_space_read_1(sc->memt, sc->romh,
230 			    dd->dd_pacode[0] + i * 4 + 3);
231 
232 	} else	/* STI_DEVTYPE4 */
233 		bus_space_read_region_4(sc->memt, sc->romh, dd->dd_pacode[0],
234 		    (u_int32_t *)sc->sc_code, size / 4);
235 
236 	/* flush from cache */
237 	MD_CACHE_CTL(sc->sc_code, size, MD_CACHE_FLUSH);
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 	pmap_protect(pmap_kernel(), sc->sc_code,
257 	    sc->sc_code + round_page(size), VM_PROT_READ|VM_PROT_EXECUTE);
258 
259 	cc = &sc->sc_cfg;
260 	bzero(cc, sizeof (*cc));
261 	{
262 		register int i = dd->dd_reglst;
263 		register u_int32_t *p;
264 		struct sti_region r;
265 
266 #ifdef STIDEBUG
267 		printf ("stiregions @%p:\n", i);
268 #endif
269 		r.last = 0;
270 		for (p = cc->regions; !r.last &&
271 		     p < &cc->regions[STI_REGION_MAX]; p++) {
272 
273 			if (sc->sc_devtype == STI_DEVTYPE1)
274 				*(u_int *)&r = parseword(i), i+= 16;
275 			else
276 				*(u_int *)&r = bus_space_read_4(sc->memt, sc->romh, i), i += 4;
277 
278 			*p = (p == cc->regions? sc->romh : sc->ioh) +
279 			    (r.offset << PGSHIFT);
280 #ifdef STIDEBUG
281 			printf("%x @ 0x%x %s%s%s%s\n",
282 			    r.length << PGSHIFT, *p, r.sys_only? "sys " : "",
283 			    r.cache? "cache " : "", r.btlb? "btlb " : "",
284 			    r.last? "last" : "");
285 #endif
286 
287 			/* rom was already mapped */
288 			if (p != cc->regions) {
289 				if (bus_space_map(sc->memt, *p,
290 				    r.length << PGSHIFT, 0, &fbh)) {
291 #ifdef STIDEBUG
292 					printf("cannot map region\n");
293 #endif
294 					/* who cares: return; */
295 				} else if (p - cc->regions == 1)
296 					sc->fbh = fbh;
297 			}
298 		}
299 	}
300 
301 	if ((error = sti_init(sc, 0))) {
302 		printf (": can not initialize (%d)\n", error);
303 		return;
304 	}
305 
306 	if ((error = sti_inqcfg(sc, &cfg))) {
307 		printf (": error %d inquiring config\n", error);
308 		return;
309 	}
310 
311 	if ((error = sti_init(sc, STI_TEXTMODE))) {
312 		printf (": can not initialize (%d)\n", error);
313 		return;
314 	}
315 
316 	ff = &sc->sc_fontcfg;
317 	if (sc->sc_devtype == STI_DEVTYPE1) {
318 		i = dd->dd_fntaddr;
319 		ff->first  = parseshort(i + 0x00);
320 		ff->last   = parseshort(i + 0x08);
321 		ff->width  = bus_space_read_1(sc->memt, sc->romh, i + 0x13);
322 		ff->height = bus_space_read_1(sc->memt, sc->romh, i + 0x17);
323 		ff->type   = bus_space_read_1(sc->memt, sc->romh, i + 0x1b);
324 		ff->bpc    = bus_space_read_1(sc->memt, sc->romh, i + 0x1f);
325 		ff->uheight= bus_space_read_1(sc->memt, sc->romh, i + 0x33);
326 		ff->uoffset= bus_space_read_1(sc->memt, sc->romh, i + 0x37);
327 	} else	/* STI_DEVTYPE4 */
328 		bus_space_read_region_4(sc->memt, sc->romh, dd->dd_fntaddr,
329 		    (u_int32_t *)ff, sizeof(*ff) / 4);
330 
331 	printf(": %s rev %d.%02d;%d\n"
332 	    "%s: %dx%d frame buffer, %dx%dx%d display, offset %dx%d\n"
333 	    "%s: %dx%d font type %d, %d bpc, charset %d-%d\n", cfg.name,
334 	    dd->dd_grrev >> 4, dd->dd_grrev & 0xf, dd->dd_lrrev,
335 	    sc->sc_dev.dv_xname, cfg.fbwidth, cfg.fbheight,
336 	    cfg.width, cfg.height, cfg.bpp, cfg.owidth, cfg.oheight,
337 	    sc->sc_dev.dv_xname,
338 	    ff->width, ff->height, ff->type,  ff->bpc, ff->first, ff->last);
339 
340 	/*
341 	 * parse screen descriptions:
342 	 *	figure number of fonts supported;
343 	 *	allocate wscons structures;
344 	 *	calculate dimentions.
345 	 */
346 
347 	sti_default_screen.ncols = cfg.width / ff->width;
348 	sti_default_screen.nrows = cfg.height / ff->height;
349 	sti_default_screen.fontwidth = ff->width;
350 	sti_default_screen.fontheight = ff->height;
351 
352 	/* attach WSDISPLAY */
353 	waa.console = sc->sc_dev.dv_unit;
354 	waa.scrdata = &sti_default_screenlist;
355 	waa.accessops = &sti_accessops;
356 	waa.accesscookie = sc;
357 
358 	config_found(&sc->sc_dev, &waa, wsemuldisplaydevprint);
359 }
360 
361 int
362 sti_init(sc, mode)
363 	struct sti_softc *sc;
364 	int mode;
365 {
366 	struct {
367 		struct sti_initflags flags;
368 		struct sti_initin in;
369 		struct sti_initout out;
370 	} a;
371 
372 	bzero(&a,  sizeof(a));
373 
374 	a.flags.flags = STI_INITF_WAIT | STI_INITF_CMB | STI_INITF_EBET |
375 	    (mode & STI_TEXTMODE? STI_INITF_TEXT | STI_INITF_PBET |
376 	     STI_INITF_PBETI | STI_INITF_ICMT : 0);
377 	a.in.text_planes = 1;
378 #ifdef STIDEBUG
379 	printf("%s: init,%p(%x, %p, %p, %p)\n", sc->sc_dev.dv_xname,
380 	    sc->init, a.flags.flags, &a.in, &a.out, &sc->sc_cfg);
381 #endif
382 	(*sc->init)(&a.flags, &a.in, &a.out, &sc->sc_cfg);
383 	return (a.out.text_planes != a.in.text_planes || a.out.errno);
384 }
385 
386 int
387 sti_inqcfg(sc, out)
388 	struct sti_softc *sc;
389 	struct sti_inqconfout *out;
390 {
391 	struct {
392 		struct sti_inqconfflags flags;
393 		struct sti_inqconfin in;
394 	} a;
395 
396 	bzero(&a,  sizeof(a));
397 	bzero(out, sizeof(*out));
398 
399 	a.flags.flags = STI_INQCONFF_WAIT;
400 	(*sc->inqconf)(&a.flags, &a.in, out, &sc->sc_cfg);
401 
402 	return out->errno;
403 }
404 
405 void
406 sti_bmove(sc, x1, y1, x2, y2, h, w, f)
407 	struct sti_softc *sc;
408 	int x1, y1, x2, y2, h, w;
409 	enum sti_bmove_funcs f;
410 {
411 	struct {
412 		struct sti_blkmvflags flags;
413 		struct sti_blkmvin in;
414 		struct sti_blkmvout out;
415 	} a;
416 
417 	bzero(&a, sizeof(a));
418 
419 	a.flags.flags = STI_BLKMVF_WAIT;
420 	switch (f) {
421 	case bmf_clear:
422 		a.flags.flags |= STI_BLKMVF_CLR;
423 		a.in.bg_colour = 0;
424 		break;
425 	case bmf_underline:
426 	case bmf_copy:
427 		a.in.fg_colour = 1;
428 		a.in.bg_colour = 0;
429 		break;
430 	case bmf_invert:
431 		a.in.fg_colour = 0;
432 		a.in.bg_colour = 1;
433 		break;
434 	}
435 	a.in.srcx = x1;
436 	a.in.srcy = y1;
437 	a.in.dstx = x2;
438 	a.in.dsty = y2;
439 	a.in.height = h;
440 	a.in.width = w;
441 
442 	(*sc->blkmv)(&a.flags, &a.in, &a.out, &sc->sc_cfg);
443 #ifdef STIDEBUG
444 	if (a.out.errno)
445 		printf ("%s: blkmv returned %d\n",
446 			sc->sc_dev.dv_xname, a.out.errno);
447 #endif
448 }
449 
450 int
451 sti_ioctl(v, cmd, data, flag, p)
452 	void *v;
453 	u_long cmd;
454 	caddr_t data;
455 	int flag;
456 	struct proc *p;
457 {
458 	/* register struct sti_softc *sc; */
459 
460 	return -1;
461 }
462 
463 paddr_t
464 sti_mmap(v, offset, prot)
465 	void *v;
466 	off_t offset;
467 	int prot;
468 {
469 	/* XXX not finished */
470 	return offset;
471 }
472 
473 int
474 sti_alloc_screen(v, type, cookiep, cxp, cyp, defattr)
475 	void *v;
476 	const struct wsscreen_descr *type;
477 	void **cookiep;
478 	int *cxp, *cyp;
479 	long *defattr;
480 {
481 	return -1;
482 }
483 
484 void
485 sti_free_screen(v, cookie)
486 	void *v;
487 	void *cookie;
488 {
489 }
490 
491 int
492 sti_show_screen(v, cookie, waitok, cb, cbarg)
493 	void *v;
494 	void *cookie;
495 	int waitok;
496 	void (*cb) __P((void *, int, int));
497 	void *cbarg;
498 {
499 	return 0;
500 }
501 
502 int
503 sti_load_font(v, cookie, font)
504 	void *v;
505 	void *cookie;
506 	struct wsdisplay_font *font;
507 {
508 	return -1;
509 }
510 
511 void
512 sti_cursor(v, on, row, col)
513 	void *v;
514 	int on, row, col;
515 {
516 	register struct sti_softc *sc = v;
517 
518 	sti_bmove(sc, row * sc->sc_fontcfg.height, col * sc->sc_fontcfg.width,
519 		  row * sc->sc_fontcfg.height, col * sc->sc_fontcfg.width,
520 		  sc->sc_fontcfg.width, sc->sc_fontcfg.height, bmf_invert);
521 }
522 
523 int
524 sti_mapchar(v, uni, index)
525 	void *v;
526 	int uni;
527 	u_int *index;
528 {
529 	if (uni < 256)
530 		*index = uni;
531 
532 	return 1;
533 }
534 
535 void
536 sti_putchar(v, row, col, uc, attr)
537 	void *v;
538 	int row, col;
539 	u_int uc;
540 	long attr;
541 {
542 	register struct sti_softc *sc = v;
543 	struct {
544 		struct sti_unpmvflags flags;
545 		struct sti_unpmvin in;
546 		struct sti_unpmvout out;
547 	} a;
548 
549 	bzero(&a, sizeof(a));
550 
551 	a.flags.flags = STI_UNPMVF_WAIT;
552 	/* XXX does not handle text attributes */
553 	a.in.fg_colour = 1;
554 	a.in.bg_colour = 0;
555 	a.in.x = col * sc->sc_fontcfg.width;
556 	a.in.y = row * sc->sc_fontcfg.height;
557 	a.in.font_addr = 0/*STI_FONTAD(sc->sc_devtype, sc->sc_rom)*/;
558 	a.in.index = uc;
559 	(*sc->unpmv)(&a.flags, &a.in, &a.out, &sc->sc_cfg);
560 }
561 
562 void
563 sti_copycols(v, row, srccol, dstcol, ncols)
564 	void *v;
565 	int row, srccol, dstcol, ncols;
566 {
567 	register struct sti_softc *sc = v;
568 
569 	sti_bmove(sc,
570 	    row * sc->sc_fontcfg.height, srccol * sc->sc_fontcfg.width,
571 	    row * sc->sc_fontcfg.height, dstcol * sc->sc_fontcfg.width,
572 	    ncols * sc->sc_fontcfg.width, sc->sc_fontcfg.height,
573 	    bmf_copy);
574 }
575 
576 void
577 sti_erasecols(v, row, startcol, ncols, attr)
578 	void *v;
579 	int row, startcol, ncols;
580 	long attr;
581 {
582 	register struct sti_softc *sc = v;
583 
584 	sti_bmove(sc,
585 	    row * sc->sc_fontcfg.height, startcol * sc->sc_fontcfg.width,
586 	    row * sc->sc_fontcfg.height, startcol * sc->sc_fontcfg.width,
587 	    ncols * sc->sc_fontcfg.width, sc->sc_fontcfg.height,
588 	    bmf_clear);
589 }
590 
591 void
592 sti_copyrows(v, srcrow, dstrow, nrows)
593 	void *v;
594 	int srcrow, dstrow, nrows;
595 {
596 	register struct sti_softc *sc = v;
597 
598 	sti_bmove(sc,
599 	    srcrow * sc->sc_fontcfg.height, 0,
600 	    dstrow * sc->sc_fontcfg.height, 0,
601 	    sc->sc_cfg.fb_width, nrows + sc->sc_fontcfg.height,
602 	    bmf_copy);
603 }
604 
605 void
606 sti_eraserows(v, srcrow, nrows, attr)
607 	void *v;
608 	int srcrow, nrows;
609 	long attr;
610 {
611 	register struct sti_softc *sc = v;
612 
613 	sti_bmove(sc,
614 	    srcrow * sc->sc_fontcfg.height, 0,
615 	    srcrow * sc->sc_fontcfg.height, 0,
616 	    sc->sc_cfg.fb_width, nrows + sc->sc_fontcfg.height,
617 	    bmf_clear);
618 }
619 
620 int
621 sti_alloc_attr(v, fg, bg, flags, pattr)
622 	void *v;
623 	int fg, bg, flags;
624 	long *pattr;
625 {
626 	/* register struct sti_softc *sc = v; */
627 
628 	*pattr = 0;
629 
630 	return 0;
631 }
632 
633