sfbplus.c revision 1.34 1 /* $NetBSD: sfbplus.c,v 1.34 2010/05/15 07:01:37 tsutsui 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.34 2010/05/15 07:01:37 tsutsui 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) *((uint32_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 uint8_t r[CMAP_SIZE];
85 uint8_t g[CMAP_SIZE];
86 uint8_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 uint8_t cc_color[6];
96 uint64_t cc_image[CURSOR_MAX_SIZE];
97 uint64_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 *, uint64_t *);
106 void (*color)(void *, uint8_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 *, uint64_t *);
177 static void bt459color(void *, uint8_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 *, uint64_t *);
183 static void bt463init(void *);
184 static void bt463color(void *, uint8_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 uint8_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 ri = malloc(sizeof(struct rasops_info), M_DEVBUF, M_NOWAIT);
267 if (ri == NULL) {
268 printf(": can't alloc memory\n");
269 return;
270 }
271 memset(ri, 0, sizeof(struct rasops_info));
272
273 ri->ri_hw = (void *)ta->ta_addr;
274 sfbp_common_init(ri);
275 sc->sc_ri = ri;
276 }
277 printf(": %dx%d, %dbpp\n", ri->ri_width, ri->ri_height,
278 (ri->ri_depth != 32) ? 8 : 24);
279
280 sc->sc_vaddr = ta->ta_addr;
281 sc->sc_cursor.cc_magic.x = HX_MAGIC_X;
282 sc->sc_cursor.cc_magic.y = HX_MAGIC_Y;
283 sc->sc_blanked = sc->sc_curenb = 0;
284
285 if (ri->ri_depth == 8) {
286 sc->sc_hwops.visible = bt459visible;
287 sc->sc_hwops.locate = bt459locate;
288 sc->sc_hwops.shape = bt459shape;
289 sc->sc_hwops.color = bt459color;
290 sc->sc_hwops.setlut = bt459setlut;
291 sc->sc_hwops.getlut = noplut;
292 } else {
293 sc->sc_hwops.visible = sfbpvisible;
294 sc->sc_hwops.locate = sfbplocate;
295 sc->sc_hwops.shape = sfbpshape;
296 sc->sc_hwops.color = bt463color;
297 sc->sc_hwops.setlut = noplut;
298 sc->sc_hwops.getlut = noplut;
299 }
300 sfbp_cmap_init(sc);
301
302 tc_intr_establish(parent, ta->ta_cookie, IPL_TTY, sfbpintr, sc);
303
304 asic = (char *)ri->ri_hw + SFB_ASIC_OFFSET;
305 *(uint32_t *)(asic + SFB_ASIC_CLEAR_INTR) = 0;
306 *(uint32_t *)(asic + SFB_ASIC_ENABLE_INTR) = 1;
307
308 waa.console = console;
309 waa.scrdata = &sfb_screenlist;
310 waa.accessops = &sfb_accessops;
311 waa.accesscookie = sc;
312
313 config_found(self, &waa, wsemuldisplaydevprint);
314 }
315
316 static void
317 sfbp_cmap_init(struct sfbp_softc *sc)
318 {
319 struct hwcmap256 *cm;
320 const uint8_t *p;
321 int index;
322
323 if (sc->sc_ri->ri_depth != 8)
324 return;
325
326 cm = &sc->sc_cmap;
327 p = rasops_cmap;
328 for (index = 0; index < CMAP_SIZE; index++, p += 3) {
329 cm->r[index] = p[0];
330 cm->g[index] = p[1];
331 cm->b[index] = p[2];
332 }
333 }
334
335 static void
336 sfbp_common_init(struct rasops_info *ri)
337 {
338 char *base, *asic;
339 int i, depth, hsetup, vsetup, vbase, cookie;
340
341 base = ri->ri_hw;
342 asic = base + SFB_ASIC_OFFSET;
343 hsetup = *(uint32_t *)(asic + SFB_ASIC_VIDEO_HSETUP);
344 vsetup = *(uint32_t *)(asic + SFB_ASIC_VIDEO_VSETUP);
345 i = *(uint32_t *)(asic + SFB_ASIC_DEEP);
346 depth = (i & 01) ? 32 : 8;
347
348 /*
349 * - neglect 0,1 cases of hsetup register.
350 * - observed 804x600?, 644x480? values.
351 */
352
353 *(uint32_t *)(asic + SFB_ASIC_VIDEO_BASE) = vbase = 1;
354 vbase *= (i & 0x20) ? 2048 : 4096; /* VRAM chip size */
355 if (i & 1) vbase *= 4; /* bytes per pixel */
356
357 *(uint32_t *)(asic + SFB_ASIC_PLANEMASK) = ~0;
358 *(uint32_t *)(asic + SFB_ASIC_PIXELMASK) = ~0;
359 *(uint32_t *)(asic + SFB_ASIC_MODE) = 0; /* MODE_SIMPLE */
360 *(uint32_t *)(asic + SFB_ASIC_ROP) = 3; /* ROP_COPY */
361
362 /* initialize colormap and cursor hardware */
363 if (depth != 32) {
364 *(uint32_t *)(asic + 0x180000) = 0; /* Bt459 reset */
365 bt459init(base + SFB_RAMDAC_OFFSET);
366 }
367 else {
368 bt463init(base + SFB_RAMDAC_OFFSET);
369 }
370
371 ri->ri_flg = RI_CENTER;
372 if (ri == &sfbp_console_ri)
373 ri->ri_flg |= RI_NO_AUTO;
374 ri->ri_flg = 0; /* XXX 32bpp RI_CENTER fails XXX */
375 ri->ri_depth = depth;
376 ri->ri_width = (hsetup & 0x1ff) << 2;
377 ri->ri_height = (vsetup & 0x7ff);
378 ri->ri_stride = ri->ri_width * (ri->ri_depth / 8);
379 ri->ri_bits = base + 0x800000 + vbase;
380
381 if (depth == 32) {
382 ri->ri_rnum = 8;
383 ri->ri_gnum = 8;
384 ri->ri_bnum = 8;
385 ri->ri_rpos = 16;
386 ri->ri_gpos = 8;
387 ri->ri_bpos = 0;
388 }
389
390 /* clear the screen */
391 memset(ri->ri_bits, 0, ri->ri_stride * ri->ri_height);
392
393 wsfont_init();
394 /* prefer 12 pixel wide font */
395 cookie = wsfont_find(NULL, 12, 0, 0, WSDISPLAY_FONTORDER_R2L,
396 WSDISPLAY_FONTORDER_L2R);
397 if (cookie <= 0)
398 cookie = wsfont_find(NULL, 0, 0, 0, WSDISPLAY_FONTORDER_R2L,
399 WSDISPLAY_FONTORDER_L2R);
400 if (cookie <= 0) {
401 printf("sfbp: font table is empty\n");
402 return;
403 }
404
405 /* the accelerated sfbp_putchar() needs LSbit left */
406 if (wsfont_lock(cookie, &ri->ri_font)) {
407 printf("sfb: couldn't lock font\n");
408 return;
409 }
410 ri->ri_wsfcookie = cookie;
411
412 rasops_init(ri, 34, 80);
413
414 /* add our accelerated functions */
415 ri->ri_ops.putchar = sfbp_putchar;
416 ri->ri_ops.erasecols = sfbp_erasecols;
417 ri->ri_ops.copyrows = sfbp_copyrows;
418 ri->ri_ops.eraserows = sfbp_eraserows;
419
420 /* XXX shouldn't be global */
421 sfbp_stdscreen.nrows = ri->ri_rows;
422 sfbp_stdscreen.ncols = ri->ri_cols;
423 sfbp_stdscreen.textops = &ri->ri_ops;
424 sfbp_stdscreen.capabilities = ri->ri_caps;
425 /* our accelerated putchar can't underline */
426 sfbp_stdscreen.capabilities &= ~WSSCREEN_UNDERLINE;
427 }
428
429 static int
430 sfbioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l)
431 {
432 struct sfbp_softc *sc = v;
433 struct rasops_info *ri = sc->sc_ri;
434 int turnoff, s;
435
436 switch (cmd) {
437 case WSDISPLAYIO_GTYPE:
438 *(u_int *)data = WSDISPLAY_TYPE_SFBP;
439 return (0);
440
441 case WSDISPLAYIO_GINFO:
442 #define wsd_fbip ((struct wsdisplay_fbinfo *)data)
443 wsd_fbip->height = ri->ri_height;
444 wsd_fbip->width = ri->ri_width;
445 wsd_fbip->depth = ri->ri_depth;
446 wsd_fbip->cmsize = CMAP_SIZE; /* XXX */
447 #undef fbt
448 return (0);
449
450 case WSDISPLAYIO_GETCMAP:
451 return get_cmap(sc, (struct wsdisplay_cmap *)data);
452
453 case WSDISPLAYIO_PUTCMAP:
454 return set_cmap(sc, (struct wsdisplay_cmap *)data);
455
456 case WSDISPLAYIO_SVIDEO:
457 turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF;
458 if ((sc->sc_blanked == 0) ^ turnoff) {
459 sc->sc_blanked = turnoff;
460 #if 0 /* XXX later XXX */
461 Low order 3bit control visibilities of screen and builtin cursor.
462 #endif /* XXX XXX XXX */
463 }
464 return (0);
465
466 case WSDISPLAYIO_GVIDEO:
467 *(u_int *)data = sc->sc_blanked ?
468 WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON;
469 return (0);
470
471 case WSDISPLAYIO_GCURPOS:
472 *(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos;
473 return (0);
474
475 case WSDISPLAYIO_SCURPOS:
476 s = spltty();
477 set_curpos(sc, (struct wsdisplay_curpos *)data);
478 sc->sc_changed |= WSDISPLAY_CURSOR_DOPOS;
479 splx(s);
480 return (0);
481
482 case WSDISPLAYIO_GCURMAX:
483 ((struct wsdisplay_curpos *)data)->x =
484 ((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE;
485 return (0);
486
487 case WSDISPLAYIO_GCURSOR:
488 return get_cursor(sc, (struct wsdisplay_cursor *)data);
489
490 case WSDISPLAYIO_SCURSOR:
491 return set_cursor(sc, (struct wsdisplay_cursor *)data);
492
493 case WSDISPLAYIO_SMODE:
494 if (*(int *)data == WSDISPLAYIO_MODE_EMUL) {
495 s = spltty();
496 sfbp_cmap_init(sc);
497 sc->sc_curenb = 0;
498 sc->sc_changed |= (WSDISPLAY_CURSOR_DOCUR |
499 WSDISPLAY_CMAP_DOLUT);
500 splx(s);
501 }
502 return (0);
503 }
504 return (EPASSTHROUGH);
505 }
506
507 paddr_t
508 sfbmmap(void *v, void *vs, off_t offset, int prot)
509 {
510 struct sfbp_softc *sc = v;
511
512 if (offset >= 0x1000000 || offset < 0) /* XXX 16MB XXX */
513 return (-1);
514 return machine_btop(sc->sc_vaddr + offset);
515 }
516
517 static int
518 sfb_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
519 int *curxp, int *curyp, long *attrp)
520 {
521 struct sfbp_softc *sc = v;
522 struct rasops_info *ri = sc->sc_ri;
523 long defattr;
524
525 if (sc->nscreens > 0)
526 return (ENOMEM);
527
528 *cookiep = ri; /* one and only for now */
529 *curxp = 0;
530 *curyp = 0;
531 (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
532 *attrp = defattr;
533 sc->nscreens++;
534 return (0);
535 }
536
537 void
538 sfb_free_screen(void *v, void *cookie)
539 {
540 struct sfbp_softc *sc = v;
541
542 if (sc->sc_ri == &sfbp_console_ri)
543 panic("sfb_free_screen: console");
544
545 sc->nscreens--;
546 }
547
548 static int
549 sfb_show_screen(void *v, void *cookie, int waitok,
550 void (*cb)(void *, int, int), void *cbarg)
551 {
552
553 return (0);
554 }
555
556 int
557 sfbp_cnattach(tc_addr_t addr)
558 {
559 struct rasops_info *ri;
560 long defattr;
561
562 ri = &sfbp_console_ri;
563 ri->ri_hw = (void *)addr;
564 sfbp_common_init(ri);
565 (*ri->ri_ops.allocattr)(&ri, 0, 0, 0, &defattr);
566 wsdisplay_cnattach(&sfbp_stdscreen, ri, 0, 0, defattr);
567 sfbp_consaddr = addr;
568 return (0);
569 }
570
571 static int
572 sfbpintr(void *arg)
573 {
574 #define cc (&sc->sc_cursor)
575 struct sfbp_softc *sc = arg;
576 char *base, *asic;
577 uint32_t sisr;
578 int v;
579
580 base = sc->sc_ri->ri_hw;
581 asic = base + SFB_ASIC_OFFSET;
582 sisr = *((uint32_t *)asic + TGA_REG_SISR);
583 *(uint32_t *)(asic + SFB_ASIC_CLEAR_INTR) = 0;
584
585 if (sc->sc_changed == 0)
586 goto done;
587
588 v = sc->sc_changed;
589 if (v & WSDISPLAY_CURSOR_DOCUR)
590 (*sc->sc_hwops.visible)(base, sc->sc_curenb);
591 if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT))
592 (*sc->sc_hwops.locate)(base, cc);
593 if (v & WSDISPLAY_CURSOR_DOCMAP)
594 (*sc->sc_hwops.color)(base, cc->cc_color);
595 if (v & WSDISPLAY_CURSOR_DOSHAPE)
596 (*sc->sc_hwops.shape)(base, &cc->cc_size, cc->cc_image);
597 if (v & WSDISPLAY_CMAP_DOLUT)
598 (*sc->sc_hwops.setlut)(base, &sc->sc_cmap);
599 sc->sc_changed = 0;
600 done:
601 *((uint32_t *)asic + TGA_REG_SISR) = sisr = 0x00000001; tc_wmb();
602 return (1);
603 #undef cc
604 }
605
606 static void
607 bt459init(void *vdac)
608 {
609 const uint8_t *p;
610 int i;
611
612 SELECT(vdac, BT459_IREG_COMMAND_0);
613 REG(vdac, bt_reg) = 0x40; /* CMD0 */ tc_wmb();
614 REG(vdac, bt_reg) = 0x0; /* CMD1 */ tc_wmb();
615 REG(vdac, bt_reg) = 0xc0; /* CMD2 */ tc_wmb();
616 REG(vdac, bt_reg) = 0xff; /* PRM */ tc_wmb();
617 REG(vdac, bt_reg) = 0; /* 205 */ tc_wmb();
618 REG(vdac, bt_reg) = 0x0; /* PBM */ tc_wmb();
619 REG(vdac, bt_reg) = 0; /* 207 */ tc_wmb();
620 REG(vdac, bt_reg) = 0x0; /* ORM */ tc_wmb();
621 REG(vdac, bt_reg) = 0x0; /* OBM */ tc_wmb();
622 REG(vdac, bt_reg) = 0x0; /* ILV */ tc_wmb();
623 REG(vdac, bt_reg) = 0x0; /* TEST */ tc_wmb();
624
625 SELECT(vdac, BT459_IREG_CCR);
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 REG(vdac, bt_reg) = 0x0; tc_wmb();
639
640 /* build sane colormap */
641 SELECT(vdac, 0);
642 p = rasops_cmap;
643 for (i = 0; i < CMAP_SIZE; i++, p += 3) {
644 REG(vdac, bt_cmap) = p[0]; tc_wmb();
645 REG(vdac, bt_cmap) = p[1]; tc_wmb();
646 REG(vdac, bt_cmap) = p[2]; tc_wmb();
647 }
648
649 /* clear out cursor image */
650 SELECT(vdac, BT459_IREG_CRAM_BASE);
651 for (i = 0; i < 1024; i++)
652 REG(vdac, bt_reg) = 0xff; tc_wmb();
653
654 /*
655 * 2 bit/pixel cursor. Assign MSB for cursor mask and LSB for
656 * cursor image. CCOLOR_2 for mask color, while CCOLOR_3 for
657 * image color. CCOLOR_1 will be never used.
658 */
659 SELECT(vdac, BT459_IREG_CCOLOR_1);
660 REG(vdac, bt_reg) = 0xff; tc_wmb();
661 REG(vdac, bt_reg) = 0xff; tc_wmb();
662 REG(vdac, bt_reg) = 0xff; tc_wmb();
663
664 REG(vdac, bt_reg) = 0; tc_wmb();
665 REG(vdac, bt_reg) = 0; tc_wmb();
666 REG(vdac, bt_reg) = 0; tc_wmb();
667
668 REG(vdac, bt_reg) = 0xff; tc_wmb();
669 REG(vdac, bt_reg) = 0xff; tc_wmb();
670 REG(vdac, bt_reg) = 0xff; tc_wmb();
671 }
672
673 static void
674 bt463init(void *vdac)
675 {
676 int i;
677
678 SELECT(vdac, BT463_IREG_COMMAND_0);
679 REG(vdac, bt_reg) = 0x40; tc_wmb(); /* CMD 0 */
680 REG(vdac, bt_reg) = 0x48; tc_wmb(); /* CMD 1 */
681 REG(vdac, bt_reg) = 0xc0; tc_wmb(); /* CMD 2 */
682 REG(vdac, bt_reg) = 0; tc_wmb(); /* !? 204 !? */
683 REG(vdac, bt_reg) = 0xff; tc_wmb(); /* plane 0:7 */
684 REG(vdac, bt_reg) = 0xff; tc_wmb(); /* plane 8:15 */
685 REG(vdac, bt_reg) = 0xff; tc_wmb(); /* plane 16:23 */
686 REG(vdac, bt_reg) = 0xff; tc_wmb(); /* plane 24:27 */
687 REG(vdac, bt_reg) = 0x00; tc_wmb(); /* blink 0:7 */
688 REG(vdac, bt_reg) = 0x00; tc_wmb(); /* blink 8:15 */
689 REG(vdac, bt_reg) = 0x00; tc_wmb(); /* blink 16:23 */
690 REG(vdac, bt_reg) = 0x00; tc_wmb(); /* blink 24:27 */
691 REG(vdac, bt_reg) = 0x00; tc_wmb();
692
693 SELECT(vdac, BT463_IREG_WINDOW_TYPE_TABLE);
694 for (i = 0; i < BT463_NWTYPE_ENTRIES; i++) {
695 REG(vdac, bt_reg) = 0x00; /* 0:7 */
696 REG(vdac, bt_reg) = 0xe1; /* 8:15 */
697 REG(vdac, bt_reg) = 0x81; /* 16:23 */
698 }
699 }
700
701 static int
702 get_cmap(struct sfbp_softc *sc, struct wsdisplay_cmap *p)
703 {
704 u_int index = p->index, count = p->count;
705 int error;
706
707 if (index >= CMAP_SIZE || count > CMAP_SIZE - index)
708 return (EINVAL);
709
710 error = copyout(&sc->sc_cmap.r[index], p->red, count);
711 if (error)
712 return error;
713 error = copyout(&sc->sc_cmap.g[index], p->green, count);
714 if (error)
715 return error;
716 error = copyout(&sc->sc_cmap.b[index], p->blue, count);
717 return error;
718 }
719
720 static int
721 set_cmap(struct sfbp_softc *sc, struct wsdisplay_cmap *p)
722 {
723 struct hwcmap256 cmap;
724 u_int index = p->index, count = p->count;
725 int error, s;
726
727 if (index >= CMAP_SIZE || count > CMAP_SIZE - index)
728 return (EINVAL);
729
730 error = copyin(p->red, &cmap.r[index], count);
731 if (error)
732 return error;
733 error = copyin(p->green, &cmap.g[index], count);
734 if (error)
735 return error;
736 error = copyin(p->blue, &cmap.b[index], count);
737 if (error)
738 return error;
739
740 s = spltty();
741 memcpy(&sc->sc_cmap.r[index], &cmap.r[index], count);
742 memcpy(&sc->sc_cmap.g[index], &cmap.g[index], count);
743 memcpy(&sc->sc_cmap.b[index], &cmap.b[index], count);
744 sc->sc_changed |= WSDISPLAY_CMAP_DOLUT;
745 splx(s);
746 return (0);
747 }
748
749 static int
750 set_cursor(struct sfbp_softc *sc, struct wsdisplay_cursor *p)
751 {
752 #define cc (&sc->sc_cursor)
753 u_int v, index = 0, count = 0, icount = 0;
754 uint8_t r[2], g[2], b[2], image[512], mask[512];
755 int error, s;
756
757 v = p->which;
758 if (v & WSDISPLAY_CURSOR_DOCMAP) {
759 index = p->cmap.index;
760 count = p->cmap.count;
761 if (index >= 2 || (index + count) > 2)
762 return (EINVAL);
763 error = copyin(p->cmap.red, &r[index], count);
764 if (error)
765 return error;
766 error = copyin(p->cmap.green, &g[index], count);
767 if (error)
768 return error;
769 error = copyin(p->cmap.blue, &b[index], count);
770 if (error)
771 return error;
772 }
773 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
774 if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE)
775 return (EINVAL);
776 icount = ((p->size.x < 33) ? 4 : 8) * p->size.y;
777 error = copyin(p->image, image, icount);
778 if (error)
779 return error;
780 error = copyin(p->mask, mask, icount);
781 if (error)
782 return error;
783 }
784
785 s = spltty();
786 if (v & WSDISPLAY_CURSOR_DOCUR)
787 sc->sc_curenb = p->enable;
788 if (v & WSDISPLAY_CURSOR_DOPOS)
789 set_curpos(sc, &p->pos);
790 if (v & WSDISPLAY_CURSOR_DOHOT)
791 cc->cc_hot = p->hot;
792 if (v & WSDISPLAY_CURSOR_DOCMAP) {
793 memcpy(&cc->cc_color[index], &r[index], count);
794 memcpy(&cc->cc_color[index + 2], &g[index], count);
795 memcpy(&cc->cc_color[index + 4], &b[index], count);
796 }
797 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
798 cc->cc_size = p->size;
799 memset(cc->cc_image, 0, sizeof cc->cc_image);
800 memcpy(cc->cc_image, image, icount);
801 memset(cc->cc_mask, 0, sizeof cc->cc_mask);
802 memcpy(cc->cc_mask, mask, icount);
803 }
804 sc->sc_changed |= v;
805 splx(s);
806
807 return (0);
808 #undef cc
809 }
810
811 static int
812 get_cursor(struct sfbp_softc *sc, struct wsdisplay_cursor *p)
813 {
814 return (EPASSTHROUGH); /* XXX */
815 }
816
817 static void
818 set_curpos(struct sfbp_softc *sc, struct wsdisplay_curpos *curpos)
819 {
820 struct rasops_info *ri = sc->sc_ri;
821 int x = curpos->x, y = curpos->y;
822
823 if (y < 0)
824 y = 0;
825 else if (y > ri->ri_height)
826 y = ri->ri_height;
827 if (x < 0)
828 x = 0;
829 else if (x > ri->ri_width)
830 x = ri->ri_width;
831 sc->sc_cursor.cc_pos.x = x;
832 sc->sc_cursor.cc_pos.y = y;
833 }
834
835 static void
836 bt459visible(void *hw, int on)
837 {
838 hw = (char *)hw + SFB_RAMDAC_OFFSET;
839 SELECT(hw, BT459_IREG_CCR);
840 REG(hw, bt_reg) = (on) ? 0xc0 : 0x00;
841 tc_wmb();
842 }
843
844 static void
845 sfbpvisible(void *hw, int on)
846 {
847 /* XXX use SFBplus ASIC XX */
848 }
849
850 static void
851 bt459locate(void *hw, struct hwcursor64 *cc)
852 {
853 int x, y, s;
854
855 x = cc->cc_pos.x - cc->cc_hot.x;
856 y = cc->cc_pos.y - cc->cc_hot.y;
857 x += cc->cc_magic.x;
858 y += cc->cc_magic.y;
859
860 hw = (char *)hw + SFB_RAMDAC_OFFSET;
861
862 s = spltty();
863 SELECT(hw, BT459_IREG_CURSOR_X_LOW);
864 REG(hw, bt_reg) = x; tc_wmb();
865 REG(hw, bt_reg) = x >> 8; tc_wmb();
866 REG(hw, bt_reg) = y; tc_wmb();
867 REG(hw, bt_reg) = y >> 8; tc_wmb();
868 splx(s);
869 }
870
871 static void
872 sfbplocate(void *hw, struct hwcursor64 *cc)
873 {
874 int x, y;
875
876 x = cc->cc_pos.x - cc->cc_hot.x;
877 y = cc->cc_pos.y - cc->cc_hot.y;
878
879 hw = (char *)hw + SFB_ASIC_OFFSET;
880 *((uint32_t *)hw + TGA_REG_CXYR) = ((y & 0xfff) << 12) | (x & 0xfff);
881 tc_wmb();
882 }
883
884 static void
885 bt459color(void *hw, uint8_t *cp)
886 {
887
888 hw = (char *)hw + SFB_RAMDAC_OFFSET;
889
890 SELECT(hw, BT459_IREG_CCOLOR_2);
891 REG(hw, bt_reg) = cp[1]; tc_wmb();
892 REG(hw, bt_reg) = cp[3]; tc_wmb();
893 REG(hw, bt_reg) = cp[5]; tc_wmb();
894
895 REG(hw, bt_reg) = cp[0]; tc_wmb();
896 REG(hw, bt_reg) = cp[2]; tc_wmb();
897 REG(hw, bt_reg) = cp[4]; tc_wmb();
898 }
899
900 static void
901 bt463color(void *hw, uint8_t *cp)
902 {
903 }
904
905 static void
906 bt459shape(void *hw, struct wsdisplay_curpos *size, uint64_t *image)
907 {
908 uint8_t *ip, *mp, img, msk;
909 uint8_t u;
910 int bcnt;
911
912 hw = (char *)hw + SFB_RAMDAC_OFFSET;
913 ip = (uint8_t *)image;
914 mp = (uint8_t *)(image + CURSOR_MAX_SIZE);
915
916 bcnt = 0;
917 SELECT(hw, BT459_IREG_CRAM_BASE+0);
918 /* 64 pixel scan line is consisted with 16 byte cursor ram */
919 while (bcnt < size->y * 16) {
920 /* pad right half 32 pixel when smaller than 33 */
921 if ((bcnt & 0x8) && size->x < 33) {
922 REG(hw, bt_reg) = 0; tc_wmb();
923 REG(hw, bt_reg) = 0; tc_wmb();
924 }
925 else {
926 img = *ip++;
927 msk = *mp++;
928 img &= msk; /* cookie off image */
929 u = (msk & 0x0f) << 4 | (img & 0x0f);
930 REG(hw, bt_reg) = shuffle[u]; tc_wmb();
931 u = (msk & 0xf0) | (img & 0xf0) >> 4;
932 REG(hw, bt_reg) = shuffle[u]; tc_wmb();
933 }
934 bcnt += 2;
935 }
936 /* pad unoccupied scan lines */
937 while (bcnt < CURSOR_MAX_SIZE * 16) {
938 REG(hw, bt_reg) = 0; tc_wmb();
939 REG(hw, bt_reg) = 0; tc_wmb();
940 bcnt += 2;
941 }
942 }
943
944 static void
945 sfbpshape(void *hw, struct wsdisplay_curpos *size, uint64_t *image)
946 {
947 /* XXX use SFBplus ASIC XXX */
948 }
949
950 static void
951 bt459setlut(void *hw, struct hwcmap256 *cm)
952 {
953 int index;
954
955 hw = (char *)hw + SFB_RAMDAC_OFFSET;
956 SELECT(hw, 0);
957 for (index = 0; index < CMAP_SIZE; index++) {
958 REG(hw, bt_cmap) = cm->r[index]; tc_wmb();
959 REG(hw, bt_cmap) = cm->g[index]; tc_wmb();
960 REG(hw, bt_cmap) = cm->b[index]; tc_wmb();
961 }
962 }
963
964 static void
965 noplut(void *hw, struct hwcmap256 *cm)
966 {
967 }
968
969 #define SFBBPP 32
970
971 #define MODE_SIMPLE 0
972 #define MODE_OPAQUESTIPPLE 1
973 #define MODE_OPAQUELINE 2
974 #define MODE_TRANSPARENTSTIPPLE 5
975 #define MODE_TRANSPARENTLINE 6
976 #define MODE_COPY 7
977
978 #if SFBBPP == 8
979 /* parameters for 8bpp configuration */
980 #define SFBALIGNMASK 0x7
981 #define SFBPIXELBYTES 1
982 #define SFBSTIPPLEALL1 0xffffffff
983 #define SFBSTIPPLEBITS 32
984 #define SFBSTIPPLEBITMASK 0x1f
985 #define SFBSTIPPLEBYTESDONE 32
986 #define SFBCOPYALL1 0xffffffff
987 #define SFBCOPYBITS 32
988 #define SFBCOPYBITMASK 0x1f
989 #define SFBCOPYBYTESDONE 32
990
991 #elif SFBBPP == 32
992 /* parameters for 32bpp configuration */
993 #define SFBALIGNMASK 0x7
994 #define SFBPIXELBYTES 4
995 #define SFBSTIPPLEALL1 0x0000ffff
996 #define SFBSTIPPLEBITS 16
997 #define SFBSTIPPLEBITMASK 0xf
998 #define SFBSTIPPLEBYTESDONE 32
999 #define SFBCOPYALL1 0x000000ff
1000 #define SFBCOPYBITS 8
1001 #define SFBCOPYBITMASK 0x3
1002 #define SFBCOPYBYTESDONE 32
1003 #endif
1004
1005 #ifdef pmax
1006 #define WRITE_MB()
1007 #define BUMP(p) (p)
1008 #endif
1009
1010 #ifdef alpha
1011 #define WRITE_MB() tc_wmb()
1012 /* registers is replicated in 1KB stride; rap round 4th iteration */
1013 #define BUMP(p) ((p) = (void *)(((long)(p) + 0x400) & ~0x1000))
1014 #endif
1015
1016 #define SFBMODE(p, v) \
1017 (*(uint32_t *)(BUMP(p) + SFB_ASIC_MODE) = (v))
1018 #define SFBROP(p, v) \
1019 (*(uint32_t *)(BUMP(p) + SFB_ASIC_ROP) = (v))
1020 #define SFBPLANEMASK(p, v) \
1021 (*(uint32_t *)(BUMP(p) + SFB_ASIC_PLANEMASK) = (v))
1022 #define SFBPIXELMASK(p, v) \
1023 (*(uint32_t *)(BUMP(p) + SFB_ASIC_PIXELMASK) = (v))
1024 #define SFBADDRESS(p, v) \
1025 (*(uint32_t *)(BUMP(p) + SFB_ASIC_ADDRESS) = (v))
1026 #define SFBSTART(p, v) \
1027 (*(uint32_t *)(BUMP(p) + SFB_ASIC_START) = (v))
1028 #define SFBPIXELSHIFT(p, v) \
1029 (*(uint32_t *)(BUMP(p) + SFB_ASIC_PIXELSHIFT) = (v))
1030 #define SFBFG(p, v) \
1031 (*(uint32_t *)(BUMP(p) + SFB_ASIC_FG) = (v))
1032 #define SFBBG(p, v) \
1033 (*(uint32_t *)(BUMP(p) + SFB_ASIC_BG) = (v))
1034 #define SFBBCONT(p, v) \
1035 (*(uint32_t *)(BUMP(p) + SFB_ASIC_BCONT) = (v))
1036
1037 #define SFBDATA(p, v) \
1038 (*((uint32_t *)BUMP(p) + TGA_REG_GDAR) = (v))
1039
1040 #define SFBCOPY64BYTESDONE 8
1041 #define SFBCOPY64BITS 64
1042 #define SFBCOPY64SRC(p, v) \
1043 (*((uint32_t *)BUMP(p) + TGA_REG_GCSR) = (long)(v))
1044 #define SFBCOPY64DST(p, v) \
1045 (*((uint32_t *)BUMP(p) + TGA_REG_GCDR) = (long)(v))
1046
1047 /*
1048 * Actually write a string to the frame buffer.
1049 */
1050 static void
1051 sfbp_putchar(void *id, int row, int col, u_int uc, long attr)
1052 {
1053 struct rasops_info *ri = id;
1054 char *sfb, *p;
1055 int scanspan, height, width, align, x, y;
1056 uint32_t lmask, rmask, glyph;
1057 uint8_t *g;
1058
1059 x = col * ri->ri_font->fontwidth;
1060 y = row * ri->ri_font->fontheight;
1061 scanspan = ri->ri_stride;
1062 height = ri->ri_font->fontheight;
1063 uc -= ri->ri_font->firstchar;
1064 g = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
1065
1066 p = ri->ri_bits + y * scanspan + x * SFBPIXELBYTES;
1067 align = (long)p & SFBALIGNMASK;
1068 p -= align;
1069 align /= SFBPIXELBYTES;
1070 width = ri->ri_font->fontwidth + align;
1071 lmask = SFBSTIPPLEALL1 << align;
1072 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
1073 sfb = (char *)ri->ri_hw + SFB_ASIC_OFFSET;
1074
1075 SFBMODE(sfb, MODE_OPAQUESTIPPLE);
1076 SFBPLANEMASK(sfb, ~0);
1077 SFBFG(sfb, ri->ri_devcmap[(attr >> 24) & 15]);
1078 SFBBG(sfb, ri->ri_devcmap[(attr >> 16) & 15]);
1079 SFBROP(sfb, (3 << 8) | 3); /* ROP_COPY24 */
1080 *((uint32_t *)sfb + TGA_REG_GPXR_P) = lmask & rmask;
1081
1082 /* XXX 2B stride fonts only XXX */
1083 while (height > 0) {
1084 glyph = *(uint16_t *)g; /* XXX */
1085 *(uint32_t *)p = glyph << align;
1086 p += scanspan;
1087 g += 2; /* XXX */
1088 height--;
1089 }
1090 SFBMODE(sfb, MODE_SIMPLE);
1091 *((uint32_t *)sfb + TGA_REG_GPXR_P) = ~0;
1092 }
1093
1094 #undef SFBSTIPPLEALL1
1095 #undef SFBSTIPPLEBITS
1096 #undef SFBSTIPPLEBITMASK
1097 #define SFBSTIPPLEALL1 SFBCOPYALL1
1098 #define SFBSTIPPLEBITS SFBCOPYBITS
1099 #define SFBSTIPPLEBITMASK SFBCOPYBITMASK
1100
1101 /*
1102 * Clear characters in a line.
1103 */
1104 static void
1105 sfbp_erasecols(void *id, int row, int startcol, int ncols, long attr)
1106 {
1107 struct rasops_info *ri = id;
1108 char *sfb, *p;
1109 int scanspan, startx, height, width, align, w, y;
1110 uint32_t lmask, rmask;
1111
1112 scanspan = ri->ri_stride;
1113 y = row * ri->ri_font->fontheight;
1114 startx = startcol * ri->ri_font->fontwidth;
1115 height = ri->ri_font->fontheight;
1116 w = ri->ri_font->fontwidth * ncols;
1117
1118 p = ri->ri_bits + y * scanspan + startx * SFBPIXELBYTES;
1119 align = (long)p & SFBALIGNMASK;
1120 align /= SFBPIXELBYTES;
1121 p -= align;
1122 width = w + align;
1123 lmask = SFBSTIPPLEALL1 << align;
1124 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
1125 sfb = (char *)ri->ri_hw + SFB_ASIC_OFFSET;
1126
1127 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
1128 SFBPLANEMASK(sfb, ~0);
1129 SFBFG(sfb, ri->ri_devcmap[(attr >> 16) & 15]); /* fill with bg */
1130 if (width <= SFBSTIPPLEBITS) {
1131 lmask = lmask & rmask;
1132 while (height > 0) {
1133 *(uint32_t *)p = lmask;
1134 p += scanspan;
1135 height--;
1136 }
1137 }
1138 else {
1139 char *q = p;
1140 while (height > 0) {
1141 *(uint32_t *)p = lmask;
1142 WRITE_MB();
1143 width -= 2 * SFBSTIPPLEBITS;
1144 while (width > 0) {
1145 p += SFBSTIPPLEBYTESDONE;
1146 *(uint32_t *)p = SFBSTIPPLEALL1;
1147 WRITE_MB();
1148 width -= SFBSTIPPLEBITS;
1149 }
1150 p += SFBSTIPPLEBYTESDONE;
1151 *(uint32_t *)p = rmask;
1152 WRITE_MB();
1153
1154 p = (q += scanspan);
1155 width = w + align;
1156 height--;
1157 }
1158 }
1159 SFBMODE(sfb, MODE_SIMPLE);
1160 }
1161
1162 #if 1
1163 /*
1164 * Copy lines.
1165 */
1166 static void
1167 sfbp_copyrows(void *id, int srcrow, int dstrow, int nrows)
1168 {
1169 struct rasops_info *ri = id;
1170 char *sfb, *p;
1171 int scanspan, offset, srcy, height, width, align, w;
1172 uint32_t lmask, rmask;
1173
1174 scanspan = ri->ri_stride;
1175 height = ri->ri_font->fontheight * nrows;
1176 offset = (dstrow - srcrow) * ri->ri_yscale;
1177 srcy = ri->ri_font->fontheight * srcrow;
1178 if (srcrow < dstrow && srcrow + nrows > dstrow) {
1179 scanspan = -scanspan;
1180 srcy += height;
1181 }
1182
1183 p = ri->ri_bits + srcy * ri->ri_stride;
1184 align = (long)p & SFBALIGNMASK;
1185 p -= align;
1186 align /= SFBPIXELBYTES;
1187 w = ri->ri_emuwidth;
1188 width = w + align;
1189 lmask = SFBCOPYALL1 << align;
1190 rmask = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
1191 sfb = (char *)ri->ri_hw + SFB_ASIC_OFFSET;
1192
1193 SFBMODE(sfb, MODE_COPY);
1194 SFBPLANEMASK(sfb, ~0);
1195 SFBPIXELSHIFT(sfb, 0);
1196 if (width <= SFBCOPYBITS) {
1197 /* never happens */;
1198 }
1199 else {
1200 char *q = p;
1201 while (height > 0) {
1202 *(uint32_t *)p = lmask;
1203 *(uint32_t *)(p + offset) = lmask;
1204 width -= 2 * SFBCOPYBITS;
1205 while (width > 0) {
1206 p += SFBCOPYBYTESDONE;
1207 *(uint32_t *)p = SFBCOPYALL1;
1208 *(uint32_t *)(p + offset) = SFBCOPYALL1;
1209 width -= SFBCOPYBITS;
1210 }
1211 p += SFBCOPYBYTESDONE;
1212 *(uint32_t *)p = rmask;
1213 *(uint32_t *)(p + offset) = rmask;
1214
1215 p = (q += scanspan);
1216 width = w + align;
1217 height--;
1218 }
1219 }
1220 SFBMODE(sfb, MODE_SIMPLE);
1221 }
1222
1223 #else
1224
1225
1226 static void
1227 sfbp_copyrows(void *id, int srcrow, int dstrow, int nrows)
1228 {
1229 struct rasops_info *ri = id;
1230 void *sfb, *p, *q;
1231 int scanspan, offset, srcy, height, width, w, align;
1232 uint32_t rmask, lmask;
1233
1234 scanspan = ri->ri_stride;
1235 height = ri->ri_font->fontheight * nrows;
1236 offset = (dstrow - srcrow) * ri->ri_yscale;
1237 srcy = ri->ri_font->fontheight * srcrow;
1238 if (srcrow < dstrow && srcrow + nrows > dstrow) {
1239 scanspan = -scanspan;
1240 srcy += height;
1241 }
1242
1243 p = ri->ri_bits + srcy * ri->ri_stride;
1244 align = (long)p & SFBALIGNMASK;
1245 w = ri->ri_emuwidth;
1246 width = w + align;
1247 lmask = SFBCOPYALL1 << align;
1248 rmask = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
1249 sfb = (void *)ri->ri_hw + SFB_ASIC_OFFSET;
1250 q = p;
1251
1252 SFBMODE(sfb, MODE_COPY);
1253 SFBPLANEMASK(sfb, ~0);
1254 SFBPIXELSHIFT(sfb, 0);
1255
1256 if (width <= SFBCOPYBITS)
1257 ; /* never happens */
1258 else if (width < SFBCOPY64BITS) {
1259 ; /* unlikely happens */
1260
1261 }
1262 else {
1263 while (height > 0) {
1264 while (width >= SFBCOPY64BITS) {
1265 SFBCOPY64SRC(sfb, *p);
1266 SFBCOPY64DST(sfb, *p + offset);
1267 p += SFBCOPY64BYTESDONE;
1268 width -= SFBCOPY64BITS;
1269 }
1270 if (width >= SFBCOPYBITS) {
1271 *(uint32_t *)p = SFBCOPYALL1;
1272 *(uint32_t *)(p + offset) = SFBCOPYALL1;
1273 p += SFBCOPYBYTESDONE;
1274 width -= SFBCOPYBITS;
1275 }
1276 if (width > 0) {
1277 *(uint32_t *)p = rmask;
1278 *(uint32_t *)(p + offset) = rmask;
1279 }
1280
1281 p = (q += scanspan);
1282 width = w;
1283 height--;
1284 }
1285 }
1286 SFBMODE(sfb, MODE_SIMPLE);
1287 }
1288 #endif
1289
1290 /*
1291 * Erase lines.
1292 */
1293 static void
1294 sfbp_eraserows(void *id, int startrow, int nrows, long attr)
1295 {
1296 struct rasops_info *ri = id;
1297 char *sfb, *p;
1298 int scanspan, starty, height, width, align, w;
1299 uint32_t lmask, rmask;
1300
1301 scanspan = ri->ri_stride;
1302 starty = ri->ri_font->fontheight * startrow;
1303 height = ri->ri_font->fontheight * nrows;
1304
1305 p = ri->ri_bits + starty * scanspan;
1306 align = (long)p & SFBALIGNMASK;
1307 p -= align;
1308 align /= SFBPIXELBYTES;
1309 w = ri->ri_emuwidth * SFBPIXELBYTES;
1310 width = w + align;
1311 lmask = SFBSTIPPLEALL1 << align;
1312 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
1313 sfb = (char *)ri->ri_hw + SFB_ASIC_OFFSET;
1314
1315 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
1316 SFBPLANEMASK(sfb, ~0);
1317 SFBFG(sfb, ri->ri_devcmap[(attr >> 16) & 15]);
1318 if (width <= SFBSTIPPLEBITS) {
1319 /* never happens */;
1320 }
1321 else {
1322 char *q = p;
1323 while (height > 0) {
1324 *(uint32_t *)p = lmask;
1325 WRITE_MB();
1326 width -= 2 * SFBSTIPPLEBITS;
1327 while (width > 0) {
1328 p += SFBSTIPPLEBYTESDONE;
1329 *(uint32_t *)p = SFBSTIPPLEALL1;
1330 WRITE_MB();
1331 width -= SFBSTIPPLEBITS;
1332 }
1333 p += SFBSTIPPLEBYTESDONE;
1334 *(uint32_t *)p = rmask;
1335 WRITE_MB();
1336
1337 p = (q += scanspan);
1338 width = w + align;
1339 height--;
1340 }
1341 }
1342 SFBMODE(sfb, MODE_SIMPLE);
1343 }
1344