sfb.c revision 1.29 1 /* $NetBSD: sfb.c,v 1.29 1999/12/04 14:01:56 drochner 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.29 1999/12/04 14:01:56 drochner 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 #include <vm/vm.h>
45
46 #include <machine/bus.h>
47 #include <machine/intr.h>
48
49 #include <dev/wscons/wsconsio.h>
50 #include <dev/wscons/wsdisplayvar.h>
51
52 #include <dev/rasops/rasops.h>
53 #include <dev/wsfont/wsfont.h>
54
55 #include <dev/tc/tcvar.h>
56 #include <dev/ic/bt459reg.h>
57 #include <dev/tc/sfbreg.h>
58
59 #include <uvm/uvm_extern.h>
60
61 #if defined(pmax)
62 #define machine_btop(x) mips_btop(x)
63 #define MACHINE_KSEG0_TO_PHYS(x) MIPS_KSEG1_TO_PHYS(x)
64 #endif
65
66 #if defined(__alpha__) || defined(alpha)
67 #define machine_btop(x) alpha_btop(x)
68 #define MACHINE_KSEG0_TO_PHYS(x) ALPHA_K0SEG_TO_PHYS(x)
69 #endif
70
71 /*
72 * N.B., Bt459 registers are 8bit width. Some of TC framebuffers have
73 * obscure register layout such as 2nd and 3rd Bt459 registers are
74 * adjacent each other in a word, i.e.,
75 * struct bt459triplet {
76 * struct {
77 * u_int8_t u0;
78 * u_int8_t u1;
79 * u_int8_t u2;
80 * unsigned :8;
81 * } bt_lo;
82 * struct {
83 *
84 * Although HX has single Bt459, 32bit R/W can be done w/o any trouble.
85 * struct bt459reg {
86 * u_int32_t bt_lo;
87 * u_int32_t bt_hi;
88 * u_int32_t bt_reg;
89 * u_int32_t bt_cmap;
90 * };
91 *
92 */
93
94 /* Bt459 hardware registers */
95 #define bt_lo 0
96 #define bt_hi 1
97 #define bt_reg 2
98 #define bt_cmap 3
99
100 #define REG(base, index) *((u_int32_t *)(base) + (index))
101 #define SELECT(vdac, regno) do { \
102 REG(vdac, bt_lo) = ((regno) & 0x00ff); \
103 REG(vdac, bt_hi) = ((regno) & 0x0f00) >> 8; \
104 tc_wmb(); \
105 } while (0)
106
107 struct fb_devconfig {
108 vaddr_t dc_vaddr; /* memory space virtual base address */
109 paddr_t dc_paddr; /* memory space physical base address */
110 vsize_t dc_size; /* size of slot memory */
111 int dc_wid; /* width of frame buffer */
112 int dc_ht; /* height of frame buffer */
113 int dc_depth; /* depth, bits per pixel */
114 int dc_rowbytes; /* bytes in a FB scan line */
115 vaddr_t dc_videobase; /* base of flat frame buffer */
116 int dc_blanked; /* currently has video disabled */
117
118 struct rasops_info rinfo;
119 };
120
121 struct hwcmap256 {
122 #define CMAP_SIZE 256 /* 256 R/G/B entries */
123 u_int8_t r[CMAP_SIZE];
124 u_int8_t g[CMAP_SIZE];
125 u_int8_t b[CMAP_SIZE];
126 };
127
128 struct hwcursor64 {
129 struct wsdisplay_curpos cc_pos;
130 struct wsdisplay_curpos cc_hot;
131 struct wsdisplay_curpos cc_size;
132 struct wsdisplay_curpos cc_magic;
133 #define CURSOR_MAX_SIZE 64
134 u_int8_t cc_color[6];
135 u_int64_t cc_image[64 + 64];
136 };
137
138 struct sfb_softc {
139 struct device sc_dev;
140 struct fb_devconfig *sc_dc; /* device configuration */
141 struct hwcmap256 sc_cmap; /* software copy of colormap */
142 struct hwcursor64 sc_cursor; /* software copy of cursor */
143 int sc_curenb; /* cursor sprite enabled */
144 int sc_changed; /* need update of colormap */
145 #define DATA_ENB_CHANGED 0x01 /* cursor enable changed */
146 #define DATA_CURCMAP_CHANGED 0x02 /* cursor colormap changed */
147 #define DATA_CURSHAPE_CHANGED 0x04 /* cursor size, image, mask changed */
148 #define DATA_CMAP_CHANGED 0x08 /* colormap changed */
149 #define DATA_ALL_CHANGED 0x0f
150 int nscreens;
151 };
152
153 #define HX_MAGIC_X 368
154 #define HX_MAGIC_Y 38
155
156 static int sfbmatch __P((struct device *, struct cfdata *, void *));
157 static void sfbattach __P((struct device *, struct device *, void *));
158
159 const struct cfattach sfb_ca = {
160 sizeof(struct sfb_softc), sfbmatch, sfbattach,
161 };
162
163 static void sfb_getdevconfig __P((tc_addr_t, struct fb_devconfig *));
164 static struct fb_devconfig sfb_console_dc;
165 static tc_addr_t sfb_consaddr;
166
167 #if 0
168 static void sfb_cursor __P((void *, int, int, int));
169 static void sfb_copycols __P((void *, int, int, int, int));
170 static void sfb_erasecols __P((void *, int, int, int, long));
171 static void sfb_eraserows __P((void *, int, int, long));
172 #endif
173 static void sfb_putchar __P((void *, int, int, u_int, long));
174 static void sfb_copyrows __P((void *, int, int, int));
175
176 static struct wsscreen_descr sfb_stdscreen = {
177 "std", 0, 0,
178 0, /* textops */
179 0, 0,
180 0 /* capabilities */
181 };
182
183 static const struct wsscreen_descr *_sfb_scrlist[] = {
184 &sfb_stdscreen,
185 };
186
187 static const struct wsscreen_list sfb_screenlist = {
188 sizeof(_sfb_scrlist) / sizeof(struct wsscreen_descr *), _sfb_scrlist
189 };
190
191 static int sfbioctl __P((void *, u_long, caddr_t, int, struct proc *));
192 static int sfbmmap __P((void *, off_t, int));
193
194 static int sfb_alloc_screen __P((void *, const struct wsscreen_descr *,
195 void **, int *, int *, long *));
196 static void sfb_free_screen __P((void *, void *));
197 static void sfb_show_screen __P((void *, 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_depth = dc->dc_depth;
306 dc->rinfo.ri_bits = (void *)dc->dc_videobase;
307 dc->rinfo.ri_width = dc->dc_wid;
308 dc->rinfo.ri_height = dc->dc_ht;
309 dc->rinfo.ri_stride = dc->dc_rowbytes;
310 dc->rinfo.ri_hw = sfbasic;
311
312 /*
313 * the accelerated sfb_putchar() needs LSbit left,
314 * so we can't use the rasops default font
315 */
316 wsfont_init();
317 /* prefer 8 pixel wide font */
318 if ((cookie = wsfont_find(NULL, 8, 0, 0)) <= 0)
319 cookie = wsfont_find(NULL, 0, 0, 0);
320 if (cookie <= 0) {
321 printf("sfb: font table is empty\n");
322 return;
323 }
324 if (wsfont_lock(cookie, &dc->rinfo.ri_font,
325 WSFONT_R2L, WSFONT_L2R) <= 0) {
326 printf("sfb: couldn't lock font\n");
327 return;
328 }
329 dc->rinfo.ri_wsfcookie = cookie;
330
331 rasops_init(&dc->rinfo, 1000, 1000); /* as large as possible */
332
333 /* add our accelerated functions */
334 dc->rinfo.ri_ops.copyrows = sfb_copyrows;
335 dc->rinfo.ri_ops.putchar = sfb_putchar;
336
337 /* XXX shouldn't be global */
338 sfb_stdscreen.nrows = dc->rinfo.ri_rows;
339 sfb_stdscreen.ncols = dc->rinfo.ri_cols;
340 sfb_stdscreen.textops = &dc->rinfo.ri_ops;
341 sfb_stdscreen.capabilities = dc->rinfo.ri_caps;
342 /* our accelerated putchar can't underline */
343 sfb_stdscreen.capabilities &= ~WSSCREEN_UNDERLINE;
344 }
345
346 static void
347 sfbattach(parent, self, aux)
348 struct device *parent, *self;
349 void *aux;
350 {
351 struct sfb_softc *sc = (struct sfb_softc *)self;
352 struct tc_attach_args *ta = aux;
353 struct wsemuldisplaydev_attach_args waa;
354 caddr_t sfbasic;
355 int console;
356
357 console = (ta->ta_addr == sfb_consaddr);
358 if (console) {
359 sc->sc_dc = &sfb_console_dc;
360 sc->nscreens = 1;
361 }
362 else {
363 sc->sc_dc = (struct fb_devconfig *)
364 malloc(sizeof(struct fb_devconfig), M_DEVBUF, M_WAITOK);
365 memset(sc->sc_dc, 0, sizeof(struct fb_devconfig));
366 sfb_getdevconfig(ta->ta_addr, sc->sc_dc);
367 }
368 printf(": %d x %d, %dbpp\n", sc->sc_dc->dc_wid, sc->sc_dc->dc_ht,
369 sc->sc_dc->dc_depth);
370
371 memcpy(&sc->sc_cmap, rasops_cmap, sizeof(struct hwcmap256));
372
373 sc->sc_cursor.cc_magic.x = HX_MAGIC_X;
374 sc->sc_cursor.cc_magic.y = HX_MAGIC_Y;
375
376 tc_intr_establish(parent, ta->ta_cookie, IPL_TTY, sfbintr, sc);
377
378 sfbasic = (caddr_t)(sc->sc_dc->dc_vaddr + SFB_ASIC_OFFSET);
379 *(u_int32_t *)(sfbasic + SFB_ASIC_CLEAR_INTR) = 0;
380 *(u_int32_t *)(sfbasic + SFB_ASIC_ENABLE_INTR) = 1;
381
382 waa.console = console;
383 waa.scrdata = &sfb_screenlist;
384 waa.accessops = &sfb_accessops;
385 waa.accesscookie = sc;
386
387 config_found(self, &waa, wsemuldisplaydevprint);
388 }
389
390 static int
391 sfbioctl(v, cmd, data, flag, p)
392 void *v;
393 u_long cmd;
394 caddr_t data;
395 int flag;
396 struct proc *p;
397 {
398 struct sfb_softc *sc = v;
399 struct fb_devconfig *dc = sc->sc_dc;
400 int turnoff;
401
402 switch (cmd) {
403 case WSDISPLAYIO_GTYPE:
404 *(u_int *)data = WSDISPLAY_TYPE_SFB;
405 return (0);
406
407 case WSDISPLAYIO_GINFO:
408 #define wsd_fbip ((struct wsdisplay_fbinfo *)data)
409 wsd_fbip->height = sc->sc_dc->dc_ht;
410 wsd_fbip->width = sc->sc_dc->dc_wid;
411 wsd_fbip->depth = sc->sc_dc->dc_depth;
412 wsd_fbip->cmsize = CMAP_SIZE;
413 #undef fbt
414 return (0);
415
416 case WSDISPLAYIO_GETCMAP:
417 return get_cmap(sc, (struct wsdisplay_cmap *)data);
418
419 case WSDISPLAYIO_PUTCMAP:
420 return set_cmap(sc, (struct wsdisplay_cmap *)data);
421
422 case WSDISPLAYIO_SVIDEO:
423 turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF;
424 if ((dc->dc_blanked == 0) ^ turnoff) {
425 dc->dc_blanked = turnoff;
426 #if 0 /* XXX later XXX */
427 To turn off, assign value 0 in ASIC_VIDEO_VALID register.
428 #endif /* XXX XXX XXX */
429 }
430 return (0);
431
432 case WSDISPLAYIO_GVIDEO:
433 *(u_int *)data = dc->dc_blanked ?
434 WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON;
435 return (0);
436
437 case WSDISPLAYIO_GCURPOS:
438 *(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos;
439 return (0);
440
441 case WSDISPLAYIO_SCURPOS:
442 set_curpos(sc, (struct wsdisplay_curpos *)data);
443 bt459_set_curpos(sc);
444 return (0);
445
446 case WSDISPLAYIO_GCURMAX:
447 ((struct wsdisplay_curpos *)data)->x =
448 ((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE;
449 return (0);
450
451 case WSDISPLAYIO_GCURSOR:
452 return get_cursor(sc, (struct wsdisplay_cursor *)data);
453
454 case WSDISPLAYIO_SCURSOR:
455 return set_cursor(sc, (struct wsdisplay_cursor *)data);
456 }
457 return ENOTTY;
458 }
459
460 static int
461 sfbmmap(v, offset, prot)
462 void *v;
463 off_t offset;
464 int prot;
465 {
466 struct sfb_softc *sc = v;
467
468 if (offset >= SFB_SIZE || offset < 0)
469 return (-1);
470 return machine_btop(sc->sc_dc->dc_paddr + offset);
471 }
472
473 static int
474 sfb_alloc_screen(v, type, cookiep, curxp, curyp, attrp)
475 void *v;
476 const struct wsscreen_descr *type;
477 void **cookiep;
478 int *curxp, *curyp;
479 long *attrp;
480 {
481 struct sfb_softc *sc = v;
482 long defattr;
483
484 if (sc->nscreens > 0)
485 return (ENOMEM);
486
487 *cookiep = &sc->sc_dc->rinfo; /* one and only for now */
488 *curxp = 0;
489 *curyp = 0;
490 (*sc->sc_dc->rinfo.ri_ops.alloc_attr)(&sc->sc_dc->rinfo, 0, 0, 0, &defattr);
491 *attrp = defattr;
492 sc->nscreens++;
493 return (0);
494 }
495
496 static void
497 sfb_free_screen(v, cookie)
498 void *v;
499 void *cookie;
500 {
501 struct sfb_softc *sc = v;
502
503 if (sc->sc_dc == &sfb_console_dc)
504 panic("sfb_free_screen: console");
505
506 sc->nscreens--;
507 }
508
509 static void
510 sfb_show_screen(v, cookie)
511 void *v;
512 void *cookie;
513 {
514 }
515
516 /* EXPORT */ int
517 sfb_cnattach(addr)
518 tc_addr_t addr;
519 {
520 struct fb_devconfig *dcp = &sfb_console_dc;
521 long defattr;
522
523 sfb_getdevconfig(addr, dcp);
524
525 (*dcp->rinfo.ri_ops.alloc_attr)(&dcp->rinfo, 0, 0, 0, &defattr);
526
527 wsdisplay_cnattach(&sfb_stdscreen, &dcp->rinfo, 0, 0, defattr);
528 sfb_consaddr = addr;
529 return(0);
530 }
531
532 static int
533 sfbintr(arg)
534 void *arg;
535 {
536 struct sfb_softc *sc = arg;
537 caddr_t sfbbase = (caddr_t)sc->sc_dc->dc_vaddr;
538 caddr_t sfbasic = sfbbase + SFB_ASIC_OFFSET;
539 caddr_t vdac;
540 int v;
541
542 *(u_int32_t *)(sfbasic + SFB_ASIC_CLEAR_INTR) = 0;
543 /* *(u_int32_t *)(sfbasic + SFB_ASIC_ENABLE_INTR) = 1; */
544
545 if (sc->sc_changed == 0)
546 return (1);
547
548 vdac = (void *)(sfbbase + SFB_RAMDAC_OFFSET);
549 v = sc->sc_changed;
550 sc->sc_changed = 0;
551
552 if (v & DATA_ENB_CHANGED) {
553 SELECT(vdac, BT459_REG_CCR);
554 REG(vdac, bt_reg) = (sc->sc_curenb) ? 0xc0 : 0x00;
555 }
556 if (v & DATA_CURCMAP_CHANGED) {
557 u_int8_t *cp = sc->sc_cursor.cc_color;
558
559 SELECT(vdac, BT459_REG_CCOLOR_2);
560 REG(vdac, bt_reg) = cp[1]; tc_wmb();
561 REG(vdac, bt_reg) = cp[3]; tc_wmb();
562 REG(vdac, bt_reg) = cp[5]; tc_wmb();
563
564 REG(vdac, bt_reg) = cp[0]; tc_wmb();
565 REG(vdac, bt_reg) = cp[2]; tc_wmb();
566 REG(vdac, bt_reg) = cp[4]; tc_wmb();
567 }
568 if (v & DATA_CURSHAPE_CHANGED) {
569 u_int8_t *ip, *mp, img, msk;
570 u_int8_t u;
571 int bcnt;
572
573 ip = (u_int8_t *)sc->sc_cursor.cc_image;
574 mp = (u_int8_t *)(sc->sc_cursor.cc_image + CURSOR_MAX_SIZE);
575
576 bcnt = 0;
577 SELECT(vdac, BT459_REG_CRAM_BASE+0);
578 /* 64 pixel scan line is consisted with 16 byte cursor ram */
579 while (bcnt < sc->sc_cursor.cc_size.y * 16) {
580 /* pad right half 32 pixel when smaller than 33 */
581 if ((bcnt & 0x8) && sc->sc_cursor.cc_size.x < 33) {
582 REG(vdac, bt_reg) = 0; tc_wmb();
583 REG(vdac, bt_reg) = 0; tc_wmb();
584 }
585 else {
586 img = *ip++;
587 msk = *mp++;
588 img &= msk; /* cookie off image */
589 u = (msk & 0x0f) << 4 | (img & 0x0f);
590 REG(vdac, bt_reg) = shuffle[u]; tc_wmb();
591 u = (msk & 0xf0) | (img & 0xf0) >> 4;
592 REG(vdac, bt_reg) = shuffle[u]; tc_wmb();
593 }
594 bcnt += 2;
595 }
596 /* pad unoccupied scan lines */
597 while (bcnt < CURSOR_MAX_SIZE * 16) {
598 REG(vdac, bt_reg) = 0; tc_wmb();
599 REG(vdac, bt_reg) = 0; tc_wmb();
600 bcnt += 2;
601 }
602 }
603 if (v & DATA_CMAP_CHANGED) {
604 struct hwcmap256 *cm = &sc->sc_cmap;
605 int index;
606
607 SELECT(vdac, 0);
608 for (index = 0; index < CMAP_SIZE; index++) {
609 REG(vdac, bt_cmap) = cm->r[index]; tc_wmb();
610 REG(vdac, bt_cmap) = cm->g[index]; tc_wmb();
611 REG(vdac, bt_cmap) = cm->b[index]; tc_wmb();
612 }
613 }
614 return (1);
615 }
616
617 static void
618 sfbinit(dc)
619 struct fb_devconfig *dc;
620 {
621 caddr_t sfbasic = (caddr_t)(dc->dc_vaddr + SFB_ASIC_OFFSET);
622 caddr_t vdac = (void *)(dc->dc_vaddr + SFB_RAMDAC_OFFSET);
623 int i;
624
625 *(u_int32_t *)(sfbasic + SFB_ASIC_PLANEMASK) = ~0;
626 *(u_int32_t *)(sfbasic + SFB_ASIC_PIXELMASK) = ~0;
627 *(u_int32_t *)(sfbasic + SFB_ASIC_MODE) = 0; /* MODE_SIMPLE */
628 *(u_int32_t *)(sfbasic + SFB_ASIC_ROP) = 3; /* ROP_COPY */
629
630 *(u_int32_t *)(sfbasic + 0x180000) = 0; /* Bt459 reset */
631
632 SELECT(vdac, BT459_REG_COMMAND_0);
633 REG(vdac, bt_reg) = 0x40; /* CMD0 */ tc_wmb();
634 REG(vdac, bt_reg) = 0x0; /* CMD1 */ tc_wmb();
635 REG(vdac, bt_reg) = 0xc0; /* CMD2 */ tc_wmb();
636 REG(vdac, bt_reg) = 0xff; /* PRM */ tc_wmb();
637 REG(vdac, bt_reg) = 0; /* 205 */ tc_wmb();
638 REG(vdac, bt_reg) = 0x0; /* PBM */ tc_wmb();
639 REG(vdac, bt_reg) = 0; /* 207 */ tc_wmb();
640 REG(vdac, bt_reg) = 0x0; /* ORM */ tc_wmb();
641 REG(vdac, bt_reg) = 0x0; /* OBM */ tc_wmb();
642 REG(vdac, bt_reg) = 0x0; /* ILV */ tc_wmb();
643 REG(vdac, bt_reg) = 0x0; /* TEST */ tc_wmb();
644
645 SELECT(vdac, BT459_REG_CCR);
646 REG(vdac, bt_reg) = 0x0; tc_wmb();
647 REG(vdac, bt_reg) = 0x0; tc_wmb();
648 REG(vdac, bt_reg) = 0x0; tc_wmb();
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
660 /* build sane colormap */
661 SELECT(vdac, 0);
662 for (i = 0; i < CMAP_SIZE; i++) {
663 REG(vdac, bt_cmap) = rasops_cmap[3 * i + 0];
664 tc_wmb();
665 REG(vdac, bt_cmap) = rasops_cmap[3 * i + 1];
666 tc_wmb();
667 REG(vdac, bt_cmap) = rasops_cmap[3 * i + 2];
668 tc_wmb();
669 }
670
671 /* clear out cursor image */
672 SELECT(vdac, BT459_REG_CRAM_BASE);
673 for (i = 0; i < 1024; i++)
674 REG(vdac, bt_reg) = 0xff; tc_wmb();
675
676 /*
677 * 2 bit/pixel cursor. Assign MSB for cursor mask and LSB for
678 * cursor image. CCOLOR_2 for mask color, while CCOLOR_3 for
679 * image color. CCOLOR_1 will be never used.
680 */
681 SELECT(vdac, BT459_REG_CCOLOR_1);
682 REG(vdac, bt_reg) = 0xff; tc_wmb();
683 REG(vdac, bt_reg) = 0xff; tc_wmb();
684 REG(vdac, bt_reg) = 0xff; tc_wmb();
685
686 REG(vdac, bt_reg) = 0; tc_wmb();
687 REG(vdac, bt_reg) = 0; tc_wmb();
688 REG(vdac, bt_reg) = 0; tc_wmb();
689
690 REG(vdac, bt_reg) = 0xff; tc_wmb();
691 REG(vdac, bt_reg) = 0xff; tc_wmb();
692 REG(vdac, bt_reg) = 0xff; tc_wmb();
693 }
694
695 static int
696 get_cmap(sc, p)
697 struct sfb_softc *sc;
698 struct wsdisplay_cmap *p;
699 {
700 u_int index = p->index, count = p->count;
701
702 if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE)
703 return (EINVAL);
704
705 if (!uvm_useracc(p->red, count, B_WRITE) ||
706 !uvm_useracc(p->green, count, B_WRITE) ||
707 !uvm_useracc(p->blue, count, B_WRITE))
708 return (EFAULT);
709
710 copyout(&sc->sc_cmap.r[index], p->red, count);
711 copyout(&sc->sc_cmap.g[index], p->green, count);
712 copyout(&sc->sc_cmap.b[index], p->blue, count);
713
714 return (0);
715 }
716
717 static int
718 set_cmap(sc, p)
719 struct sfb_softc *sc;
720 struct wsdisplay_cmap *p;
721 {
722 u_int index = p->index, count = p->count;
723
724 if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE)
725 return (EINVAL);
726
727 if (!uvm_useracc(p->red, count, B_READ) ||
728 !uvm_useracc(p->green, count, B_READ) ||
729 !uvm_useracc(p->blue, count, B_READ))
730 return (EFAULT);
731
732 copyin(p->red, &sc->sc_cmap.r[index], count);
733 copyin(p->green, &sc->sc_cmap.g[index], count);
734 copyin(p->blue, &sc->sc_cmap.b[index], count);
735
736 sc->sc_changed |= DATA_CMAP_CHANGED;
737
738 return (0);
739 }
740
741
742 static int
743 set_cursor(sc, p)
744 struct sfb_softc *sc;
745 struct wsdisplay_cursor *p;
746 {
747 #define cc (&sc->sc_cursor)
748 int v, index, count, icount;
749
750 v = p->which;
751 if (v & WSDISPLAY_CURSOR_DOCMAP) {
752 index = p->cmap.index;
753 count = p->cmap.count;
754 if (index >= 2 || (index + count) > 2)
755 return (EINVAL);
756 if (!uvm_useracc(p->cmap.red, count, B_READ) ||
757 !uvm_useracc(p->cmap.green, count, B_READ) ||
758 !uvm_useracc(p->cmap.blue, count, B_READ))
759 return (EFAULT);
760 }
761 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
762 if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE)
763 return (EINVAL);
764 icount = ((p->size.x < 33) ? 4 : 8) * p->size.y;
765 if (!uvm_useracc(p->image, icount, B_READ) ||
766 !uvm_useracc(p->mask, icount, B_READ))
767 return (EFAULT);
768 }
769 if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOCUR)) {
770 if (v & WSDISPLAY_CURSOR_DOCUR)
771 cc->cc_hot = p->hot;
772 if (v & WSDISPLAY_CURSOR_DOPOS)
773 set_curpos(sc, &p->pos);
774 bt459_set_curpos(sc);
775 }
776
777 sc->sc_changed = 0;
778 if (v & WSDISPLAY_CURSOR_DOCUR) {
779 sc->sc_curenb = p->enable;
780 sc->sc_changed |= DATA_ENB_CHANGED;
781 }
782 if (v & WSDISPLAY_CURSOR_DOCMAP) {
783 copyin(p->cmap.red, &cc->cc_color[index], count);
784 copyin(p->cmap.green, &cc->cc_color[index + 2], count);
785 copyin(p->cmap.blue, &cc->cc_color[index + 4], count);
786 sc->sc_changed |= DATA_CURCMAP_CHANGED;
787 }
788 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
789 cc->cc_size = p->size;
790 memset(cc->cc_image, 0, sizeof cc->cc_image);
791 copyin(p->image, cc->cc_image, icount);
792 copyin(p->mask, cc->cc_image+CURSOR_MAX_SIZE, icount);
793 sc->sc_changed |= DATA_CURSHAPE_CHANGED;
794 }
795
796 return (0);
797 #undef cc
798 }
799
800 static int
801 get_cursor(sc, p)
802 struct sfb_softc *sc;
803 struct wsdisplay_cursor *p;
804 {
805 return (ENOTTY); /* XXX */
806 }
807
808 static void
809 set_curpos(sc, curpos)
810 struct sfb_softc *sc;
811 struct wsdisplay_curpos *curpos;
812 {
813 struct fb_devconfig *dc = sc->sc_dc;
814 int x = curpos->x, y = curpos->y;
815
816 if (y < 0)
817 y = 0;
818 else if (y > dc->dc_ht)
819 y = dc->dc_ht;
820 if (x < 0)
821 x = 0;
822 else if (x > dc->dc_wid)
823 x = dc->dc_wid;
824 sc->sc_cursor.cc_pos.x = x;
825 sc->sc_cursor.cc_pos.y = y;
826 }
827
828 static void
829 bt459_set_curpos(sc)
830 struct sfb_softc *sc;
831 {
832 caddr_t vdac = (caddr_t)sc->sc_dc->dc_vaddr + SFB_RAMDAC_OFFSET;
833 int x, y, s;
834
835 x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x;
836 y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y;
837
838 x += sc->sc_cursor.cc_magic.x;
839 y += sc->sc_cursor.cc_magic.y;
840
841 s = spltty();
842
843 SELECT(vdac, BT459_REG_CURSOR_X_LOW);
844 REG(vdac, bt_reg) = x; tc_wmb();
845 REG(vdac, bt_reg) = x >> 8; tc_wmb();
846 REG(vdac, bt_reg) = y; tc_wmb();
847 REG(vdac, bt_reg) = y >> 8; tc_wmb();
848
849 splx(s);
850 }
851
852 #define MODE_SIMPLE 0
853 #define MODE_OPAQUESTIPPLE 1
854 #define MODE_OPAQUELINE 2
855 #define MODE_TRANSPARENTSTIPPLE 5
856 #define MODE_TRANSPARENTLINE 6
857 #define MODE_COPY 7
858
859 /* parameters for 8bpp configuration */
860 #define SFBALIGNMASK 0x7
861 #define SFBSTIPPLEALL1 0xffffffff
862 #define SFBSTIPPLEBITS 32
863 #define SFBSTIPPLEBITMASK 0x1f
864 #define SFBSTIPPLEBYTESDONE 32
865 #define SFBCOPYALL1 0xffffffff
866 #define SFBCOPYBITS 32
867 #define SFBCOPYBITMASK 0x1f
868 #define SFBCOPYBYTESDONE 32
869
870 #ifdef pmax
871 #define WRITE_MB()
872 #define BUMP(p) (p)
873 #endif
874
875 #ifdef alpha
876 #define WRITE_MB() tc_wmb()
877 #define BUMP(p) ((p) = (caddr_t)(((long)(p) + 128) & ~0x400))
878 #endif
879
880 #define SFBMODE(p, v) \
881 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_MODE) = (v))
882 #define SFBROP(p, v) \
883 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_ROP) = (v))
884 #define SFBPLANEMASK(p, v) \
885 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_PLANEMASK) = (v))
886 #define SFBPIXELMASK(p, v) \
887 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELMASK) = (v))
888 #define SFBADDRESS(p, v) \
889 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_ADDRESS) = (v))
890 #define SFBSTART(p, v) \
891 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_START) = (v))
892 #define SFBPIXELSHIFT(p, v) \
893 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELSHIFT) = (v))
894 #define SFBFG(p, v) \
895 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_FG) = (v))
896 #define SFBBG(p, v) \
897 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_BG) = (v))
898
899
900 #if 0
901 /*
902 * Paint (or unpaint) the cursor.
903 */
904 static void
905 sfb_cursor(id, on, row, col)
906 void *id;
907 int on, row, col;
908 {
909 struct rcons *rc = id;
910 struct raster *rap = rc->rc_sp;
911 caddr_t sfb, p;
912 int scanspan, height, width, align, x, y;
913 u_int32_t lmask, rmask;
914
915 /* turn the cursor off */
916 if (!on) {
917 /* make sure it's on */
918 if ((rc->rc_bits & RC_CURSOR) == 0)
919 return;
920
921 row = *rc->rc_crowp;
922 col = *rc->rc_ccolp;
923 } else {
924 /* unpaint the old copy. */
925 *rc->rc_crowp = row;
926 *rc->rc_ccolp = col;
927 }
928
929 x = col * rc->rc_font->width + rc->rc_xorigin;
930 y = row * rc->rc_font->height + rc->rc_yorigin;
931 scanspan = rap->linelongs * 4;
932 height = rc->rc_font->height;
933
934 p = (caddr_t)rap->pixels + y * scanspan + x;
935 align = (long)p & SFBALIGNMASK;
936 p -= align;
937 width = rc->rc_font->width + align;
938 lmask = SFBSTIPPLEALL1 << align;
939 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
940 sfb = rap->data;
941
942 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
943 SFBPLANEMASK(sfb, ~0);
944 SFBROP(sfb, 6); /* ROP_XOR */
945 SFBFG(sfb, 0x01010101); /* (fg ^ bg) to swap fg/bg */
946 if (width <= SFBSTIPPLEBITS) {
947 lmask = lmask & rmask;
948 while (height > 0) {
949 SFBADDRESS(sfb, (long)p);
950 SFBSTART(sfb, lmask);
951 p += scanspan;
952 height--;
953 }
954 }
955 else {
956 caddr_t q = p;
957 while (height > 0) {
958 *(u_int32_t *)p = lmask;
959 WRITE_MB();
960 p += SFBSTIPPLEBYTESDONE;
961 *(u_int32_t *)p = rmask;
962 WRITE_MB();
963
964 p = (q += scanspan);
965 height--;
966 }
967 }
968 SFBMODE(sfb, MODE_SIMPLE);
969 SFBROP(sfb, 3); /* ROP_COPY */
970
971 rc->rc_bits ^= RC_CURSOR;
972 }
973 #endif
974
975 /*
976 * Actually write a string to the frame buffer.
977 */
978 static void
979 sfb_putchar(id, row, col, uc, attr)
980 void *id;
981 int row, col;
982 u_int uc;
983 long attr;
984 {
985 struct rasops_info *ri = id;
986 caddr_t sfb, p;
987 int scanspan, height, width, align, x, y;
988 u_int32_t lmask, rmask, glyph;
989 u_int8_t *g;
990 int fg, bg;
991
992 x = col * ri->ri_font->fontwidth;
993 y = row * ri->ri_font->fontheight;
994 scanspan = ri->ri_stride;
995 height = ri->ri_font->fontheight;
996 uc -= ri->ri_font->firstchar;
997 g = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
998
999 p = ri->ri_bits + y * scanspan + x;
1000 align = (long)p & SFBALIGNMASK;
1001 p -= align;
1002 width = ri->ri_font->fontwidth + align;
1003 lmask = SFBSTIPPLEALL1 << align;
1004 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
1005 sfb = ri->ri_hw;
1006
1007 SFBMODE(sfb, MODE_OPAQUESTIPPLE);
1008 SFBPLANEMASK(sfb, ~0);
1009 rasops_unpack_attr(attr, &fg, &bg, 0);
1010 SFBFG(sfb, fg * 0x01010101);
1011 SFBBG(sfb, bg * 0x01010101);
1012 if (width <= SFBSTIPPLEBITS) {
1013 lmask = lmask & rmask;
1014 while (height > 0) {
1015 glyph = g[0];
1016 if (ri->ri_font->fontwidth > 8)
1017 glyph |= (g[1] << 8);
1018 SFBPIXELMASK(sfb, lmask);
1019 SFBADDRESS(sfb, (long)p);
1020 SFBSTART(sfb, glyph << align);
1021 p += scanspan;
1022 g += ri->ri_font->stride;
1023 height--;
1024 }
1025 }
1026 else {
1027 caddr_t q = p;
1028 while (height > 0) {
1029 glyph = *g;
1030 SFBPIXELMASK(sfb, lmask);
1031 WRITE_MB();
1032 *(u_int32_t *)p = glyph << align;
1033 WRITE_MB();
1034 p += SFBSTIPPLEBYTESDONE;
1035 SFBPIXELMASK(sfb, rmask);
1036 WRITE_MB();
1037 *(u_int32_t *)p = glyph >> (-width & SFBSTIPPLEBITMASK);
1038 WRITE_MB();
1039
1040 p = (q += scanspan);
1041 g += 1;
1042 height--;
1043 }
1044 }
1045 SFBMODE(sfb, MODE_SIMPLE);
1046 SFBPIXELMASK(sfb, ~0); /* entire pixel */
1047 }
1048
1049 #if 0
1050 /*
1051 * Copy characters in a line.
1052 */
1053 static void
1054 sfb_copycols(id, row, srccol, dstcol, ncols)
1055 void *id;
1056 int row, srccol, dstcol, ncols;
1057 {
1058 struct rcons *rc = id;
1059 struct raster *rap = rc->rc_sp;
1060 caddr_t sp, dp, basex, sfb;
1061 int scanspan, height, width, aligns, alignd, shift, w, y;
1062 u_int32_t lmasks, rmasks, lmaskd, rmaskd;
1063
1064 scanspan = rap->linelongs * 4;
1065 y = rc->rc_yorigin + rc->rc_font->height * row;
1066 basex = (caddr_t)rap->pixels + y * scanspan + rc->rc_xorigin;
1067 height = rc->rc_font->height;
1068 w = rc->rc_font->width * ncols;
1069
1070 sp = basex + rc->rc_font->width * srccol;
1071 aligns = (long)sp & SFBALIGNMASK;
1072 dp = basex + rc->rc_font->width * dstcol;
1073 alignd = (long)dp & SFBALIGNMASK;
1074 sfb = rap->data;
1075
1076 SFBMODE(sfb, MODE_COPY);
1077 SFBPLANEMASK(sfb, ~0);
1078
1079 /* copy forward (left-to-right) */
1080 if (dstcol < srccol || srccol + ncols < dstcol) {
1081 caddr_t sq, dq;
1082
1083 shift = alignd - aligns;
1084 if (shift < 0) {
1085 dp -= 8; /* prime left edge */
1086 alignd += 8; /* compensate it */
1087 width = aligns + w + 8; /* adjust total width */
1088 shift = 8 + shift; /* enforce right rotate */
1089 }
1090 else if (shift > 0)
1091 width = aligns + w + 8; /* enfore drain at right edge */
1092
1093 lmasks = SFBCOPYALL1 << aligns;
1094 rmasks = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
1095 lmaskd = SFBCOPYALL1 << alignd;
1096 rmaskd = SFBCOPYALL1 >> (-(w + alignd) & SFBCOPYBITMASK);
1097
1098 if (w + alignd <= SFBCOPYBITS)
1099 goto singlewrite;
1100
1101 SFBPIXELSHIFT(sfb, shift);
1102 w = width;
1103 sq = sp;
1104 dq = dp;
1105 while (height > 0) {
1106 *(u_int32_t *)sp = lmasks;
1107 WRITE_MB();
1108 *(u_int32_t *)dp = lmaskd;
1109 WRITE_MB();
1110 width -= 2 * SFBCOPYBITS;
1111 while (width > 0) {
1112 sp += SFBCOPYBYTESDONE;
1113 dp += SFBCOPYBYTESDONE;
1114 *(u_int32_t *)sp = SFBCOPYALL1;
1115 WRITE_MB();
1116 *(u_int32_t *)dp = SFBCOPYALL1;
1117 WRITE_MB();
1118 width -= SFBCOPYBITS;
1119 }
1120 sp += SFBCOPYBYTESDONE;
1121 dp += SFBCOPYBYTESDONE;
1122 *(u_int32_t *)sp = rmasks;
1123 WRITE_MB();
1124 *(u_int32_t *)dp = rmaskd;
1125 WRITE_MB();
1126
1127 sp = (sq += scanspan);
1128 dp = (dq += scanspan);
1129 width = w;
1130 height--;
1131 }
1132 }
1133 /* copy backward (right-to-left) */
1134 else {
1135 caddr_t sq, dq;
1136
1137 shift = alignd - aligns;
1138 if (shift > 0) {
1139 shift = shift - 8;
1140 w += 8;
1141 }
1142 width = w + aligns;
1143 lmasks = SFBCOPYALL1 << aligns;
1144 rmasks = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
1145 lmaskd = SFBCOPYALL1 << alignd;
1146 rmaskd = SFBCOPYALL1 >> (-(w + alignd) & SFBCOPYBITMASK);
1147
1148 if (w + alignd <= SFBCOPYBITS)
1149 goto singlewrite;
1150
1151 SFBPIXELSHIFT(sfb, shift);
1152 w = width;
1153 sq = (sp += width);
1154 dq = (dp += width);
1155 while (height > 0) {
1156 *(u_int32_t *)sp = rmasks;
1157 WRITE_MB();
1158 *(u_int32_t *)dp = rmaskd;
1159 WRITE_MB();
1160 width -= 2 * SFBCOPYBITS;
1161 while (width > 0) {
1162 sp -= SFBCOPYBYTESDONE;
1163 dp -= SFBCOPYBYTESDONE;
1164 *(u_int32_t *)sp = SFBCOPYALL1;
1165 WRITE_MB();
1166 *(u_int32_t *)dp = SFBCOPYALL1;
1167 WRITE_MB();
1168 width -= SFBCOPYBITS;
1169 }
1170 sp -= SFBCOPYBYTESDONE;
1171 dp -= SFBCOPYBYTESDONE;
1172 *(u_int32_t *)sp = lmasks;
1173 WRITE_MB();
1174 *(u_int32_t *)dp = lmaskd;
1175 WRITE_MB();
1176
1177 sp = (sq += scanspan);
1178 dp = (dq += scanspan);
1179 width = w;
1180 height--;
1181 }
1182 }
1183 SFBMODE(sfb, MODE_SIMPLE);
1184 SFBPIXELSHIFT(sfb, 0);
1185 return;
1186
1187 singlewrite:
1188 SFBPIXELSHIFT(sfb, shift);
1189 lmasks = lmasks & rmasks;
1190 lmaskd = lmaskd & rmaskd;
1191 while (height > 0) {
1192 *(u_int32_t *)sp = lmasks;
1193 WRITE_MB();
1194 *(u_int32_t *)dp = lmaskd;
1195 WRITE_MB();
1196 sp += scanspan;
1197 dp += scanspan;
1198 height--;
1199 }
1200 SFBMODE(sfb, MODE_SIMPLE);
1201 SFBPIXELSHIFT(sfb, 0);
1202 }
1203 #endif
1204
1205 #if 0
1206 /*
1207 * Clear characters in a line.
1208 */
1209 static void
1210 sfb_erasecols(id, row, startcol, ncols, attr)
1211 void *id;
1212 int row, startcol, ncols;
1213 long attr;
1214 {
1215 struct rcons *rc = id;
1216 struct raster *rap = rc->rc_sp;
1217 caddr_t sfb, p;
1218 int scanspan, startx, height, width, align, w, y;
1219 u_int32_t lmask, rmask;
1220
1221 scanspan = rap->linelongs * 4;
1222 y = rc->rc_yorigin + rc->rc_font->height * row;
1223 startx = rc->rc_xorigin + rc->rc_font->width * startcol;
1224 height = rc->rc_font->height;
1225 w = rc->rc_font->width * ncols;
1226
1227 p = (caddr_t)rap->pixels + y * scanspan + startx;
1228 align = (long)p & SFBALIGNMASK;
1229 p -= align;
1230 width = w + align;
1231 lmask = SFBSTIPPLEALL1 << align;
1232 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
1233 sfb = rap->data;
1234
1235 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
1236 SFBPLANEMASK(sfb, ~0);
1237 SFBFG(sfb, 0); /* fill with bg color */
1238 if (width <= SFBSTIPPLEBITS) {
1239 lmask = lmask & rmask;
1240 while (height > 0) {
1241 SFBADDRESS(sfb, (long)p);
1242 SFBSTART(sfb, lmask);
1243 p += scanspan;
1244 height--;
1245 }
1246 }
1247 else {
1248 caddr_t q = p;
1249 while (height > 0) {
1250 *(u_int32_t *)p = lmask;
1251 WRITE_MB();
1252 width -= 2 * SFBSTIPPLEBITS;
1253 while (width > 0) {
1254 p += SFBSTIPPLEBYTESDONE;
1255 *(u_int32_t *)p = SFBSTIPPLEALL1;
1256 WRITE_MB();
1257 width -= SFBSTIPPLEBITS;
1258 }
1259 p += SFBSTIPPLEBYTESDONE;
1260 *(u_int32_t *)p = rmask;
1261 WRITE_MB();
1262
1263 p = (q += scanspan);
1264 width = w + align;
1265 height--;
1266 }
1267 }
1268 SFBMODE(sfb, MODE_SIMPLE);
1269 }
1270 #endif
1271
1272 /*
1273 * Copy lines.
1274 */
1275 static void
1276 sfb_copyrows(id, srcrow, dstrow, nrows)
1277 void *id;
1278 int srcrow, dstrow, nrows;
1279 {
1280 struct rasops_info *ri = id;
1281 caddr_t sfb, p;
1282 int scanspan, offset, srcy, height, width, align, w;
1283 u_int32_t lmask, rmask;
1284
1285 scanspan = ri->ri_stride;
1286 height = ri->ri_font->fontheight * nrows;
1287 offset = (dstrow - srcrow) * ri->ri_yscale;
1288 srcy = ri->ri_font->fontheight * srcrow;
1289 if (srcrow < dstrow && srcrow + nrows > dstrow) {
1290 scanspan = -scanspan;
1291 srcy += height;
1292 }
1293
1294 p = (caddr_t)(ri->ri_bits + srcy * ri->ri_stride);
1295 align = (long)p & SFBALIGNMASK;
1296 p -= align;
1297 w = ri->ri_emuwidth;
1298 width = w + align;
1299 lmask = SFBCOPYALL1 << align;
1300 rmask = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
1301 sfb = ri->ri_hw;
1302
1303 SFBMODE(sfb, MODE_COPY);
1304 SFBPLANEMASK(sfb, ~0);
1305 SFBPIXELSHIFT(sfb, 0);
1306 if (width <= SFBCOPYBITS) {
1307 /* never happens */;
1308 }
1309 else {
1310 caddr_t q = p;
1311 while (height > 0) {
1312 *(u_int32_t *)p = lmask;
1313 *(u_int32_t *)(p + offset) = lmask;
1314 width -= 2 * SFBCOPYBITS;
1315 while (width > 0) {
1316 p += SFBCOPYBYTESDONE;
1317 *(u_int32_t *)p = SFBCOPYALL1;
1318 *(u_int32_t *)(p + offset) = SFBCOPYALL1;
1319 width -= SFBCOPYBITS;
1320 }
1321 p += SFBCOPYBYTESDONE;
1322 *(u_int32_t *)p = rmask;
1323 *(u_int32_t *)(p + offset) = rmask;
1324
1325 p = (q += scanspan);
1326 width = w + align;
1327 height--;
1328 }
1329 }
1330 SFBMODE(sfb, MODE_SIMPLE);
1331 }
1332
1333 #if 0
1334 /*
1335 * Erase lines.
1336 */
1337 void
1338 sfb_eraserows(id, startrow, nrows, attr)
1339 void *id;
1340 int startrow, nrows;
1341 long attr;
1342 {
1343 struct rcons *rc = id;
1344 struct raster *rap = rc->rc_sp;
1345 caddr_t sfb, p;
1346 int scanspan, starty, height, width, align, w;
1347 u_int32_t lmask, rmask;
1348
1349 scanspan = rap->linelongs * 4;
1350 starty = rc->rc_yorigin + rc->rc_font->height * startrow;
1351 height = rc->rc_font->height * nrows;
1352
1353 p = (caddr_t)rap->pixels + starty * scanspan + rc->rc_xorigin;
1354 align = (long)p & SFBALIGNMASK;
1355 p -= align;
1356 w = rc->rc_font->width * rc->rc_maxcol;
1357 width = w + align;
1358 lmask = SFBSTIPPLEALL1 << align;
1359 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
1360 sfb = rap->data;
1361
1362 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
1363 SFBPLANEMASK(sfb, ~0);
1364 SFBFG(sfb, 0); /* fill with bg color */
1365 if (width <= SFBSTIPPLEBITS) {
1366 /* never happens */;
1367 }
1368 else {
1369 caddr_t q = p;
1370 while (height > 0) {
1371 *(u_int32_t *)p = lmask;
1372 WRITE_MB();
1373 width -= 2 * SFBSTIPPLEBITS;
1374 while (width > 0) {
1375 p += SFBSTIPPLEBYTESDONE;
1376 *(u_int32_t *)p = SFBSTIPPLEALL1;
1377 WRITE_MB();
1378 width -= SFBSTIPPLEBITS;
1379 }
1380 p += SFBSTIPPLEBYTESDONE;
1381 *(u_int32_t *)p = rmask;
1382 WRITE_MB();
1383
1384 p = (q += scanspan);
1385 width = w + align;
1386 height--;
1387 }
1388 }
1389 SFBMODE(sfb, MODE_SIMPLE);
1390 }
1391 #endif
1392