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