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