sfb.c revision 1.49 1 /* $NetBSD: sfb.c,v 1.49 2001/11/13 06:26:10 lukem 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.49 2001/11/13 06:26:10 lukem 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[64 + 64];
116 };
117
118 struct sfb_softc {
119 struct device sc_dev;
120 vaddr_t sc_vaddr;
121 size_t sc_size;
122 struct rasops_info *sc_ri;
123 struct hwcmap256 sc_cmap; /* software copy of colormap */
124 struct hwcursor64 sc_cursor; /* software copy of cursor */
125 int sc_blanked; /* video visibility disabled */
126 int sc_curenb; /* cursor sprite enabled */
127 int sc_changed; /* need update of hardware */
128 #define WSDISPLAY_CMAP_DOLUT 0x20
129 int nscreens;
130 };
131
132 #define HX_MAGIC_X 368
133 #define HX_MAGIC_Y 38
134
135 static int sfbmatch __P((struct device *, struct cfdata *, void *));
136 static void sfbattach __P((struct device *, struct device *, void *));
137
138 const struct cfattach sfb_ca = {
139 sizeof(struct sfb_softc), sfbmatch, sfbattach,
140 };
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 if ((cookie = wsfont_find(NULL, 12, 0, 0)) <= 0)
349 cookie = wsfont_find(NULL, 0, 0, 0);
350 if (cookie <= 0) {
351 printf("sfb: font table is empty\n");
352 return;
353 }
354
355 /* the accelerated sfb_putchar() needs LSbit left */
356 if (wsfont_lock(cookie, &ri->ri_font,
357 WSDISPLAY_FONTORDER_R2L, WSDISPLAY_FONTORDER_L2R) <= 0) {
358 printf("sfb: couldn't lock font\n");
359 return;
360 }
361 ri->ri_wsfcookie = cookie;
362
363 rasops_init(ri, 34, 80);
364
365 /* add our accelerated functions */
366 ri->ri_ops.putchar = sfb_putchar;
367 ri->ri_ops.erasecols = sfb_erasecols;
368 ri->ri_ops.copyrows = sfb_copyrows;
369 ri->ri_ops.eraserows = sfb_eraserows;
370 ri->ri_do_cursor = sfb_do_cursor;
371
372 /* XXX shouldn't be global */
373 sfb_stdscreen.nrows = ri->ri_rows;
374 sfb_stdscreen.ncols = ri->ri_cols;
375 sfb_stdscreen.textops = &ri->ri_ops;
376 sfb_stdscreen.capabilities = ri->ri_caps;
377 }
378
379 static int
380 sfbioctl(v, cmd, data, flag, p)
381 void *v;
382 u_long cmd;
383 caddr_t data;
384 int flag;
385 struct proc *p;
386 {
387 struct sfb_softc *sc = v;
388 struct rasops_info *ri = sc->sc_ri;
389 int turnoff;
390
391 switch (cmd) {
392 case WSDISPLAYIO_GTYPE:
393 *(u_int *)data = WSDISPLAY_TYPE_SFB;
394 return (0);
395
396 case WSDISPLAYIO_GINFO:
397 #define wsd_fbip ((struct wsdisplay_fbinfo *)data)
398 wsd_fbip->height = ri->ri_height;
399 wsd_fbip->width = ri->ri_width;
400 wsd_fbip->depth = ri->ri_depth;
401 wsd_fbip->cmsize = CMAP_SIZE;
402 #undef fbt
403 return (0);
404
405 case WSDISPLAYIO_GETCMAP:
406 return get_cmap(sc, (struct wsdisplay_cmap *)data);
407
408 case WSDISPLAYIO_PUTCMAP:
409 return set_cmap(sc, (struct wsdisplay_cmap *)data);
410
411 case WSDISPLAYIO_SVIDEO:
412 turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF;
413 if (sc->sc_blanked ^ turnoff) {
414 caddr_t asic = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET;
415 *(u_int32_t *)(asic + SFB_ASIC_VIDEO_VALID)
416 = !turnoff;
417 tc_wmb();
418 sc->sc_blanked = turnoff;
419 }
420 return (0);
421
422 case WSDISPLAYIO_GVIDEO:
423 *(u_int *)data = sc->sc_blanked ?
424 WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON;
425 return (0);
426
427 case WSDISPLAYIO_GCURPOS:
428 *(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos;
429 return (0);
430
431 case WSDISPLAYIO_SCURPOS:
432 set_curpos(sc, (struct wsdisplay_curpos *)data);
433 sc->sc_changed |= WSDISPLAY_CURSOR_DOPOS;
434 return (0);
435
436 case WSDISPLAYIO_GCURMAX:
437 ((struct wsdisplay_curpos *)data)->x =
438 ((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE;
439 return (0);
440
441 case WSDISPLAYIO_GCURSOR:
442 return get_cursor(sc, (struct wsdisplay_cursor *)data);
443
444 case WSDISPLAYIO_SCURSOR:
445 return set_cursor(sc, (struct wsdisplay_cursor *)data);
446 }
447 return (ENOTTY);
448 }
449
450 static paddr_t
451 sfbmmap(v, offset, prot)
452 void *v;
453 off_t offset;
454 int prot;
455 {
456 struct sfb_softc *sc = v;
457
458 if (offset >= SFB_SIZE || offset < 0)
459 return (-1);
460 return machine_btop(sc->sc_vaddr + offset);
461 }
462
463 static int
464 sfb_alloc_screen(v, type, cookiep, curxp, curyp, attrp)
465 void *v;
466 const struct wsscreen_descr *type;
467 void **cookiep;
468 int *curxp, *curyp;
469 long *attrp;
470 {
471 struct sfb_softc *sc = v;
472 struct rasops_info *ri = sc->sc_ri;
473 long defattr;
474
475 if (sc->nscreens > 0)
476 return (ENOMEM);
477
478 *cookiep = ri; /* one and only for now */
479 *curxp = 0;
480 *curyp = 0;
481 (*ri->ri_ops.alloc_attr)(ri, 0, 0, 0, &defattr);
482 *attrp = defattr;
483 sc->nscreens++;
484 return (0);
485 }
486
487 static void
488 sfb_free_screen(v, cookie)
489 void *v;
490 void *cookie;
491 {
492 struct sfb_softc *sc = v;
493
494 if (sc->sc_ri == &sfb_console_ri)
495 panic("sfb_free_screen: console");
496
497 sc->nscreens--;
498 }
499
500 static int
501 sfb_show_screen(v, cookie, waitok, cb, cbarg)
502 void *v;
503 void *cookie;
504 int waitok;
505 void (*cb) __P((void *, int, int));
506 void *cbarg;
507 {
508
509 return (0);
510 }
511
512 /* EXPORT */ int
513 sfb_cnattach(addr)
514 tc_addr_t addr;
515 {
516 struct rasops_info *ri;
517 long defattr;
518
519 ri = &sfb_console_ri;
520 ri->ri_hw = (void *)addr;
521 sfb_common_init(ri);
522 (*ri->ri_ops.alloc_attr)(&ri, 0, 0, 0, &defattr);
523 wsdisplay_cnattach(&sfb_stdscreen, ri, 0, 0, defattr);
524 sfb_consaddr = addr;
525 return (0);
526 }
527
528 static int
529 sfbintr(arg)
530 void *arg;
531 {
532 struct sfb_softc *sc = arg;
533 caddr_t base, asic, vdac;
534 int v;
535
536 base = (caddr_t)sc->sc_ri->ri_hw;
537 asic = base + 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 done;
543
544 vdac = base + 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 done:
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