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