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