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