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