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