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