sfb.c revision 1.77 1 /* $NetBSD: sfb.c,v 1.77 2008/07/09 13:19:33 joerg Exp $ */
2
3 /*-
4 * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Tohru Nishimura.
9 *
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.
18 *
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.
30 */
31
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: sfb.c,v 1.77 2008/07/09 13:19:33 joerg Exp $");
34
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>
42
43 #include <sys/bus.h>
44 #include <sys/intr.h>
45
46 #include <dev/wscons/wsconsio.h>
47 #include <dev/wscons/wsdisplayvar.h>
48
49 #include <dev/rasops/rasops.h>
50 #include <dev/wsfont/wsfont.h>
51
52 #include <dev/tc/tcvar.h>
53 #include <dev/ic/bt459reg.h>
54 #include <dev/tc/sfbreg.h>
55
56 #include <uvm/uvm_extern.h>
57
58 #if defined(pmax)
59 #define machine_btop(x) mips_btop(MIPS_KSEG1_TO_PHYS(x))
60 #endif
61
62 #if defined(alpha)
63 #define machine_btop(x) alpha_btop(ALPHA_K0SEG_TO_PHYS(x))
64 #endif
65
66 /*
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 * u_int8_t u0;
73 * u_int8_t u1;
74 * u_int8_t u2;
75 * unsigned :8;
76 * } bt_lo;
77 *
78 * Although HX has single Bt459, 32bit R/W can be done w/o any trouble.
79 * struct bt459reg {
80 * u_int32_t bt_lo;
81 * u_int32_t bt_hi;
82 * u_int32_t bt_reg;
83 * u_int32_t bt_cmap;
84 * };
85 */
86
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
92
93 #define REGWRITE32(p,i,v) do { \
94 *(volatile u_int32_t *)((p) + (i)) = (v); tc_wmb(); \
95 } while (/* CONSTCOND */ 0)
96 #define SFBWRITE32(p,i,v) do { \
97 *(volatile u_int32_t *)((p) + (i)) = (v); \
98 } while (/* CONSTCOND */ 0)
99 #define MEMWRITE32(p,v) do { \
100 *(volatile u_int32_t *)(p) = (v); \
101 } while (/* CONSTCOND */ 0)
102
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)
107
108 struct hwcmap256 {
109 #define CMAP_SIZE 256 /* 256 R/G/B entries */
110 u_int8_t r[CMAP_SIZE];
111 u_int8_t g[CMAP_SIZE];
112 u_int8_t b[CMAP_SIZE];
113 };
114
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 u_int8_t cc_color[6];
122 u_int64_t cc_image[CURSOR_MAX_SIZE];
123 u_int64_t cc_mask[CURSOR_MAX_SIZE];
124 };
125
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;
137 };
138
139 #define HX_MAGIC_X 368
140 #define HX_MAGIC_Y 38
141
142 static int sfbmatch(device_t, cfdata_t, void *);
143 static void sfbattach(device_t, device_t, void *);
144
145 CFATTACH_DECL_NEW(sfb, sizeof(struct sfb_softc),
146 sfbmatch, sfbattach, NULL, NULL);
147
148 static void sfb_common_init(struct rasops_info *);
149 static struct rasops_info sfb_console_ri;
150 static tc_addr_t sfb_consaddr;
151
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
160
161 static struct wsscreen_descr sfb_stdscreen = {
162 "std", 0, 0,
163 0, /* textops */
164 0, 0,
165 WSSCREEN_REVERSE
166 };
167
168 static const struct wsscreen_descr *_sfb_scrlist[] = {
169 &sfb_stdscreen,
170 };
171
172 static const struct wsscreen_list sfb_screenlist = {
173 sizeof(_sfb_scrlist) / sizeof(struct wsscreen_descr *), _sfb_scrlist
174 };
175
176 static int sfbioctl(void *, void *, u_long, void *, int, struct lwp *);
177 static paddr_t sfbmmap(void *, void *, off_t, int);
178
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 *);
184
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 */
192 };
193
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 *);
199
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 *);
205
206 /*
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
212 */
213 static const u_int8_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,
246 };
247
248 static int
249 sfbmatch(device_t parent, cfdata_t match, void *aux)
250 {
251 struct tc_attach_args *ta = aux;
252
253 if (strncmp("PMAGB-BA", ta->ta_modname, TC_ROM_LLEN) != 0)
254 return (0);
255 return (1);
256 }
257
258 static void
259 sfbattach(device_t parent, device_t self, void *aux)
260 {
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;
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 sfb_cmap_init(sc);
289
290 sc->sc_vaddr = ta->ta_addr;
291 sc->sc_cursor.cc_magic.x = HX_MAGIC_X;
292 sc->sc_cursor.cc_magic.y = HX_MAGIC_Y;
293 sc->sc_blanked = sc->sc_curenb = 0;
294
295 tc_intr_establish(parent, ta->ta_cookie, IPL_TTY, sfbintr, sc);
296
297 asic = (char *)ri->ri_hw + SFB_ASIC_OFFSET;
298
299 SFBWRITE32(asic, SFB_ASIC_CLEAR_INTR, 0);
300 SFBWRITE32(asic, SFB_ASIC_ENABLE_INTR, 1);
301
302 waa.console = console;
303 waa.scrdata = &sfb_screenlist;
304 waa.accessops = &sfb_accessops;
305 waa.accesscookie = sc;
306
307 config_found(self, &waa, wsemuldisplaydevprint);
308 }
309
310 static void
311 sfb_cmap_init(struct sfb_softc *sc)
312 {
313 struct hwcmap256 *cm;
314 const u_int8_t *p;
315 int index;
316
317 cm = &sc->sc_cmap;
318 p = rasops_cmap;
319 for (index = 0; index < CMAP_SIZE; index++, p += 3) {
320 cm->r[index] = p[0];
321 cm->g[index] = p[1];
322 cm->b[index] = p[2];
323 }
324 }
325
326 static void
327 sfb_common_init(struct rasops_info *ri)
328 {
329 char *base, *asic;
330 int hsetup, vsetup, vbase, cookie;
331
332 base = (void *)ri->ri_hw;
333 asic = base + SFB_ASIC_OFFSET;
334 hsetup = *(u_int32_t *)(asic + SFB_ASIC_VIDEO_HSETUP);
335 vsetup = *(u_int32_t *)(asic + SFB_ASIC_VIDEO_VSETUP);
336
337 vbase = 1;
338 SFBWRITE32(asic, SFB_ASIC_VIDEO_BASE, vbase);
339 SFBWRITE32(asic, SFB_ASIC_PLANEMASK, ~0);
340 SFBWRITE32(asic, SFB_ASIC_PIXELMASK, ~0);
341 SFBWRITE32(asic, SFB_ASIC_MODE, 0); /* MODE_SIMPLE */
342 SFBWRITE32(asic, SFB_ASIC_ROP, 3); /* ROP_COPY */
343 SFBWRITE32(asic, 0x180000, 0); /* Bt459 reset */
344
345 /* initialize colormap and cursor hardware */
346 sfbhwinit(base);
347
348 ri->ri_flg = RI_CENTER;
349 ri->ri_depth = 8;
350 ri->ri_width = (hsetup & 0x1ff) << 2;
351 ri->ri_height = (vsetup & 0x7ff);
352 ri->ri_stride = ri->ri_width * (ri->ri_depth / 8);
353 ri->ri_bits = base + SFB_FB_OFFSET + vbase * 4096;
354
355 /* clear the screen */
356 memset(ri->ri_bits, 0, ri->ri_stride * ri->ri_height);
357
358 wsfont_init();
359 /* prefer 12 pixel wide font */
360 cookie = wsfont_find(NULL, 12, 0, 0, WSDISPLAY_FONTORDER_R2L,
361 WSDISPLAY_FONTORDER_L2R);
362 if (cookie <= 0)
363 cookie = wsfont_find(NULL, 0, 0, 0, WSDISPLAY_FONTORDER_R2L,
364 WSDISPLAY_FONTORDER_L2R);
365 if (cookie <= 0) {
366 printf("sfb: font table is empty\n");
367 return;
368 }
369
370 /* the accelerated sfb_putchar() needs LSbit left */
371 if (wsfont_lock(cookie, &ri->ri_font)) {
372 printf("sfb: couldn't lock font\n");
373 return;
374 }
375 ri->ri_wsfcookie = cookie;
376
377 rasops_init(ri, 34, 80);
378
379 /* add our accelerated functions */
380 ri->ri_ops.putchar = sfb_putchar;
381 ri->ri_ops.erasecols = sfb_erasecols;
382 ri->ri_ops.copyrows = sfb_copyrows;
383 ri->ri_ops.eraserows = sfb_eraserows;
384 ri->ri_do_cursor = sfb_do_cursor;
385
386 /* XXX shouldn't be global */
387 sfb_stdscreen.nrows = ri->ri_rows;
388 sfb_stdscreen.ncols = ri->ri_cols;
389 sfb_stdscreen.textops = &ri->ri_ops;
390 sfb_stdscreen.capabilities = ri->ri_caps;
391 }
392
393 static int
394 sfbioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l)
395 {
396 struct sfb_softc *sc = v;
397 struct rasops_info *ri = sc->sc_ri;
398 int turnoff, s;
399
400 switch (cmd) {
401 case WSDISPLAYIO_GTYPE:
402 *(u_int *)data = WSDISPLAY_TYPE_SFB;
403 return (0);
404
405 case WSDISPLAYIO_GINFO:
406 #define wsd_fbip ((struct wsdisplay_fbinfo *)data)
407 wsd_fbip->height = ri->ri_height;
408 wsd_fbip->width = ri->ri_width;
409 wsd_fbip->depth = ri->ri_depth;
410 wsd_fbip->cmsize = CMAP_SIZE;
411 #undef fbt
412 return (0);
413
414 case WSDISPLAYIO_GETCMAP:
415 return get_cmap(sc, (struct wsdisplay_cmap *)data);
416
417 case WSDISPLAYIO_PUTCMAP:
418 return set_cmap(sc, (struct wsdisplay_cmap *)data);
419
420 case WSDISPLAYIO_SVIDEO:
421 turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF;
422 if (sc->sc_blanked != turnoff) {
423 sc->sc_blanked = turnoff;
424 sfb_screenblank(sc);
425 }
426 return (0);
427
428 case WSDISPLAYIO_GVIDEO:
429 *(u_int *)data = sc->sc_blanked ?
430 WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON;
431 return (0);
432
433 case WSDISPLAYIO_GCURPOS:
434 *(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos;
435 return (0);
436
437 case WSDISPLAYIO_SCURPOS:
438 s = spltty();
439 set_curpos(sc, (struct wsdisplay_curpos *)data);
440 sc->sc_changed |= WSDISPLAY_CURSOR_DOPOS;
441 splx(s);
442 return (0);
443
444 case WSDISPLAYIO_GCURMAX:
445 ((struct wsdisplay_curpos *)data)->x =
446 ((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE;
447 return (0);
448
449 case WSDISPLAYIO_GCURSOR:
450 return get_cursor(sc, (struct wsdisplay_cursor *)data);
451
452 case WSDISPLAYIO_SCURSOR:
453 return set_cursor(sc, (struct wsdisplay_cursor *)data);
454
455 case WSDISPLAYIO_SMODE:
456 if (*(int *)data == WSDISPLAYIO_MODE_EMUL) {
457 s = spltty();
458 sfb_cmap_init(sc);
459 sc->sc_curenb = 0;
460 sc->sc_blanked = 0;
461 sc->sc_changed |= (WSDISPLAY_CURSOR_DOCUR |
462 WSDISPLAY_CMAP_DOLUT);
463 splx(s);
464 sfb_screenblank(sc);
465 }
466 return (0);
467 }
468 return (EPASSTHROUGH);
469 }
470
471 static void
472 sfb_screenblank(struct sfb_softc *sc)
473 {
474 struct rasops_info *ri;
475 char *asic;
476
477 ri = sc->sc_ri;
478 asic = (char *)ri->ri_hw + SFB_ASIC_OFFSET;
479 SFBWRITE32(asic, SFB_ASIC_VIDEO_VALID, !sc->sc_blanked);
480 tc_wmb();
481 }
482
483 static paddr_t
484 sfbmmap(void *v, void *vs, off_t offset, int prot)
485 {
486 struct sfb_softc *sc = v;
487
488 if (offset >= SFB_SIZE || offset < 0)
489 return (-1);
490 return machine_btop(sc->sc_vaddr + offset);
491 }
492
493 static int
494 sfb_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
495 int *curxp, int *curyp, long *attrp)
496 {
497 struct sfb_softc *sc = v;
498 struct rasops_info *ri = sc->sc_ri;
499 long defattr;
500
501 if (sc->nscreens > 0)
502 return (ENOMEM);
503
504 *cookiep = ri; /* one and only for now */
505 *curxp = 0;
506 *curyp = 0;
507 (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
508 *attrp = defattr;
509 sc->nscreens++;
510 return (0);
511 }
512
513 static void
514 sfb_free_screen(void *v, void *cookie)
515 {
516 struct sfb_softc *sc = v;
517
518 if (sc->sc_ri == &sfb_console_ri)
519 panic("sfb_free_screen: console");
520
521 sc->nscreens--;
522 }
523
524 static int
525 sfb_show_screen(void *v, void *cookie, int waitok,
526 void (*cb)(void *, int, int), void *cbarg)
527 {
528
529 return (0);
530 }
531
532 /* EXPORT */ int
533 sfb_cnattach(tc_addr_t addr)
534 {
535 struct rasops_info *ri;
536 long defattr;
537
538 ri = &sfb_console_ri;
539 ri->ri_hw = (void *)addr;
540 sfb_common_init(ri);
541 (*ri->ri_ops.allocattr)(&ri, 0, 0, 0, &defattr);
542 wsdisplay_cnattach(&sfb_stdscreen, ri, 0, 0, defattr);
543 sfb_consaddr = addr;
544 return (0);
545 }
546
547 static int
548 sfbintr(void *arg)
549 {
550 struct sfb_softc *sc = arg;
551 char *base, *asic, *vdac;
552 int v;
553
554 base = (void *)sc->sc_ri->ri_hw;
555 asic = base + SFB_ASIC_OFFSET;
556 SFBWRITE32(asic, SFB_ASIC_CLEAR_INTR, 0);
557 /* SFBWRITE32(asic, SFB_ASIC_ENABLE_INTR, 1); */
558
559 if (sc->sc_changed == 0)
560 goto done;
561
562 vdac = base + SFB_RAMDAC_OFFSET;
563 v = sc->sc_changed;
564 if (v & WSDISPLAY_CURSOR_DOCUR) {
565 int onoff;
566
567 onoff = (sc->sc_curenb) ? 0xc0 : 0x00;
568 VDACSELECT(vdac, BT459_IREG_CCR);
569 REGWRITE32(vdac, bt_reg, onoff);
570 }
571 if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT)) {
572 int x, y;
573
574 x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x;
575 y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y;
576 x += sc->sc_cursor.cc_magic.x;
577 y += sc->sc_cursor.cc_magic.y;
578
579 VDACSELECT(vdac, BT459_IREG_CURSOR_X_LOW);
580 REGWRITE32(vdac, bt_reg, x);
581 REGWRITE32(vdac, bt_reg, x >> 8);
582 REGWRITE32(vdac, bt_reg, y);
583 REGWRITE32(vdac, bt_reg, y >> 8);
584 }
585 if (v & WSDISPLAY_CURSOR_DOCMAP) {
586 u_int8_t *cp = sc->sc_cursor.cc_color;
587
588 VDACSELECT(vdac, BT459_IREG_CCOLOR_2);
589 REGWRITE32(vdac, bt_reg, cp[1]);
590 REGWRITE32(vdac, bt_reg, cp[3]);
591 REGWRITE32(vdac, bt_reg, cp[5]);
592
593 REGWRITE32(vdac, bt_reg, cp[0]);
594 REGWRITE32(vdac, bt_reg, cp[2]);
595 REGWRITE32(vdac, bt_reg, cp[4]);
596 }
597 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
598 u_int8_t *ip, *mp, img, msk;
599 u_int8_t u;
600 int bcnt;
601
602 ip = (u_int8_t *)sc->sc_cursor.cc_image;
603 mp = (u_int8_t *)sc->sc_cursor.cc_mask;
604
605 bcnt = 0;
606 VDACSELECT(vdac, BT459_IREG_CRAM_BASE+0);
607 /* 64 pixel scan line is consisted with 16 byte cursor ram */
608 while (bcnt < sc->sc_cursor.cc_size.y * 16) {
609 /* pad right half 32 pixel when smaller than 33 */
610 if ((bcnt & 0x8) && sc->sc_cursor.cc_size.x < 33) {
611 REGWRITE32(vdac, bt_reg, 0);
612 REGWRITE32(vdac, bt_reg, 0);
613 }
614 else {
615 img = *ip++;
616 msk = *mp++;
617 img &= msk; /* cookie off image */
618 u = (msk & 0x0f) << 4 | (img & 0x0f);
619 REGWRITE32(vdac, bt_reg, shuffle[u]);
620 u = (msk & 0xf0) | (img & 0xf0) >> 4;
621 REGWRITE32(vdac, bt_reg, shuffle[u]);
622 }
623 bcnt += 2;
624 }
625 /* pad unoccupied scan lines */
626 while (bcnt < CURSOR_MAX_SIZE * 16) {
627 REGWRITE32(vdac, bt_reg, 0);
628 REGWRITE32(vdac, bt_reg, 0);
629 bcnt += 2;
630 }
631 }
632 if (v & WSDISPLAY_CMAP_DOLUT) {
633 struct hwcmap256 *cm = &sc->sc_cmap;
634 int index;
635
636 VDACSELECT(vdac, 0);
637 for (index = 0; index < CMAP_SIZE; index++) {
638 REGWRITE32(vdac, bt_cmap, cm->r[index]);
639 REGWRITE32(vdac, bt_cmap, cm->g[index]);
640 REGWRITE32(vdac, bt_cmap, cm->b[index]);
641 }
642 }
643 sc->sc_changed = 0;
644 done:
645 return (1);
646 }
647
648 static void
649 sfbhwinit(void *base)
650 {
651 char *vdac = (char *)base + SFB_RAMDAC_OFFSET;
652 const u_int8_t *p;
653 int i;
654
655 VDACSELECT(vdac, BT459_IREG_COMMAND_0);
656 REGWRITE32(vdac, bt_reg, 0x40); /* CMD0 */
657 REGWRITE32(vdac, bt_reg, 0x0); /* CMD1 */
658 REGWRITE32(vdac, bt_reg, 0xc0); /* CMD2 */
659 REGWRITE32(vdac, bt_reg, 0xff); /* PRM */
660 REGWRITE32(vdac, bt_reg, 0); /* 205 */
661 REGWRITE32(vdac, bt_reg, 0x0); /* PBM */
662 REGWRITE32(vdac, bt_reg, 0); /* 207 */
663 REGWRITE32(vdac, bt_reg, 0x0); /* ORM */
664 REGWRITE32(vdac, bt_reg, 0x0); /* OBM */
665 REGWRITE32(vdac, bt_reg, 0x0); /* ILV */
666 REGWRITE32(vdac, bt_reg, 0x0); /* TEST */
667
668 VDACSELECT(vdac, BT459_IREG_CCR);
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);
681 REGWRITE32(vdac, bt_reg, 0x0);
682
683 /* build sane colormap */
684 VDACSELECT(vdac, 0);
685 p = rasops_cmap;
686 for (i = 0; i < CMAP_SIZE; i++, p += 3) {
687 REGWRITE32(vdac, bt_cmap, p[0]);
688 REGWRITE32(vdac, bt_cmap, p[1]);
689 REGWRITE32(vdac, bt_cmap, p[2]);
690 }
691
692 /* clear out cursor image */
693 VDACSELECT(vdac, BT459_IREG_CRAM_BASE);
694 for (i = 0; i < 1024; i++)
695 REGWRITE32(vdac, bt_reg, 0xff);
696
697 /*
698 * 2 bit/pixel cursor. Assign MSB for cursor mask and LSB for
699 * cursor image. CCOLOR_2 for mask color, while CCOLOR_3 for
700 * image color. CCOLOR_1 will be never used.
701 */
702 VDACSELECT(vdac, BT459_IREG_CCOLOR_1);
703 REGWRITE32(vdac, bt_reg, 0xff);
704 REGWRITE32(vdac, bt_reg, 0xff);
705 REGWRITE32(vdac, bt_reg, 0xff);
706
707 REGWRITE32(vdac, bt_reg, 0);
708 REGWRITE32(vdac, bt_reg, 0);
709 REGWRITE32(vdac, bt_reg, 0);
710
711 REGWRITE32(vdac, bt_reg, 0xff);
712 REGWRITE32(vdac, bt_reg, 0xff);
713 REGWRITE32(vdac, bt_reg, 0xff);
714 }
715
716 static int
717 get_cmap(struct sfb_softc *sc, struct wsdisplay_cmap *p)
718 {
719 u_int index = p->index, count = p->count;
720 int error;
721
722 if (index >= CMAP_SIZE || count > CMAP_SIZE - index)
723 return (EINVAL);
724
725 error = copyout(&sc->sc_cmap.r[index], p->red, count);
726 if (error)
727 return error;
728 error = copyout(&sc->sc_cmap.g[index], p->green, count);
729 if (error)
730 return error;
731 error = copyout(&sc->sc_cmap.b[index], p->blue, count);
732 return error;
733 }
734
735 static int
736 set_cmap(struct sfb_softc *sc, struct wsdisplay_cmap *p)
737 {
738 struct hwcmap256 cmap;
739 u_int index = p->index, count = p->count;
740 int error, s;
741
742 if (index >= CMAP_SIZE || count > CMAP_SIZE - index)
743 return (EINVAL);
744
745 error = copyin(p->red, &cmap.r[index], count);
746 if (error)
747 return error;
748 error = copyin(p->green, &cmap.g[index], count);
749 if (error)
750 return error;
751 error = copyin(p->blue, &cmap.b[index], count);
752 if (error)
753 return error;
754
755 s = spltty();
756 memcpy(&sc->sc_cmap.r[index], &cmap.r[index], count);
757 memcpy(&sc->sc_cmap.g[index], &cmap.g[index], count);
758 memcpy(&sc->sc_cmap.b[index], &cmap.b[index], count);
759 sc->sc_changed |= WSDISPLAY_CMAP_DOLUT;
760 splx(s);
761 return (0);
762 }
763
764 static int
765 set_cursor(struct sfb_softc *sc, struct wsdisplay_cursor *p)
766 {
767 #define cc (&sc->sc_cursor)
768 u_int v, index = 0, count = 0, icount = 0;
769 uint8_t r[2], g[2], b[2], image[512], mask[512];
770 int error, s;
771
772 v = p->which;
773 if (v & WSDISPLAY_CURSOR_DOCMAP) {
774 index = p->cmap.index;
775 count = p->cmap.count;
776 if (index >= 2 || (index + count) > 2)
777 return (EINVAL);
778 error = copyin(p->cmap.red, &r[index], count);
779 if (error)
780 return error;
781 error = copyin(p->cmap.green, &g[index], count);
782 if (error)
783 return error;
784 error = copyin(p->cmap.blue, &b[index], count);
785 if (error)
786 return error;
787 }
788 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
789 if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE)
790 return (EINVAL);
791 icount = ((p->size.x < 33) ? 4 : 8) * p->size.y;
792 error = copyin(p->image, image, icount);
793 if (error)
794 return error;
795 error = copyin(p->mask, mask, icount);
796 if (error)
797 return error;
798 }
799
800 s = spltty();
801 if (v & WSDISPLAY_CURSOR_DOCUR)
802 sc->sc_curenb = p->enable;
803 if (v & WSDISPLAY_CURSOR_DOPOS)
804 set_curpos(sc, &p->pos);
805 if (v & WSDISPLAY_CURSOR_DOHOT)
806 cc->cc_hot = p->hot;
807 if (v & WSDISPLAY_CURSOR_DOCMAP) {
808 memcpy(&cc->cc_color[index], &r[index], count);
809 memcpy(&cc->cc_color[index + 2], &g[index], count);
810 memcpy(&cc->cc_color[index + 4], &b[index], count);
811 }
812 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
813 cc->cc_size = p->size;
814 memset(cc->cc_image, 0, sizeof cc->cc_image);
815 memcpy(cc->cc_image, image, icount);
816 memset(cc->cc_mask, 0, sizeof cc->cc_mask);
817 memcpy(cc->cc_mask, mask, icount);
818 }
819 sc->sc_changed |= v;
820 splx(s);
821
822 return (0);
823 #undef cc
824 }
825
826 static int
827 get_cursor(struct sfb_softc *sc, struct wsdisplay_cursor *p)
828 {
829
830 return (EPASSTHROUGH); /* XXX */
831 }
832
833 static void
834 set_curpos(struct sfb_softc *sc, struct wsdisplay_curpos *curpos)
835 {
836 struct rasops_info *ri = sc->sc_ri;
837 int x = curpos->x, y = curpos->y;
838
839 if (y < 0)
840 y = 0;
841 else if (y > ri->ri_height)
842 y = ri->ri_height;
843 if (x < 0)
844 x = 0;
845 else if (x > ri->ri_width)
846 x = ri->ri_width;
847 sc->sc_cursor.cc_pos.x = x;
848 sc->sc_cursor.cc_pos.y = y;
849 }
850
851 #define MODE_SIMPLE 0
852 #define MODE_OPAQUESTIPPLE 1
853 #define MODE_OPAQUELINE 2
854 #define MODE_TRANSPARENTSTIPPLE 5
855 #define MODE_TRANSPARENTLINE 6
856 #define MODE_COPY 7
857
858 /* parameters for 8bpp configuration */
859 #define SFBALIGNMASK 0x7
860 #define SFBSTIPPLEALL1 0xffffffff
861 #define SFBSTIPPLEBITS 32
862 #define SFBSTIPPLEBITMASK 0x1f
863 #define SFBSTIPPLEBYTESDONE 32
864 #define SFBCOPYALL1 0xffffffff
865 #define SFBCOPYBITS 32
866 #define SFBCOPYBITMASK 0x1f
867 #define SFBCOPYBYTESDONE 32
868
869 #if defined(pmax)
870 #define WRITE_MB()
871 #define BUMP(p) (p)
872 #endif
873
874 #if defined(alpha)
875 #define WRITE_MB() tc_wmb()
876 /* SFB registers replicated in 128B stride; cycle after eight iterations */
877 #define BUMP(p) ((p) = (void *)(((long)(p) + 0x80) & ~0x400))
878 #endif
879
880 #define SFBMODE(p, v) \
881 SFBWRITE32(BUMP(p), SFB_ASIC_MODE, (v))
882 #define SFBROP(p, v) \
883 SFBWRITE32(BUMP(p), SFB_ASIC_ROP, (v))
884 #define SFBPLANEMASK(p, v) \
885 SFBWRITE32(BUMP(p), SFB_ASIC_PLANEMASK, (v))
886 #define SFBPIXELMASK(p, v) \
887 SFBWRITE32(BUMP(p), SFB_ASIC_PIXELMASK, (v))
888 #define SFBADDRESS(p, v) \
889 SFBWRITE32(BUMP(p), SFB_ASIC_ADDRESS, (v))
890 #define SFBSTART(p, v) \
891 SFBWRITE32(BUMP(p), SFB_ASIC_START, (v))
892 #define SFBPIXELSHIFT(p, v) \
893 SFBWRITE32(BUMP(p), SFB_ASIC_PIXELSHIFT, (v))
894 #define SFBFG(p, v) \
895 SFBWRITE32(BUMP(p), SFB_ASIC_FG, (v))
896 #define SFBBG(p, v) \
897 SFBWRITE32(BUMP(p), SFB_ASIC_BG, (v))
898
899 /*
900 * Paint the cursor.
901 */
902 static void
903 sfb_do_cursor(struct rasops_info *ri)
904 {
905 char *sfb, *p;
906 int scanspan, height, width, align, x, y;
907 u_int32_t lmask, rmask;
908
909 x = ri->ri_ccol * ri->ri_font->fontwidth;
910 y = ri->ri_crow * ri->ri_font->fontheight;
911 scanspan = ri->ri_stride;
912 height = ri->ri_font->fontheight;
913
914 p = ri->ri_bits + y * scanspan + x;
915 align = (long)p & SFBALIGNMASK;
916 p -= align;
917 width = ri->ri_font->fontwidth + align;
918 lmask = SFBSTIPPLEALL1 << align;
919 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
920 sfb = (char *)ri->ri_hw + SFB_ASIC_OFFSET;
921
922 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
923 SFBPLANEMASK(sfb, ~0);
924 SFBROP(sfb, 6); /* ROP_XOR */
925 SFBFG(sfb, ~0);
926
927 lmask = lmask & rmask;
928 while (height > 0) {
929 SFBADDRESS(sfb, (long)p);
930 SFBSTART(sfb, lmask);
931 p += scanspan;
932 height--;
933 }
934 SFBMODE(sfb, MODE_SIMPLE);
935 SFBROP(sfb, 3); /* ROP_COPY */
936 }
937
938 /*
939 * Paint a character.
940 */
941 static void
942 sfb_putchar(void *id, int row, int col, u_int uc, long attr)
943 {
944 struct rasops_info *ri = id;
945 char *sfb, *p;
946 int scanspan, height, width, align, x, y;
947 u_int32_t lmask, rmask, glyph;
948 u_int8_t *g;
949
950 x = col * ri->ri_font->fontwidth;
951 y = row * ri->ri_font->fontheight;
952 scanspan = ri->ri_stride;
953 height = ri->ri_font->fontheight;
954 uc -= ri->ri_font->firstchar;
955 g = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
956
957 p = ri->ri_bits + y * scanspan + x;
958 align = (long)p & SFBALIGNMASK;
959 p -= align;
960 width = ri->ri_font->fontwidth + align;
961 lmask = SFBSTIPPLEALL1 << align;
962 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
963 sfb = (char *)ri->ri_hw + SFB_ASIC_OFFSET;
964
965 SFBMODE(sfb, MODE_OPAQUESTIPPLE);
966 SFBPLANEMASK(sfb, ~0);
967 SFBFG(sfb, ri->ri_devcmap[(attr >> 24) & 15]);
968 SFBBG(sfb, ri->ri_devcmap[(attr >> 16) & 15]);
969
970 /* XXX 2B stride fonts only XXX */
971 lmask = lmask & rmask;
972 while (height > 0) {
973 glyph = *(u_int16_t *)g; /* XXX */
974 SFBPIXELMASK(sfb, lmask);
975 SFBADDRESS(sfb, (long)p);
976 SFBSTART(sfb, glyph << align);
977 p += scanspan;
978 g += 2; /* XXX */
979 height--;
980 }
981 if (attr & 1 /* UNDERLINE */) {
982 p -= scanspan * 2;
983 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
984 SFBADDRESS(sfb, (long)p);
985 SFBSTART(sfb, lmask);
986 }
987
988 SFBMODE(sfb, MODE_SIMPLE);
989 SFBPIXELMASK(sfb, ~0); /* entire pixel */
990 }
991
992 #if 0
993 /*
994 * Copy characters in a line.
995 */
996 static void
997 sfb_copycols(void *id, int row, int srccol, int dstcol, int ncols)
998 {
999 struct rasops_info *ri = id;
1000 void *sp, *dp, *basex, *sfb;
1001 int scanspan, height, width, aligns, alignd, shift, w, y;
1002 u_int32_t lmaskd, rmaskd;
1003
1004 scanspan = ri->ri_stride;
1005 y = row * ri->ri_font->fontheight;
1006 basex = ri->ri_bits + y * scanspan;
1007 height = ri->ri_font->fontheight;
1008 w = ri->ri_font->fontwidth * ncols;
1009
1010 sp = basex + ri->ri_font->fontwidth * srccol;
1011 aligns = (long)sp & SFBALIGNMASK;
1012 dp = basex + ri->ri_font->fontwidth * dstcol;
1013 alignd = (long)dp & SFBALIGNMASK;
1014 sfb = (void *)ri->ri_hw + SFB_ASIC_OFFSET;
1015
1016 SFBMODE(sfb, MODE_COPY);
1017 SFBPLANEMASK(sfb, ~0);
1018 /* small enough to fit in a single 32bit */
1019 if ((aligns + w) <= SFBCOPYBITS && (alignd + w) <= SFBCOPYBITS) {
1020 SFBPIXELSHIFT(sfb, alignd - aligns);
1021 lmaskd = SFBCOPYALL1 << alignd;
1022 rmaskd = SFBCOPYALL1 >> (-(alignd + w) & SFBCOPYBITMASK);
1023 lmaskd = lmaskd & rmaskd;
1024 sp -= aligns;
1025 dp -= alignd;
1026 while (height > 0) {
1027 MEMWRITE32(sp, SFBCOPYALL1); WRITE_MB();
1028 MEMWRITE32(dp, lmaskd); WRITE_MB();
1029 sp += scanspan;
1030 dp += scanspan;
1031 height--;
1032 }
1033 }
1034 /* copy forward (left-to-right) */
1035 else if (dstcol < srccol || srccol + ncols < dstcol) {
1036 void *sq, dq;
1037
1038 shift = alignd - aligns;
1039 if (shift < 0) {
1040 shift = 8 + shift; /* enforce right rotate */
1041 alignd += 8; /* bearing on left edge */
1042 }
1043 width = alignd + w;
1044 lmaskd = SFBCOPYALL1 << alignd;
1045 rmaskd = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
1046 sp -= aligns;
1047 dp -= alignd;
1048
1049 SFBPIXELSHIFT(sfb, shift);
1050 w = width;
1051 sq = sp;
1052 dq = dp;
1053 while (height > 0) {
1054 MEMWRITE32(sp, SFBCOPYALL1); WRITE_MB();
1055 MEMWRITE32(dp, lmaskd); WRITE_MB();
1056 width -= 2 * SFBCOPYBITS;
1057 while (width > 0) {
1058 sp += SFBCOPYBYTESDONE;
1059 dp += SFBCOPYBYTESDONE;
1060 MEMWRITE32(sp, SFBCOPYALL1); WRITE_MB();
1061 MEMWRITE32(dp, SFBCOPYALL1); WRITE_MB();
1062 width -= SFBCOPYBITS;
1063 }
1064 sp += SFBCOPYBYTESDONE;
1065 dp += SFBCOPYBYTESDONE;
1066 MEMWRITE32(sp, SFBCOPYALL1); WRITE_MB();
1067 MEMWRITE32(dp, rmaskd); WRITE_MB();
1068 sp = (sq += scanspan);
1069 dp = (dq += scanspan);
1070 width = w;
1071 height--;
1072 }
1073 }
1074 /* copy backward (right-to-left) */
1075 else {
1076 void *sq, dq;
1077
1078 shift = alignd - aligns;
1079 if (shift > 0) {
1080 shift = shift - 8; /* force left rotate */
1081 alignd += 24;
1082 }
1083 width = alignd + w;
1084 lmaskd = SFBCOPYALL1 << alignd;
1085 rmaskd = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
1086 sp -= aligns;
1087 dp -= alignd;
1088
1089 SFBPIXELSHIFT(sfb, shift);
1090 w = width;
1091 sq = sp += (((aligns + w) - 1) & ~31);
1092 dq = dp += (((alignd + w) - 1) & ~31);
1093 while (height > 0) {
1094 MEMWRITE32(sp, SFBCOPYALL1); WRITE_MB();
1095 MEMWRITE32(dp, rmaskd); WRITE_MB();
1096 width -= 2 * SFBCOPYBITS;
1097 while (width > 0) {
1098 sp -= SFBCOPYBYTESDONE;
1099 dp -= SFBCOPYBYTESDONE;
1100 MEMWRITE32(sp, SFBCOPYALL1); WRITE_MB();
1101 MEMWRITE32(dp, SFBCOPYALL1); WRITE_MB();
1102 width -= SFBCOPYBITS;
1103 }
1104 sp -= SFBCOPYBYTESDONE;
1105 dp -= SFBCOPYBYTESDONE;
1106 MEMWRITE32(sp, SFBCOPYALL1); WRITE_MB();
1107 MEMWRITE32(dp, lmaskd); WRITE_MB();
1108
1109 sp = (sq += scanspan);
1110 dp = (dq += scanspan);
1111 width = w;
1112 height--;
1113 }
1114 }
1115 SFBMODE(sfb, MODE_SIMPLE);
1116 SFBPIXELSHIFT(sfb, 0);
1117 }
1118 #endif
1119
1120 /*
1121 * Clear characters in a line.
1122 */
1123 static void
1124 sfb_erasecols(void *id, int row, int startcol, int ncols, long attr)
1125 {
1126 struct rasops_info *ri = id;
1127 char *sfb, *p;
1128 int scanspan, startx, height, width, align, w, y;
1129 u_int32_t lmask, rmask;
1130
1131 scanspan = ri->ri_stride;
1132 y = row * ri->ri_font->fontheight;
1133 startx = startcol * ri->ri_font->fontwidth;
1134 height = ri->ri_font->fontheight;
1135 w = ri->ri_font->fontwidth * ncols;
1136
1137 p = ri->ri_bits + y * scanspan + startx;
1138 align = (long)p & SFBALIGNMASK;
1139 p -= align;
1140 width = w + align;
1141 lmask = SFBSTIPPLEALL1 << align;
1142 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
1143 sfb = (char *)ri->ri_hw + SFB_ASIC_OFFSET;
1144
1145 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
1146 SFBPLANEMASK(sfb, ~0);
1147 SFBFG(sfb, ri->ri_devcmap[(attr >> 16) & 15]); /* fill with bg */
1148 if (width <= SFBSTIPPLEBITS) {
1149 lmask = lmask & rmask;
1150 while (height > 0) {
1151 SFBADDRESS(sfb, (long)p);
1152 SFBSTART(sfb, lmask);
1153 p += scanspan;
1154 height--;
1155 }
1156 }
1157 else {
1158 char *q = p;
1159 while (height > 0) {
1160 MEMWRITE32(p, lmask); WRITE_MB();
1161 width -= 2 * SFBSTIPPLEBITS;
1162 while (width > 0) {
1163 p += SFBSTIPPLEBYTESDONE;
1164 MEMWRITE32(p, SFBSTIPPLEALL1); WRITE_MB();
1165 width -= SFBSTIPPLEBITS;
1166 }
1167 p += SFBSTIPPLEBYTESDONE;
1168 MEMWRITE32(p, rmask); WRITE_MB();
1169 WRITE_MB();
1170
1171 p = (q += scanspan);
1172 width = w + align;
1173 height--;
1174 }
1175 }
1176 SFBMODE(sfb, MODE_SIMPLE);
1177 }
1178
1179 /*
1180 * Copy lines.
1181 */
1182 static void
1183 sfb_copyrows(void *id, int srcrow, int dstrow, int nrows)
1184 {
1185 struct rasops_info *ri = id;
1186 char *sfb, *p;
1187 int scanspan, offset, srcy, height, width, align, w;
1188 u_int32_t lmask, rmask;
1189
1190 scanspan = ri->ri_stride;
1191 height = ri->ri_font->fontheight * nrows;
1192 offset = (dstrow - srcrow) * ri->ri_yscale;
1193 srcy = ri->ri_font->fontheight * srcrow;
1194 if (srcrow < dstrow && srcrow + nrows > dstrow) {
1195 scanspan = -scanspan;
1196 srcy += height;
1197 }
1198
1199 p = ri->ri_bits + srcy * ri->ri_stride;
1200 align = (long)p & SFBALIGNMASK;
1201 p -= align;
1202 w = ri->ri_emuwidth;
1203 width = w + align;
1204 lmask = SFBCOPYALL1 << align;
1205 rmask = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
1206 sfb = (char *)ri->ri_hw + SFB_ASIC_OFFSET;
1207
1208 SFBMODE(sfb, MODE_COPY);
1209 SFBPLANEMASK(sfb, ~0);
1210 SFBPIXELSHIFT(sfb, 0);
1211 if (width <= SFBCOPYBITS) {
1212 /* never happens */;
1213 }
1214 else {
1215 char *q = p;
1216 while (height > 0) {
1217 MEMWRITE32(p, lmask);
1218 MEMWRITE32(p + offset, lmask);
1219 width -= 2 * SFBCOPYBITS;
1220 while (width > 0) {
1221 p += SFBCOPYBYTESDONE;
1222 MEMWRITE32(p, SFBCOPYALL1);
1223 MEMWRITE32(p + offset, SFBCOPYALL1);
1224 width -= SFBCOPYBITS;
1225 }
1226 p += SFBCOPYBYTESDONE;
1227 MEMWRITE32(p, rmask);
1228 MEMWRITE32(p + offset, rmask);
1229
1230 p = (q += scanspan);
1231 width = w + align;
1232 height--;
1233 }
1234 }
1235 SFBMODE(sfb, MODE_SIMPLE);
1236 }
1237
1238 /*
1239 * Erase lines.
1240 */
1241 void
1242 sfb_eraserows(void *id, int startrow, int nrows, long attr)
1243 {
1244 struct rasops_info *ri = id;
1245 char *sfb, *p;
1246 int scanspan, starty, height, width, align, w;
1247 u_int32_t lmask, rmask;
1248
1249 scanspan = ri->ri_stride;
1250 starty = ri->ri_font->fontheight * startrow;
1251 height = ri->ri_font->fontheight * nrows;
1252
1253 p = ri->ri_bits + starty * scanspan;
1254 align = (long)p & SFBALIGNMASK;
1255 p -= align;
1256 w = ri->ri_emuwidth;
1257 width = w + align;
1258 lmask = SFBSTIPPLEALL1 << align;
1259 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
1260 sfb = (char *)ri->ri_hw + SFB_ASIC_OFFSET;
1261
1262 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
1263 SFBPLANEMASK(sfb, ~0);
1264 SFBFG(sfb, ri->ri_devcmap[(attr >> 16) & 15]); /* fill with bg */
1265 if (width <= SFBSTIPPLEBITS) {
1266 /* never happens */;
1267 }
1268 else {
1269 char *q = p;
1270 while (height > 0) {
1271 MEMWRITE32(p, lmask); WRITE_MB();
1272 width -= 2 * SFBSTIPPLEBITS;
1273 while (width > 0) {
1274 p += SFBSTIPPLEBYTESDONE;
1275 MEMWRITE32(p, SFBSTIPPLEALL1); WRITE_MB();
1276 width -= SFBSTIPPLEBITS;
1277 }
1278 p += SFBSTIPPLEBYTESDONE;
1279 MEMWRITE32(p, rmask); WRITE_MB();
1280
1281 p = (q += scanspan);
1282 width = w + align;
1283 height--;
1284 }
1285 }
1286 SFBMODE(sfb, MODE_SIMPLE);
1287 }
1288