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