sfb.c revision 1.47 1 /* $NetBSD: sfb.c,v 1.47 2001/08/20 08:34:39 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.47 2001/08/20 08:34:39 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)(sc->sc_vaddr + 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 vaddr_t asic = sc->sc_vaddr + 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 asic, vdac;
535 int v;
536
537 asic = (caddr_t)sc->sc_vaddr + SFB_ASIC_OFFSET;
538 *(u_int32_t *)(asic + SFB_ASIC_CLEAR_INTR) = 0;
539 /* *(u_int32_t *)(asic + SFB_ASIC_ENABLE_INTR) = 1; */
540
541 if (sc->sc_changed == 0)
542 goto finish;
543
544 vdac = (caddr_t)sc->sc_vaddr + SFB_RAMDAC_OFFSET;
545 v = sc->sc_changed;
546 if (v & WSDISPLAY_CURSOR_DOCUR) {
547 SELECT(vdac, BT459_IREG_CCR);
548 REG(vdac, bt_reg) = (sc->sc_curenb) ? 0xc0 : 0x00;
549 }
550 if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT)) {
551 int x, y;
552
553 x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x;
554 y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y;
555 x += sc->sc_cursor.cc_magic.x;
556 y += sc->sc_cursor.cc_magic.y;
557
558 SELECT(vdac, BT459_IREG_CURSOR_X_LOW);
559 REG(vdac, bt_reg) = x; tc_wmb();
560 REG(vdac, bt_reg) = x >> 8; tc_wmb();
561 REG(vdac, bt_reg) = y; tc_wmb();
562 REG(vdac, bt_reg) = y >> 8; tc_wmb();
563 }
564 if (v & WSDISPLAY_CURSOR_DOCMAP) {
565 u_int8_t *cp = sc->sc_cursor.cc_color;
566
567 SELECT(vdac, BT459_IREG_CCOLOR_2);
568 REG(vdac, bt_reg) = cp[1]; tc_wmb();
569 REG(vdac, bt_reg) = cp[3]; tc_wmb();
570 REG(vdac, bt_reg) = cp[5]; tc_wmb();
571
572 REG(vdac, bt_reg) = cp[0]; tc_wmb();
573 REG(vdac, bt_reg) = cp[2]; tc_wmb();
574 REG(vdac, bt_reg) = cp[4]; tc_wmb();
575 }
576 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
577 u_int8_t *ip, *mp, img, msk;
578 u_int8_t u;
579 int bcnt;
580
581 ip = (u_int8_t *)sc->sc_cursor.cc_image;
582 mp = (u_int8_t *)(sc->sc_cursor.cc_image + CURSOR_MAX_SIZE);
583
584 bcnt = 0;
585 SELECT(vdac, BT459_IREG_CRAM_BASE+0);
586 /* 64 pixel scan line is consisted with 16 byte cursor ram */
587 while (bcnt < sc->sc_cursor.cc_size.y * 16) {
588 /* pad right half 32 pixel when smaller than 33 */
589 if ((bcnt & 0x8) && sc->sc_cursor.cc_size.x < 33) {
590 REG(vdac, bt_reg) = 0; tc_wmb();
591 REG(vdac, bt_reg) = 0; tc_wmb();
592 }
593 else {
594 img = *ip++;
595 msk = *mp++;
596 img &= msk; /* cookie off image */
597 u = (msk & 0x0f) << 4 | (img & 0x0f);
598 REG(vdac, bt_reg) = shuffle[u]; tc_wmb();
599 u = (msk & 0xf0) | (img & 0xf0) >> 4;
600 REG(vdac, bt_reg) = shuffle[u]; tc_wmb();
601 }
602 bcnt += 2;
603 }
604 /* pad unoccupied scan lines */
605 while (bcnt < CURSOR_MAX_SIZE * 16) {
606 REG(vdac, bt_reg) = 0; tc_wmb();
607 REG(vdac, bt_reg) = 0; tc_wmb();
608 bcnt += 2;
609 }
610 }
611 if (v & WSDISPLAY_CMAP_DOLUT) {
612 struct hwcmap256 *cm = &sc->sc_cmap;
613 int index;
614
615 SELECT(vdac, 0);
616 for (index = 0; index < CMAP_SIZE; index++) {
617 REG(vdac, bt_cmap) = cm->r[index]; tc_wmb();
618 REG(vdac, bt_cmap) = cm->g[index]; tc_wmb();
619 REG(vdac, bt_cmap) = cm->b[index]; tc_wmb();
620 }
621 }
622 sc->sc_changed = 0;
623 finish:
624 return (1);
625 }
626
627 static void
628 sfbhwinit(base)
629 caddr_t base;
630 {
631 caddr_t vdac = base + SFB_RAMDAC_OFFSET;
632 const u_int8_t *p;
633 int i;
634
635 SELECT(vdac, BT459_IREG_COMMAND_0);
636 REG(vdac, bt_reg) = 0x40; /* CMD0 */ tc_wmb();
637 REG(vdac, bt_reg) = 0x0; /* CMD1 */ tc_wmb();
638 REG(vdac, bt_reg) = 0xc0; /* CMD2 */ tc_wmb();
639 REG(vdac, bt_reg) = 0xff; /* PRM */ tc_wmb();
640 REG(vdac, bt_reg) = 0; /* 205 */ tc_wmb();
641 REG(vdac, bt_reg) = 0x0; /* PBM */ tc_wmb();
642 REG(vdac, bt_reg) = 0; /* 207 */ tc_wmb();
643 REG(vdac, bt_reg) = 0x0; /* ORM */ tc_wmb();
644 REG(vdac, bt_reg) = 0x0; /* OBM */ tc_wmb();
645 REG(vdac, bt_reg) = 0x0; /* ILV */ tc_wmb();
646 REG(vdac, bt_reg) = 0x0; /* TEST */ tc_wmb();
647
648 SELECT(vdac, BT459_IREG_CCR);
649 REG(vdac, bt_reg) = 0x0; tc_wmb();
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
663 /* build sane colormap */
664 SELECT(vdac, 0);
665 p = rasops_cmap;
666 for (i = 0; i < CMAP_SIZE; i++, p += 3) {
667 REG(vdac, bt_cmap) = p[0]; tc_wmb();
668 REG(vdac, bt_cmap) = p[1]; tc_wmb();
669 REG(vdac, bt_cmap) = p[2]; tc_wmb();
670 }
671
672 /* clear out cursor image */
673 SELECT(vdac, BT459_IREG_CRAM_BASE);
674 for (i = 0; i < 1024; i++)
675 REG(vdac, bt_reg) = 0xff; tc_wmb();
676
677 /*
678 * 2 bit/pixel cursor. Assign MSB for cursor mask and LSB for
679 * cursor image. CCOLOR_2 for mask color, while CCOLOR_3 for
680 * image color. CCOLOR_1 will be never used.
681 */
682 SELECT(vdac, BT459_IREG_CCOLOR_1);
683 REG(vdac, bt_reg) = 0xff; tc_wmb();
684 REG(vdac, bt_reg) = 0xff; tc_wmb();
685 REG(vdac, bt_reg) = 0xff; tc_wmb();
686
687 REG(vdac, bt_reg) = 0; tc_wmb();
688 REG(vdac, bt_reg) = 0; tc_wmb();
689 REG(vdac, bt_reg) = 0; tc_wmb();
690
691 REG(vdac, bt_reg) = 0xff; tc_wmb();
692 REG(vdac, bt_reg) = 0xff; tc_wmb();
693 REG(vdac, bt_reg) = 0xff; tc_wmb();
694 }
695
696 static int
697 get_cmap(sc, p)
698 struct sfb_softc *sc;
699 struct wsdisplay_cmap *p;
700 {
701 u_int index = p->index, count = p->count;
702
703 if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE)
704 return (EINVAL);
705
706 if (!uvm_useracc(p->red, count, B_WRITE) ||
707 !uvm_useracc(p->green, count, B_WRITE) ||
708 !uvm_useracc(p->blue, count, B_WRITE))
709 return (EFAULT);
710
711 copyout(&sc->sc_cmap.r[index], p->red, count);
712 copyout(&sc->sc_cmap.g[index], p->green, count);
713 copyout(&sc->sc_cmap.b[index], p->blue, count);
714
715 return (0);
716 }
717
718 static int
719 set_cmap(sc, p)
720 struct sfb_softc *sc;
721 struct wsdisplay_cmap *p;
722 {
723 u_int index = p->index, count = p->count;
724
725 if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE)
726 return (EINVAL);
727
728 if (!uvm_useracc(p->red, count, B_READ) ||
729 !uvm_useracc(p->green, count, B_READ) ||
730 !uvm_useracc(p->blue, count, B_READ))
731 return (EFAULT);
732
733 copyin(p->red, &sc->sc_cmap.r[index], count);
734 copyin(p->green, &sc->sc_cmap.g[index], count);
735 copyin(p->blue, &sc->sc_cmap.b[index], count);
736 sc->sc_changed |= WSDISPLAY_CMAP_DOLUT;
737 return (0);
738 }
739
740 static int
741 set_cursor(sc, p)
742 struct sfb_softc *sc;
743 struct wsdisplay_cursor *p;
744 {
745 #define cc (&sc->sc_cursor)
746 u_int v, index, count, icount;
747
748 v = p->which;
749 if (v & WSDISPLAY_CURSOR_DOCMAP) {
750 index = p->cmap.index;
751 count = p->cmap.count;
752 if (index >= 2 || (index + count) > 2)
753 return (EINVAL);
754 if (!uvm_useracc(p->cmap.red, count, B_READ) ||
755 !uvm_useracc(p->cmap.green, count, B_READ) ||
756 !uvm_useracc(p->cmap.blue, count, B_READ))
757 return (EFAULT);
758 }
759 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
760 if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE)
761 return (EINVAL);
762 icount = ((p->size.x < 33) ? 4 : 8) * p->size.y;
763 if (!uvm_useracc(p->image, icount, B_READ) ||
764 !uvm_useracc(p->mask, icount, B_READ))
765 return (EFAULT);
766 }
767
768 if (v & WSDISPLAY_CURSOR_DOCUR)
769 sc->sc_curenb = p->enable;
770 if (v & WSDISPLAY_CURSOR_DOPOS)
771 set_curpos(sc, &p->pos);
772 if (v & WSDISPLAY_CURSOR_DOHOT)
773 cc->cc_hot = p->hot;
774 if (v & WSDISPLAY_CURSOR_DOCMAP) {
775 copyin(p->cmap.red, &cc->cc_color[index], count);
776 copyin(p->cmap.green, &cc->cc_color[index + 2], count);
777 copyin(p->cmap.blue, &cc->cc_color[index + 4], count);
778 }
779 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
780 cc->cc_size = p->size;
781 memset(cc->cc_image, 0, sizeof cc->cc_image);
782 copyin(p->image, cc->cc_image, icount);
783 copyin(p->mask, cc->cc_image+CURSOR_MAX_SIZE, icount);
784 }
785 sc->sc_changed |= v;
786
787 return (0);
788 #undef cc
789 }
790
791 static int
792 get_cursor(sc, p)
793 struct sfb_softc *sc;
794 struct wsdisplay_cursor *p;
795 {
796
797 return (ENOTTY); /* XXX */
798 }
799
800 static void
801 set_curpos(sc, curpos)
802 struct sfb_softc *sc;
803 struct wsdisplay_curpos *curpos;
804 {
805 struct rasops_info *ri = sc->sc_ri;
806 int x = curpos->x, y = curpos->y;
807
808 if (y < 0)
809 y = 0;
810 else if (y > ri->ri_height);
811 y = ri->ri_height;
812 if (x < 0)
813 x = 0;
814 else if (x > ri->ri_width);
815 x = ri->ri_width;
816 sc->sc_cursor.cc_pos.x = x;
817 sc->sc_cursor.cc_pos.y = y;
818 }
819
820 #define MODE_SIMPLE 0
821 #define MODE_OPAQUESTIPPLE 1
822 #define MODE_OPAQUELINE 2
823 #define MODE_TRANSPARENTSTIPPLE 5
824 #define MODE_TRANSPARENTLINE 6
825 #define MODE_COPY 7
826
827 /* parameters for 8bpp configuration */
828 #define SFBALIGNMASK 0x7
829 #define SFBSTIPPLEALL1 0xffffffff
830 #define SFBSTIPPLEBITS 32
831 #define SFBSTIPPLEBITMASK 0x1f
832 #define SFBSTIPPLEBYTESDONE 32
833 #define SFBCOPYALL1 0xffffffff
834 #define SFBCOPYBITS 32
835 #define SFBCOPYBITMASK 0x1f
836 #define SFBCOPYBYTESDONE 32
837
838 #if defined(pmax)
839 #define WRITE_MB()
840 #define BUMP(p) (p)
841 #endif
842
843 #if defined(alpha)
844 #define WRITE_MB() tc_wmb()
845 /* SFB registers replicated in 128B stride; cycle after eight iterations */
846 #define BUMP(p) ((p) = (caddr_t)(((long)(p) + 0x80) & ~0x400))
847 #endif
848
849 #define SFBMODE(p, v) \
850 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_MODE) = (v))
851 #define SFBROP(p, v) \
852 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_ROP) = (v))
853 #define SFBPLANEMASK(p, v) \
854 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_PLANEMASK) = (v))
855 #define SFBPIXELMASK(p, v) \
856 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELMASK) = (v))
857 #define SFBADDRESS(p, v) \
858 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_ADDRESS) = (v))
859 #define SFBSTART(p, v) \
860 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_START) = (v))
861 #define SFBPIXELSHIFT(p, v) \
862 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELSHIFT) = (v))
863 #define SFBFG(p, v) \
864 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_FG) = (v))
865 #define SFBBG(p, v) \
866 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_BG) = (v))
867
868 /*
869 * Paint the cursor.
870 */
871 static void
872 sfb_do_cursor(ri)
873 struct rasops_info *ri;
874 {
875 caddr_t sfb, p;
876 int scanspan, height, width, align, x, y;
877 u_int32_t lmask, rmask;
878
879 x = ri->ri_ccol * ri->ri_font->fontwidth;
880 y = ri->ri_crow * ri->ri_font->fontheight;
881 scanspan = ri->ri_stride;
882 height = ri->ri_font->fontheight;
883
884 p = ri->ri_bits + y * scanspan + x;
885 align = (long)p & SFBALIGNMASK;
886 p -= align;
887 width = ri->ri_font->fontwidth + align;
888 lmask = SFBSTIPPLEALL1 << align;
889 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
890 sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET;
891
892 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
893 SFBPLANEMASK(sfb, ~0);
894 SFBROP(sfb, 6); /* ROP_XOR */
895 SFBFG(sfb, ~0);
896
897 lmask = lmask & rmask;
898 while (height > 0) {
899 SFBADDRESS(sfb, (long)p);
900 SFBSTART(sfb, lmask);
901 p += scanspan;
902 height--;
903 }
904 SFBMODE(sfb, MODE_SIMPLE);
905 SFBROP(sfb, 3); /* ROP_COPY */
906 }
907
908 /*
909 * Paint a character.
910 */
911 static void
912 sfb_putchar(id, row, col, uc, attr)
913 void *id;
914 int row, col;
915 u_int uc;
916 long attr;
917 {
918 struct rasops_info *ri = id;
919 caddr_t sfb, p;
920 int scanspan, height, width, align, x, y;
921 u_int32_t lmask, rmask, glyph;
922 u_int8_t *g;
923
924 x = col * ri->ri_font->fontwidth;
925 y = row * ri->ri_font->fontheight;
926 scanspan = ri->ri_stride;
927 height = ri->ri_font->fontheight;
928 uc -= ri->ri_font->firstchar;
929 g = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
930
931 p = ri->ri_bits + y * scanspan + x;
932 align = (long)p & SFBALIGNMASK;
933 p -= align;
934 width = ri->ri_font->fontwidth + align;
935 lmask = SFBSTIPPLEALL1 << align;
936 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
937 sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET;
938
939 SFBMODE(sfb, MODE_OPAQUESTIPPLE);
940 SFBPLANEMASK(sfb, ~0);
941 SFBFG(sfb, ri->ri_devcmap[(attr >> 24) & 15]);
942 SFBBG(sfb, ri->ri_devcmap[(attr >> 16) & 15]);
943
944 /* XXX 2B stride fonts only XXX */
945 lmask = lmask & rmask;
946 while (height > 0) {
947 glyph = *(u_int16_t *)g; /* XXX */
948 SFBPIXELMASK(sfb, lmask);
949 SFBADDRESS(sfb, (long)p);
950 SFBSTART(sfb, glyph << align);
951 p += scanspan;
952 g += 2; /* XXX */
953 height--;
954 }
955 if (attr & 1 /* UNDERLINE */) {
956 p -= scanspan * 2;
957 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
958 SFBADDRESS(sfb, (long)p);
959 SFBSTART(sfb, lmask);
960 }
961
962 SFBMODE(sfb, MODE_SIMPLE);
963 SFBPIXELMASK(sfb, ~0); /* entire pixel */
964 }
965
966 #if 0
967 /*
968 * Copy characters in a line.
969 */
970 static void
971 sfb_copycols(id, row, srccol, dstcol, ncols)
972 void *id;
973 int row, srccol, dstcol, ncols;
974 {
975 struct rasops_info *ri = id;
976 caddr_t sp, dp, basex, sfb;
977 int scanspan, height, width, aligns, alignd, shift, w, y;
978 u_int32_t lmaskd, rmaskd;
979
980 scanspan = ri->ri_stride;
981 y = row * ri->ri_font->fontheight;
982 basex = ri->ri_bits + y * scanspan;
983 height = ri->ri_font->fontheight;
984 w = ri->ri_font->fontwidth * ncols;
985
986 sp = basex + ri->ri_font->fontwidth * srccol;
987 aligns = (long)sp & SFBALIGNMASK;
988 dp = basex + ri->ri_font->fontwidth * dstcol;
989 alignd = (long)dp & SFBALIGNMASK;
990 sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET;
991
992 SFBMODE(sfb, MODE_COPY);
993 SFBPLANEMASK(sfb, ~0);
994 /* small enough to fit in a single 32bit */
995 if ((aligns + w) <= SFBCOPYBITS && (alignd + w) <= SFBCOPYBITS) {
996 SFBPIXELSHIFT(sfb, alignd - aligns);
997 lmaskd = SFBCOPYALL1 << alignd;
998 rmaskd = SFBCOPYALL1 >> (-(alignd + w) & SFBCOPYBITMASK);
999 lmaskd = lmaskd & rmaskd;
1000 sp -= aligns;
1001 dp -= alignd;
1002 while (height > 0) {
1003 *(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB();
1004 *(u_int32_t *)dp = lmaskd; WRITE_MB();
1005 sp += scanspan;
1006 dp += scanspan;
1007 height--;
1008 }
1009 }
1010 /* copy forward (left-to-right) */
1011 else if (dstcol < srccol || srccol + ncols < dstcol) {
1012 caddr_t sq, dq;
1013
1014 shift = alignd - aligns;
1015 if (shift < 0) {
1016 shift = 8 + shift; /* enforce right rotate */
1017 alignd += 8; /* bearing on left edge */
1018 }
1019 width = alignd + w;
1020 lmaskd = SFBCOPYALL1 << alignd;
1021 rmaskd = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
1022 sp -= aligns;
1023 dp -= alignd;
1024
1025 SFBPIXELSHIFT(sfb, shift);
1026 w = width;
1027 sq = sp;
1028 dq = dp;
1029 while (height > 0) {
1030 *(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB();
1031 *(u_int32_t *)dp = lmaskd; WRITE_MB();
1032 width -= 2 * SFBCOPYBITS;
1033 while (width > 0) {
1034 sp += SFBCOPYBYTESDONE;
1035 dp += SFBCOPYBYTESDONE;
1036 *(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB();
1037 *(u_int32_t *)dp = SFBCOPYALL1; WRITE_MB();
1038 width -= SFBCOPYBITS;
1039 }
1040 sp += SFBCOPYBYTESDONE;
1041 dp += SFBCOPYBYTESDONE;
1042 *(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB();
1043 *(u_int32_t *)dp = rmaskd; WRITE_MB();
1044 sp = (sq += scanspan);
1045 dp = (dq += scanspan);
1046 width = w;
1047 height--;
1048 }
1049 }
1050 /* copy backward (right-to-left) */
1051 else {
1052 caddr_t sq, dq;
1053
1054 shift = alignd - aligns;
1055 if (shift > 0) {
1056 shift = shift - 8; /* force left rotate */
1057 alignd += 24;
1058 }
1059 width = alignd + w;
1060 lmaskd = SFBCOPYALL1 << alignd;
1061 rmaskd = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
1062 sp -= aligns;
1063 dp -= alignd;
1064
1065 SFBPIXELSHIFT(sfb, shift);
1066 w = width;
1067 sq = sp += (((aligns + w) - 1) & ~31);
1068 dq = dp += (((alignd + w) - 1) & ~31);
1069 while (height > 0) {
1070 *(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB();
1071 *(u_int32_t *)dp = rmaskd; WRITE_MB();
1072 width -= 2 * SFBCOPYBITS;
1073 while (width > 0) {
1074 sp -= SFBCOPYBYTESDONE;
1075 dp -= SFBCOPYBYTESDONE;
1076 *(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB();
1077 *(u_int32_t *)dp = SFBCOPYALL1; WRITE_MB();
1078 width -= SFBCOPYBITS;
1079 }
1080 sp -= SFBCOPYBYTESDONE;
1081 dp -= SFBCOPYBYTESDONE;
1082 *(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB();
1083 *(u_int32_t *)dp = lmaskd; WRITE_MB();
1084
1085 sp = (sq += scanspan);
1086 dp = (dq += scanspan);
1087 width = w;
1088 height--;
1089 }
1090 }
1091 SFBMODE(sfb, MODE_SIMPLE);
1092 SFBPIXELSHIFT(sfb, 0);
1093 }
1094 #endif
1095
1096 /*
1097 * Clear characters in a line.
1098 */
1099 static void
1100 sfb_erasecols(id, row, startcol, ncols, attr)
1101 void *id;
1102 int row, startcol, ncols;
1103 long attr;
1104 {
1105 struct rasops_info *ri = id;
1106 caddr_t sfb, p;
1107 int scanspan, startx, height, width, align, w, y;
1108 u_int32_t lmask, rmask;
1109
1110 scanspan = ri->ri_stride;
1111 y = row * ri->ri_font->fontheight;
1112 startx = startcol * ri->ri_font->fontwidth;
1113 height = ri->ri_font->fontheight;
1114 w = ri->ri_font->fontwidth * ncols;
1115
1116 p = ri->ri_bits + y * scanspan + startx;
1117 align = (long)p & SFBALIGNMASK;
1118 p -= align;
1119 width = w + align;
1120 lmask = SFBSTIPPLEALL1 << align;
1121 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
1122 sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET;
1123
1124 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
1125 SFBPLANEMASK(sfb, ~0);
1126 SFBFG(sfb, ri->ri_devcmap[(attr >> 16) & 15]); /* fill with bg */
1127 if (width <= SFBSTIPPLEBITS) {
1128 lmask = lmask & rmask;
1129 while (height > 0) {
1130 SFBADDRESS(sfb, (long)p);
1131 SFBSTART(sfb, lmask);
1132 p += scanspan;
1133 height--;
1134 }
1135 }
1136 else {
1137 caddr_t q = p;
1138 while (height > 0) {
1139 *(u_int32_t *)p = lmask;
1140 WRITE_MB();
1141 width -= 2 * SFBSTIPPLEBITS;
1142 while (width > 0) {
1143 p += SFBSTIPPLEBYTESDONE;
1144 *(u_int32_t *)p = SFBSTIPPLEALL1;
1145 WRITE_MB();
1146 width -= SFBSTIPPLEBITS;
1147 }
1148 p += SFBSTIPPLEBYTESDONE;
1149 *(u_int32_t *)p = rmask;
1150 WRITE_MB();
1151
1152 p = (q += scanspan);
1153 width = w + align;
1154 height--;
1155 }
1156 }
1157 SFBMODE(sfb, MODE_SIMPLE);
1158 }
1159
1160 /*
1161 * Copy lines.
1162 */
1163 static void
1164 sfb_copyrows(id, srcrow, dstrow, nrows)
1165 void *id;
1166 int srcrow, dstrow, nrows;
1167 {
1168 struct rasops_info *ri = id;
1169 caddr_t sfb, p;
1170 int scanspan, offset, srcy, height, width, align, w;
1171 u_int32_t lmask, rmask;
1172
1173 scanspan = ri->ri_stride;
1174 height = ri->ri_font->fontheight * nrows;
1175 offset = (dstrow - srcrow) * ri->ri_yscale;
1176 srcy = ri->ri_font->fontheight * srcrow;
1177 if (srcrow < dstrow && srcrow + nrows > dstrow) {
1178 scanspan = -scanspan;
1179 srcy += height;
1180 }
1181
1182 p = ri->ri_bits + srcy * ri->ri_stride;
1183 align = (long)p & SFBALIGNMASK;
1184 p -= align;
1185 w = ri->ri_emuwidth;
1186 width = w + align;
1187 lmask = SFBCOPYALL1 << align;
1188 rmask = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
1189 sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET;
1190
1191 SFBMODE(sfb, MODE_COPY);
1192 SFBPLANEMASK(sfb, ~0);
1193 SFBPIXELSHIFT(sfb, 0);
1194 if (width <= SFBCOPYBITS) {
1195 /* never happens */;
1196 }
1197 else {
1198 caddr_t q = p;
1199 while (height > 0) {
1200 *(u_int32_t *)p = lmask;
1201 *(u_int32_t *)(p + offset) = lmask;
1202 width -= 2 * SFBCOPYBITS;
1203 while (width > 0) {
1204 p += SFBCOPYBYTESDONE;
1205 *(u_int32_t *)p = SFBCOPYALL1;
1206 *(u_int32_t *)(p + offset) = SFBCOPYALL1;
1207 width -= SFBCOPYBITS;
1208 }
1209 p += SFBCOPYBYTESDONE;
1210 *(u_int32_t *)p = rmask;
1211 *(u_int32_t *)(p + offset) = rmask;
1212
1213 p = (q += scanspan);
1214 width = w + align;
1215 height--;
1216 }
1217 }
1218 SFBMODE(sfb, MODE_SIMPLE);
1219 }
1220
1221 /*
1222 * Erase lines.
1223 */
1224 void
1225 sfb_eraserows(id, startrow, nrows, attr)
1226 void *id;
1227 int startrow, nrows;
1228 long attr;
1229 {
1230 struct rasops_info *ri = id;
1231 caddr_t sfb, p;
1232 int scanspan, starty, height, width, align, w;
1233 u_int32_t lmask, rmask;
1234
1235 scanspan = ri->ri_stride;
1236 starty = ri->ri_font->fontheight * startrow;
1237 height = ri->ri_font->fontheight * nrows;
1238
1239 p = ri->ri_bits + starty * scanspan;
1240 align = (long)p & SFBALIGNMASK;
1241 p -= align;
1242 w = ri->ri_emuwidth;
1243 width = w + align;
1244 lmask = SFBSTIPPLEALL1 << align;
1245 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
1246 sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET;
1247
1248 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
1249 SFBPLANEMASK(sfb, ~0);
1250 SFBFG(sfb, ri->ri_devcmap[(attr >> 16) & 15]); /* fill with bg */
1251 if (width <= SFBSTIPPLEBITS) {
1252 /* never happens */;
1253 }
1254 else {
1255 caddr_t q = p;
1256 while (height > 0) {
1257 *(u_int32_t *)p = lmask;
1258 WRITE_MB();
1259 width -= 2 * SFBSTIPPLEBITS;
1260 while (width > 0) {
1261 p += SFBSTIPPLEBYTESDONE;
1262 *(u_int32_t *)p = SFBSTIPPLEALL1;
1263 WRITE_MB();
1264 width -= SFBSTIPPLEBITS;
1265 }
1266 p += SFBSTIPPLEBYTESDONE;
1267 *(u_int32_t *)p = rmask;
1268 WRITE_MB();
1269
1270 p = (q += scanspan);
1271 width = w + align;
1272 height--;
1273 }
1274 }
1275 SFBMODE(sfb, MODE_SIMPLE);
1276 }
1277