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