sfb.c revision 1.30 1 /* $NetBSD: sfb.c,v 1.30 1999/12/06 19:26:00 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.30 1999/12/06 19:26:00 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 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 /*
314 * the accelerated sfb_putchar() needs LSbit left,
315 * so we can't use the rasops default font
316 */
317 wsfont_init();
318 /* prefer 8 pixel wide font */
319 if ((cookie = wsfont_find(NULL, 8, 0, 0)) <= 0)
320 cookie = wsfont_find(NULL, 0, 0, 0);
321 if (cookie <= 0) {
322 printf("sfb: font table is empty\n");
323 return;
324 }
325 if (wsfont_lock(cookie, &dc->rinfo.ri_font,
326 WSFONT_R2L, WSFONT_L2R) <= 0) {
327 printf("sfb: couldn't lock font\n");
328 return;
329 }
330 dc->rinfo.ri_wsfcookie = cookie;
331
332 rasops_init(&dc->rinfo, 1000, 1000); /* as large as possible */
333
334 /* add our accelerated functions */
335 dc->rinfo.ri_ops.copyrows = sfb_copyrows;
336 dc->rinfo.ri_ops.putchar = sfb_putchar;
337
338 /* XXX shouldn't be global */
339 sfb_stdscreen.nrows = dc->rinfo.ri_rows;
340 sfb_stdscreen.ncols = dc->rinfo.ri_cols;
341 sfb_stdscreen.textops = &dc->rinfo.ri_ops;
342 sfb_stdscreen.capabilities = dc->rinfo.ri_caps;
343 /* our accelerated putchar can't underline */
344 sfb_stdscreen.capabilities &= ~WSSCREEN_UNDERLINE;
345 }
346
347 static void
348 sfbattach(parent, self, aux)
349 struct device *parent, *self;
350 void *aux;
351 {
352 struct sfb_softc *sc = (struct sfb_softc *)self;
353 struct tc_attach_args *ta = aux;
354 struct wsemuldisplaydev_attach_args waa;
355 caddr_t sfbasic;
356 int console;
357
358 console = (ta->ta_addr == sfb_consaddr);
359 if (console) {
360 sc->sc_dc = &sfb_console_dc;
361 sc->nscreens = 1;
362 }
363 else {
364 sc->sc_dc = (struct fb_devconfig *)
365 malloc(sizeof(struct fb_devconfig), M_DEVBUF, M_WAITOK);
366 memset(sc->sc_dc, 0, sizeof(struct fb_devconfig));
367 sfb_getdevconfig(ta->ta_addr, sc->sc_dc);
368 }
369 printf(": %d x %d, %dbpp\n", sc->sc_dc->dc_wid, sc->sc_dc->dc_ht,
370 sc->sc_dc->dc_depth);
371
372 memcpy(&sc->sc_cmap, rasops_cmap, sizeof(struct hwcmap256));
373
374 sc->sc_cursor.cc_magic.x = HX_MAGIC_X;
375 sc->sc_cursor.cc_magic.y = HX_MAGIC_Y;
376
377 tc_intr_establish(parent, ta->ta_cookie, IPL_TTY, sfbintr, sc);
378
379 sfbasic = (caddr_t)(sc->sc_dc->dc_vaddr + SFB_ASIC_OFFSET);
380 *(u_int32_t *)(sfbasic + SFB_ASIC_CLEAR_INTR) = 0;
381 *(u_int32_t *)(sfbasic + SFB_ASIC_ENABLE_INTR) = 1;
382
383 waa.console = console;
384 waa.scrdata = &sfb_screenlist;
385 waa.accessops = &sfb_accessops;
386 waa.accesscookie = sc;
387
388 config_found(self, &waa, wsemuldisplaydevprint);
389 }
390
391 static int
392 sfbioctl(v, cmd, data, flag, p)
393 void *v;
394 u_long cmd;
395 caddr_t data;
396 int flag;
397 struct proc *p;
398 {
399 struct sfb_softc *sc = v;
400 struct fb_devconfig *dc = sc->sc_dc;
401 int turnoff;
402
403 switch (cmd) {
404 case WSDISPLAYIO_GTYPE:
405 *(u_int *)data = WSDISPLAY_TYPE_SFB;
406 return (0);
407
408 case WSDISPLAYIO_GINFO:
409 #define wsd_fbip ((struct wsdisplay_fbinfo *)data)
410 wsd_fbip->height = sc->sc_dc->dc_ht;
411 wsd_fbip->width = sc->sc_dc->dc_wid;
412 wsd_fbip->depth = sc->sc_dc->dc_depth;
413 wsd_fbip->cmsize = CMAP_SIZE;
414 #undef fbt
415 return (0);
416
417 case WSDISPLAYIO_GETCMAP:
418 return get_cmap(sc, (struct wsdisplay_cmap *)data);
419
420 case WSDISPLAYIO_PUTCMAP:
421 return set_cmap(sc, (struct wsdisplay_cmap *)data);
422
423 case WSDISPLAYIO_SVIDEO:
424 turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF;
425 if ((dc->dc_blanked == 0) ^ turnoff) {
426 dc->dc_blanked = turnoff;
427 #if 0 /* XXX later XXX */
428 To turn off, assign value 0 in ASIC_VIDEO_VALID register.
429 #endif /* XXX XXX XXX */
430 }
431 return (0);
432
433 case WSDISPLAYIO_GVIDEO:
434 *(u_int *)data = dc->dc_blanked ?
435 WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON;
436 return (0);
437
438 case WSDISPLAYIO_GCURPOS:
439 *(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos;
440 return (0);
441
442 case WSDISPLAYIO_SCURPOS:
443 set_curpos(sc, (struct wsdisplay_curpos *)data);
444 bt459_set_curpos(sc);
445 return (0);
446
447 case WSDISPLAYIO_GCURMAX:
448 ((struct wsdisplay_curpos *)data)->x =
449 ((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE;
450 return (0);
451
452 case WSDISPLAYIO_GCURSOR:
453 return get_cursor(sc, (struct wsdisplay_cursor *)data);
454
455 case WSDISPLAYIO_SCURSOR:
456 return set_cursor(sc, (struct wsdisplay_cursor *)data);
457 }
458 return ENOTTY;
459 }
460
461 static int
462 sfbmmap(v, offset, prot)
463 void *v;
464 off_t offset;
465 int prot;
466 {
467 struct sfb_softc *sc = v;
468
469 if (offset >= SFB_SIZE || offset < 0)
470 return (-1);
471 return machine_btop(sc->sc_dc->dc_paddr + offset);
472 }
473
474 static int
475 sfb_alloc_screen(v, type, cookiep, curxp, curyp, attrp)
476 void *v;
477 const struct wsscreen_descr *type;
478 void **cookiep;
479 int *curxp, *curyp;
480 long *attrp;
481 {
482 struct sfb_softc *sc = v;
483 long defattr;
484
485 if (sc->nscreens > 0)
486 return (ENOMEM);
487
488 *cookiep = &sc->sc_dc->rinfo; /* one and only for now */
489 *curxp = 0;
490 *curyp = 0;
491 (*sc->sc_dc->rinfo.ri_ops.alloc_attr)(&sc->sc_dc->rinfo, 0, 0, 0, &defattr);
492 *attrp = defattr;
493 sc->nscreens++;
494 return (0);
495 }
496
497 static void
498 sfb_free_screen(v, cookie)
499 void *v;
500 void *cookie;
501 {
502 struct sfb_softc *sc = v;
503
504 if (sc->sc_dc == &sfb_console_dc)
505 panic("sfb_free_screen: console");
506
507 sc->nscreens--;
508 }
509
510 static int
511 sfb_show_screen(v, cookie, waitok, cb, cbarg)
512 void *v;
513 void *cookie;
514 int waitok;
515 void (*cb) __P((void *, int, int));
516 void *cbarg;
517 {
518
519 return (0);
520 }
521
522 /* EXPORT */ int
523 sfb_cnattach(addr)
524 tc_addr_t addr;
525 {
526 struct fb_devconfig *dcp = &sfb_console_dc;
527 long defattr;
528
529 sfb_getdevconfig(addr, dcp);
530
531 (*dcp->rinfo.ri_ops.alloc_attr)(&dcp->rinfo, 0, 0, 0, &defattr);
532
533 wsdisplay_cnattach(&sfb_stdscreen, &dcp->rinfo, 0, 0, defattr);
534 sfb_consaddr = addr;
535 return(0);
536 }
537
538 static int
539 sfbintr(arg)
540 void *arg;
541 {
542 struct sfb_softc *sc = arg;
543 caddr_t sfbbase = (caddr_t)sc->sc_dc->dc_vaddr;
544 caddr_t sfbasic = sfbbase + SFB_ASIC_OFFSET;
545 caddr_t vdac;
546 int v;
547
548 *(u_int32_t *)(sfbasic + SFB_ASIC_CLEAR_INTR) = 0;
549 /* *(u_int32_t *)(sfbasic + SFB_ASIC_ENABLE_INTR) = 1; */
550
551 if (sc->sc_changed == 0)
552 return (1);
553
554 vdac = (void *)(sfbbase + SFB_RAMDAC_OFFSET);
555 v = sc->sc_changed;
556 sc->sc_changed = 0;
557
558 if (v & DATA_ENB_CHANGED) {
559 SELECT(vdac, BT459_REG_CCR);
560 REG(vdac, bt_reg) = (sc->sc_curenb) ? 0xc0 : 0x00;
561 }
562 if (v & DATA_CURCMAP_CHANGED) {
563 u_int8_t *cp = sc->sc_cursor.cc_color;
564
565 SELECT(vdac, BT459_REG_CCOLOR_2);
566 REG(vdac, bt_reg) = cp[1]; tc_wmb();
567 REG(vdac, bt_reg) = cp[3]; tc_wmb();
568 REG(vdac, bt_reg) = cp[5]; tc_wmb();
569
570 REG(vdac, bt_reg) = cp[0]; tc_wmb();
571 REG(vdac, bt_reg) = cp[2]; tc_wmb();
572 REG(vdac, bt_reg) = cp[4]; tc_wmb();
573 }
574 if (v & DATA_CURSHAPE_CHANGED) {
575 u_int8_t *ip, *mp, img, msk;
576 u_int8_t u;
577 int bcnt;
578
579 ip = (u_int8_t *)sc->sc_cursor.cc_image;
580 mp = (u_int8_t *)(sc->sc_cursor.cc_image + CURSOR_MAX_SIZE);
581
582 bcnt = 0;
583 SELECT(vdac, BT459_REG_CRAM_BASE+0);
584 /* 64 pixel scan line is consisted with 16 byte cursor ram */
585 while (bcnt < sc->sc_cursor.cc_size.y * 16) {
586 /* pad right half 32 pixel when smaller than 33 */
587 if ((bcnt & 0x8) && sc->sc_cursor.cc_size.x < 33) {
588 REG(vdac, bt_reg) = 0; tc_wmb();
589 REG(vdac, bt_reg) = 0; tc_wmb();
590 }
591 else {
592 img = *ip++;
593 msk = *mp++;
594 img &= msk; /* cookie off image */
595 u = (msk & 0x0f) << 4 | (img & 0x0f);
596 REG(vdac, bt_reg) = shuffle[u]; tc_wmb();
597 u = (msk & 0xf0) | (img & 0xf0) >> 4;
598 REG(vdac, bt_reg) = shuffle[u]; tc_wmb();
599 }
600 bcnt += 2;
601 }
602 /* pad unoccupied scan lines */
603 while (bcnt < CURSOR_MAX_SIZE * 16) {
604 REG(vdac, bt_reg) = 0; tc_wmb();
605 REG(vdac, bt_reg) = 0; tc_wmb();
606 bcnt += 2;
607 }
608 }
609 if (v & DATA_CMAP_CHANGED) {
610 struct hwcmap256 *cm = &sc->sc_cmap;
611 int index;
612
613 SELECT(vdac, 0);
614 for (index = 0; index < CMAP_SIZE; index++) {
615 REG(vdac, bt_cmap) = cm->r[index]; tc_wmb();
616 REG(vdac, bt_cmap) = cm->g[index]; tc_wmb();
617 REG(vdac, bt_cmap) = cm->b[index]; tc_wmb();
618 }
619 }
620 return (1);
621 }
622
623 static void
624 sfbinit(dc)
625 struct fb_devconfig *dc;
626 {
627 caddr_t sfbasic = (caddr_t)(dc->dc_vaddr + SFB_ASIC_OFFSET);
628 caddr_t vdac = (void *)(dc->dc_vaddr + SFB_RAMDAC_OFFSET);
629 int i;
630
631 *(u_int32_t *)(sfbasic + SFB_ASIC_PLANEMASK) = ~0;
632 *(u_int32_t *)(sfbasic + SFB_ASIC_PIXELMASK) = ~0;
633 *(u_int32_t *)(sfbasic + SFB_ASIC_MODE) = 0; /* MODE_SIMPLE */
634 *(u_int32_t *)(sfbasic + SFB_ASIC_ROP) = 3; /* ROP_COPY */
635
636 *(u_int32_t *)(sfbasic + 0x180000) = 0; /* Bt459 reset */
637
638 SELECT(vdac, BT459_REG_COMMAND_0);
639 REG(vdac, bt_reg) = 0x40; /* CMD0 */ tc_wmb();
640 REG(vdac, bt_reg) = 0x0; /* CMD1 */ tc_wmb();
641 REG(vdac, bt_reg) = 0xc0; /* CMD2 */ tc_wmb();
642 REG(vdac, bt_reg) = 0xff; /* PRM */ tc_wmb();
643 REG(vdac, bt_reg) = 0; /* 205 */ tc_wmb();
644 REG(vdac, bt_reg) = 0x0; /* PBM */ tc_wmb();
645 REG(vdac, bt_reg) = 0; /* 207 */ tc_wmb();
646 REG(vdac, bt_reg) = 0x0; /* ORM */ tc_wmb();
647 REG(vdac, bt_reg) = 0x0; /* OBM */ tc_wmb();
648 REG(vdac, bt_reg) = 0x0; /* ILV */ tc_wmb();
649 REG(vdac, bt_reg) = 0x0; /* TEST */ tc_wmb();
650
651 SELECT(vdac, BT459_REG_CCR);
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 REG(vdac, bt_reg) = 0x0; tc_wmb();
664 REG(vdac, bt_reg) = 0x0; tc_wmb();
665
666 /* build sane colormap */
667 SELECT(vdac, 0);
668 for (i = 0; i < CMAP_SIZE; i++) {
669 REG(vdac, bt_cmap) = rasops_cmap[3 * i + 0];
670 tc_wmb();
671 REG(vdac, bt_cmap) = rasops_cmap[3 * i + 1];
672 tc_wmb();
673 REG(vdac, bt_cmap) = rasops_cmap[3 * i + 2];
674 tc_wmb();
675 }
676
677 /* clear out cursor image */
678 SELECT(vdac, BT459_REG_CRAM_BASE);
679 for (i = 0; i < 1024; i++)
680 REG(vdac, bt_reg) = 0xff; tc_wmb();
681
682 /*
683 * 2 bit/pixel cursor. Assign MSB for cursor mask and LSB for
684 * cursor image. CCOLOR_2 for mask color, while CCOLOR_3 for
685 * image color. CCOLOR_1 will be never used.
686 */
687 SELECT(vdac, BT459_REG_CCOLOR_1);
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 REG(vdac, bt_reg) = 0; tc_wmb();
693 REG(vdac, bt_reg) = 0; tc_wmb();
694 REG(vdac, bt_reg) = 0; tc_wmb();
695
696 REG(vdac, bt_reg) = 0xff; tc_wmb();
697 REG(vdac, bt_reg) = 0xff; tc_wmb();
698 REG(vdac, bt_reg) = 0xff; tc_wmb();
699 }
700
701 static int
702 get_cmap(sc, p)
703 struct sfb_softc *sc;
704 struct wsdisplay_cmap *p;
705 {
706 u_int index = p->index, count = p->count;
707
708 if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE)
709 return (EINVAL);
710
711 if (!uvm_useracc(p->red, count, B_WRITE) ||
712 !uvm_useracc(p->green, count, B_WRITE) ||
713 !uvm_useracc(p->blue, count, B_WRITE))
714 return (EFAULT);
715
716 copyout(&sc->sc_cmap.r[index], p->red, count);
717 copyout(&sc->sc_cmap.g[index], p->green, count);
718 copyout(&sc->sc_cmap.b[index], p->blue, count);
719
720 return (0);
721 }
722
723 static int
724 set_cmap(sc, p)
725 struct sfb_softc *sc;
726 struct wsdisplay_cmap *p;
727 {
728 u_int index = p->index, count = p->count;
729
730 if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE)
731 return (EINVAL);
732
733 if (!uvm_useracc(p->red, count, B_READ) ||
734 !uvm_useracc(p->green, count, B_READ) ||
735 !uvm_useracc(p->blue, count, B_READ))
736 return (EFAULT);
737
738 copyin(p->red, &sc->sc_cmap.r[index], count);
739 copyin(p->green, &sc->sc_cmap.g[index], count);
740 copyin(p->blue, &sc->sc_cmap.b[index], count);
741
742 sc->sc_changed |= DATA_CMAP_CHANGED;
743
744 return (0);
745 }
746
747
748 static int
749 set_cursor(sc, p)
750 struct sfb_softc *sc;
751 struct wsdisplay_cursor *p;
752 {
753 #define cc (&sc->sc_cursor)
754 int v, index, count, icount;
755
756 v = p->which;
757 if (v & WSDISPLAY_CURSOR_DOCMAP) {
758 index = p->cmap.index;
759 count = p->cmap.count;
760 if (index >= 2 || (index + count) > 2)
761 return (EINVAL);
762 if (!uvm_useracc(p->cmap.red, count, B_READ) ||
763 !uvm_useracc(p->cmap.green, count, B_READ) ||
764 !uvm_useracc(p->cmap.blue, count, B_READ))
765 return (EFAULT);
766 }
767 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
768 if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE)
769 return (EINVAL);
770 icount = ((p->size.x < 33) ? 4 : 8) * p->size.y;
771 if (!uvm_useracc(p->image, icount, B_READ) ||
772 !uvm_useracc(p->mask, icount, B_READ))
773 return (EFAULT);
774 }
775 if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOCUR)) {
776 if (v & WSDISPLAY_CURSOR_DOCUR)
777 cc->cc_hot = p->hot;
778 if (v & WSDISPLAY_CURSOR_DOPOS)
779 set_curpos(sc, &p->pos);
780 bt459_set_curpos(sc);
781 }
782
783 sc->sc_changed = 0;
784 if (v & WSDISPLAY_CURSOR_DOCUR) {
785 sc->sc_curenb = p->enable;
786 sc->sc_changed |= DATA_ENB_CHANGED;
787 }
788 if (v & WSDISPLAY_CURSOR_DOCMAP) {
789 copyin(p->cmap.red, &cc->cc_color[index], count);
790 copyin(p->cmap.green, &cc->cc_color[index + 2], count);
791 copyin(p->cmap.blue, &cc->cc_color[index + 4], count);
792 sc->sc_changed |= DATA_CURCMAP_CHANGED;
793 }
794 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
795 cc->cc_size = p->size;
796 memset(cc->cc_image, 0, sizeof cc->cc_image);
797 copyin(p->image, cc->cc_image, icount);
798 copyin(p->mask, cc->cc_image+CURSOR_MAX_SIZE, icount);
799 sc->sc_changed |= DATA_CURSHAPE_CHANGED;
800 }
801
802 return (0);
803 #undef cc
804 }
805
806 static int
807 get_cursor(sc, p)
808 struct sfb_softc *sc;
809 struct wsdisplay_cursor *p;
810 {
811 return (ENOTTY); /* XXX */
812 }
813
814 static void
815 set_curpos(sc, curpos)
816 struct sfb_softc *sc;
817 struct wsdisplay_curpos *curpos;
818 {
819 struct fb_devconfig *dc = sc->sc_dc;
820 int x = curpos->x, y = curpos->y;
821
822 if (y < 0)
823 y = 0;
824 else if (y > dc->dc_ht)
825 y = dc->dc_ht;
826 if (x < 0)
827 x = 0;
828 else if (x > dc->dc_wid)
829 x = dc->dc_wid;
830 sc->sc_cursor.cc_pos.x = x;
831 sc->sc_cursor.cc_pos.y = y;
832 }
833
834 static void
835 bt459_set_curpos(sc)
836 struct sfb_softc *sc;
837 {
838 caddr_t vdac = (caddr_t)sc->sc_dc->dc_vaddr + SFB_RAMDAC_OFFSET;
839 int x, y, s;
840
841 x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x;
842 y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y;
843
844 x += sc->sc_cursor.cc_magic.x;
845 y += sc->sc_cursor.cc_magic.y;
846
847 s = spltty();
848
849 SELECT(vdac, BT459_REG_CURSOR_X_LOW);
850 REG(vdac, bt_reg) = x; tc_wmb();
851 REG(vdac, bt_reg) = x >> 8; tc_wmb();
852 REG(vdac, bt_reg) = y; tc_wmb();
853 REG(vdac, bt_reg) = y >> 8; tc_wmb();
854
855 splx(s);
856 }
857
858 #define MODE_SIMPLE 0
859 #define MODE_OPAQUESTIPPLE 1
860 #define MODE_OPAQUELINE 2
861 #define MODE_TRANSPARENTSTIPPLE 5
862 #define MODE_TRANSPARENTLINE 6
863 #define MODE_COPY 7
864
865 /* parameters for 8bpp configuration */
866 #define SFBALIGNMASK 0x7
867 #define SFBSTIPPLEALL1 0xffffffff
868 #define SFBSTIPPLEBITS 32
869 #define SFBSTIPPLEBITMASK 0x1f
870 #define SFBSTIPPLEBYTESDONE 32
871 #define SFBCOPYALL1 0xffffffff
872 #define SFBCOPYBITS 32
873 #define SFBCOPYBITMASK 0x1f
874 #define SFBCOPYBYTESDONE 32
875
876 #ifdef pmax
877 #define WRITE_MB()
878 #define BUMP(p) (p)
879 #endif
880
881 #ifdef alpha
882 #define WRITE_MB() tc_wmb()
883 #define BUMP(p) ((p) = (caddr_t)(((long)(p) + 128) & ~0x400))
884 #endif
885
886 #define SFBMODE(p, v) \
887 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_MODE) = (v))
888 #define SFBROP(p, v) \
889 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_ROP) = (v))
890 #define SFBPLANEMASK(p, v) \
891 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_PLANEMASK) = (v))
892 #define SFBPIXELMASK(p, v) \
893 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELMASK) = (v))
894 #define SFBADDRESS(p, v) \
895 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_ADDRESS) = (v))
896 #define SFBSTART(p, v) \
897 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_START) = (v))
898 #define SFBPIXELSHIFT(p, v) \
899 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELSHIFT) = (v))
900 #define SFBFG(p, v) \
901 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_FG) = (v))
902 #define SFBBG(p, v) \
903 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_BG) = (v))
904
905
906 #if 0
907 /*
908 * Paint (or unpaint) the cursor.
909 */
910 static void
911 sfb_cursor(id, on, row, col)
912 void *id;
913 int on, row, col;
914 {
915 struct rcons *rc = id;
916 struct raster *rap = rc->rc_sp;
917 caddr_t sfb, p;
918 int scanspan, height, width, align, x, y;
919 u_int32_t lmask, rmask;
920
921 /* turn the cursor off */
922 if (!on) {
923 /* make sure it's on */
924 if ((rc->rc_bits & RC_CURSOR) == 0)
925 return;
926
927 row = *rc->rc_crowp;
928 col = *rc->rc_ccolp;
929 } else {
930 /* unpaint the old copy. */
931 *rc->rc_crowp = row;
932 *rc->rc_ccolp = col;
933 }
934
935 x = col * rc->rc_font->width + rc->rc_xorigin;
936 y = row * rc->rc_font->height + rc->rc_yorigin;
937 scanspan = rap->linelongs * 4;
938 height = rc->rc_font->height;
939
940 p = (caddr_t)rap->pixels + y * scanspan + x;
941 align = (long)p & SFBALIGNMASK;
942 p -= align;
943 width = rc->rc_font->width + align;
944 lmask = SFBSTIPPLEALL1 << align;
945 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
946 sfb = rap->data;
947
948 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
949 SFBPLANEMASK(sfb, ~0);
950 SFBROP(sfb, 6); /* ROP_XOR */
951 SFBFG(sfb, 0x01010101); /* (fg ^ bg) to swap fg/bg */
952 if (width <= SFBSTIPPLEBITS) {
953 lmask = lmask & rmask;
954 while (height > 0) {
955 SFBADDRESS(sfb, (long)p);
956 SFBSTART(sfb, lmask);
957 p += scanspan;
958 height--;
959 }
960 }
961 else {
962 caddr_t q = p;
963 while (height > 0) {
964 *(u_int32_t *)p = lmask;
965 WRITE_MB();
966 p += SFBSTIPPLEBYTESDONE;
967 *(u_int32_t *)p = rmask;
968 WRITE_MB();
969
970 p = (q += scanspan);
971 height--;
972 }
973 }
974 SFBMODE(sfb, MODE_SIMPLE);
975 SFBROP(sfb, 3); /* ROP_COPY */
976
977 rc->rc_bits ^= RC_CURSOR;
978 }
979 #endif
980
981 /*
982 * Actually write a string to the frame buffer.
983 */
984 static void
985 sfb_putchar(id, row, col, uc, attr)
986 void *id;
987 int row, col;
988 u_int uc;
989 long attr;
990 {
991 struct rasops_info *ri = id;
992 caddr_t sfb, p;
993 int scanspan, height, width, align, x, y;
994 u_int32_t lmask, rmask, glyph;
995 u_int8_t *g;
996 int fg, bg;
997
998 x = col * ri->ri_font->fontwidth;
999 y = row * ri->ri_font->fontheight;
1000 scanspan = ri->ri_stride;
1001 height = ri->ri_font->fontheight;
1002 uc -= ri->ri_font->firstchar;
1003 g = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
1004
1005 p = ri->ri_bits + y * scanspan + x;
1006 align = (long)p & SFBALIGNMASK;
1007 p -= align;
1008 width = ri->ri_font->fontwidth + align;
1009 lmask = SFBSTIPPLEALL1 << align;
1010 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
1011 sfb = ri->ri_hw;
1012
1013 SFBMODE(sfb, MODE_OPAQUESTIPPLE);
1014 SFBPLANEMASK(sfb, ~0);
1015 rasops_unpack_attr(attr, &fg, &bg, 0);
1016 SFBFG(sfb, fg * 0x01010101);
1017 SFBBG(sfb, bg * 0x01010101);
1018 if (width <= SFBSTIPPLEBITS) {
1019 lmask = lmask & rmask;
1020 while (height > 0) {
1021 glyph = g[0];
1022 if (ri->ri_font->fontwidth > 8)
1023 glyph |= (g[1] << 8);
1024 SFBPIXELMASK(sfb, lmask);
1025 SFBADDRESS(sfb, (long)p);
1026 SFBSTART(sfb, glyph << align);
1027 p += scanspan;
1028 g += ri->ri_font->stride;
1029 height--;
1030 }
1031 }
1032 else {
1033 caddr_t q = p;
1034 while (height > 0) {
1035 glyph = *g;
1036 SFBPIXELMASK(sfb, lmask);
1037 WRITE_MB();
1038 *(u_int32_t *)p = glyph << align;
1039 WRITE_MB();
1040 p += SFBSTIPPLEBYTESDONE;
1041 SFBPIXELMASK(sfb, rmask);
1042 WRITE_MB();
1043 *(u_int32_t *)p = glyph >> (-width & SFBSTIPPLEBITMASK);
1044 WRITE_MB();
1045
1046 p = (q += scanspan);
1047 g += 1;
1048 height--;
1049 }
1050 }
1051 SFBMODE(sfb, MODE_SIMPLE);
1052 SFBPIXELMASK(sfb, ~0); /* entire pixel */
1053 }
1054
1055 #if 0
1056 /*
1057 * Copy characters in a line.
1058 */
1059 static void
1060 sfb_copycols(id, row, srccol, dstcol, ncols)
1061 void *id;
1062 int row, srccol, dstcol, ncols;
1063 {
1064 struct rcons *rc = id;
1065 struct raster *rap = rc->rc_sp;
1066 caddr_t sp, dp, basex, sfb;
1067 int scanspan, height, width, aligns, alignd, shift, w, y;
1068 u_int32_t lmasks, rmasks, lmaskd, rmaskd;
1069
1070 scanspan = rap->linelongs * 4;
1071 y = rc->rc_yorigin + rc->rc_font->height * row;
1072 basex = (caddr_t)rap->pixels + y * scanspan + rc->rc_xorigin;
1073 height = rc->rc_font->height;
1074 w = rc->rc_font->width * ncols;
1075
1076 sp = basex + rc->rc_font->width * srccol;
1077 aligns = (long)sp & SFBALIGNMASK;
1078 dp = basex + rc->rc_font->width * dstcol;
1079 alignd = (long)dp & SFBALIGNMASK;
1080 sfb = rap->data;
1081
1082 SFBMODE(sfb, MODE_COPY);
1083 SFBPLANEMASK(sfb, ~0);
1084
1085 /* copy forward (left-to-right) */
1086 if (dstcol < srccol || srccol + ncols < dstcol) {
1087 caddr_t sq, dq;
1088
1089 shift = alignd - aligns;
1090 if (shift < 0) {
1091 dp -= 8; /* prime left edge */
1092 alignd += 8; /* compensate it */
1093 width = aligns + w + 8; /* adjust total width */
1094 shift = 8 + shift; /* enforce right rotate */
1095 }
1096 else if (shift > 0)
1097 width = aligns + w + 8; /* enfore drain at right edge */
1098
1099 lmasks = SFBCOPYALL1 << aligns;
1100 rmasks = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
1101 lmaskd = SFBCOPYALL1 << alignd;
1102 rmaskd = SFBCOPYALL1 >> (-(w + alignd) & SFBCOPYBITMASK);
1103
1104 if (w + alignd <= SFBCOPYBITS)
1105 goto singlewrite;
1106
1107 SFBPIXELSHIFT(sfb, shift);
1108 w = width;
1109 sq = sp;
1110 dq = dp;
1111 while (height > 0) {
1112 *(u_int32_t *)sp = lmasks;
1113 WRITE_MB();
1114 *(u_int32_t *)dp = lmaskd;
1115 WRITE_MB();
1116 width -= 2 * SFBCOPYBITS;
1117 while (width > 0) {
1118 sp += SFBCOPYBYTESDONE;
1119 dp += SFBCOPYBYTESDONE;
1120 *(u_int32_t *)sp = SFBCOPYALL1;
1121 WRITE_MB();
1122 *(u_int32_t *)dp = SFBCOPYALL1;
1123 WRITE_MB();
1124 width -= SFBCOPYBITS;
1125 }
1126 sp += SFBCOPYBYTESDONE;
1127 dp += SFBCOPYBYTESDONE;
1128 *(u_int32_t *)sp = rmasks;
1129 WRITE_MB();
1130 *(u_int32_t *)dp = rmaskd;
1131 WRITE_MB();
1132
1133 sp = (sq += scanspan);
1134 dp = (dq += scanspan);
1135 width = w;
1136 height--;
1137 }
1138 }
1139 /* copy backward (right-to-left) */
1140 else {
1141 caddr_t sq, dq;
1142
1143 shift = alignd - aligns;
1144 if (shift > 0) {
1145 shift = shift - 8;
1146 w += 8;
1147 }
1148 width = w + aligns;
1149 lmasks = SFBCOPYALL1 << aligns;
1150 rmasks = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
1151 lmaskd = SFBCOPYALL1 << alignd;
1152 rmaskd = SFBCOPYALL1 >> (-(w + alignd) & SFBCOPYBITMASK);
1153
1154 if (w + alignd <= SFBCOPYBITS)
1155 goto singlewrite;
1156
1157 SFBPIXELSHIFT(sfb, shift);
1158 w = width;
1159 sq = (sp += width);
1160 dq = (dp += width);
1161 while (height > 0) {
1162 *(u_int32_t *)sp = rmasks;
1163 WRITE_MB();
1164 *(u_int32_t *)dp = rmaskd;
1165 WRITE_MB();
1166 width -= 2 * SFBCOPYBITS;
1167 while (width > 0) {
1168 sp -= SFBCOPYBYTESDONE;
1169 dp -= SFBCOPYBYTESDONE;
1170 *(u_int32_t *)sp = SFBCOPYALL1;
1171 WRITE_MB();
1172 *(u_int32_t *)dp = SFBCOPYALL1;
1173 WRITE_MB();
1174 width -= SFBCOPYBITS;
1175 }
1176 sp -= SFBCOPYBYTESDONE;
1177 dp -= SFBCOPYBYTESDONE;
1178 *(u_int32_t *)sp = lmasks;
1179 WRITE_MB();
1180 *(u_int32_t *)dp = lmaskd;
1181 WRITE_MB();
1182
1183 sp = (sq += scanspan);
1184 dp = (dq += scanspan);
1185 width = w;
1186 height--;
1187 }
1188 }
1189 SFBMODE(sfb, MODE_SIMPLE);
1190 SFBPIXELSHIFT(sfb, 0);
1191 return;
1192
1193 singlewrite:
1194 SFBPIXELSHIFT(sfb, shift);
1195 lmasks = lmasks & rmasks;
1196 lmaskd = lmaskd & rmaskd;
1197 while (height > 0) {
1198 *(u_int32_t *)sp = lmasks;
1199 WRITE_MB();
1200 *(u_int32_t *)dp = lmaskd;
1201 WRITE_MB();
1202 sp += scanspan;
1203 dp += scanspan;
1204 height--;
1205 }
1206 SFBMODE(sfb, MODE_SIMPLE);
1207 SFBPIXELSHIFT(sfb, 0);
1208 }
1209 #endif
1210
1211 #if 0
1212 /*
1213 * Clear characters in a line.
1214 */
1215 static void
1216 sfb_erasecols(id, row, startcol, ncols, attr)
1217 void *id;
1218 int row, startcol, ncols;
1219 long attr;
1220 {
1221 struct rcons *rc = id;
1222 struct raster *rap = rc->rc_sp;
1223 caddr_t sfb, p;
1224 int scanspan, startx, height, width, align, w, y;
1225 u_int32_t lmask, rmask;
1226
1227 scanspan = rap->linelongs * 4;
1228 y = rc->rc_yorigin + rc->rc_font->height * row;
1229 startx = rc->rc_xorigin + rc->rc_font->width * startcol;
1230 height = rc->rc_font->height;
1231 w = rc->rc_font->width * ncols;
1232
1233 p = (caddr_t)rap->pixels + y * scanspan + startx;
1234 align = (long)p & SFBALIGNMASK;
1235 p -= align;
1236 width = w + align;
1237 lmask = SFBSTIPPLEALL1 << align;
1238 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
1239 sfb = rap->data;
1240
1241 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
1242 SFBPLANEMASK(sfb, ~0);
1243 SFBFG(sfb, 0); /* fill with bg color */
1244 if (width <= SFBSTIPPLEBITS) {
1245 lmask = lmask & rmask;
1246 while (height > 0) {
1247 SFBADDRESS(sfb, (long)p);
1248 SFBSTART(sfb, lmask);
1249 p += scanspan;
1250 height--;
1251 }
1252 }
1253 else {
1254 caddr_t q = p;
1255 while (height > 0) {
1256 *(u_int32_t *)p = lmask;
1257 WRITE_MB();
1258 width -= 2 * SFBSTIPPLEBITS;
1259 while (width > 0) {
1260 p += SFBSTIPPLEBYTESDONE;
1261 *(u_int32_t *)p = SFBSTIPPLEALL1;
1262 WRITE_MB();
1263 width -= SFBSTIPPLEBITS;
1264 }
1265 p += SFBSTIPPLEBYTESDONE;
1266 *(u_int32_t *)p = rmask;
1267 WRITE_MB();
1268
1269 p = (q += scanspan);
1270 width = w + align;
1271 height--;
1272 }
1273 }
1274 SFBMODE(sfb, MODE_SIMPLE);
1275 }
1276 #endif
1277
1278 /*
1279 * Copy lines.
1280 */
1281 static void
1282 sfb_copyrows(id, srcrow, dstrow, nrows)
1283 void *id;
1284 int srcrow, dstrow, nrows;
1285 {
1286 struct rasops_info *ri = id;
1287 caddr_t sfb, p;
1288 int scanspan, offset, srcy, height, width, align, w;
1289 u_int32_t lmask, rmask;
1290
1291 scanspan = ri->ri_stride;
1292 height = ri->ri_font->fontheight * nrows;
1293 offset = (dstrow - srcrow) * ri->ri_yscale;
1294 srcy = ri->ri_font->fontheight * srcrow;
1295 if (srcrow < dstrow && srcrow + nrows > dstrow) {
1296 scanspan = -scanspan;
1297 srcy += height;
1298 }
1299
1300 p = (caddr_t)(ri->ri_bits + srcy * ri->ri_stride);
1301 align = (long)p & SFBALIGNMASK;
1302 p -= align;
1303 w = ri->ri_emuwidth;
1304 width = w + align;
1305 lmask = SFBCOPYALL1 << align;
1306 rmask = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
1307 sfb = ri->ri_hw;
1308
1309 SFBMODE(sfb, MODE_COPY);
1310 SFBPLANEMASK(sfb, ~0);
1311 SFBPIXELSHIFT(sfb, 0);
1312 if (width <= SFBCOPYBITS) {
1313 /* never happens */;
1314 }
1315 else {
1316 caddr_t q = p;
1317 while (height > 0) {
1318 *(u_int32_t *)p = lmask;
1319 *(u_int32_t *)(p + offset) = lmask;
1320 width -= 2 * SFBCOPYBITS;
1321 while (width > 0) {
1322 p += SFBCOPYBYTESDONE;
1323 *(u_int32_t *)p = SFBCOPYALL1;
1324 *(u_int32_t *)(p + offset) = SFBCOPYALL1;
1325 width -= SFBCOPYBITS;
1326 }
1327 p += SFBCOPYBYTESDONE;
1328 *(u_int32_t *)p = rmask;
1329 *(u_int32_t *)(p + offset) = rmask;
1330
1331 p = (q += scanspan);
1332 width = w + align;
1333 height--;
1334 }
1335 }
1336 SFBMODE(sfb, MODE_SIMPLE);
1337 }
1338
1339 #if 0
1340 /*
1341 * Erase lines.
1342 */
1343 void
1344 sfb_eraserows(id, startrow, nrows, attr)
1345 void *id;
1346 int startrow, nrows;
1347 long attr;
1348 {
1349 struct rcons *rc = id;
1350 struct raster *rap = rc->rc_sp;
1351 caddr_t sfb, p;
1352 int scanspan, starty, height, width, align, w;
1353 u_int32_t lmask, rmask;
1354
1355 scanspan = rap->linelongs * 4;
1356 starty = rc->rc_yorigin + rc->rc_font->height * startrow;
1357 height = rc->rc_font->height * nrows;
1358
1359 p = (caddr_t)rap->pixels + starty * scanspan + rc->rc_xorigin;
1360 align = (long)p & SFBALIGNMASK;
1361 p -= align;
1362 w = rc->rc_font->width * rc->rc_maxcol;
1363 width = w + align;
1364 lmask = SFBSTIPPLEALL1 << align;
1365 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
1366 sfb = rap->data;
1367
1368 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
1369 SFBPLANEMASK(sfb, ~0);
1370 SFBFG(sfb, 0); /* fill with bg color */
1371 if (width <= SFBSTIPPLEBITS) {
1372 /* never happens */;
1373 }
1374 else {
1375 caddr_t q = p;
1376 while (height > 0) {
1377 *(u_int32_t *)p = lmask;
1378 WRITE_MB();
1379 width -= 2 * SFBSTIPPLEBITS;
1380 while (width > 0) {
1381 p += SFBSTIPPLEBYTESDONE;
1382 *(u_int32_t *)p = SFBSTIPPLEALL1;
1383 WRITE_MB();
1384 width -= SFBSTIPPLEBITS;
1385 }
1386 p += SFBSTIPPLEBYTESDONE;
1387 *(u_int32_t *)p = rmask;
1388 WRITE_MB();
1389
1390 p = (q += scanspan);
1391 width = w + align;
1392 height--;
1393 }
1394 }
1395 SFBMODE(sfb, MODE_SIMPLE);
1396 }
1397 #endif
1398