sfbplus.c revision 1.7 1 /* $NetBSD: sfbplus.c,v 1.7 2001/01/16 05:06:02 nisimura 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.7 2001/01/16 05:06:02 nisimura 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, 5) != 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 *(u_int32_t *)(sfbasic + SFB_ASIC_VIDEO_BASE) = vbase = 1;
286
287 dc->dc_wid = (hsetup & 0x1ff) << 2;
288 dc->dc_ht = (vsetup & 0x7ff);
289 dc->dc_depth = (i & 1) ? 32 : 8;
290 dc->dc_rowbytes = dc->dc_wid * (dc->dc_depth / 8);
291 dc->dc_videobase = dc->dc_vaddr + 0x800000 + vbase * 4096; /* XXX */
292 dc->dc_blanked = 0;
293
294 *(u_int32_t *)(sfbasic + SFB_ASIC_PLANEMASK) = ~0;
295 *(u_int32_t *)(sfbasic + SFB_ASIC_PIXELMASK) = ~0;
296 *(u_int32_t *)(sfbasic + SFB_ASIC_MODE) = 0; /* MODE_SIMPLE */
297 *(u_int32_t *)(sfbasic + SFB_ASIC_ROP) = 3 | (3 << 8); /* ROP_COPY */
298
299 /* initialize colormap and cursor resource */
300 sfbpinit(dc);
301
302 /* clear the screen */
303 for (i = 0; i < dc->dc_ht * dc->dc_rowbytes; i += sizeof(u_int32_t))
304 *(u_int32_t *)(dc->dc_videobase + i) = 0x0;
305
306 ri = &dc->rinfo;
307 ri->ri_flg = RI_CENTER;
308 ri->ri_depth = dc->dc_depth;
309 ri->ri_bits = (void *)dc->dc_videobase;
310 ri->ri_width = dc->dc_wid;
311 ri->ri_height = dc->dc_ht;
312 ri->ri_stride = dc->dc_rowbytes;
313 ri->ri_hw = sfbasic;
314
315 ri->ri_flg = 0; /* XXX PATCH HOLES IN rasops XXX */
316
317 if (dc->dc_depth == 32) {
318 ri->ri_rnum = 8;
319 ri->ri_gnum = 8;
320 ri->ri_bnum = 8;
321 ri->ri_rpos = 16;
322 ri->ri_gpos = 8;
323 ri->ri_bpos = 0;
324 }
325
326 wsfont_init();
327 /* prefer 8 pixel wide font */
328 if ((cookie = wsfont_find(NULL, 8, 0, 0)) <= 0)
329 cookie = wsfont_find(NULL, 0, 0, 0);
330 if (cookie <= 0) {
331 printf("sfbp: font table is empty\n");
332 return;
333 }
334
335 /* the accelerated sfbp_putchar() needs LSbit left */
336 if (wsfont_lock(cookie, &dc->rinfo.ri_font,
337 WSDISPLAY_FONTORDER_R2L, WSDISPLAY_FONTORDER_L2R) <= 0) {
338 printf("sfb: couldn't lock font\n");
339 return;
340 }
341 dc->rinfo.ri_wsfcookie = cookie;
342
343 rasops_init(&dc->rinfo, 34, 80);
344
345 /* add our accelerated functions */
346 dc->rinfo.ri_ops.putchar = sfbp_putchar;
347 dc->rinfo.ri_ops.erasecols = sfbp_erasecols;
348 dc->rinfo.ri_ops.copyrows = sfbp_copyrows;
349 dc->rinfo.ri_ops.eraserows = sfbp_eraserows;
350
351 /* XXX shouldn't be global */
352 sfbp_stdscreen.nrows = dc->rinfo.ri_rows;
353 sfbp_stdscreen.ncols = dc->rinfo.ri_cols;
354 sfbp_stdscreen.textops = &dc->rinfo.ri_ops;
355 sfbp_stdscreen.capabilities = dc->rinfo.ri_caps;
356 /* our accelerated putchar can't underline */
357 sfbp_stdscreen.capabilities &= ~WSSCREEN_UNDERLINE;
358 }
359
360 static void
361 sfbpattach(parent, self, aux)
362 struct device *parent, *self;
363 void *aux;
364 {
365 struct sfbp_softc *sc = (struct sfbp_softc *)self;
366 struct tc_attach_args *ta = aux;
367 struct wsemuldisplaydev_attach_args waa;
368 caddr_t sfbasic;
369 int console;
370
371 console = (ta->ta_addr == sfbp_consaddr);
372 if (console) {
373 sc->sc_dc = &sfbp_console_dc;
374 sc->nscreens = 1;
375 }
376 else {
377 sc->sc_dc = (struct fb_devconfig *)
378 malloc(sizeof(struct fb_devconfig), M_DEVBUF, M_WAITOK);
379 sfbp_getdevconfig(ta->ta_addr, sc->sc_dc);
380 }
381 printf(": %d x %d, %dbpp\n", sc->sc_dc->dc_wid, sc->sc_dc->dc_ht,
382 sc->sc_dc->dc_depth);
383 #if 1
384 { int i;
385 struct rasops_info *rip = &sc->sc_dc->rinfo;
386 for (i = 0; i < 16; i++) { printf("i: %02x\n", rip->ri_devcmap[i]); }
387 }
388 #endif
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) = 0x46; 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 int v, index, count, icount, x, y;
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 if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT)) {
807 if (v & WSDISPLAY_CURSOR_DOHOT)
808 cc->cc_hot = p->hot;
809 if (v & WSDISPLAY_CURSOR_DOPOS) {
810 struct fb_devconfig *dc = sc->sc_dc;
811
812 x = p->pos.x;
813 y = p->pos.y;
814 if (y < 0)
815 y = 0;
816 else if (y > dc->dc_ht)
817 y = dc->dc_ht;
818 if (x < 0)
819 x = 0;
820 else if (x > dc->dc_wid)
821 x = dc->dc_wid;
822 sc->sc_cursor.cc_pos.x = x;
823 sc->sc_cursor.cc_pos.y = y;
824 }
825 }
826
827 if (v & WSDISPLAY_CURSOR_DOCUR)
828 sc->sc_curenb = p->enable;
829 if (v & WSDISPLAY_CURSOR_DOPOS)
830 set_curpos(sc, &p->pos);
831 if (v & WSDISPLAY_CURSOR_DOHOT)
832 cc->cc_hot = p->hot;
833 if (v & WSDISPLAY_CURSOR_DOCMAP) {
834 copyin(p->cmap.red, &cc->cc_color[index], count);
835 copyin(p->cmap.green, &cc->cc_color[index + 2], count);
836 copyin(p->cmap.blue, &cc->cc_color[index + 4], count);
837 }
838 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
839 cc->cc_size = p->size;
840 memset(cc->cc_image, 0, sizeof cc->cc_image);
841 copyin(p->image, cc->cc_image, icount);
842 copyin(p->mask, cc->cc_image+CURSOR_MAX_SIZE, icount);
843 }
844 sc->sc_changed = v;
845
846 return (0);
847 #undef cc
848 }
849
850 static int
851 get_cursor(sc, p)
852 struct sfbp_softc *sc;
853 struct wsdisplay_cursor *p;
854 {
855 return (ENOTTY); /* XXX */
856 }
857
858 static void
859 set_curpos(sc, curpos)
860 struct sfbp_softc *sc;
861 struct wsdisplay_curpos *curpos;
862 {
863 struct fb_devconfig *dc = sc->sc_dc;
864 int x = curpos->x, y = curpos->y;
865
866 if (y < 0)
867 y = 0;
868 else if (y > dc->dc_ht)
869 y = dc->dc_ht;
870 if (x < 0)
871 x = 0;
872 else if (x > dc->dc_wid)
873 x = dc->dc_wid;
874 sc->sc_cursor.cc_pos.x = x;
875 sc->sc_cursor.cc_pos.y = y;
876 }
877
878 static void
879 bt459visible(hw, on)
880 void *hw;
881 int on;
882 {
883 SELECT(hw, BT459_IREG_CCR);
884 REG(hw, bt_reg) = (on) ? 0xc0 : 0x00;
885 tc_wmb();
886 }
887
888 static void
889 sfbpvisible(hw, on)
890 void *hw;
891 int on;
892 {
893 /* XXX use SFBplus ASIC XX */
894 }
895
896 static void
897 bt459locate(hw, cc)
898 void *hw;
899 struct hwcursor64 *cc;
900 {
901 int x, y, s;
902
903 x = cc->cc_pos.x - cc->cc_hot.x;
904 y = cc->cc_pos.y - cc->cc_hot.y;
905 x += cc->cc_magic.x;
906 y += cc->cc_magic.y;
907
908 s = spltty();
909 SELECT(hw, BT459_IREG_CURSOR_X_LOW);
910 REG(hw, bt_reg) = x; tc_wmb();
911 REG(hw, bt_reg) = x >> 8; tc_wmb();
912 REG(hw, bt_reg) = y; tc_wmb();
913 REG(hw, bt_reg) = y >> 8; tc_wmb();
914 splx(s);
915 }
916
917 static void
918 sfbplocate(hw, cc)
919 void *hw;
920 struct hwcursor64 *cc;
921 {
922 int x, y;
923
924 x = cc->cc_pos.x - cc->cc_hot.x;
925 y = cc->cc_pos.y - cc->cc_hot.y;
926 *((u_int32_t *)hw + TGA_REG_CXYR) = ((y & 0xfff) << 12) | (x & 0xfff);
927 tc_wmb();
928 }
929
930 static void
931 bt459color(hw, cp)
932 void *hw;
933 u_int8_t *cp;
934 {
935 SELECT(hw, BT459_IREG_CCOLOR_2);
936 REG(hw, bt_reg) = cp[1]; tc_wmb();
937 REG(hw, bt_reg) = cp[3]; tc_wmb();
938 REG(hw, bt_reg) = cp[5]; tc_wmb();
939
940 REG(hw, bt_reg) = cp[0]; tc_wmb();
941 REG(hw, bt_reg) = cp[2]; tc_wmb();
942 REG(hw, bt_reg) = cp[4]; tc_wmb();
943 }
944
945 static void
946 bt463color(hw, cp)
947 void *hw;
948 u_int8_t *cp;
949 {
950 }
951
952 static void
953 bt459shape(hw, size, image)
954 void *hw;
955 struct wsdisplay_curpos *size;
956 u_int64_t *image;
957 {
958 u_int8_t *ip, *mp, img, msk;
959 u_int8_t u;
960 int bcnt;
961
962 ip = (u_int8_t *)image;
963 mp = (u_int8_t *)(image + CURSOR_MAX_SIZE);
964
965 bcnt = 0;
966 SELECT(hw, BT459_IREG_CRAM_BASE+0);
967 /* 64 pixel scan line is consisted with 16 byte cursor ram */
968 while (bcnt < size->y * 16) {
969 /* pad right half 32 pixel when smaller than 33 */
970 if ((bcnt & 0x8) && size->x < 33) {
971 REG(hw, bt_reg) = 0; tc_wmb();
972 REG(hw, bt_reg) = 0; tc_wmb();
973 }
974 else {
975 img = *ip++;
976 msk = *mp++;
977 img &= msk; /* cookie off image */
978 u = (msk & 0x0f) << 4 | (img & 0x0f);
979 REG(hw, bt_reg) = shuffle[u]; tc_wmb();
980 u = (msk & 0xf0) | (img & 0xf0) >> 4;
981 REG(hw, bt_reg) = shuffle[u]; tc_wmb();
982 }
983 bcnt += 2;
984 }
985 /* pad unoccupied scan lines */
986 while (bcnt < CURSOR_MAX_SIZE * 16) {
987 REG(hw, bt_reg) = 0; tc_wmb();
988 REG(hw, bt_reg) = 0; tc_wmb();
989 bcnt += 2;
990 }
991 }
992
993 static void
994 sfbpshape(hw, size, image)
995 void *hw;
996 struct wsdisplay_curpos *size;
997 u_int64_t *image;
998 {
999 /* XXX use SFBplus ASIC XXX */
1000 }
1001
1002 static void
1003 bt459setlut(hw, cm)
1004 void *hw;
1005 struct hwcmap256 *cm;
1006 {
1007 int index;
1008
1009 SELECT(hw, 0);
1010 for (index = 0; index < CMAP_SIZE; index++) {
1011 REG(hw, bt_cmap) = cm->r[index]; tc_wmb();
1012 REG(hw, bt_cmap) = cm->g[index]; tc_wmb();
1013 REG(hw, bt_cmap) = cm->b[index]; tc_wmb();
1014 }
1015 }
1016
1017 static void
1018 noplut(hw, cm)
1019 void *hw;
1020 struct hwcmap256 *cm;
1021 {
1022 }
1023
1024 #define SFBBPP 32
1025
1026 #define MODE_SIMPLE 0
1027 #define MODE_OPAQUESTIPPLE 1
1028 #define MODE_OPAQUELINE 2
1029 #define MODE_TRANSPARENTSTIPPLE 5
1030 #define MODE_TRANSPARENTLINE 6
1031 #define MODE_COPY 7
1032
1033 #define MODE_TRANSPARENTFILL (5+0x20)
1034
1035 #if SFBBPP == 8
1036 /* parameters for 8bpp configuration */
1037 #define SFBALIGNMASK 0x7
1038 #define SFBPIXELBYTES 1
1039 #define SFBSTIPPLEALL1 0xffffffff
1040 #define SFBSTIPPLEBITS 32
1041 #define SFBSTIPPLEBITMASK 0x1f
1042 #define SFBSTIPPLEBYTESDONE 32
1043 #define SFBCOPYALL1 0xffffffff
1044 #define SFBCOPYBITS 32
1045 #define SFBCOPYBITMASK 0x1f
1046 #define SFBCOPYBYTESDONE 32
1047
1048 #elif SFBBPP == 32
1049 /* parameters for 32bpp configuration */
1050 #define SFBALIGNMASK 0x7
1051 #define SFBPIXELBYTES 4
1052 #define SFBSTIPPLEALL1 0x0000ffff
1053 #define SFBSTIPPLEBITS 16
1054 #define SFBSTIPPLEBITMASK 0xf
1055 #define SFBSTIPPLEBYTESDONE 32
1056 #define SFBCOPYALL1 0x000000ff
1057 #define SFBCOPYBITS 8
1058 #define SFBCOPYBITMASK 0x3
1059 #define SFBCOPYBYTESDONE 32
1060 #endif
1061
1062 #ifdef pmax
1063 #define WRITE_MB()
1064 #define BUMP(p) (p)
1065 #endif
1066
1067 #ifdef alpha
1068 #define WRITE_MB() tc_wmb()
1069 /* registers is replicated in 1KB stride; rap round 4th iteration */
1070 #define BUMP(p) ((p) = (caddr_t)(((long)(p) + 0x400) & ~0x1000))
1071 #endif
1072
1073 #define SFBMODE(p, v) \
1074 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_MODE) = (v))
1075 #define SFBROP(p, v) \
1076 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_ROP) = (v))
1077 #define SFBPLANEMASK(p, v) \
1078 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_PLANEMASK) = (v))
1079 #define SFBPIXELMASK(p, v) \
1080 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELMASK) = (v))
1081 #define SFBADDRESS(p, v) \
1082 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_ADDRESS) = (v))
1083 #define SFBSTART(p, v) \
1084 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_START) = (v))
1085 #define SFBPIXELSHIFT(p, v) \
1086 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELSHIFT) = (v))
1087 #define SFBFG(p, v) \
1088 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_FG) = (v))
1089 #define SFBBG(p, v) \
1090 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_BG) = (v))
1091 #define SFBBCONT(p, v) \
1092 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_BCONT) = (v))
1093
1094 #define SFBDATA(p, v) \
1095 (*((u_int32_t *)BUMP(p) + TGA_REG_GDAR) = (v))
1096
1097 #define SFBCOPY64BYTESDONE 8
1098 #define SFBCOPY64BITS 64
1099 #define SFBCOPY64SRC(p, v) \
1100 (*((u_int32_t *)BUMP(p) + TGA_REG_GCSR) = (long)(v))
1101 #define SFBCOPY64DST(p, v) \
1102 (*((u_int32_t *)BUMP(p) + TGA_REG_GCDR) = (long)(v))
1103
1104 /*
1105 * Actually write a string to the frame buffer.
1106 */
1107 static void
1108 sfbp_putchar(id, row, col, uc, attr)
1109 void *id;
1110 int row, col;
1111 u_int uc;
1112 long attr;
1113 {
1114 struct rasops_info *ri = id;
1115 caddr_t sfb, p;
1116 int scanspan, height, width, align, x, y;
1117 u_int32_t lmask, rmask, glyph;
1118 u_int8_t *g;
1119
1120 x = col * ri->ri_font->fontwidth;
1121 y = row * ri->ri_font->fontheight;
1122 scanspan = ri->ri_stride;
1123 height = ri->ri_font->fontheight;
1124 uc -= ri->ri_font->firstchar;
1125 g = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
1126
1127 p = ri->ri_bits + y * scanspan + x * SFBPIXELBYTES;
1128 align = (long)p & SFBALIGNMASK;
1129 p -= align;
1130 align /= SFBPIXELBYTES;
1131 width = ri->ri_font->fontwidth + align;
1132 lmask = SFBSTIPPLEALL1 << align;
1133 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
1134 sfb = ri->ri_hw;
1135
1136 SFBMODE(sfb, MODE_OPAQUESTIPPLE);
1137 SFBPLANEMASK(sfb, ~0);
1138 SFBFG(sfb, ri->ri_devcmap[(attr >> 24) & 15]);
1139 SFBBG(sfb, ri->ri_devcmap[(attr >> 16) & 15]);
1140 SFBROP(sfb, (3 << 8) | 3);
1141 *((u_int32_t *)sfb + TGA_REG_GPXR_P) = lmask & rmask;
1142
1143 /* XXX 2B stride fonts only XXX */
1144 while (height > 0) {
1145 glyph = *(u_int16_t *)g; /* XXX */
1146 *(u_int32_t *)p = glyph << align;
1147 p += scanspan;
1148 g += 2; /* XXX */
1149 height--;
1150 }
1151 SFBMODE(sfb, MODE_SIMPLE);
1152 *((u_int32_t *)sfb + TGA_REG_GPXR_P) = ~0;
1153 }
1154
1155 /*
1156 * Clear characters in a line.
1157 */
1158 static void
1159 sfbp_erasecols(id, row, startcol, ncols, attr)
1160 void *id;
1161 int row, startcol, ncols;
1162 long attr;
1163 {
1164 struct rasops_info *ri = id;
1165 caddr_t sfb, p;
1166 int scanspan, startx, height, w, y;
1167
1168 scanspan = ri->ri_stride;
1169 y = row * ri->ri_font->fontheight;
1170 startx = startcol * ri->ri_font->fontwidth;
1171 height = ri->ri_font->fontheight;
1172 w = ri->ri_font->fontwidth * ncols;
1173
1174 p = ri->ri_bits + y * scanspan + startx * SFBPIXELBYTES;
1175 sfb = ri->ri_hw;
1176
1177 SFBMODE(sfb, MODE_TRANSPARENTFILL);
1178 SFBPLANEMASK(sfb, ~0);
1179 SFBFG(sfb, ri->ri_devcmap[(attr >> 16) & 15]);
1180 SFBDATA(sfb, ~0);
1181 while (height > 0) {
1182 SFBADDRESS(sfb, (long)p);
1183 SFBBCONT(sfb, w);
1184 p += scanspan;
1185 height--;
1186 }
1187 SFBMODE(sfb, MODE_SIMPLE);
1188 }
1189
1190 #if 1
1191 /*
1192 * Copy lines.
1193 */
1194 static void
1195 sfbp_copyrows(id, srcrow, dstrow, nrows)
1196 void *id;
1197 int srcrow, dstrow, nrows;
1198 {
1199 struct rasops_info *ri = id;
1200 caddr_t sfb, p;
1201 int scanspan, offset, srcy, height, width, align, w;
1202 u_int32_t lmask, rmask;
1203
1204 scanspan = ri->ri_stride;
1205 height = ri->ri_font->fontheight * nrows;
1206 offset = (dstrow - srcrow) * ri->ri_yscale;
1207 srcy = ri->ri_font->fontheight * srcrow;
1208 if (srcrow < dstrow && srcrow + nrows > dstrow) {
1209 scanspan = -scanspan;
1210 srcy += height;
1211 }
1212
1213 p = ri->ri_bits + srcy * ri->ri_stride;
1214 align = (long)p & SFBALIGNMASK;
1215 p -= align;
1216 align /= SFBPIXELBYTES;
1217 w = ri->ri_emuwidth;
1218 width = w + align;
1219 lmask = SFBCOPYALL1 << align;
1220 rmask = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
1221 sfb = ri->ri_hw;
1222
1223 SFBMODE(sfb, MODE_COPY);
1224 SFBPLANEMASK(sfb, ~0);
1225 SFBPIXELSHIFT(sfb, 0);
1226 if (width <= SFBCOPYBITS) {
1227 /* never happens */;
1228 }
1229 else {
1230 caddr_t q = p;
1231 while (height > 0) {
1232 *(u_int32_t *)p = lmask;
1233 *(u_int32_t *)(p + offset) = lmask;
1234 width -= 2 * SFBCOPYBITS;
1235 while (width > 0) {
1236 p += SFBCOPYBYTESDONE;
1237 *(u_int32_t *)p = SFBCOPYALL1;
1238 *(u_int32_t *)(p + offset) = SFBCOPYALL1;
1239 width -= SFBCOPYBITS;
1240 }
1241 p += SFBCOPYBYTESDONE;
1242 *(u_int32_t *)p = rmask;
1243 *(u_int32_t *)(p + offset) = rmask;
1244
1245 p = (q += scanspan);
1246 width = w + align;
1247 height--;
1248 }
1249 }
1250 SFBMODE(sfb, MODE_SIMPLE);
1251 }
1252
1253 #else
1254
1255
1256 static void
1257 sfbp_copyrows(id, srcrow, dstrow, nrows)
1258 void *id;
1259 int srcrow, dstrow, nrows;
1260 {
1261 struct rasops_info *ri = id;
1262 caddr_t sfb, p, q;
1263 int scanspan, offset, srcy, height, width, w, align;
1264 u_int32_t rmask, lmask;
1265
1266 scanspan = ri->ri_stride;
1267 height = ri->ri_font->fontheight * nrows;
1268 offset = (dstrow - srcrow) * ri->ri_yscale;
1269 srcy = ri->ri_font->fontheight * srcrow;
1270 if (srcrow < dstrow && srcrow + nrows > dstrow) {
1271 scanspan = -scanspan;
1272 srcy += height;
1273 }
1274
1275 p = ri->ri_bits + srcy * ri->ri_stride;
1276 align = (long)p & SFBALIGNMASK;
1277 w = ri->ri_emuwidth;
1278 width = w + align;
1279 lmask = SFBCOPYALL1 << align;
1280 rmask = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
1281 sfb = ri->ri_hw;
1282 q = p;
1283
1284 SFBMODE(sfb, MODE_COPY);
1285 SFBPLANEMASK(sfb, ~0);
1286 SFBPIXELSHIFT(sfb, 0);
1287
1288 if (width <= SFBCOPYBITS)
1289 ; /* never happens */
1290 else if (width < SFBCOPY64BITS) {
1291 ; /* unlikely happens */
1292
1293 }
1294 else {
1295 while (height > 0) {
1296 while (width >= SFBCOPY64BITS) {
1297 SFBCOPY64SRC(sfb, p);
1298 SFBCOPY64DST(sfb, p + offset);
1299 p += SFBCOPY64BYTESDONE;
1300 width -= SFBCOPY64BITS;
1301 }
1302 if (width >= SFBCOPYBITS) {
1303 *(u_int32_t *)p = SFBCOPYALL1;
1304 *(u_int32_t *)(p + offset) = SFBCOPYALL1;
1305 p += SFBCOPYBYTESDONE;
1306 width -= SFBCOPYBITS;
1307 }
1308 if (width > 0) {
1309 *(u_int32_t *)p = rmask;
1310 *(u_int32_t *)(p + offset) = rmask;
1311 }
1312
1313 p = (q += scanspan);
1314 width = w;
1315 height--;
1316 }
1317 }
1318 SFBMODE(sfb, MODE_SIMPLE);
1319 }
1320 #endif
1321
1322 /*
1323 * Erase lines.
1324 */
1325 static void
1326 sfbp_eraserows(id, startrow, nrows, attr)
1327 void *id;
1328 int startrow, nrows;
1329 long attr;
1330 {
1331 struct rasops_info *ri = id;
1332 caddr_t sfb, p;
1333 int scanspan, starty, height, width, align, w;
1334 u_int32_t lmask, rmask;
1335
1336 scanspan = ri->ri_stride;
1337 starty = ri->ri_font->fontheight * startrow;
1338 height = ri->ri_font->fontheight * nrows;
1339
1340 p = ri->ri_bits + starty * scanspan;
1341 align = (long)p & SFBALIGNMASK;
1342 p -= align;
1343 align /= SFBPIXELBYTES;
1344 w = ri->ri_emuwidth;
1345 width = w + align;
1346 lmask = SFBSTIPPLEALL1 << align;
1347 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
1348 sfb = ri->ri_hw;
1349
1350 #if 1
1351 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
1352 SFBPLANEMASK(sfb, ~0);
1353 SFBFG(sfb, ri->ri_devcmap[(attr >> 16) & 15]);
1354 if (width <= SFBSTIPPLEBITS) {
1355 /* never happens */;
1356 }
1357 else {
1358 caddr_t q = p;
1359 while (height > 0) {
1360 *(u_int32_t *)p = lmask;
1361 WRITE_MB();
1362 width -= 2 * SFBSTIPPLEBITS;
1363 while (width > 0) {
1364 p += SFBSTIPPLEBYTESDONE;
1365 *(u_int32_t *)p = SFBSTIPPLEALL1;
1366 WRITE_MB();
1367 width -= SFBSTIPPLEBITS;
1368 }
1369 p += SFBSTIPPLEBYTESDONE;
1370 *(u_int32_t *)p = rmask;
1371 WRITE_MB();
1372
1373 p = (q += scanspan);
1374 width = w + align;
1375 height--;
1376 }
1377 }
1378 SFBMODE(sfb, MODE_SIMPLE);
1379 #else
1380 SFBMODE(sfb, MODE_TRANSPARENTFILL);
1381 SFBPLANEMASK(sfb, ~0);
1382 SFBFG(sfb, ri->ri_devcmap[(attr >> 16) & 15]);
1383 SFBDATA(sfb, ~0);
1384 while (height > 0) {
1385 SFBADDRESS(sfb, (long)p);
1386 SFBBCONT(sfb, w);
1387 p += scanspan;
1388 height--;
1389 }
1390 SFBMODE(sfb, MODE_SIMPLE);
1391 #endif
1392 }
1393