Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / dev / tc / sfb.c
blob3de0f8f6a9de2a096748e65964e035d0074fc8df
1 /* $NetBSD: sfb.c,v 1.79 2009/08/20 12:55:26 tsutsui Exp $ */
3 /*-
4 * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Tohru Nishimura.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: sfb.c,v 1.79 2009/08/20 12:55:26 tsutsui Exp $");
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/kernel.h>
38 #include <sys/device.h>
39 #include <sys/malloc.h>
40 #include <sys/buf.h>
41 #include <sys/ioctl.h>
43 #include <sys/bus.h>
44 #include <sys/intr.h>
46 #include <dev/wscons/wsconsio.h>
47 #include <dev/wscons/wsdisplayvar.h>
49 #include <dev/rasops/rasops.h>
50 #include <dev/wsfont/wsfont.h>
52 #include <dev/tc/tcvar.h>
53 #include <dev/ic/bt459reg.h>
54 #include <dev/tc/sfbreg.h>
56 #include <uvm/uvm_extern.h>
58 #if defined(pmax)
59 #define machine_btop(x) mips_btop(MIPS_KSEG1_TO_PHYS(x))
60 #endif
62 #if defined(alpha)
63 #define machine_btop(x) alpha_btop(ALPHA_K0SEG_TO_PHYS(x))
64 #endif
67 * N.B., Bt459 registers are 8bit width. Some of TC framebuffers have
68 * obscure register layout such as 2nd and 3rd Bt459 registers are
69 * adjacent each other in a word, i.e.,
70 * struct bt459triplet {
71 * struct {
72 * uint8_t u0;
73 * uint8_t u1;
74 * uint8_t u2;
75 * unsigned :8;
76 * } bt_lo;
78 * Although HX has single Bt459, 32bit R/W can be done w/o any trouble.
79 * struct bt459reg {
80 * uint32_t bt_lo;
81 * uint32_t bt_hi;
82 * uint32_t bt_reg;
83 * uint32_t bt_cmap;
84 * };
87 /* Bt459 hardware registers, memory-mapped in 32bit stride */
88 #define bt_lo 0x0
89 #define bt_hi 0x4
90 #define bt_reg 0x8
91 #define bt_cmap 0xc
93 #define REGWRITE32(p,i,v) do { \
94 *(volatile uint32_t *)((p) + (i)) = (v); tc_wmb(); \
95 } while (/* CONSTCOND */ 0)
96 #define SFBWRITE32(p,i,v) do { \
97 *(volatile uint32_t *)((p) + (i)) = (v); \
98 } while (/* CONSTCOND */ 0)
99 #define MEMWRITE32(p,v) do { \
100 *(volatile uint32_t *)(p) = (v); \
101 } while (/* CONSTCOND */ 0)
103 #define VDACSELECT(p,r) do { \
104 REGWRITE32(p, bt_lo, 0xff & (r)); \
105 REGWRITE32(p, bt_hi, 0x0f & ((r)>>8)); \
106 } while (/* CONSTCOND */ 0)
108 struct hwcmap256 {
109 #define CMAP_SIZE 256 /* 256 R/G/B entries */
110 uint8_t r[CMAP_SIZE];
111 uint8_t g[CMAP_SIZE];
112 uint8_t b[CMAP_SIZE];
115 struct hwcursor64 {
116 struct wsdisplay_curpos cc_pos;
117 struct wsdisplay_curpos cc_hot;
118 struct wsdisplay_curpos cc_size;
119 struct wsdisplay_curpos cc_magic;
120 #define CURSOR_MAX_SIZE 64
121 uint8_t cc_color[6];
122 uint64_t cc_image[CURSOR_MAX_SIZE];
123 uint64_t cc_mask[CURSOR_MAX_SIZE];
126 struct sfb_softc {
127 vaddr_t sc_vaddr;
128 size_t sc_size;
129 struct rasops_info *sc_ri;
130 struct hwcmap256 sc_cmap; /* software copy of colormap */
131 struct hwcursor64 sc_cursor; /* software copy of cursor */
132 int sc_blanked; /* video visibility disabled */
133 int sc_curenb; /* cursor sprite enabled */
134 int sc_changed; /* need update of hardware */
135 #define WSDISPLAY_CMAP_DOLUT 0x20
136 int nscreens;
139 #define HX_MAGIC_X 368
140 #define HX_MAGIC_Y 38
142 static int sfbmatch(device_t, cfdata_t, void *);
143 static void sfbattach(device_t, device_t, void *);
145 CFATTACH_DECL_NEW(sfb, sizeof(struct sfb_softc),
146 sfbmatch, sfbattach, NULL, NULL);
148 static void sfb_common_init(struct rasops_info *);
149 static struct rasops_info sfb_console_ri;
150 static tc_addr_t sfb_consaddr;
152 static void sfb_putchar(void *, int, int, u_int, long);
153 static void sfb_erasecols(void *, int, int, int, long);
154 static void sfb_eraserows(void *, int, int, long);
155 static void sfb_copyrows(void *, int, int, int);
156 static void sfb_do_cursor(struct rasops_info *);
157 #if 0
158 static void sfb_copycols(void *, int, int, int, int);
159 #endif
161 static struct wsscreen_descr sfb_stdscreen = {
162 "std", 0, 0,
163 0, /* textops */
164 0, 0,
165 WSSCREEN_REVERSE
168 static const struct wsscreen_descr *_sfb_scrlist[] = {
169 &sfb_stdscreen,
172 static const struct wsscreen_list sfb_screenlist = {
173 sizeof(_sfb_scrlist) / sizeof(struct wsscreen_descr *), _sfb_scrlist
176 static int sfbioctl(void *, void *, u_long, void *, int, struct lwp *);
177 static paddr_t sfbmmap(void *, void *, off_t, int);
179 static int sfb_alloc_screen(void *, const struct wsscreen_descr *,
180 void **, int *, int *, long *);
181 static void sfb_free_screen(void *, void *);
182 static int sfb_show_screen(void *, void *, int,
183 void (*) (void *, int, int), void *);
185 static const struct wsdisplay_accessops sfb_accessops = {
186 sfbioctl,
187 sfbmmap,
188 sfb_alloc_screen,
189 sfb_free_screen,
190 sfb_show_screen,
191 0 /* load_font */
194 int sfb_cnattach(tc_addr_t);
195 static int sfbintr(void *);
196 static void sfbhwinit(void *);
197 static void sfb_cmap_init(struct sfb_softc *);
198 static void sfb_screenblank(struct sfb_softc *);
200 static int get_cmap(struct sfb_softc *, struct wsdisplay_cmap *);
201 static int set_cmap(struct sfb_softc *, struct wsdisplay_cmap *);
202 static int set_cursor(struct sfb_softc *, struct wsdisplay_cursor *);
203 static int get_cursor(struct sfb_softc *, struct wsdisplay_cursor *);
204 static void set_curpos(struct sfb_softc *, struct wsdisplay_curpos *);
207 * Compose 2 bit/pixel cursor image. Bit order will be reversed.
208 * M M M M I I I I M I M I M I M I
209 * [ before ] [ after ]
210 * 3 2 1 0 3 2 1 0 0 0 1 1 2 2 3 3
211 * 7 6 5 4 7 6 5 4 4 4 5 5 6 6 7 7
213 static const uint8_t shuffle[256] = {
214 0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54,
215 0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55,
216 0x80, 0xc0, 0x90, 0xd0, 0x84, 0xc4, 0x94, 0xd4,
217 0x81, 0xc1, 0x91, 0xd1, 0x85, 0xc5, 0x95, 0xd5,
218 0x20, 0x60, 0x30, 0x70, 0x24, 0x64, 0x34, 0x74,
219 0x21, 0x61, 0x31, 0x71, 0x25, 0x65, 0x35, 0x75,
220 0xa0, 0xe0, 0xb0, 0xf0, 0xa4, 0xe4, 0xb4, 0xf4,
221 0xa1, 0xe1, 0xb1, 0xf1, 0xa5, 0xe5, 0xb5, 0xf5,
222 0x08, 0x48, 0x18, 0x58, 0x0c, 0x4c, 0x1c, 0x5c,
223 0x09, 0x49, 0x19, 0x59, 0x0d, 0x4d, 0x1d, 0x5d,
224 0x88, 0xc8, 0x98, 0xd8, 0x8c, 0xcc, 0x9c, 0xdc,
225 0x89, 0xc9, 0x99, 0xd9, 0x8d, 0xcd, 0x9d, 0xdd,
226 0x28, 0x68, 0x38, 0x78, 0x2c, 0x6c, 0x3c, 0x7c,
227 0x29, 0x69, 0x39, 0x79, 0x2d, 0x6d, 0x3d, 0x7d,
228 0xa8, 0xe8, 0xb8, 0xf8, 0xac, 0xec, 0xbc, 0xfc,
229 0xa9, 0xe9, 0xb9, 0xf9, 0xad, 0xed, 0xbd, 0xfd,
230 0x02, 0x42, 0x12, 0x52, 0x06, 0x46, 0x16, 0x56,
231 0x03, 0x43, 0x13, 0x53, 0x07, 0x47, 0x17, 0x57,
232 0x82, 0xc2, 0x92, 0xd2, 0x86, 0xc6, 0x96, 0xd6,
233 0x83, 0xc3, 0x93, 0xd3, 0x87, 0xc7, 0x97, 0xd7,
234 0x22, 0x62, 0x32, 0x72, 0x26, 0x66, 0x36, 0x76,
235 0x23, 0x63, 0x33, 0x73, 0x27, 0x67, 0x37, 0x77,
236 0xa2, 0xe2, 0xb2, 0xf2, 0xa6, 0xe6, 0xb6, 0xf6,
237 0xa3, 0xe3, 0xb3, 0xf3, 0xa7, 0xe7, 0xb7, 0xf7,
238 0x0a, 0x4a, 0x1a, 0x5a, 0x0e, 0x4e, 0x1e, 0x5e,
239 0x0b, 0x4b, 0x1b, 0x5b, 0x0f, 0x4f, 0x1f, 0x5f,
240 0x8a, 0xca, 0x9a, 0xda, 0x8e, 0xce, 0x9e, 0xde,
241 0x8b, 0xcb, 0x9b, 0xdb, 0x8f, 0xcf, 0x9f, 0xdf,
242 0x2a, 0x6a, 0x3a, 0x7a, 0x2e, 0x6e, 0x3e, 0x7e,
243 0x2b, 0x6b, 0x3b, 0x7b, 0x2f, 0x6f, 0x3f, 0x7f,
244 0xaa, 0xea, 0xba, 0xfa, 0xae, 0xee, 0xbe, 0xfe,
245 0xab, 0xeb, 0xbb, 0xfb, 0xaf, 0xef, 0xbf, 0xff,
248 static int
249 sfbmatch(device_t parent, cfdata_t match, void *aux)
251 struct tc_attach_args *ta = aux;
253 if (strncmp("PMAGB-BA", ta->ta_modname, TC_ROM_LLEN) != 0)
254 return (0);
255 return (1);
258 static void
259 sfbattach(device_t parent, device_t self, void *aux)
261 struct sfb_softc *sc = device_private(self);
262 struct tc_attach_args *ta = aux;
263 struct rasops_info *ri;
264 struct wsemuldisplaydev_attach_args waa;
265 char *asic;
266 int console;
268 console = (ta->ta_addr == sfb_consaddr);
269 if (console) {
270 sc->sc_ri = ri = &sfb_console_ri;
271 sc->nscreens = 1;
273 else {
274 ri = malloc(sizeof(struct rasops_info),
275 M_DEVBUF, M_NOWAIT|M_ZERO);
276 if (ri == NULL) {
277 printf(": can't alloc memory\n");
278 return;
281 ri->ri_hw = (void *)ta->ta_addr;
282 sfb_common_init(ri);
283 sc->sc_ri = ri;
285 printf(": %dx%d, %dbpp\n", ri->ri_width, ri->ri_height, ri->ri_depth);
287 sfb_cmap_init(sc);
289 sc->sc_vaddr = ta->ta_addr;
290 sc->sc_cursor.cc_magic.x = HX_MAGIC_X;
291 sc->sc_cursor.cc_magic.y = HX_MAGIC_Y;
292 sc->sc_blanked = sc->sc_curenb = 0;
294 tc_intr_establish(parent, ta->ta_cookie, IPL_TTY, sfbintr, sc);
296 asic = (char *)ri->ri_hw + SFB_ASIC_OFFSET;
298 SFBWRITE32(asic, SFB_ASIC_CLEAR_INTR, 0);
299 SFBWRITE32(asic, SFB_ASIC_ENABLE_INTR, 1);
301 waa.console = console;
302 waa.scrdata = &sfb_screenlist;
303 waa.accessops = &sfb_accessops;
304 waa.accesscookie = sc;
306 config_found(self, &waa, wsemuldisplaydevprint);
309 static void
310 sfb_cmap_init(struct sfb_softc *sc)
312 struct hwcmap256 *cm;
313 const uint8_t *p;
314 int index;
316 cm = &sc->sc_cmap;
317 p = rasops_cmap;
318 for (index = 0; index < CMAP_SIZE; index++, p += 3) {
319 cm->r[index] = p[0];
320 cm->g[index] = p[1];
321 cm->b[index] = p[2];
325 static void
326 sfb_common_init(struct rasops_info *ri)
328 char *base, *asic;
329 int hsetup, vsetup, vbase, cookie;
331 base = (void *)ri->ri_hw;
332 asic = base + SFB_ASIC_OFFSET;
333 hsetup = *(volatile uint32_t *)(asic + SFB_ASIC_VIDEO_HSETUP);
334 vsetup = *(volatile uint32_t *)(asic + SFB_ASIC_VIDEO_VSETUP);
336 vbase = 1;
337 SFBWRITE32(asic, SFB_ASIC_VIDEO_BASE, vbase);
338 SFBWRITE32(asic, SFB_ASIC_PLANEMASK, ~0);
339 SFBWRITE32(asic, SFB_ASIC_PIXELMASK, ~0);
340 SFBWRITE32(asic, SFB_ASIC_MODE, 0); /* MODE_SIMPLE */
341 SFBWRITE32(asic, SFB_ASIC_ROP, 3); /* ROP_COPY */
342 SFBWRITE32(asic, 0x180000, 0); /* Bt459 reset */
344 /* initialize colormap and cursor hardware */
345 sfbhwinit(base);
347 ri->ri_flg = RI_CENTER;
348 ri->ri_depth = 8;
349 ri->ri_width = (hsetup & 0x1ff) << 2;
350 ri->ri_height = (vsetup & 0x7ff);
351 ri->ri_stride = ri->ri_width * (ri->ri_depth / 8);
352 ri->ri_bits = base + SFB_FB_OFFSET + vbase * 4096;
354 /* clear the screen */
355 memset(ri->ri_bits, 0, ri->ri_stride * ri->ri_height);
357 wsfont_init();
358 /* prefer 12 pixel wide font */
359 cookie = wsfont_find(NULL, 12, 0, 0, WSDISPLAY_FONTORDER_R2L,
360 WSDISPLAY_FONTORDER_L2R);
361 if (cookie <= 0)
362 cookie = wsfont_find(NULL, 0, 0, 0, WSDISPLAY_FONTORDER_R2L,
363 WSDISPLAY_FONTORDER_L2R);
364 if (cookie <= 0) {
365 printf("sfb: font table is empty\n");
366 return;
369 /* the accelerated sfb_putchar() needs LSbit left */
370 if (wsfont_lock(cookie, &ri->ri_font)) {
371 printf("sfb: couldn't lock font\n");
372 return;
374 ri->ri_wsfcookie = cookie;
376 rasops_init(ri, 34, 80);
378 /* add our accelerated functions */
379 ri->ri_ops.putchar = sfb_putchar;
380 ri->ri_ops.erasecols = sfb_erasecols;
381 ri->ri_ops.copyrows = sfb_copyrows;
382 ri->ri_ops.eraserows = sfb_eraserows;
383 ri->ri_do_cursor = sfb_do_cursor;
385 /* XXX shouldn't be global */
386 sfb_stdscreen.nrows = ri->ri_rows;
387 sfb_stdscreen.ncols = ri->ri_cols;
388 sfb_stdscreen.textops = &ri->ri_ops;
389 sfb_stdscreen.capabilities = ri->ri_caps;
392 static int
393 sfbioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l)
395 struct sfb_softc *sc = v;
396 struct rasops_info *ri = sc->sc_ri;
397 int turnoff, s;
399 switch (cmd) {
400 case WSDISPLAYIO_GTYPE:
401 *(u_int *)data = WSDISPLAY_TYPE_SFB;
402 return (0);
404 case WSDISPLAYIO_GINFO:
405 #define wsd_fbip ((struct wsdisplay_fbinfo *)data)
406 wsd_fbip->height = ri->ri_height;
407 wsd_fbip->width = ri->ri_width;
408 wsd_fbip->depth = ri->ri_depth;
409 wsd_fbip->cmsize = CMAP_SIZE;
410 #undef fbt
411 return (0);
413 case WSDISPLAYIO_GETCMAP:
414 return get_cmap(sc, (struct wsdisplay_cmap *)data);
416 case WSDISPLAYIO_PUTCMAP:
417 return set_cmap(sc, (struct wsdisplay_cmap *)data);
419 case WSDISPLAYIO_SVIDEO:
420 turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF;
421 if (sc->sc_blanked != turnoff) {
422 sc->sc_blanked = turnoff;
423 sfb_screenblank(sc);
425 return (0);
427 case WSDISPLAYIO_GVIDEO:
428 *(u_int *)data = sc->sc_blanked ?
429 WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON;
430 return (0);
432 case WSDISPLAYIO_GCURPOS:
433 *(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos;
434 return (0);
436 case WSDISPLAYIO_SCURPOS:
437 s = spltty();
438 set_curpos(sc, (struct wsdisplay_curpos *)data);
439 sc->sc_changed |= WSDISPLAY_CURSOR_DOPOS;
440 splx(s);
441 return (0);
443 case WSDISPLAYIO_GCURMAX:
444 ((struct wsdisplay_curpos *)data)->x =
445 ((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE;
446 return (0);
448 case WSDISPLAYIO_GCURSOR:
449 return get_cursor(sc, (struct wsdisplay_cursor *)data);
451 case WSDISPLAYIO_SCURSOR:
452 return set_cursor(sc, (struct wsdisplay_cursor *)data);
454 case WSDISPLAYIO_SMODE:
455 if (*(int *)data == WSDISPLAYIO_MODE_EMUL) {
456 s = spltty();
457 sfb_cmap_init(sc);
458 sc->sc_curenb = 0;
459 sc->sc_blanked = 0;
460 sc->sc_changed |= (WSDISPLAY_CURSOR_DOCUR |
461 WSDISPLAY_CMAP_DOLUT);
462 splx(s);
463 sfb_screenblank(sc);
465 return (0);
467 return (EPASSTHROUGH);
470 static void
471 sfb_screenblank(struct sfb_softc *sc)
473 struct rasops_info *ri;
474 char *asic;
476 ri = sc->sc_ri;
477 asic = (char *)ri->ri_hw + SFB_ASIC_OFFSET;
478 SFBWRITE32(asic, SFB_ASIC_VIDEO_VALID, !sc->sc_blanked);
479 tc_wmb();
482 static paddr_t
483 sfbmmap(void *v, void *vs, off_t offset, int prot)
485 struct sfb_softc *sc = v;
487 if (offset >= SFB_SIZE || offset < 0)
488 return (-1);
489 return machine_btop(sc->sc_vaddr + offset);
492 static int
493 sfb_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
494 int *curxp, int *curyp, long *attrp)
496 struct sfb_softc *sc = v;
497 struct rasops_info *ri = sc->sc_ri;
498 long defattr;
500 if (sc->nscreens > 0)
501 return (ENOMEM);
503 *cookiep = ri; /* one and only for now */
504 *curxp = 0;
505 *curyp = 0;
506 (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
507 *attrp = defattr;
508 sc->nscreens++;
509 return (0);
512 static void
513 sfb_free_screen(void *v, void *cookie)
515 struct sfb_softc *sc = v;
517 if (sc->sc_ri == &sfb_console_ri)
518 panic("sfb_free_screen: console");
520 sc->nscreens--;
523 static int
524 sfb_show_screen(void *v, void *cookie, int waitok,
525 void (*cb)(void *, int, int), void *cbarg)
528 return (0);
531 /* EXPORT */ int
532 sfb_cnattach(tc_addr_t addr)
534 struct rasops_info *ri;
535 long defattr;
537 ri = &sfb_console_ri;
538 ri->ri_hw = (void *)addr;
539 sfb_common_init(ri);
540 (*ri->ri_ops.allocattr)(&ri, 0, 0, 0, &defattr);
541 wsdisplay_cnattach(&sfb_stdscreen, ri, 0, 0, defattr);
542 sfb_consaddr = addr;
543 return (0);
546 static int
547 sfbintr(void *arg)
549 struct sfb_softc *sc = arg;
550 char *base, *asic, *vdac;
551 int v;
553 base = (void *)sc->sc_ri->ri_hw;
554 asic = base + SFB_ASIC_OFFSET;
555 SFBWRITE32(asic, SFB_ASIC_CLEAR_INTR, 0);
556 /* SFBWRITE32(asic, SFB_ASIC_ENABLE_INTR, 1); */
558 if (sc->sc_changed == 0)
559 goto done;
561 vdac = base + SFB_RAMDAC_OFFSET;
562 v = sc->sc_changed;
563 if (v & WSDISPLAY_CURSOR_DOCUR) {
564 int onoff;
566 onoff = (sc->sc_curenb) ? 0xc0 : 0x00;
567 VDACSELECT(vdac, BT459_IREG_CCR);
568 REGWRITE32(vdac, bt_reg, onoff);
570 if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT)) {
571 int x, y;
573 x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x;
574 y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y;
575 x += sc->sc_cursor.cc_magic.x;
576 y += sc->sc_cursor.cc_magic.y;
578 VDACSELECT(vdac, BT459_IREG_CURSOR_X_LOW);
579 REGWRITE32(vdac, bt_reg, x);
580 REGWRITE32(vdac, bt_reg, x >> 8);
581 REGWRITE32(vdac, bt_reg, y);
582 REGWRITE32(vdac, bt_reg, y >> 8);
584 if (v & WSDISPLAY_CURSOR_DOCMAP) {
585 uint8_t *cp = sc->sc_cursor.cc_color;
587 VDACSELECT(vdac, BT459_IREG_CCOLOR_2);
588 REGWRITE32(vdac, bt_reg, cp[1]);
589 REGWRITE32(vdac, bt_reg, cp[3]);
590 REGWRITE32(vdac, bt_reg, cp[5]);
592 REGWRITE32(vdac, bt_reg, cp[0]);
593 REGWRITE32(vdac, bt_reg, cp[2]);
594 REGWRITE32(vdac, bt_reg, cp[4]);
596 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
597 uint8_t *ip, *mp, img, msk;
598 uint8_t u;
599 int bcnt;
601 ip = (uint8_t *)sc->sc_cursor.cc_image;
602 mp = (uint8_t *)sc->sc_cursor.cc_mask;
604 bcnt = 0;
605 VDACSELECT(vdac, BT459_IREG_CRAM_BASE+0);
606 /* 64 pixel scan line is consisted with 16 byte cursor ram */
607 while (bcnt < sc->sc_cursor.cc_size.y * 16) {
608 /* pad right half 32 pixel when smaller than 33 */
609 if ((bcnt & 0x8) && sc->sc_cursor.cc_size.x < 33) {
610 REGWRITE32(vdac, bt_reg, 0);
611 REGWRITE32(vdac, bt_reg, 0);
613 else {
614 img = *ip++;
615 msk = *mp++;
616 img &= msk; /* cookie off image */
617 u = (msk & 0x0f) << 4 | (img & 0x0f);
618 REGWRITE32(vdac, bt_reg, shuffle[u]);
619 u = (msk & 0xf0) | (img & 0xf0) >> 4;
620 REGWRITE32(vdac, bt_reg, shuffle[u]);
622 bcnt += 2;
624 /* pad unoccupied scan lines */
625 while (bcnt < CURSOR_MAX_SIZE * 16) {
626 REGWRITE32(vdac, bt_reg, 0);
627 REGWRITE32(vdac, bt_reg, 0);
628 bcnt += 2;
631 if (v & WSDISPLAY_CMAP_DOLUT) {
632 struct hwcmap256 *cm = &sc->sc_cmap;
633 int index;
635 VDACSELECT(vdac, 0);
636 for (index = 0; index < CMAP_SIZE; index++) {
637 REGWRITE32(vdac, bt_cmap, cm->r[index]);
638 REGWRITE32(vdac, bt_cmap, cm->g[index]);
639 REGWRITE32(vdac, bt_cmap, cm->b[index]);
642 sc->sc_changed = 0;
643 done:
644 return (1);
647 static void
648 sfbhwinit(void *base)
650 char *vdac = (char *)base + SFB_RAMDAC_OFFSET;
651 const uint8_t *p;
652 int i;
654 VDACSELECT(vdac, BT459_IREG_COMMAND_0);
655 REGWRITE32(vdac, bt_reg, 0x40); /* CMD0 */
656 REGWRITE32(vdac, bt_reg, 0x0); /* CMD1 */
657 REGWRITE32(vdac, bt_reg, 0xc0); /* CMD2 */
658 REGWRITE32(vdac, bt_reg, 0xff); /* PRM */
659 REGWRITE32(vdac, bt_reg, 0); /* 205 */
660 REGWRITE32(vdac, bt_reg, 0x0); /* PBM */
661 REGWRITE32(vdac, bt_reg, 0); /* 207 */
662 REGWRITE32(vdac, bt_reg, 0x0); /* ORM */
663 REGWRITE32(vdac, bt_reg, 0x0); /* OBM */
664 REGWRITE32(vdac, bt_reg, 0x0); /* ILV */
665 REGWRITE32(vdac, bt_reg, 0x0); /* TEST */
667 VDACSELECT(vdac, BT459_IREG_CCR);
668 REGWRITE32(vdac, bt_reg, 0x0);
669 REGWRITE32(vdac, bt_reg, 0x0);
670 REGWRITE32(vdac, bt_reg, 0x0);
671 REGWRITE32(vdac, bt_reg, 0x0);
672 REGWRITE32(vdac, bt_reg, 0x0);
673 REGWRITE32(vdac, bt_reg, 0x0);
674 REGWRITE32(vdac, bt_reg, 0x0);
675 REGWRITE32(vdac, bt_reg, 0x0);
676 REGWRITE32(vdac, bt_reg, 0x0);
677 REGWRITE32(vdac, bt_reg, 0x0);
678 REGWRITE32(vdac, bt_reg, 0x0);
679 REGWRITE32(vdac, bt_reg, 0x0);
680 REGWRITE32(vdac, bt_reg, 0x0);
682 /* build sane colormap */
683 VDACSELECT(vdac, 0);
684 p = rasops_cmap;
685 for (i = 0; i < CMAP_SIZE; i++, p += 3) {
686 REGWRITE32(vdac, bt_cmap, p[0]);
687 REGWRITE32(vdac, bt_cmap, p[1]);
688 REGWRITE32(vdac, bt_cmap, p[2]);
691 /* clear out cursor image */
692 VDACSELECT(vdac, BT459_IREG_CRAM_BASE);
693 for (i = 0; i < 1024; i++)
694 REGWRITE32(vdac, bt_reg, 0xff);
697 * 2 bit/pixel cursor. Assign MSB for cursor mask and LSB for
698 * cursor image. CCOLOR_2 for mask color, while CCOLOR_3 for
699 * image color. CCOLOR_1 will be never used.
701 VDACSELECT(vdac, BT459_IREG_CCOLOR_1);
702 REGWRITE32(vdac, bt_reg, 0xff);
703 REGWRITE32(vdac, bt_reg, 0xff);
704 REGWRITE32(vdac, bt_reg, 0xff);
706 REGWRITE32(vdac, bt_reg, 0);
707 REGWRITE32(vdac, bt_reg, 0);
708 REGWRITE32(vdac, bt_reg, 0);
710 REGWRITE32(vdac, bt_reg, 0xff);
711 REGWRITE32(vdac, bt_reg, 0xff);
712 REGWRITE32(vdac, bt_reg, 0xff);
715 static int
716 get_cmap(struct sfb_softc *sc, struct wsdisplay_cmap *p)
718 u_int index = p->index, count = p->count;
719 int error;
721 if (index >= CMAP_SIZE || count > CMAP_SIZE - index)
722 return (EINVAL);
724 error = copyout(&sc->sc_cmap.r[index], p->red, count);
725 if (error)
726 return error;
727 error = copyout(&sc->sc_cmap.g[index], p->green, count);
728 if (error)
729 return error;
730 error = copyout(&sc->sc_cmap.b[index], p->blue, count);
731 return error;
734 static int
735 set_cmap(struct sfb_softc *sc, struct wsdisplay_cmap *p)
737 struct hwcmap256 cmap;
738 u_int index = p->index, count = p->count;
739 int error, s;
741 if (index >= CMAP_SIZE || count > CMAP_SIZE - index)
742 return (EINVAL);
744 error = copyin(p->red, &cmap.r[index], count);
745 if (error)
746 return error;
747 error = copyin(p->green, &cmap.g[index], count);
748 if (error)
749 return error;
750 error = copyin(p->blue, &cmap.b[index], count);
751 if (error)
752 return error;
754 s = spltty();
755 memcpy(&sc->sc_cmap.r[index], &cmap.r[index], count);
756 memcpy(&sc->sc_cmap.g[index], &cmap.g[index], count);
757 memcpy(&sc->sc_cmap.b[index], &cmap.b[index], count);
758 sc->sc_changed |= WSDISPLAY_CMAP_DOLUT;
759 splx(s);
760 return (0);
763 static int
764 set_cursor(struct sfb_softc *sc, struct wsdisplay_cursor *p)
766 #define cc (&sc->sc_cursor)
767 u_int v, index = 0, count = 0, icount = 0;
768 uint8_t r[2], g[2], b[2], image[512], mask[512];
769 int error, s;
771 v = p->which;
772 if (v & WSDISPLAY_CURSOR_DOCMAP) {
773 index = p->cmap.index;
774 count = p->cmap.count;
775 if (index >= 2 || (index + count) > 2)
776 return (EINVAL);
777 error = copyin(p->cmap.red, &r[index], count);
778 if (error)
779 return error;
780 error = copyin(p->cmap.green, &g[index], count);
781 if (error)
782 return error;
783 error = copyin(p->cmap.blue, &b[index], count);
784 if (error)
785 return error;
787 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
788 if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE)
789 return (EINVAL);
790 icount = ((p->size.x < 33) ? 4 : 8) * p->size.y;
791 error = copyin(p->image, image, icount);
792 if (error)
793 return error;
794 error = copyin(p->mask, mask, icount);
795 if (error)
796 return error;
799 s = spltty();
800 if (v & WSDISPLAY_CURSOR_DOCUR)
801 sc->sc_curenb = p->enable;
802 if (v & WSDISPLAY_CURSOR_DOPOS)
803 set_curpos(sc, &p->pos);
804 if (v & WSDISPLAY_CURSOR_DOHOT)
805 cc->cc_hot = p->hot;
806 if (v & WSDISPLAY_CURSOR_DOCMAP) {
807 memcpy(&cc->cc_color[index], &r[index], count);
808 memcpy(&cc->cc_color[index + 2], &g[index], count);
809 memcpy(&cc->cc_color[index + 4], &b[index], count);
811 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
812 cc->cc_size = p->size;
813 memset(cc->cc_image, 0, sizeof cc->cc_image);
814 memcpy(cc->cc_image, image, icount);
815 memset(cc->cc_mask, 0, sizeof cc->cc_mask);
816 memcpy(cc->cc_mask, mask, icount);
818 sc->sc_changed |= v;
819 splx(s);
821 return (0);
822 #undef cc
825 static int
826 get_cursor(struct sfb_softc *sc, struct wsdisplay_cursor *p)
829 return (EPASSTHROUGH); /* XXX */
832 static void
833 set_curpos(struct sfb_softc *sc, struct wsdisplay_curpos *curpos)
835 struct rasops_info *ri = sc->sc_ri;
836 int x = curpos->x, y = curpos->y;
838 if (y < 0)
839 y = 0;
840 else if (y > ri->ri_height)
841 y = ri->ri_height;
842 if (x < 0)
843 x = 0;
844 else if (x > ri->ri_width)
845 x = ri->ri_width;
846 sc->sc_cursor.cc_pos.x = x;
847 sc->sc_cursor.cc_pos.y = y;
850 #define MODE_SIMPLE 0
851 #define MODE_OPAQUESTIPPLE 1
852 #define MODE_OPAQUELINE 2
853 #define MODE_TRANSPARENTSTIPPLE 5
854 #define MODE_TRANSPARENTLINE 6
855 #define MODE_COPY 7
857 /* parameters for 8bpp configuration */
858 #define SFBALIGNMASK 0x7
859 #define SFBSTIPPLEALL1 0xffffffff
860 #define SFBSTIPPLEBITS 32
861 #define SFBSTIPPLEBITMASK 0x1f
862 #define SFBSTIPPLEBYTESDONE 32
863 #define SFBCOPYALL1 0xffffffff
864 #define SFBCOPYBITS 32
865 #define SFBCOPYBITMASK 0x1f
866 #define SFBCOPYBYTESDONE 32
868 #if defined(pmax)
869 #define WRITE_MB()
870 #define BUMP(p) (p)
871 #endif
873 #if defined(alpha)
874 #define WRITE_MB() tc_wmb()
875 /* SFB registers replicated in 128B stride; cycle after eight iterations */
876 #define BUMP(p) ((p) = (void *)(((long)(p) + 0x80) & ~0x400))
877 #endif
879 #define SFBMODE(p, v) \
880 SFBWRITE32(BUMP(p), SFB_ASIC_MODE, (v))
881 #define SFBROP(p, v) \
882 SFBWRITE32(BUMP(p), SFB_ASIC_ROP, (v))
883 #define SFBPLANEMASK(p, v) \
884 SFBWRITE32(BUMP(p), SFB_ASIC_PLANEMASK, (v))
885 #define SFBPIXELMASK(p, v) \
886 SFBWRITE32(BUMP(p), SFB_ASIC_PIXELMASK, (v))
887 #define SFBADDRESS(p, v) \
888 SFBWRITE32(BUMP(p), SFB_ASIC_ADDRESS, (v))
889 #define SFBSTART(p, v) \
890 SFBWRITE32(BUMP(p), SFB_ASIC_START, (v))
891 #define SFBPIXELSHIFT(p, v) \
892 SFBWRITE32(BUMP(p), SFB_ASIC_PIXELSHIFT, (v))
893 #define SFBFG(p, v) \
894 SFBWRITE32(BUMP(p), SFB_ASIC_FG, (v))
895 #define SFBBG(p, v) \
896 SFBWRITE32(BUMP(p), SFB_ASIC_BG, (v))
899 * Paint the cursor.
901 static void
902 sfb_do_cursor(struct rasops_info *ri)
904 char *sfb, *p;
905 int scanspan, height, width, align, x, y;
906 uint32_t lmask, rmask;
908 x = ri->ri_ccol * ri->ri_font->fontwidth;
909 y = ri->ri_crow * ri->ri_font->fontheight;
910 scanspan = ri->ri_stride;
911 height = ri->ri_font->fontheight;
913 p = ri->ri_bits + y * scanspan + x;
914 align = (long)p & SFBALIGNMASK;
915 p -= align;
916 width = ri->ri_font->fontwidth + align;
917 lmask = SFBSTIPPLEALL1 << align;
918 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
919 sfb = (char *)ri->ri_hw + SFB_ASIC_OFFSET;
921 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
922 SFBPLANEMASK(sfb, ~0);
923 SFBROP(sfb, 6); /* ROP_XOR */
924 SFBFG(sfb, ~0);
926 lmask = lmask & rmask;
927 while (height > 0) {
928 SFBADDRESS(sfb, (long)p);
929 SFBSTART(sfb, lmask);
930 p += scanspan;
931 height--;
933 SFBMODE(sfb, MODE_SIMPLE);
934 SFBROP(sfb, 3); /* ROP_COPY */
938 * Paint a character.
940 static void
941 sfb_putchar(void *id, int row, int col, u_int uc, long attr)
943 struct rasops_info *ri = id;
944 char *sfb, *p;
945 int scanspan, height, width, align, x, y;
946 uint32_t lmask, rmask, glyph;
947 uint8_t *g;
949 x = col * ri->ri_font->fontwidth;
950 y = row * ri->ri_font->fontheight;
951 scanspan = ri->ri_stride;
952 height = ri->ri_font->fontheight;
953 uc -= ri->ri_font->firstchar;
954 g = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
956 p = ri->ri_bits + y * scanspan + x;
957 align = (long)p & SFBALIGNMASK;
958 p -= align;
959 width = ri->ri_font->fontwidth + align;
960 lmask = SFBSTIPPLEALL1 << align;
961 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
962 sfb = (char *)ri->ri_hw + SFB_ASIC_OFFSET;
964 SFBMODE(sfb, MODE_OPAQUESTIPPLE);
965 SFBPLANEMASK(sfb, ~0);
966 SFBFG(sfb, ri->ri_devcmap[(attr >> 24) & 15]);
967 SFBBG(sfb, ri->ri_devcmap[(attr >> 16) & 15]);
969 /* XXX 2B stride fonts only XXX */
970 lmask = lmask & rmask;
971 while (height > 0) {
972 glyph = *(uint16_t *)g; /* XXX */
973 SFBPIXELMASK(sfb, lmask);
974 SFBADDRESS(sfb, (long)p);
975 SFBSTART(sfb, glyph << align);
976 p += scanspan;
977 g += 2; /* XXX */
978 height--;
980 if (attr & 1 /* UNDERLINE */) {
981 p -= scanspan * 2;
982 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
983 SFBADDRESS(sfb, (long)p);
984 SFBSTART(sfb, lmask);
987 SFBMODE(sfb, MODE_SIMPLE);
988 SFBPIXELMASK(sfb, ~0); /* entire pixel */
991 #if 0
993 * Copy characters in a line.
995 static void
996 sfb_copycols(void *id, int row, int srccol, int dstcol, int ncols)
998 struct rasops_info *ri = id;
999 void *sp, *dp, *basex, *sfb;
1000 int scanspan, height, width, aligns, alignd, shift, w, y;
1001 uint32_t lmaskd, rmaskd;
1003 scanspan = ri->ri_stride;
1004 y = row * ri->ri_font->fontheight;
1005 basex = ri->ri_bits + y * scanspan;
1006 height = ri->ri_font->fontheight;
1007 w = ri->ri_font->fontwidth * ncols;
1009 sp = basex + ri->ri_font->fontwidth * srccol;
1010 aligns = (long)sp & SFBALIGNMASK;
1011 dp = basex + ri->ri_font->fontwidth * dstcol;
1012 alignd = (long)dp & SFBALIGNMASK;
1013 sfb = (void *)ri->ri_hw + SFB_ASIC_OFFSET;
1015 SFBMODE(sfb, MODE_COPY);
1016 SFBPLANEMASK(sfb, ~0);
1017 /* small enough to fit in a single 32bit */
1018 if ((aligns + w) <= SFBCOPYBITS && (alignd + w) <= SFBCOPYBITS) {
1019 SFBPIXELSHIFT(sfb, alignd - aligns);
1020 lmaskd = SFBCOPYALL1 << alignd;
1021 rmaskd = SFBCOPYALL1 >> (-(alignd + w) & SFBCOPYBITMASK);
1022 lmaskd = lmaskd & rmaskd;
1023 sp -= aligns;
1024 dp -= alignd;
1025 while (height > 0) {
1026 MEMWRITE32(sp, SFBCOPYALL1); WRITE_MB();
1027 MEMWRITE32(dp, lmaskd); WRITE_MB();
1028 sp += scanspan;
1029 dp += scanspan;
1030 height--;
1033 /* copy forward (left-to-right) */
1034 else if (dstcol < srccol || srccol + ncols < dstcol) {
1035 void *sq, dq;
1037 shift = alignd - aligns;
1038 if (shift < 0) {
1039 shift = 8 + shift; /* enforce right rotate */
1040 alignd += 8; /* bearing on left edge */
1042 width = alignd + w;
1043 lmaskd = SFBCOPYALL1 << alignd;
1044 rmaskd = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
1045 sp -= aligns;
1046 dp -= alignd;
1048 SFBPIXELSHIFT(sfb, shift);
1049 w = width;
1050 sq = sp;
1051 dq = dp;
1052 while (height > 0) {
1053 MEMWRITE32(sp, SFBCOPYALL1); WRITE_MB();
1054 MEMWRITE32(dp, lmaskd); WRITE_MB();
1055 width -= 2 * SFBCOPYBITS;
1056 while (width > 0) {
1057 sp += SFBCOPYBYTESDONE;
1058 dp += SFBCOPYBYTESDONE;
1059 MEMWRITE32(sp, SFBCOPYALL1); WRITE_MB();
1060 MEMWRITE32(dp, SFBCOPYALL1); WRITE_MB();
1061 width -= SFBCOPYBITS;
1063 sp += SFBCOPYBYTESDONE;
1064 dp += SFBCOPYBYTESDONE;
1065 MEMWRITE32(sp, SFBCOPYALL1); WRITE_MB();
1066 MEMWRITE32(dp, rmaskd); WRITE_MB();
1067 sp = (sq += scanspan);
1068 dp = (dq += scanspan);
1069 width = w;
1070 height--;
1073 /* copy backward (right-to-left) */
1074 else {
1075 void *sq, dq;
1077 shift = alignd - aligns;
1078 if (shift > 0) {
1079 shift = shift - 8; /* force left rotate */
1080 alignd += 24;
1082 width = alignd + w;
1083 lmaskd = SFBCOPYALL1 << alignd;
1084 rmaskd = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
1085 sp -= aligns;
1086 dp -= alignd;
1088 SFBPIXELSHIFT(sfb, shift);
1089 w = width;
1090 sq = sp += (((aligns + w) - 1) & ~31);
1091 dq = dp += (((alignd + w) - 1) & ~31);
1092 while (height > 0) {
1093 MEMWRITE32(sp, SFBCOPYALL1); WRITE_MB();
1094 MEMWRITE32(dp, rmaskd); WRITE_MB();
1095 width -= 2 * SFBCOPYBITS;
1096 while (width > 0) {
1097 sp -= SFBCOPYBYTESDONE;
1098 dp -= SFBCOPYBYTESDONE;
1099 MEMWRITE32(sp, SFBCOPYALL1); WRITE_MB();
1100 MEMWRITE32(dp, SFBCOPYALL1); WRITE_MB();
1101 width -= SFBCOPYBITS;
1103 sp -= SFBCOPYBYTESDONE;
1104 dp -= SFBCOPYBYTESDONE;
1105 MEMWRITE32(sp, SFBCOPYALL1); WRITE_MB();
1106 MEMWRITE32(dp, lmaskd); WRITE_MB();
1108 sp = (sq += scanspan);
1109 dp = (dq += scanspan);
1110 width = w;
1111 height--;
1114 SFBMODE(sfb, MODE_SIMPLE);
1115 SFBPIXELSHIFT(sfb, 0);
1117 #endif
1120 * Clear characters in a line.
1122 static void
1123 sfb_erasecols(void *id, int row, int startcol, int ncols, long attr)
1125 struct rasops_info *ri = id;
1126 char *sfb, *p;
1127 int scanspan, startx, height, width, align, w, y;
1128 uint32_t lmask, rmask;
1130 scanspan = ri->ri_stride;
1131 y = row * ri->ri_font->fontheight;
1132 startx = startcol * ri->ri_font->fontwidth;
1133 height = ri->ri_font->fontheight;
1134 w = ri->ri_font->fontwidth * ncols;
1136 p = ri->ri_bits + y * scanspan + startx;
1137 align = (long)p & SFBALIGNMASK;
1138 p -= align;
1139 width = w + align;
1140 lmask = SFBSTIPPLEALL1 << align;
1141 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
1142 sfb = (char *)ri->ri_hw + SFB_ASIC_OFFSET;
1144 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
1145 SFBPLANEMASK(sfb, ~0);
1146 SFBFG(sfb, ri->ri_devcmap[(attr >> 16) & 15]); /* fill with bg */
1147 if (width <= SFBSTIPPLEBITS) {
1148 lmask = lmask & rmask;
1149 while (height > 0) {
1150 SFBADDRESS(sfb, (long)p);
1151 SFBSTART(sfb, lmask);
1152 p += scanspan;
1153 height--;
1156 else {
1157 char *q = p;
1158 while (height > 0) {
1159 MEMWRITE32(p, lmask); WRITE_MB();
1160 width -= 2 * SFBSTIPPLEBITS;
1161 while (width > 0) {
1162 p += SFBSTIPPLEBYTESDONE;
1163 MEMWRITE32(p, SFBSTIPPLEALL1); WRITE_MB();
1164 width -= SFBSTIPPLEBITS;
1166 p += SFBSTIPPLEBYTESDONE;
1167 MEMWRITE32(p, rmask); WRITE_MB();
1168 WRITE_MB();
1170 p = (q += scanspan);
1171 width = w + align;
1172 height--;
1175 SFBMODE(sfb, MODE_SIMPLE);
1179 * Copy lines.
1181 static void
1182 sfb_copyrows(void *id, int srcrow, int dstrow, int nrows)
1184 struct rasops_info *ri = id;
1185 char *sfb, *p;
1186 int scanspan, offset, srcy, height, width, align, w;
1187 uint32_t lmask, rmask;
1189 scanspan = ri->ri_stride;
1190 height = ri->ri_font->fontheight * nrows;
1191 offset = (dstrow - srcrow) * ri->ri_yscale;
1192 srcy = ri->ri_font->fontheight * srcrow;
1193 if (srcrow < dstrow && srcrow + nrows > dstrow) {
1194 scanspan = -scanspan;
1195 srcy += height;
1198 p = ri->ri_bits + srcy * ri->ri_stride;
1199 align = (long)p & SFBALIGNMASK;
1200 p -= align;
1201 w = ri->ri_emuwidth;
1202 width = w + align;
1203 lmask = SFBCOPYALL1 << align;
1204 rmask = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
1205 sfb = (char *)ri->ri_hw + SFB_ASIC_OFFSET;
1207 SFBMODE(sfb, MODE_COPY);
1208 SFBPLANEMASK(sfb, ~0);
1209 SFBPIXELSHIFT(sfb, 0);
1210 if (width <= SFBCOPYBITS) {
1211 /* never happens */;
1213 else {
1214 char *q = p;
1215 while (height > 0) {
1216 MEMWRITE32(p, lmask);
1217 MEMWRITE32(p + offset, lmask);
1218 width -= 2 * SFBCOPYBITS;
1219 while (width > 0) {
1220 p += SFBCOPYBYTESDONE;
1221 MEMWRITE32(p, SFBCOPYALL1);
1222 MEMWRITE32(p + offset, SFBCOPYALL1);
1223 width -= SFBCOPYBITS;
1225 p += SFBCOPYBYTESDONE;
1226 MEMWRITE32(p, rmask);
1227 MEMWRITE32(p + offset, rmask);
1229 p = (q += scanspan);
1230 width = w + align;
1231 height--;
1234 SFBMODE(sfb, MODE_SIMPLE);
1238 * Erase lines.
1240 void
1241 sfb_eraserows(void *id, int startrow, int nrows, long attr)
1243 struct rasops_info *ri = id;
1244 char *sfb, *p;
1245 int scanspan, starty, height, width, align, w;
1246 uint32_t lmask, rmask;
1248 scanspan = ri->ri_stride;
1249 starty = ri->ri_font->fontheight * startrow;
1250 height = ri->ri_font->fontheight * nrows;
1252 p = ri->ri_bits + starty * scanspan;
1253 align = (long)p & SFBALIGNMASK;
1254 p -= align;
1255 w = ri->ri_emuwidth;
1256 width = w + align;
1257 lmask = SFBSTIPPLEALL1 << align;
1258 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
1259 sfb = (char *)ri->ri_hw + SFB_ASIC_OFFSET;
1261 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
1262 SFBPLANEMASK(sfb, ~0);
1263 SFBFG(sfb, ri->ri_devcmap[(attr >> 16) & 15]); /* fill with bg */
1264 if (width <= SFBSTIPPLEBITS) {
1265 /* never happens */;
1267 else {
1268 char *q = p;
1269 while (height > 0) {
1270 MEMWRITE32(p, lmask); WRITE_MB();
1271 width -= 2 * SFBSTIPPLEBITS;
1272 while (width > 0) {
1273 p += SFBSTIPPLEBYTESDONE;
1274 MEMWRITE32(p, SFBSTIPPLEALL1); WRITE_MB();
1275 width -= SFBSTIPPLEBITS;
1277 p += SFBSTIPPLEBYTESDONE;
1278 MEMWRITE32(p, rmask); WRITE_MB();
1280 p = (q += scanspan);
1281 width = w + align;
1282 height--;
1285 SFBMODE(sfb, MODE_SIMPLE);