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