1 /* $NetBSD: sfb.c,v 1.79 2009/08/20 12:55:26 tsutsui Exp $ */
4 * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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>
41 #include <sys/ioctl.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>
59 #define machine_btop(x) mips_btop(MIPS_KSEG1_TO_PHYS(x))
63 #define machine_btop(x) alpha_btop(ALPHA_K0SEG_TO_PHYS(x))
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 {
78 * Although HX has single Bt459, 32bit R/W can be done w/o any trouble.
87 /* Bt459 hardware registers, memory-mapped in 32bit stride */
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)
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
];
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
122 uint64_t cc_image
[CURSOR_MAX_SIZE
];
123 uint64_t cc_mask
[CURSOR_MAX_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
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
*);
158 static void sfb_copycols(void *, int, int, int, int);
161 static struct wsscreen_descr sfb_stdscreen
= {
168 static const struct wsscreen_descr
*_sfb_scrlist
[] = {
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
= {
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,
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)
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
;
268 console
= (ta
->ta_addr
== sfb_consaddr
);
270 sc
->sc_ri
= ri
= &sfb_console_ri
;
274 ri
= malloc(sizeof(struct rasops_info
),
275 M_DEVBUF
, M_NOWAIT
|M_ZERO
);
277 printf(": can't alloc memory\n");
281 ri
->ri_hw
= (void *)ta
->ta_addr
;
285 printf(": %dx%d, %dbpp\n", ri
->ri_width
, ri
->ri_height
, ri
->ri_depth
);
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
);
310 sfb_cmap_init(struct sfb_softc
*sc
)
312 struct hwcmap256
*cm
;
318 for (index
= 0; index
< CMAP_SIZE
; index
++, p
+= 3) {
326 sfb_common_init(struct rasops_info
*ri
)
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
);
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 */
347 ri
->ri_flg
= RI_CENTER
;
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
);
358 /* prefer 12 pixel wide font */
359 cookie
= wsfont_find(NULL
, 12, 0, 0, WSDISPLAY_FONTORDER_R2L
,
360 WSDISPLAY_FONTORDER_L2R
);
362 cookie
= wsfont_find(NULL
, 0, 0, 0, WSDISPLAY_FONTORDER_R2L
,
363 WSDISPLAY_FONTORDER_L2R
);
365 printf("sfb: font table is empty\n");
369 /* the accelerated sfb_putchar() needs LSbit left */
370 if (wsfont_lock(cookie
, &ri
->ri_font
)) {
371 printf("sfb: couldn't lock font\n");
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
;
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
;
400 case WSDISPLAYIO_GTYPE
:
401 *(u_int
*)data
= WSDISPLAY_TYPE_SFB
;
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
;
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
;
427 case WSDISPLAYIO_GVIDEO
:
428 *(u_int
*)data
= sc
->sc_blanked
?
429 WSDISPLAYIO_VIDEO_OFF
: WSDISPLAYIO_VIDEO_ON
;
432 case WSDISPLAYIO_GCURPOS
:
433 *(struct wsdisplay_curpos
*)data
= sc
->sc_cursor
.cc_pos
;
436 case WSDISPLAYIO_SCURPOS
:
438 set_curpos(sc
, (struct wsdisplay_curpos
*)data
);
439 sc
->sc_changed
|= WSDISPLAY_CURSOR_DOPOS
;
443 case WSDISPLAYIO_GCURMAX
:
444 ((struct wsdisplay_curpos
*)data
)->x
=
445 ((struct wsdisplay_curpos
*)data
)->y
= CURSOR_MAX_SIZE
;
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
) {
460 sc
->sc_changed
|= (WSDISPLAY_CURSOR_DOCUR
|
461 WSDISPLAY_CMAP_DOLUT
);
467 return (EPASSTHROUGH
);
471 sfb_screenblank(struct sfb_softc
*sc
)
473 struct rasops_info
*ri
;
477 asic
= (char *)ri
->ri_hw
+ SFB_ASIC_OFFSET
;
478 SFBWRITE32(asic
, SFB_ASIC_VIDEO_VALID
, !sc
->sc_blanked
);
483 sfbmmap(void *v
, void *vs
, off_t offset
, int prot
)
485 struct sfb_softc
*sc
= v
;
487 if (offset
>= SFB_SIZE
|| offset
< 0)
489 return machine_btop(sc
->sc_vaddr
+ offset
);
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
;
500 if (sc
->nscreens
> 0)
503 *cookiep
= ri
; /* one and only for now */
506 (*ri
->ri_ops
.allocattr
)(ri
, 0, 0, 0, &defattr
);
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");
524 sfb_show_screen(void *v
, void *cookie
, int waitok
,
525 void (*cb
)(void *, int, int), void *cbarg
)
532 sfb_cnattach(tc_addr_t addr
)
534 struct rasops_info
*ri
;
537 ri
= &sfb_console_ri
;
538 ri
->ri_hw
= (void *)addr
;
540 (*ri
->ri_ops
.allocattr
)(&ri
, 0, 0, 0, &defattr
);
541 wsdisplay_cnattach(&sfb_stdscreen
, ri
, 0, 0, defattr
);
549 struct sfb_softc
*sc
= arg
;
550 char *base
, *asic
, *vdac
;
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)
561 vdac
= base
+ SFB_RAMDAC_OFFSET
;
563 if (v
& WSDISPLAY_CURSOR_DOCUR
) {
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
)) {
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
;
601 ip
= (uint8_t *)sc
->sc_cursor
.cc_image
;
602 mp
= (uint8_t *)sc
->sc_cursor
.cc_mask
;
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);
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
]);
624 /* pad unoccupied scan lines */
625 while (bcnt
< CURSOR_MAX_SIZE
* 16) {
626 REGWRITE32(vdac
, bt_reg
, 0);
627 REGWRITE32(vdac
, bt_reg
, 0);
631 if (v
& WSDISPLAY_CMAP_DOLUT
) {
632 struct hwcmap256
*cm
= &sc
->sc_cmap
;
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
]);
648 sfbhwinit(void *base
)
650 char *vdac
= (char *)base
+ SFB_RAMDAC_OFFSET
;
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 */
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);
716 get_cmap(struct sfb_softc
*sc
, struct wsdisplay_cmap
*p
)
718 u_int index
= p
->index
, count
= p
->count
;
721 if (index
>= CMAP_SIZE
|| count
> CMAP_SIZE
- index
)
724 error
= copyout(&sc
->sc_cmap
.r
[index
], p
->red
, count
);
727 error
= copyout(&sc
->sc_cmap
.g
[index
], p
->green
, count
);
730 error
= copyout(&sc
->sc_cmap
.b
[index
], p
->blue
, count
);
735 set_cmap(struct sfb_softc
*sc
, struct wsdisplay_cmap
*p
)
737 struct hwcmap256 cmap
;
738 u_int index
= p
->index
, count
= p
->count
;
741 if (index
>= CMAP_SIZE
|| count
> CMAP_SIZE
- index
)
744 error
= copyin(p
->red
, &cmap
.r
[index
], count
);
747 error
= copyin(p
->green
, &cmap
.g
[index
], count
);
750 error
= copyin(p
->blue
, &cmap
.b
[index
], count
);
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
;
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];
772 if (v
& WSDISPLAY_CURSOR_DOCMAP
) {
773 index
= p
->cmap
.index
;
774 count
= p
->cmap
.count
;
775 if (index
>= 2 || (index
+ count
) > 2)
777 error
= copyin(p
->cmap
.red
, &r
[index
], count
);
780 error
= copyin(p
->cmap
.green
, &g
[index
], count
);
783 error
= copyin(p
->cmap
.blue
, &b
[index
], count
);
787 if (v
& WSDISPLAY_CURSOR_DOSHAPE
) {
788 if (p
->size
.x
> CURSOR_MAX_SIZE
|| p
->size
.y
> CURSOR_MAX_SIZE
)
790 icount
= ((p
->size
.x
< 33) ? 4 : 8) * p
->size
.y
;
791 error
= copyin(p
->image
, image
, icount
);
794 error
= copyin(p
->mask
, mask
, icount
);
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
)
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
);
826 get_cursor(struct sfb_softc
*sc
, struct wsdisplay_cursor
*p
)
829 return (EPASSTHROUGH
); /* XXX */
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
;
840 else if (y
> ri
->ri_height
)
844 else if (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
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
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))
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))
902 sfb_do_cursor(struct rasops_info
*ri
)
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
;
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 */
926 lmask
= lmask
& rmask
;
928 SFBADDRESS(sfb
, (long)p
);
929 SFBSTART(sfb
, lmask
);
933 SFBMODE(sfb
, MODE_SIMPLE
);
934 SFBROP(sfb
, 3); /* ROP_COPY */
941 sfb_putchar(void *id
, int row
, int col
, u_int uc
, long attr
)
943 struct rasops_info
*ri
= id
;
945 int scanspan
, height
, width
, align
, x
, y
;
946 uint32_t lmask
, rmask
, glyph
;
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
;
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
;
972 glyph
= *(uint16_t *)g
; /* XXX */
973 SFBPIXELMASK(sfb
, lmask
);
974 SFBADDRESS(sfb
, (long)p
);
975 SFBSTART(sfb
, glyph
<< align
);
980 if (attr
& 1 /* UNDERLINE */) {
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 */
993 * Copy characters in a line.
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
;
1025 while (height
> 0) {
1026 MEMWRITE32(sp
, SFBCOPYALL1
); WRITE_MB();
1027 MEMWRITE32(dp
, lmaskd
); WRITE_MB();
1033 /* copy forward (left-to-right) */
1034 else if (dstcol
< srccol
|| srccol
+ ncols
< dstcol
) {
1037 shift
= alignd
- aligns
;
1039 shift
= 8 + shift
; /* enforce right rotate */
1040 alignd
+= 8; /* bearing on left edge */
1043 lmaskd
= SFBCOPYALL1
<< alignd
;
1044 rmaskd
= SFBCOPYALL1
>> (-width
& SFBCOPYBITMASK
);
1048 SFBPIXELSHIFT(sfb
, shift
);
1052 while (height
> 0) {
1053 MEMWRITE32(sp
, SFBCOPYALL1
); WRITE_MB();
1054 MEMWRITE32(dp
, lmaskd
); WRITE_MB();
1055 width
-= 2 * SFBCOPYBITS
;
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
);
1073 /* copy backward (right-to-left) */
1077 shift
= alignd
- aligns
;
1079 shift
= shift
- 8; /* force left rotate */
1083 lmaskd
= SFBCOPYALL1
<< alignd
;
1084 rmaskd
= SFBCOPYALL1
>> (-width
& SFBCOPYBITMASK
);
1088 SFBPIXELSHIFT(sfb
, shift
);
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
;
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
);
1114 SFBMODE(sfb
, MODE_SIMPLE
);
1115 SFBPIXELSHIFT(sfb
, 0);
1120 * Clear characters in a line.
1123 sfb_erasecols(void *id
, int row
, int startcol
, int ncols
, long attr
)
1125 struct rasops_info
*ri
= id
;
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
;
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
);
1158 while (height
> 0) {
1159 MEMWRITE32(p
, lmask
); WRITE_MB();
1160 width
-= 2 * SFBSTIPPLEBITS
;
1162 p
+= SFBSTIPPLEBYTESDONE
;
1163 MEMWRITE32(p
, SFBSTIPPLEALL1
); WRITE_MB();
1164 width
-= SFBSTIPPLEBITS
;
1166 p
+= SFBSTIPPLEBYTESDONE
;
1167 MEMWRITE32(p
, rmask
); WRITE_MB();
1170 p
= (q
+= scanspan
);
1175 SFBMODE(sfb
, MODE_SIMPLE
);
1182 sfb_copyrows(void *id
, int srcrow
, int dstrow
, int nrows
)
1184 struct rasops_info
*ri
= id
;
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
;
1198 p
= ri
->ri_bits
+ srcy
* ri
->ri_stride
;
1199 align
= (long)p
& SFBALIGNMASK
;
1201 w
= ri
->ri_emuwidth
;
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 */;
1215 while (height
> 0) {
1216 MEMWRITE32(p
, lmask
);
1217 MEMWRITE32(p
+ offset
, lmask
);
1218 width
-= 2 * SFBCOPYBITS
;
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
);
1234 SFBMODE(sfb
, MODE_SIMPLE
);
1241 sfb_eraserows(void *id
, int startrow
, int nrows
, long attr
)
1243 struct rasops_info
*ri
= id
;
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
;
1255 w
= ri
->ri_emuwidth
;
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 */;
1269 while (height
> 0) {
1270 MEMWRITE32(p
, lmask
); WRITE_MB();
1271 width
-= 2 * SFBSTIPPLEBITS
;
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
);
1285 SFBMODE(sfb
, MODE_SIMPLE
);