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