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