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