sfbplus.c revision 1.15 1 /* $NetBSD: sfbplus.c,v 1.15 2002/07/04 14:37:13 junyoung 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.15 2002/07/04 14:37:13 junyoung 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[64 + 64];
97 };
98
99 struct hwops {
100 void (*setlut) __P((caddr_t, struct hwcmap256 *));
101 void (*getlut) __P((caddr_t, struct hwcmap256 *));
102 void (*visible) __P((caddr_t, int));
103 void (*locate) __P((caddr_t, struct hwcursor64 *));
104 void (*shape) __P((caddr_t, struct wsdisplay_curpos *, u_int64_t *));
105 void (*color) __P((caddr_t, 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 __P((struct device *, struct cfdata *, void *));
127 static void sfbpattach __P((struct device *, struct device *, void *));
128
129 const struct cfattach sfbp_ca = {
130 sizeof(struct sfbp_softc), sfbpmatch, sfbpattach,
131 };
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
714 if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE)
715 return (EINVAL);
716
717 if (!uvm_useracc(p->red, count, B_WRITE) ||
718 !uvm_useracc(p->green, count, B_WRITE) ||
719 !uvm_useracc(p->blue, count, B_WRITE))
720 return (EFAULT);
721
722 copyout(&sc->sc_cmap.r[index], p->red, count);
723 copyout(&sc->sc_cmap.g[index], p->green, count);
724 copyout(&sc->sc_cmap.b[index], p->blue, count);
725
726 return (0);
727 }
728
729 static int
730 set_cmap(sc, p)
731 struct sfbp_softc *sc;
732 struct wsdisplay_cmap *p;
733 {
734 u_int index = p->index, count = p->count;
735
736 if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE)
737 return (EINVAL);
738
739 if (!uvm_useracc(p->red, count, B_READ) ||
740 !uvm_useracc(p->green, count, B_READ) ||
741 !uvm_useracc(p->blue, count, B_READ))
742 return (EFAULT);
743
744 copyin(p->red, &sc->sc_cmap.r[index], count);
745 copyin(p->green, &sc->sc_cmap.g[index], count);
746 copyin(p->blue, &sc->sc_cmap.b[index], count);
747 sc->sc_changed |= WSDISPLAY_CMAP_DOLUT;
748 return (0);
749 }
750
751 static int
752 set_cursor(sc, p)
753 struct sfbp_softc *sc;
754 struct wsdisplay_cursor *p;
755 {
756 #define cc (&sc->sc_cursor)
757 u_int v, index, count, icount;
758
759 v = p->which;
760 if (v & WSDISPLAY_CURSOR_DOCMAP) {
761 index = p->cmap.index;
762 count = p->cmap.count;
763 if (index >= 2 || (index + count) > 2)
764 return (EINVAL);
765 if (!uvm_useracc(p->cmap.red, count, B_READ) ||
766 !uvm_useracc(p->cmap.green, count, B_READ) ||
767 !uvm_useracc(p->cmap.blue, count, B_READ))
768 return (EFAULT);
769 }
770 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
771 if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE)
772 return (EINVAL);
773 icount = ((p->size.x < 33) ? 4 : 8) * p->size.y;
774 if (!uvm_useracc(p->image, icount, B_READ) ||
775 !uvm_useracc(p->mask, icount, B_READ))
776 return (EFAULT);
777 }
778
779 if (v & WSDISPLAY_CURSOR_DOCUR)
780 sc->sc_curenb = p->enable;
781 if (v & WSDISPLAY_CURSOR_DOPOS)
782 set_curpos(sc, &p->pos);
783 if (v & WSDISPLAY_CURSOR_DOHOT)
784 cc->cc_hot = p->hot;
785 if (v & WSDISPLAY_CURSOR_DOCMAP) {
786 copyin(p->cmap.red, &cc->cc_color[index], count);
787 copyin(p->cmap.green, &cc->cc_color[index + 2], count);
788 copyin(p->cmap.blue, &cc->cc_color[index + 4], count);
789 }
790 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
791 cc->cc_size = p->size;
792 memset(cc->cc_image, 0, sizeof cc->cc_image);
793 copyin(p->image, cc->cc_image, icount);
794 copyin(p->mask, cc->cc_image+CURSOR_MAX_SIZE, icount);
795 }
796 sc->sc_changed = v;
797
798 return (0);
799 #undef cc
800 }
801
802 static int
803 get_cursor(sc, p)
804 struct sfbp_softc *sc;
805 struct wsdisplay_cursor *p;
806 {
807 return (EPASSTHROUGH); /* XXX */
808 }
809
810 static void
811 set_curpos(sc, curpos)
812 struct sfbp_softc *sc;
813 struct wsdisplay_curpos *curpos;
814 {
815 struct rasops_info *ri = sc->sc_ri;
816 int x = curpos->x, y = curpos->y;
817
818 if (y < 0)
819 y = 0;
820 else if (y > ri->ri_height)
821 y = ri->ri_height;
822 if (x < 0)
823 x = 0;
824 else if (x > ri->ri_width)
825 x = ri->ri_width;
826 sc->sc_cursor.cc_pos.x = x;
827 sc->sc_cursor.cc_pos.y = y;
828 }
829
830 static void
831 bt459visible(hw, on)
832 caddr_t hw;
833 int on;
834 {
835 hw += SFB_RAMDAC_OFFSET;
836 SELECT(hw, BT459_IREG_CCR);
837 REG(hw, bt_reg) = (on) ? 0xc0 : 0x00;
838 tc_wmb();
839 }
840
841 static void
842 sfbpvisible(hw, on)
843 caddr_t hw;
844 int on;
845 {
846 /* XXX use SFBplus ASIC XX */
847 }
848
849 static void
850 bt459locate(hw, cc)
851 caddr_t hw;
852 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(hw, cc)
874 caddr_t hw;
875 struct hwcursor64 *cc;
876 {
877 int x, y;
878
879 x = cc->cc_pos.x - cc->cc_hot.x;
880 y = cc->cc_pos.y - cc->cc_hot.y;
881
882 hw += SFB_ASIC_OFFSET;
883 *((u_int32_t *)hw + TGA_REG_CXYR) = ((y & 0xfff) << 12) | (x & 0xfff);
884 tc_wmb();
885 }
886
887 static void
888 bt459color(hw, cp)
889 caddr_t hw;
890 u_int8_t *cp;
891 {
892
893 hw += SFB_RAMDAC_OFFSET;
894
895 SELECT(hw, BT459_IREG_CCOLOR_2);
896 REG(hw, bt_reg) = cp[1]; tc_wmb();
897 REG(hw, bt_reg) = cp[3]; tc_wmb();
898 REG(hw, bt_reg) = cp[5]; tc_wmb();
899
900 REG(hw, bt_reg) = cp[0]; tc_wmb();
901 REG(hw, bt_reg) = cp[2]; tc_wmb();
902 REG(hw, bt_reg) = cp[4]; tc_wmb();
903 }
904
905 static void
906 bt463color(hw, cp)
907 caddr_t hw;
908 u_int8_t *cp;
909 {
910 }
911
912 static void
913 bt459shape(hw, size, image)
914 caddr_t hw;
915 struct wsdisplay_curpos *size;
916 u_int64_t *image;
917 {
918 u_int8_t *ip, *mp, img, msk;
919 u_int8_t u;
920 int bcnt;
921
922 hw += SFB_RAMDAC_OFFSET;
923 ip = (u_int8_t *)image;
924 mp = (u_int8_t *)(image + CURSOR_MAX_SIZE);
925
926 bcnt = 0;
927 SELECT(hw, BT459_IREG_CRAM_BASE+0);
928 /* 64 pixel scan line is consisted with 16 byte cursor ram */
929 while (bcnt < size->y * 16) {
930 /* pad right half 32 pixel when smaller than 33 */
931 if ((bcnt & 0x8) && size->x < 33) {
932 REG(hw, bt_reg) = 0; tc_wmb();
933 REG(hw, bt_reg) = 0; tc_wmb();
934 }
935 else {
936 img = *ip++;
937 msk = *mp++;
938 img &= msk; /* cookie off image */
939 u = (msk & 0x0f) << 4 | (img & 0x0f);
940 REG(hw, bt_reg) = shuffle[u]; tc_wmb();
941 u = (msk & 0xf0) | (img & 0xf0) >> 4;
942 REG(hw, bt_reg) = shuffle[u]; tc_wmb();
943 }
944 bcnt += 2;
945 }
946 /* pad unoccupied scan lines */
947 while (bcnt < CURSOR_MAX_SIZE * 16) {
948 REG(hw, bt_reg) = 0; tc_wmb();
949 REG(hw, bt_reg) = 0; tc_wmb();
950 bcnt += 2;
951 }
952 }
953
954 static void
955 sfbpshape(hw, size, image)
956 caddr_t hw;
957 struct wsdisplay_curpos *size;
958 u_int64_t *image;
959 {
960 /* XXX use SFBplus ASIC XXX */
961 }
962
963 static void
964 bt459setlut(hw, cm)
965 caddr_t hw;
966 struct hwcmap256 *cm;
967 {
968 int index;
969
970 hw += SFB_RAMDAC_OFFSET;
971 SELECT(hw, 0);
972 for (index = 0; index < CMAP_SIZE; index++) {
973 REG(hw, bt_cmap) = cm->r[index]; tc_wmb();
974 REG(hw, bt_cmap) = cm->g[index]; tc_wmb();
975 REG(hw, bt_cmap) = cm->b[index]; tc_wmb();
976 }
977 }
978
979 static void
980 noplut(hw, cm)
981 caddr_t hw;
982 struct hwcmap256 *cm;
983 {
984 }
985
986 #define SFBBPP 32
987
988 #define MODE_SIMPLE 0
989 #define MODE_OPAQUESTIPPLE 1
990 #define MODE_OPAQUELINE 2
991 #define MODE_TRANSPARENTSTIPPLE 5
992 #define MODE_TRANSPARENTLINE 6
993 #define MODE_COPY 7
994
995 #if SFBBPP == 8
996 /* parameters for 8bpp configuration */
997 #define SFBALIGNMASK 0x7
998 #define SFBPIXELBYTES 1
999 #define SFBSTIPPLEALL1 0xffffffff
1000 #define SFBSTIPPLEBITS 32
1001 #define SFBSTIPPLEBITMASK 0x1f
1002 #define SFBSTIPPLEBYTESDONE 32
1003 #define SFBCOPYALL1 0xffffffff
1004 #define SFBCOPYBITS 32
1005 #define SFBCOPYBITMASK 0x1f
1006 #define SFBCOPYBYTESDONE 32
1007
1008 #elif SFBBPP == 32
1009 /* parameters for 32bpp configuration */
1010 #define SFBALIGNMASK 0x7
1011 #define SFBPIXELBYTES 4
1012 #define SFBSTIPPLEALL1 0x0000ffff
1013 #define SFBSTIPPLEBITS 16
1014 #define SFBSTIPPLEBITMASK 0xf
1015 #define SFBSTIPPLEBYTESDONE 32
1016 #define SFBCOPYALL1 0x000000ff
1017 #define SFBCOPYBITS 8
1018 #define SFBCOPYBITMASK 0x3
1019 #define SFBCOPYBYTESDONE 32
1020 #endif
1021
1022 #ifdef pmax
1023 #define WRITE_MB()
1024 #define BUMP(p) (p)
1025 #endif
1026
1027 #ifdef alpha
1028 #define WRITE_MB() tc_wmb()
1029 /* registers is replicated in 1KB stride; rap round 4th iteration */
1030 #define BUMP(p) ((p) = (caddr_t)(((long)(p) + 0x400) & ~0x1000))
1031 #endif
1032
1033 #define SFBMODE(p, v) \
1034 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_MODE) = (v))
1035 #define SFBROP(p, v) \
1036 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_ROP) = (v))
1037 #define SFBPLANEMASK(p, v) \
1038 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_PLANEMASK) = (v))
1039 #define SFBPIXELMASK(p, v) \
1040 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELMASK) = (v))
1041 #define SFBADDRESS(p, v) \
1042 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_ADDRESS) = (v))
1043 #define SFBSTART(p, v) \
1044 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_START) = (v))
1045 #define SFBPIXELSHIFT(p, v) \
1046 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELSHIFT) = (v))
1047 #define SFBFG(p, v) \
1048 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_FG) = (v))
1049 #define SFBBG(p, v) \
1050 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_BG) = (v))
1051 #define SFBBCONT(p, v) \
1052 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_BCONT) = (v))
1053
1054 #define SFBDATA(p, v) \
1055 (*((u_int32_t *)BUMP(p) + TGA_REG_GDAR) = (v))
1056
1057 #define SFBCOPY64BYTESDONE 8
1058 #define SFBCOPY64BITS 64
1059 #define SFBCOPY64SRC(p, v) \
1060 (*((u_int32_t *)BUMP(p) + TGA_REG_GCSR) = (long)(v))
1061 #define SFBCOPY64DST(p, v) \
1062 (*((u_int32_t *)BUMP(p) + TGA_REG_GCDR) = (long)(v))
1063
1064 /*
1065 * Actually write a string to the frame buffer.
1066 */
1067 static void
1068 sfbp_putchar(id, row, col, uc, attr)
1069 void *id;
1070 int row, col;
1071 u_int uc;
1072 long attr;
1073 {
1074 struct rasops_info *ri = id;
1075 caddr_t sfb, p;
1076 int scanspan, height, width, align, x, y;
1077 u_int32_t lmask, rmask, glyph;
1078 u_int8_t *g;
1079
1080 x = col * ri->ri_font->fontwidth;
1081 y = row * ri->ri_font->fontheight;
1082 scanspan = ri->ri_stride;
1083 height = ri->ri_font->fontheight;
1084 uc -= ri->ri_font->firstchar;
1085 g = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
1086
1087 p = ri->ri_bits + y * scanspan + x * SFBPIXELBYTES;
1088 align = (long)p & SFBALIGNMASK;
1089 p -= align;
1090 align /= SFBPIXELBYTES;
1091 width = ri->ri_font->fontwidth + align;
1092 lmask = SFBSTIPPLEALL1 << align;
1093 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
1094 sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET;
1095
1096 SFBMODE(sfb, MODE_OPAQUESTIPPLE);
1097 SFBPLANEMASK(sfb, ~0);
1098 SFBFG(sfb, ri->ri_devcmap[(attr >> 24) & 15]);
1099 SFBBG(sfb, ri->ri_devcmap[(attr >> 16) & 15]);
1100 SFBROP(sfb, (3 << 8) | 3); /* ROP_COPY24 */
1101 *((u_int32_t *)sfb + TGA_REG_GPXR_P) = lmask & rmask;
1102
1103 /* XXX 2B stride fonts only XXX */
1104 while (height > 0) {
1105 glyph = *(u_int16_t *)g; /* XXX */
1106 *(u_int32_t *)p = glyph << align;
1107 p += scanspan;
1108 g += 2; /* XXX */
1109 height--;
1110 }
1111 SFBMODE(sfb, MODE_SIMPLE);
1112 *((u_int32_t *)sfb + TGA_REG_GPXR_P) = ~0;
1113 }
1114
1115 #undef SFBSTIPPLEALL1
1116 #undef SFBSTIPPLEBITS
1117 #undef SFBSTIPPLEBITMASK
1118 #define SFBSTIPPLEALL1 SFBCOPYALL1
1119 #define SFBSTIPPLEBITS SFBCOPYBITS
1120 #define SFBSTIPPLEBITMASK SFBCOPYBITMASK
1121
1122 /*
1123 * Clear characters in a line.
1124 */
1125 static void
1126 sfbp_erasecols(id, row, startcol, ncols, attr)
1127 void *id;
1128 int row, startcol, ncols;
1129 long attr;
1130 {
1131 struct rasops_info *ri = id;
1132 caddr_t sfb, p;
1133 int scanspan, startx, height, width, align, w, y;
1134 u_int32_t lmask, rmask;
1135
1136 scanspan = ri->ri_stride;
1137 y = row * ri->ri_font->fontheight;
1138 startx = startcol * ri->ri_font->fontwidth;
1139 height = ri->ri_font->fontheight;
1140 w = ri->ri_font->fontwidth * ncols;
1141
1142 p = ri->ri_bits + y * scanspan + startx * SFBPIXELBYTES;
1143 align = (long)p & SFBALIGNMASK;
1144 align /= SFBPIXELBYTES;
1145 p -= align;
1146 width = w + align;
1147 lmask = SFBSTIPPLEALL1 << align;
1148 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
1149 sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET;
1150
1151 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
1152 SFBPLANEMASK(sfb, ~0);
1153 SFBFG(sfb, ri->ri_devcmap[(attr >> 16) & 15]); /* fill with bg */
1154 if (width <= SFBSTIPPLEBITS) {
1155 lmask = lmask & rmask;
1156 while (height > 0) {
1157 *(u_int32_t *)p = lmask;
1158 p += scanspan;
1159 height--;
1160 }
1161 }
1162 else {
1163 caddr_t q = p;
1164 while (height > 0) {
1165 *(u_int32_t *)p = lmask;
1166 WRITE_MB();
1167 width -= 2 * SFBSTIPPLEBITS;
1168 while (width > 0) {
1169 p += SFBSTIPPLEBYTESDONE;
1170 *(u_int32_t *)p = SFBSTIPPLEALL1;
1171 WRITE_MB();
1172 width -= SFBSTIPPLEBITS;
1173 }
1174 p += SFBSTIPPLEBYTESDONE;
1175 *(u_int32_t *)p = rmask;
1176 WRITE_MB();
1177
1178 p = (q += scanspan);
1179 width = w + align;
1180 height--;
1181 }
1182 }
1183 SFBMODE(sfb, MODE_SIMPLE);
1184 }
1185
1186 #if 1
1187 /*
1188 * Copy lines.
1189 */
1190 static void
1191 sfbp_copyrows(id, srcrow, dstrow, nrows)
1192 void *id;
1193 int srcrow, dstrow, nrows;
1194 {
1195 struct rasops_info *ri = id;
1196 caddr_t sfb, p;
1197 int scanspan, offset, srcy, height, width, align, w;
1198 u_int32_t lmask, rmask;
1199
1200 scanspan = ri->ri_stride;
1201 height = ri->ri_font->fontheight * nrows;
1202 offset = (dstrow - srcrow) * ri->ri_yscale;
1203 srcy = ri->ri_font->fontheight * srcrow;
1204 if (srcrow < dstrow && srcrow + nrows > dstrow) {
1205 scanspan = -scanspan;
1206 srcy += height;
1207 }
1208
1209 p = ri->ri_bits + srcy * ri->ri_stride;
1210 align = (long)p & SFBALIGNMASK;
1211 p -= align;
1212 align /= SFBPIXELBYTES;
1213 w = ri->ri_emuwidth;
1214 width = w + align;
1215 lmask = SFBCOPYALL1 << align;
1216 rmask = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
1217 sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET;
1218
1219 SFBMODE(sfb, MODE_COPY);
1220 SFBPLANEMASK(sfb, ~0);
1221 SFBPIXELSHIFT(sfb, 0);
1222 if (width <= SFBCOPYBITS) {
1223 /* never happens */;
1224 }
1225 else {
1226 caddr_t q = p;
1227 while (height > 0) {
1228 *(u_int32_t *)p = lmask;
1229 *(u_int32_t *)(p + offset) = lmask;
1230 width -= 2 * SFBCOPYBITS;
1231 while (width > 0) {
1232 p += SFBCOPYBYTESDONE;
1233 *(u_int32_t *)p = SFBCOPYALL1;
1234 *(u_int32_t *)(p + offset) = SFBCOPYALL1;
1235 width -= SFBCOPYBITS;
1236 }
1237 p += SFBCOPYBYTESDONE;
1238 *(u_int32_t *)p = rmask;
1239 *(u_int32_t *)(p + offset) = rmask;
1240
1241 p = (q += scanspan);
1242 width = w + align;
1243 height--;
1244 }
1245 }
1246 SFBMODE(sfb, MODE_SIMPLE);
1247 }
1248
1249 #else
1250
1251
1252 static void
1253 sfbp_copyrows(id, srcrow, dstrow, nrows)
1254 void *id;
1255 int srcrow, dstrow, nrows;
1256 {
1257 struct rasops_info *ri = id;
1258 caddr_t sfb, p, q;
1259 int scanspan, offset, srcy, height, width, w, align;
1260 u_int32_t rmask, lmask;
1261
1262 scanspan = ri->ri_stride;
1263 height = ri->ri_font->fontheight * nrows;
1264 offset = (dstrow - srcrow) * ri->ri_yscale;
1265 srcy = ri->ri_font->fontheight * srcrow;
1266 if (srcrow < dstrow && srcrow + nrows > dstrow) {
1267 scanspan = -scanspan;
1268 srcy += height;
1269 }
1270
1271 p = ri->ri_bits + srcy * ri->ri_stride;
1272 align = (long)p & SFBALIGNMASK;
1273 w = ri->ri_emuwidth;
1274 width = w + align;
1275 lmask = SFBCOPYALL1 << align;
1276 rmask = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
1277 sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET;
1278 q = p;
1279
1280 SFBMODE(sfb, MODE_COPY);
1281 SFBPLANEMASK(sfb, ~0);
1282 SFBPIXELSHIFT(sfb, 0);
1283
1284 if (width <= SFBCOPYBITS)
1285 ; /* never happens */
1286 else if (width < SFBCOPY64BITS) {
1287 ; /* unlikely happens */
1288
1289 }
1290 else {
1291 while (height > 0) {
1292 while (width >= SFBCOPY64BITS) {
1293 SFBCOPY64SRC(sfb, p);
1294 SFBCOPY64DST(sfb, p + offset);
1295 p += SFBCOPY64BYTESDONE;
1296 width -= SFBCOPY64BITS;
1297 }
1298 if (width >= SFBCOPYBITS) {
1299 *(u_int32_t *)p = SFBCOPYALL1;
1300 *(u_int32_t *)(p + offset) = SFBCOPYALL1;
1301 p += SFBCOPYBYTESDONE;
1302 width -= SFBCOPYBITS;
1303 }
1304 if (width > 0) {
1305 *(u_int32_t *)p = rmask;
1306 *(u_int32_t *)(p + offset) = rmask;
1307 }
1308
1309 p = (q += scanspan);
1310 width = w;
1311 height--;
1312 }
1313 }
1314 SFBMODE(sfb, MODE_SIMPLE);
1315 }
1316 #endif
1317
1318 /*
1319 * Erase lines.
1320 */
1321 static void
1322 sfbp_eraserows(id, startrow, nrows, attr)
1323 void *id;
1324 int startrow, nrows;
1325 long attr;
1326 {
1327 struct rasops_info *ri = id;
1328 caddr_t sfb, p;
1329 int scanspan, starty, height, width, align, w;
1330 u_int32_t lmask, rmask;
1331
1332 scanspan = ri->ri_stride;
1333 starty = ri->ri_font->fontheight * startrow;
1334 height = ri->ri_font->fontheight * nrows;
1335
1336 p = ri->ri_bits + starty * scanspan;
1337 align = (long)p & SFBALIGNMASK;
1338 p -= align;
1339 align /= SFBPIXELBYTES;
1340 w = ri->ri_emuwidth * SFBPIXELBYTES;
1341 width = w + align;
1342 lmask = SFBSTIPPLEALL1 << align;
1343 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
1344 sfb = (caddr_t)ri->ri_hw + SFB_ASIC_OFFSET;
1345
1346 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
1347 SFBPLANEMASK(sfb, ~0);
1348 SFBFG(sfb, ri->ri_devcmap[(attr >> 16) & 15]);
1349 if (width <= SFBSTIPPLEBITS) {
1350 /* never happens */;
1351 }
1352 else {
1353 caddr_t q = p;
1354 while (height > 0) {
1355 *(u_int32_t *)p = lmask;
1356 WRITE_MB();
1357 width -= 2 * SFBSTIPPLEBITS;
1358 while (width > 0) {
1359 p += SFBSTIPPLEBYTESDONE;
1360 *(u_int32_t *)p = SFBSTIPPLEALL1;
1361 WRITE_MB();
1362 width -= SFBSTIPPLEBITS;
1363 }
1364 p += SFBSTIPPLEBYTESDONE;
1365 *(u_int32_t *)p = rmask;
1366 WRITE_MB();
1367
1368 p = (q += scanspan);
1369 width = w + align;
1370 height--;
1371 }
1372 }
1373 SFBMODE(sfb, MODE_SIMPLE);
1374 }
1375