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