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