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