sfb.c revision 1.25 1 /* $NetBSD: sfb.c,v 1.25 1999/11/05 03:28:40 nisimura 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.25 1999/11/05 03:28:40 nisimura Exp $");
36
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/kernel.h>
40 #include <sys/device.h>
41 #include <sys/malloc.h>
42 #include <sys/buf.h>
43 #include <sys/ioctl.h>
44 #include <vm/vm.h>
45
46 #include <machine/bus.h>
47 #include <machine/intr.h>
48
49 #include <dev/rcons/raster.h>
50 #include <dev/wscons/wsconsio.h>
51 #include <dev/wscons/wscons_raster.h>
52 #include <dev/wscons/wsdisplayvar.h>
53
54 #include <dev/tc/tcvar.h>
55 #include <dev/ic/bt459reg.h>
56 #include <dev/tc/sfbreg.h>
57
58 #include <uvm/uvm_extern.h>
59
60 #if defined(pmax)
61 #define machine_btop(x) mips_btop(x)
62 #define MACHINE_KSEG0_TO_PHYS(x) MIPS_KSEG1_TO_PHYS(x)
63 #endif
64
65 #if defined(__alpha__) || defined(alpha)
66 #define machine_btop(x) alpha_btop(x)
67 #define MACHINE_KSEG0_TO_PHYS(x) ALPHA_K0SEG_TO_PHYS(x)
68 #endif
69
70 /*
71 * N.B., Bt459 registers are 8bit width. Some of TC framebuffers have
72 * obscure register layout such as 2nd and 3rd Bt459 registers are
73 * adjacent each other in a word, i.e.,
74 * struct bt459triplet {
75 * struct {
76 * u_int8_t u0;
77 * u_int8_t u1;
78 * u_int8_t u2;
79 * unsigned :8;
80 * } bt_lo;
81 * struct {
82 *
83 * Although HX has single Bt459, 32bit R/W can be done w/o any trouble.
84 * struct bt459reg {
85 * u_int32_t bt_lo;
86 * u_int32_t bt_hi;
87 * u_int32_t bt_reg;
88 * u_int32_t bt_cmap;
89 * };
90 *
91 */
92
93 /* Bt459 hardware registers */
94 #define bt_lo 0
95 #define bt_hi 1
96 #define bt_reg 2
97 #define bt_cmap 3
98
99 #define REG(base, index) *((u_int32_t *)(base) + (index))
100 #define SELECT(vdac, regno) do { \
101 REG(vdac, bt_lo) = ((regno) & 0x00ff); \
102 REG(vdac, bt_hi) = ((regno) & 0x0f00) >> 8; \
103 tc_wmb(); \
104 } while (0)
105
106 struct fb_devconfig {
107 vaddr_t dc_vaddr; /* memory space virtual base address */
108 paddr_t dc_paddr; /* memory space physical base address */
109 vsize_t dc_size; /* size of slot memory */
110 int dc_wid; /* width of frame buffer */
111 int dc_ht; /* height of frame buffer */
112 int dc_depth; /* depth, bits per pixel */
113 int dc_rowbytes; /* bytes in a FB scan line */
114 vaddr_t dc_videobase; /* base of flat frame buffer */
115 struct raster dc_raster; /* raster description */
116 struct rcons dc_rcons; /* raster blitter control info */
117 int dc_blanked; /* currently has video disabled */
118 };
119
120 struct hwcmap256 {
121 #define CMAP_SIZE 256 /* 256 R/G/B entries */
122 u_int8_t r[CMAP_SIZE];
123 u_int8_t g[CMAP_SIZE];
124 u_int8_t b[CMAP_SIZE];
125 };
126
127 struct hwcursor64 {
128 struct wsdisplay_curpos cc_pos;
129 struct wsdisplay_curpos cc_hot;
130 struct wsdisplay_curpos cc_size;
131 struct wsdisplay_curpos cc_magic;
132 #define CURSOR_MAX_SIZE 64
133 u_int8_t cc_color[6];
134 u_int64_t cc_image[64 + 64];
135 };
136
137 struct sfb_softc {
138 struct device sc_dev;
139 struct fb_devconfig *sc_dc; /* device configuration */
140 struct hwcmap256 sc_cmap; /* software copy of colormap */
141 struct hwcursor64 sc_cursor; /* software copy of cursor */
142 int sc_curenb; /* cursor sprite enabled */
143 int sc_changed; /* need update of colormap */
144 #define DATA_ENB_CHANGED 0x01 /* cursor enable changed */
145 #define DATA_CURCMAP_CHANGED 0x02 /* cursor colormap changed */
146 #define DATA_CURSHAPE_CHANGED 0x04 /* cursor size, image, mask changed */
147 #define DATA_CMAP_CHANGED 0x08 /* colormap changed */
148 #define DATA_ALL_CHANGED 0x0f
149 int nscreens;
150 };
151
152 #define HX_MAGIC_X 368
153 #define HX_MAGIC_Y 38
154
155 int sfbmatch __P((struct device *, struct cfdata *, void *));
156 void sfbattach __P((struct device *, struct device *, void *));
157
158 struct cfattach sfb_ca = {
159 sizeof(struct sfb_softc), sfbmatch, sfbattach,
160 };
161
162 void sfb_getdevconfig __P((tc_addr_t, struct fb_devconfig *));
163 struct fb_devconfig sfb_console_dc;
164 tc_addr_t sfb_consaddr;
165
166 void sfb_cursor __P((void *, int, int, int));
167 int sfb_mapchar __P((void *, int, unsigned int *));
168 void sfb_putchar __P((void *, int, int, u_int, long));
169 void sfb_copycols __P((void *, int, int, int, int));
170 void sfb_erasecols __P((void *, int, int, int, long));
171 void sfb_copyrows __P((void *, int, int, int));
172 void sfb_eraserows __P((void *, int, int, long));
173 int sfb_alloc_attr __P((void *, int, int, int, long *));
174
175 struct wsdisplay_emulops sfb_emulops = {
176 sfb_cursor, /* could use hardware cursor; punt */
177 sfb_mapchar,
178 sfb_putchar,
179 sfb_copycols,
180 sfb_erasecols,
181 sfb_copyrows,
182 sfb_eraserows,
183 sfb_alloc_attr
184 };
185
186 struct wsscreen_descr sfb_stdscreen = {
187 "std", 0, 0,
188 &sfb_emulops,
189 0, 0,
190 WSSCREEN_REVERSE
191 };
192
193 const struct wsscreen_descr *_sfb_scrlist[] = {
194 &sfb_stdscreen,
195 };
196
197 struct wsscreen_list sfb_screenlist = {
198 sizeof(_sfb_scrlist) / sizeof(struct wsscreen_descr *), _sfb_scrlist
199 };
200
201 int sfbioctl __P((void *, u_long, caddr_t, int, struct proc *));
202 int sfbmmap __P((void *, off_t, int));
203
204 int sfb_alloc_screen __P((void *, const struct wsscreen_descr *,
205 void **, int *, int *, long *));
206 void sfb_free_screen __P((void *, void *));
207 void sfb_show_screen __P((void *, void *));
208
209 struct wsdisplay_accessops sfb_accessops = {
210 sfbioctl,
211 sfbmmap,
212 sfb_alloc_screen,
213 sfb_free_screen,
214 sfb_show_screen,
215 0 /* load_font */
216 };
217
218 int sfb_cnattach __P((tc_addr_t));
219 int sfbintr __P((void *));
220 void sfbinit __P((struct fb_devconfig *));
221
222 static int get_cmap __P((struct sfb_softc *, struct wsdisplay_cmap *));
223 static int set_cmap __P((struct sfb_softc *, struct wsdisplay_cmap *));
224 static int set_cursor __P((struct sfb_softc *, struct wsdisplay_cursor *));
225 static int get_cursor __P((struct sfb_softc *, struct wsdisplay_cursor *));
226 static void set_curpos __P((struct sfb_softc *, struct wsdisplay_curpos *));
227 static void bt459_set_curpos __P((struct sfb_softc *));
228
229
230 /*
231 * Compose 2 bit/pixel cursor image. Bit order will be reversed.
232 * M M M M I I I I M I M I M I M I
233 * [ before ] [ after ]
234 * 3 2 1 0 3 2 1 0 0 0 1 1 2 2 3 3
235 * 7 6 5 4 7 6 5 4 4 4 5 5 6 6 7 7
236 */
237 const static u_int8_t shuffle[256] = {
238 0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54,
239 0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55,
240 0x80, 0xc0, 0x90, 0xd0, 0x84, 0xc4, 0x94, 0xd4,
241 0x81, 0xc1, 0x91, 0xd1, 0x85, 0xc5, 0x95, 0xd5,
242 0x20, 0x60, 0x30, 0x70, 0x24, 0x64, 0x34, 0x74,
243 0x21, 0x61, 0x31, 0x71, 0x25, 0x65, 0x35, 0x75,
244 0xa0, 0xe0, 0xb0, 0xf0, 0xa4, 0xe4, 0xb4, 0xf4,
245 0xa1, 0xe1, 0xb1, 0xf1, 0xa5, 0xe5, 0xb5, 0xf5,
246 0x08, 0x48, 0x18, 0x58, 0x0c, 0x4c, 0x1c, 0x5c,
247 0x09, 0x49, 0x19, 0x59, 0x0d, 0x4d, 0x1d, 0x5d,
248 0x88, 0xc8, 0x98, 0xd8, 0x8c, 0xcc, 0x9c, 0xdc,
249 0x89, 0xc9, 0x99, 0xd9, 0x8d, 0xcd, 0x9d, 0xdd,
250 0x28, 0x68, 0x38, 0x78, 0x2c, 0x6c, 0x3c, 0x7c,
251 0x29, 0x69, 0x39, 0x79, 0x2d, 0x6d, 0x3d, 0x7d,
252 0xa8, 0xe8, 0xb8, 0xf8, 0xac, 0xec, 0xbc, 0xfc,
253 0xa9, 0xe9, 0xb9, 0xf9, 0xad, 0xed, 0xbd, 0xfd,
254 0x02, 0x42, 0x12, 0x52, 0x06, 0x46, 0x16, 0x56,
255 0x03, 0x43, 0x13, 0x53, 0x07, 0x47, 0x17, 0x57,
256 0x82, 0xc2, 0x92, 0xd2, 0x86, 0xc6, 0x96, 0xd6,
257 0x83, 0xc3, 0x93, 0xd3, 0x87, 0xc7, 0x97, 0xd7,
258 0x22, 0x62, 0x32, 0x72, 0x26, 0x66, 0x36, 0x76,
259 0x23, 0x63, 0x33, 0x73, 0x27, 0x67, 0x37, 0x77,
260 0xa2, 0xe2, 0xb2, 0xf2, 0xa6, 0xe6, 0xb6, 0xf6,
261 0xa3, 0xe3, 0xb3, 0xf3, 0xa7, 0xe7, 0xb7, 0xf7,
262 0x0a, 0x4a, 0x1a, 0x5a, 0x0e, 0x4e, 0x1e, 0x5e,
263 0x0b, 0x4b, 0x1b, 0x5b, 0x0f, 0x4f, 0x1f, 0x5f,
264 0x8a, 0xca, 0x9a, 0xda, 0x8e, 0xce, 0x9e, 0xde,
265 0x8b, 0xcb, 0x9b, 0xdb, 0x8f, 0xcf, 0x9f, 0xdf,
266 0x2a, 0x6a, 0x3a, 0x7a, 0x2e, 0x6e, 0x3e, 0x7e,
267 0x2b, 0x6b, 0x3b, 0x7b, 0x2f, 0x6f, 0x3f, 0x7f,
268 0xaa, 0xea, 0xba, 0xfa, 0xae, 0xee, 0xbe, 0xfe,
269 0xab, 0xeb, 0xbb, 0xfb, 0xaf, 0xef, 0xbf, 0xff,
270 };
271
272 int
273 sfbmatch(parent, match, aux)
274 struct device *parent;
275 struct cfdata *match;
276 void *aux;
277 {
278 struct tc_attach_args *ta = aux;
279
280 #if 1
281 if (strncmp("PMAGB-BA", ta->ta_modname, TC_ROM_LLEN) != 0
282 && strncmp("PMAGD", ta->ta_modname, 5))
283 return (0);
284 #else
285 if (strncmp("PMAGB-BA", ta->ta_modname, TC_ROM_LLEN) != 0)
286 return (0);
287 #endif
288 return (1);
289 }
290
291 void
292 sfb_getdevconfig(dense_addr, dc)
293 tc_addr_t dense_addr;
294 struct fb_devconfig *dc;
295 {
296 struct raster *rap;
297 struct rcons *rcp;
298 caddr_t sfbasic;
299 int i, hsetup, vsetup, vbase;
300
301 dc->dc_vaddr = dense_addr;
302 dc->dc_paddr = MACHINE_KSEG0_TO_PHYS(dc->dc_vaddr);
303
304 sfbasic = (caddr_t)(dc->dc_vaddr + SFB_ASIC_OFFSET);
305 hsetup = *(u_int32_t *)(sfbasic + SFB_ASIC_VIDEO_HSETUP);
306 vsetup = *(u_int32_t *)(sfbasic + SFB_ASIC_VIDEO_VSETUP);
307 *(u_int32_t *)(sfbasic + SFB_ASIC_VIDEO_BASE) = vbase = 1;
308
309 dc->dc_wid = (hsetup & 0x1ff) << 2;
310 dc->dc_ht = (vsetup & 0x7ff);
311 dc->dc_depth = 8;
312 dc->dc_rowbytes = dc->dc_wid * (dc->dc_depth / 8);
313 dc->dc_videobase = dc->dc_vaddr + SFB_FB_OFFSET + vbase * 4096;
314 dc->dc_blanked = 0;
315
316 /* initialize colormap and cursor resource */
317 sfbinit(dc);
318
319 /* clear the screen */
320 for (i = 0; i < dc->dc_ht * dc->dc_rowbytes; i += sizeof(u_int32_t))
321 *(u_int32_t *)(dc->dc_videobase + i) = 0x0;
322
323 *(u_int32_t *)(sfbasic + SFB_ASIC_VIDEO_VALID) = 1;
324
325 /* initialize the raster */
326 rap = &dc->dc_raster;
327 rap->width = dc->dc_wid;
328 rap->height = dc->dc_ht;
329 rap->depth = dc->dc_depth;
330 rap->linelongs = dc->dc_rowbytes / sizeof(u_int32_t);
331 rap->pixels = (u_int32_t *)dc->dc_videobase;
332 rap->data = sfbasic;
333
334 /* initialize the raster console blitter */
335 rcp = &dc->dc_rcons;
336 rcp->rc_sp = rap;
337 rcp->rc_crow = rcp->rc_ccol = -1;
338 rcp->rc_crowp = &rcp->rc_crow;
339 rcp->rc_ccolp = &rcp->rc_ccol;
340 rcons_init(rcp, 34, 80);
341
342 sfb_stdscreen.nrows = dc->dc_rcons.rc_maxrow;
343 sfb_stdscreen.ncols = dc->dc_rcons.rc_maxcol;
344 }
345
346 void
347 sfbattach(parent, self, aux)
348 struct device *parent, *self;
349 void *aux;
350 {
351 struct sfb_softc *sc = (struct sfb_softc *)self;
352 struct tc_attach_args *ta = aux;
353 struct wsemuldisplaydev_attach_args waa;
354 struct hwcmap256 *cm;
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 sfb_getdevconfig(ta->ta_addr, sc->sc_dc);
367 }
368 printf(": %d x %d, %dbpp\n", sc->sc_dc->dc_wid, sc->sc_dc->dc_ht,
369 sc->sc_dc->dc_depth);
370
371 cm = &sc->sc_cmap;
372 memset(cm, 255, sizeof(struct hwcmap256)); /* XXX */
373 cm->r[0] = cm->g[0] = cm->b[0] = 0; /* XXX */
374
375 sc->sc_cursor.cc_magic.x = HX_MAGIC_X;
376 sc->sc_cursor.cc_magic.y = HX_MAGIC_Y;
377
378 tc_intr_establish(parent, ta->ta_cookie, TC_IPL_TTY, sfbintr, sc);
379
380 sfbasic = (caddr_t)(sc->sc_dc->dc_vaddr + SFB_ASIC_OFFSET);
381 *(u_int32_t *)(sfbasic + SFB_ASIC_CLEAR_INTR) = 0;
382 *(u_int32_t *)(sfbasic + SFB_ASIC_ENABLE_INTR) = 1;
383
384 waa.console = console;
385 waa.scrdata = &sfb_screenlist;
386 waa.accessops = &sfb_accessops;
387 waa.accesscookie = sc;
388
389 config_found(self, &waa, wsemuldisplaydevprint);
390 }
391
392 int
393 sfbioctl(v, cmd, data, flag, p)
394 void *v;
395 u_long cmd;
396 caddr_t data;
397 int flag;
398 struct proc *p;
399 {
400 struct sfb_softc *sc = v;
401 struct fb_devconfig *dc = sc->sc_dc;
402 int turnoff;
403
404 switch (cmd) {
405 case WSDISPLAYIO_GTYPE:
406 *(u_int *)data = WSDISPLAY_TYPE_SFB;
407 return (0);
408
409 case WSDISPLAYIO_GINFO:
410 #define wsd_fbip ((struct wsdisplay_fbinfo *)data)
411 wsd_fbip->height = sc->sc_dc->dc_ht;
412 wsd_fbip->width = sc->sc_dc->dc_wid;
413 wsd_fbip->depth = sc->sc_dc->dc_depth;
414 wsd_fbip->cmsize = CMAP_SIZE;
415 #undef fbt
416 return (0);
417
418 case WSDISPLAYIO_GETCMAP:
419 return get_cmap(sc, (struct wsdisplay_cmap *)data);
420
421 case WSDISPLAYIO_PUTCMAP:
422 return set_cmap(sc, (struct wsdisplay_cmap *)data);
423
424 case WSDISPLAYIO_SVIDEO:
425 turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF;
426 if ((dc->dc_blanked == 0) ^ turnoff) {
427 dc->dc_blanked = turnoff;
428 #if 0 /* XXX later XXX */
429 To turn off, assign value 0 in ASIC_VIDEO_VALID register.
430 #endif /* XXX XXX XXX */
431 }
432 return (0);
433
434 case WSDISPLAYIO_GVIDEO:
435 *(u_int *)data = dc->dc_blanked ?
436 WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON;
437 return (0);
438
439 case WSDISPLAYIO_GCURPOS:
440 *(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos;
441 return (0);
442
443 case WSDISPLAYIO_SCURPOS:
444 set_curpos(sc, (struct wsdisplay_curpos *)data);
445 bt459_set_curpos(sc);
446 return (0);
447
448 case WSDISPLAYIO_GCURMAX:
449 ((struct wsdisplay_curpos *)data)->x =
450 ((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE;
451 return (0);
452
453 case WSDISPLAYIO_GCURSOR:
454 return get_cursor(sc, (struct wsdisplay_cursor *)data);
455
456 case WSDISPLAYIO_SCURSOR:
457 return set_cursor(sc, (struct wsdisplay_cursor *)data);
458 }
459 return ENOTTY;
460 }
461
462 int
463 sfbmmap(v, offset, prot)
464 void *v;
465 off_t offset;
466 int prot;
467 {
468 struct sfb_softc *sc = v;
469
470 if (offset >= SFB_SIZE || offset < 0)
471 return (-1);
472 return machine_btop(sc->sc_dc->dc_paddr + offset);
473 }
474
475 int
476 sfb_alloc_screen(v, type, cookiep, curxp, curyp, attrp)
477 void *v;
478 const struct wsscreen_descr *type;
479 void **cookiep;
480 int *curxp, *curyp;
481 long *attrp;
482 {
483 struct sfb_softc *sc = v;
484 long defattr;
485
486 if (sc->nscreens > 0)
487 return (ENOMEM);
488
489 *cookiep = &sc->sc_dc->dc_rcons; /* one and only for now */
490 *curxp = 0;
491 *curyp = 0;
492 sfb_alloc_attr(&sc->sc_dc->dc_rcons, 0, 0, 0, &defattr);
493 *attrp = defattr;
494 sc->nscreens++;
495 return (0);
496 }
497
498 void
499 sfb_free_screen(v, cookie)
500 void *v;
501 void *cookie;
502 {
503 struct sfb_softc *sc = v;
504
505 if (sc->sc_dc == &sfb_console_dc)
506 panic("sfb_free_screen: console");
507
508 sc->nscreens--;
509 }
510
511 void
512 sfb_show_screen(v, cookie)
513 void *v;
514 void *cookie;
515 {
516 }
517
518 int
519 sfb_cnattach(addr)
520 tc_addr_t addr;
521 {
522 struct fb_devconfig *dcp = &sfb_console_dc;
523 long defattr;
524
525 sfb_getdevconfig(addr, dcp);
526
527 sfb_alloc_attr(&dcp->dc_rcons, 0, 0, 0, &defattr);
528
529 wsdisplay_cnattach(&sfb_stdscreen, &dcp->dc_rcons,
530 0, 0, defattr);
531 sfb_consaddr = addr;
532 return(0);
533 }
534
535 int
536 sfbintr(arg)
537 void *arg;
538 {
539 struct sfb_softc *sc = arg;
540 caddr_t sfbbase = (caddr_t)sc->sc_dc->dc_vaddr;
541 caddr_t sfbasic = sfbbase + SFB_ASIC_OFFSET;
542 caddr_t vdac;
543 int v;
544
545 *(u_int32_t *)(sfbasic + SFB_ASIC_CLEAR_INTR) = 0;
546 /* *(u_int32_t *)(sfbasic + SFB_ASIC_ENABLE_INTR) = 1; */
547
548 if (sc->sc_changed == 0)
549 return (1);
550
551 vdac = (void *)(sfbbase + SFB_RAMDAC_OFFSET);
552 v = sc->sc_changed;
553 sc->sc_changed = 0;
554
555 if (v & DATA_ENB_CHANGED) {
556 SELECT(vdac, BT459_REG_CCR);
557 REG(vdac, bt_reg) = (sc->sc_curenb) ? 0xc0 : 0x00;
558 }
559 if (v & DATA_CURCMAP_CHANGED) {
560 u_int8_t *cp = sc->sc_cursor.cc_color;
561
562 SELECT(vdac, BT459_REG_CCOLOR_2);
563 REG(vdac, bt_reg) = cp[1]; tc_wmb();
564 REG(vdac, bt_reg) = cp[3]; tc_wmb();
565 REG(vdac, bt_reg) = cp[5]; tc_wmb();
566
567 REG(vdac, bt_reg) = cp[0]; tc_wmb();
568 REG(vdac, bt_reg) = cp[2]; tc_wmb();
569 REG(vdac, bt_reg) = cp[4]; tc_wmb();
570 }
571 if (v & DATA_CURSHAPE_CHANGED) {
572 u_int8_t *ip, *mp, img, msk;
573 u_int8_t u;
574 int bcnt;
575
576 ip = (u_int8_t *)sc->sc_cursor.cc_image;
577 mp = (u_int8_t *)(sc->sc_cursor.cc_image + CURSOR_MAX_SIZE);
578
579 bcnt = 0;
580 SELECT(vdac, BT459_REG_CRAM_BASE+0);
581 /* 64 pixel scan line is consisted with 16 byte cursor ram */
582 while (bcnt < sc->sc_cursor.cc_size.y * 16) {
583 /* pad right half 32 pixel when smaller than 33 */
584 if ((bcnt & 0x8) && sc->sc_cursor.cc_size.x < 33) {
585 REG(vdac, bt_reg) = 0; tc_wmb();
586 REG(vdac, bt_reg) = 0; tc_wmb();
587 }
588 else {
589 img = *ip++;
590 msk = *mp++;
591 img &= msk; /* cookie off image */
592 u = (msk & 0x0f) << 4 | (img & 0x0f);
593 REG(vdac, bt_reg) = shuffle[u]; tc_wmb();
594 u = (msk & 0xf0) | (img & 0xf0) >> 4;
595 REG(vdac, bt_reg) = shuffle[u]; tc_wmb();
596 }
597 bcnt += 2;
598 }
599 /* pad unoccupied scan lines */
600 while (bcnt < CURSOR_MAX_SIZE * 16) {
601 REG(vdac, bt_reg) = 0; tc_wmb();
602 REG(vdac, bt_reg) = 0; tc_wmb();
603 bcnt += 2;
604 }
605 }
606 if (v & DATA_CMAP_CHANGED) {
607 struct hwcmap256 *cm = &sc->sc_cmap;
608 int index;
609
610 SELECT(vdac, 0);
611 for (index = 0; index < CMAP_SIZE; index++) {
612 REG(vdac, bt_cmap) = cm->r[index]; tc_wmb();
613 REG(vdac, bt_cmap) = cm->g[index]; tc_wmb();
614 REG(vdac, bt_cmap) = cm->b[index]; tc_wmb();
615 }
616 }
617 return (1);
618 }
619
620 void
621 sfbinit(dc)
622 struct fb_devconfig *dc;
623 {
624 caddr_t sfbasic = (caddr_t)(dc->dc_vaddr + SFB_ASIC_OFFSET);
625 caddr_t vdac = (void *)(dc->dc_vaddr + SFB_RAMDAC_OFFSET);
626 int i;
627
628 *(u_int32_t *)(sfbasic + SFB_ASIC_VIDEO_VALID) = 0;
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_REG_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_REG_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 REG(vdac, bt_cmap) = 0; tc_wmb();
667 REG(vdac, bt_cmap) = 0; tc_wmb();
668 REG(vdac, bt_cmap) = 0; tc_wmb();
669 for (i = 1; i < CMAP_SIZE; i++) {
670 REG(vdac, bt_cmap) = 0xff; tc_wmb();
671 REG(vdac, bt_cmap) = 0xff; tc_wmb();
672 REG(vdac, bt_cmap) = 0xff; tc_wmb();
673 }
674
675 /* clear out cursor image */
676 SELECT(vdac, BT459_REG_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_REG_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 sfbbase = (caddr_t)sc->sc_dc->dc_vaddr;
837 caddr_t vdac = (void *)(sfbbase + SFB_RAMDAC_OFFSET);
838 int x, y, s;
839
840 x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x;
841 y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y;
842
843 x += sc->sc_cursor.cc_magic.x;
844 y += sc->sc_cursor.cc_magic.y;
845
846 s = spltty();
847
848 SELECT(vdac, BT459_REG_CURSOR_X_LOW);
849 REG(vdac, bt_reg) = x; tc_wmb();
850 REG(vdac, bt_reg) = x >> 8; tc_wmb();
851 REG(vdac, bt_reg) = y; tc_wmb();
852 REG(vdac, bt_reg) = y >> 8; tc_wmb();
853
854 splx(s);
855 }
856
857 #define MODE_SIMPLE 0
858 #define MODE_OPAQUESTIPPLE 1
859 #define MODE_OPAQUELINE 2
860 #define MODE_TRANSPARENTSTIPPLE 5
861 #define MODE_TRANSPARENTLINE 6
862 #define MODE_COPY 7
863
864 /* parameters for 8bpp configuration */
865 #define SFBALIGNMASK 0x7
866 #define SFBSTIPPLEALL1 0xffffffff
867 #define SFBSTIPPLEBITS 32
868 #define SFBSTIPPLEBITMASK 0x1f
869 #define SFBSTIPPLEBYTESDONE 32
870 #define SFBCOPYALL1 0xffffffff
871 #define SFBCOPYBITS 32
872 #define SFBCOPYBITMASK 0x1f
873 #define SFBCOPYBYTESDONE 32
874
875 #ifdef pmax
876 #define WRITE_MB()
877 #define BUMP(p) (p)
878 #endif
879
880 #ifdef alpha
881 #define WRITE_MB() tc_wmb()
882 #define BUMP(p) ((p) = (caddr_t)(((long)(p) + 128) & ~0x400))
883 #endif
884
885 #define SFBMODE(p, v) \
886 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_MODE) = (v))
887 #define SFBROP(p, v) \
888 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_ROP) = (v))
889 #define SFBPLANEMASK(p, v) \
890 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_PLANEMASK) = (v))
891 #define SFBPIXELMASK(p, v) \
892 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELMASK) = (v))
893 #define SFBADDRESS(p, v) \
894 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_ADDRESS) = (v))
895 #define SFBSTART(p, v) \
896 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_START) = (v))
897 #define SFBPIXELSHIFT(p, v) \
898 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELSHIFT) = (v))
899 #define SFBFG(p, v) \
900 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_FG) = (v))
901 #define SFBBG(p, v) \
902 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_BG) = (v))
903
904
905 /*
906 * Paint (or unpaint) the cursor.
907 */
908 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
978 /*
979 * Actually write a string to the frame buffer.
980 */
981 int
982 sfb_mapchar(id, uni, index)
983 void *id;
984 int uni;
985 unsigned int *index;
986 {
987 if (uni < 128) {
988 *index = uni;
989 return (5);
990 }
991 *index = ' ';
992 return (0);
993 }
994
995 /*
996 * Actually write a string to the frame buffer.
997 */
998 void
999 sfb_putchar(id, row, col, uc, attr)
1000 void *id;
1001 int row, col;
1002 u_int uc;
1003 long attr;
1004 {
1005 struct rcons *rc = id;
1006 struct raster *rap = rc->rc_sp;
1007 caddr_t sfb, p;
1008 int scanspan, height, width, align, x, y;
1009 u_int32_t lmask, rmask, glyph;
1010 u_int32_t *g;
1011
1012 if (uc < 0x20 || uc >= 127) return; /* XXX why \033 is creaping in !? XXX */
1013
1014 x = col * rc->rc_font->width + rc->rc_xorigin;
1015 y = row * rc->rc_font->height + rc->rc_yorigin;
1016 scanspan = rap->linelongs * 4;
1017 height = rc->rc_font->height;
1018 g = rc->rc_font->chars[uc].r->pixels;
1019
1020 p = (caddr_t)rap->pixels + y * scanspan + x;
1021 align = (long)p & SFBALIGNMASK;
1022 p -= align;
1023 width = rc->rc_font->width + align;
1024 lmask = SFBSTIPPLEALL1 << align;
1025 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
1026 sfb = rap->data;
1027 attr = (attr != 0) ^ (rc->rc_bits & RC_INVERT);
1028
1029 SFBMODE(sfb, MODE_OPAQUESTIPPLE);
1030 SFBPLANEMASK(sfb, ~0);
1031 SFBFG(sfb, (attr == 0) ? 0x01010101 : 0);
1032 SFBBG(sfb, (attr == 0) ? 0 : 0x01010101);
1033 if (width <= SFBSTIPPLEBITS) {
1034 lmask = lmask & rmask;
1035 while (height > 0) {
1036 glyph = *g;
1037 SFBPIXELMASK(sfb, lmask);
1038 SFBADDRESS(sfb, (long)p);
1039 SFBSTART(sfb, glyph << align);
1040 p += scanspan;
1041 g += 1;
1042 height--;
1043 }
1044 }
1045 else {
1046 caddr_t q = p;
1047 while (height > 0) {
1048 glyph = *g;
1049 SFBPIXELMASK(sfb, lmask);
1050 WRITE_MB();
1051 *(u_int32_t *)p = glyph << align;
1052 WRITE_MB();
1053 p += SFBSTIPPLEBYTESDONE;
1054 SFBPIXELMASK(sfb, rmask);
1055 WRITE_MB();
1056 *(u_int32_t *)p = glyph >> (-width & SFBSTIPPLEBITMASK);
1057 WRITE_MB();
1058
1059 p = (q += scanspan);
1060 g += 1;
1061 height--;
1062 }
1063 }
1064 SFBMODE(sfb, MODE_SIMPLE);
1065 SFBPIXELMASK(sfb, ~0); /* entire pixel */
1066 }
1067
1068 /*
1069 * Copy characters in a line.
1070 */
1071 void
1072 sfb_copycols(id, row, srccol, dstcol, ncols)
1073 void *id;
1074 int row, srccol, dstcol, ncols;
1075 {
1076 struct rcons *rc = id;
1077 struct raster *rap = rc->rc_sp;
1078 caddr_t sp, dp, basex, sfb;
1079 int scanspan, height, width, aligns, alignd, shift, w, y;
1080 u_int32_t lmasks, rmasks, lmaskd, rmaskd;
1081
1082 scanspan = rap->linelongs * 4;
1083 y = rc->rc_yorigin + rc->rc_font->height * row;
1084 basex = (caddr_t)rap->pixels + y * scanspan + rc->rc_xorigin;
1085 height = rc->rc_font->height;
1086 w = rc->rc_font->width * ncols;
1087
1088 sp = basex + rc->rc_font->width * srccol;
1089 aligns = (long)sp & SFBALIGNMASK;
1090 dp = basex + rc->rc_font->width * dstcol;
1091 alignd = (long)dp & SFBALIGNMASK;
1092
1093 shift = alignd - aligns;
1094 /* right shift; prime left edge compensating width */
1095 if (shift < 0) {
1096 dp -= 8;
1097 alignd += 8;
1098 w += 8;
1099 }
1100 /* left shift; increase width to drain right edge */
1101 else if (shift > 0) {
1102 w += 8;
1103 }
1104 width = w + aligns;
1105 lmasks = SFBSTIPPLEALL1 << aligns;
1106 rmasks = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
1107 lmaskd = SFBSTIPPLEALL1 << alignd;
1108 rmaskd = SFBSTIPPLEALL1 >> (-(w + alignd) & SFBSTIPPLEBITMASK);
1109 sfb = rap->data;
1110
1111 SFBMODE(sfb, MODE_COPY);
1112 SFBPLANEMASK(sfb, ~0);
1113 SFBPIXELSHIFT(sfb, shift);
1114 if (width <= SFBCOPYBITS) {
1115 lmasks = lmasks & rmasks;
1116 lmaskd = lmaskd & rmaskd;
1117 while (height > 0) {
1118 *(u_int32_t *)sp = lmasks;
1119 WRITE_MB();
1120 *(u_int32_t *)dp = lmaskd;
1121 WRITE_MB();
1122 sp += scanspan;
1123 dp += scanspan;
1124 height--;
1125 }
1126 }
1127 /* copy forward (left-to-right) */
1128 else if (dstcol < srccol || srccol + ncols < dstcol) {
1129 caddr_t sq = sp, dq = dp;
1130
1131 w = width;
1132 while (height > 0) {
1133 *(u_int32_t *)sp = lmasks;
1134 WRITE_MB();
1135 *(u_int32_t *)dp = lmaskd;
1136 WRITE_MB();
1137 width -= 2 * SFBCOPYBITS;
1138 while (width > 0) {
1139 sp += SFBCOPYBYTESDONE;
1140 dp += SFBCOPYBYTESDONE;
1141 *(u_int32_t *)sp = SFBCOPYALL1;
1142 WRITE_MB();
1143 *(u_int32_t *)dp = SFBCOPYALL1;
1144 WRITE_MB();
1145 width -= SFBCOPYBITS;
1146 }
1147 sp += SFBCOPYBYTESDONE;
1148 dp += SFBCOPYBYTESDONE;
1149 *(u_int32_t *)sp = rmasks;
1150 WRITE_MB();
1151 *(u_int32_t *)dp = rmaskd;
1152 WRITE_MB();
1153
1154 sp = (sq += scanspan);
1155 dp = (dq += scanspan);
1156 width = w;
1157 height--;
1158 }
1159 }
1160 /* copy backward (right-to-left) */
1161 else {
1162 caddr_t sq = (sp += width), dq = (dp += width);
1163
1164 w = width;
1165 while (height > 0) {
1166 *(u_int32_t *)sp = rmasks;
1167 WRITE_MB();
1168 *(u_int32_t *)dp = rmaskd;
1169 WRITE_MB();
1170 width -= 2 * SFBCOPYBITS;
1171 while (width > 0) {
1172 sp -= SFBCOPYBYTESDONE;
1173 dp -= SFBCOPYBYTESDONE;
1174 *(u_int32_t *)sp = SFBCOPYALL1;
1175 WRITE_MB();
1176 *(u_int32_t *)dp = SFBCOPYALL1;
1177 WRITE_MB();
1178 width -= SFBCOPYBITS;
1179 }
1180 sp -= SFBCOPYBYTESDONE;
1181 dp -= SFBCOPYBYTESDONE;
1182 *(u_int32_t *)sp = lmasks;
1183 WRITE_MB();
1184 *(u_int32_t *)dp = lmaskd;
1185 WRITE_MB();
1186
1187 sp = (sq += scanspan);
1188 dp = (dq += scanspan);
1189 width = w;
1190 height--;
1191 }
1192 }
1193 SFBMODE(sfb, MODE_SIMPLE);
1194 }
1195
1196 /*
1197 * Clear characters in a line.
1198 */
1199 void
1200 sfb_erasecols(id, row, startcol, ncols, attr)
1201 void *id;
1202 int row, startcol, ncols;
1203 long attr;
1204 {
1205 struct rcons *rc = id;
1206 struct raster *rap = rc->rc_sp;
1207 caddr_t sfb, p;
1208 int scanspan, startx, height, width, align, w, y;
1209 u_int32_t lmask, rmask;
1210
1211 scanspan = rap->linelongs * 4;
1212 y = rc->rc_yorigin + rc->rc_font->height * row;
1213 startx = rc->rc_xorigin + rc->rc_font->width * startcol;
1214 height = rc->rc_font->height;
1215 w = rc->rc_font->width * ncols;
1216
1217 p = (caddr_t)rap->pixels + y * scanspan + startx;
1218 align = (long)p & SFBALIGNMASK;
1219 p -= align;
1220 width = w + align;
1221 lmask = SFBSTIPPLEALL1 << align;
1222 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
1223 sfb = rap->data;
1224
1225 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
1226 SFBPLANEMASK(sfb, ~0);
1227 SFBFG(sfb, 0); /* fill with bg color */
1228 if (width <= SFBSTIPPLEBITS) {
1229 lmask = lmask & rmask;
1230 while (height > 0) {
1231 SFBADDRESS(sfb, (long)p);
1232 SFBSTART(sfb, lmask);
1233 p += scanspan;
1234 height--;
1235 }
1236 }
1237 else {
1238 caddr_t q = p;
1239 while (height > 0) {
1240 *(u_int32_t *)p = lmask;
1241 WRITE_MB();
1242 width -= 2 * SFBSTIPPLEBITS;
1243 while (width > 0) {
1244 p += SFBSTIPPLEBYTESDONE;
1245 *(u_int32_t *)p = SFBSTIPPLEALL1;
1246 WRITE_MB();
1247 width -= SFBSTIPPLEBITS;
1248 }
1249 p += SFBSTIPPLEBYTESDONE;
1250 *(u_int32_t *)p = rmask;
1251 WRITE_MB();
1252
1253 p = (q += scanspan);
1254 width = w + align;
1255 height--;
1256 }
1257 }
1258 SFBMODE(sfb, MODE_SIMPLE);
1259 }
1260
1261 /*
1262 * Copy lines.
1263 */
1264 void
1265 sfb_copyrows(id, srcrow, dstrow, nrows)
1266 void *id;
1267 int srcrow, dstrow, nrows;
1268 {
1269 struct rcons *rc = id;
1270 struct raster *rap = rc->rc_sp;
1271 caddr_t sfb, p;
1272 int scanspan, offset, srcy, height, width, align, w;
1273 u_int32_t lmask, rmask;
1274
1275 scanspan = rap->linelongs * 4;
1276 height = rc->rc_font->height * nrows;
1277 offset = (dstrow - srcrow) * scanspan * rc->rc_font->height;
1278 srcy = rc->rc_yorigin + rc->rc_font->height * srcrow;
1279 if (srcrow < dstrow && srcrow + nrows > dstrow) {
1280 scanspan = -scanspan;
1281 srcy += height;
1282 }
1283
1284 p = (caddr_t)(rap->pixels + srcy * rap->linelongs) + rc->rc_xorigin;
1285 align = (long)p & SFBALIGNMASK;
1286 p -= align;
1287 w = rc->rc_font->width * rc->rc_maxcol;
1288 width = w + align;
1289 lmask = SFBCOPYALL1 << align;
1290 rmask = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
1291 sfb = rap->data;
1292
1293 SFBMODE(sfb, MODE_COPY);
1294 SFBPLANEMASK(sfb, ~0);
1295 SFBPIXELSHIFT(sfb, 0);
1296 if (width <= SFBCOPYBITS) {
1297 /* never happens */;
1298 }
1299 else {
1300 caddr_t q = p;
1301 while (height > 0) {
1302 *(u_int32_t *)p = lmask;
1303 *(u_int32_t *)(p + offset) = lmask;
1304 width -= 2 * SFBCOPYBITS;
1305 while (width > 0) {
1306 p += SFBCOPYBYTESDONE;
1307 *(u_int32_t *)p = SFBCOPYALL1;
1308 *(u_int32_t *)(p + offset) = SFBCOPYALL1;
1309 width -= SFBCOPYBITS;
1310 }
1311 p += SFBCOPYBYTESDONE;
1312 *(u_int32_t *)p = rmask;
1313 *(u_int32_t *)(p + offset) = rmask;
1314
1315 p = (q += scanspan);
1316 width = w + align;
1317 height--;
1318 }
1319 }
1320 SFBMODE(sfb, MODE_SIMPLE);
1321 }
1322
1323 /*
1324 * Erase lines.
1325 */
1326 void
1327 sfb_eraserows(id, startrow, nrows, attr)
1328 void *id;
1329 int startrow, nrows;
1330 long attr;
1331 {
1332 struct rcons *rc = id;
1333 struct raster *rap = rc->rc_sp;
1334 caddr_t sfb, p;
1335 int scanspan, starty, height, width, align, w;
1336 u_int32_t lmask, rmask;
1337
1338 scanspan = rap->linelongs * 4;
1339 starty = rc->rc_yorigin + rc->rc_font->height * startrow;
1340 height = rc->rc_font->height * nrows;
1341
1342 p = (caddr_t)rap->pixels + starty * scanspan + rc->rc_xorigin;
1343 align = (long)p & SFBALIGNMASK;
1344 p -= align;
1345 w = rc->rc_font->width * rc->rc_maxcol;
1346 width = w + align;
1347 lmask = SFBSTIPPLEALL1 << align;
1348 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
1349 sfb = rap->data;
1350
1351 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
1352 SFBPLANEMASK(sfb, ~0);
1353 SFBFG(sfb, 0); /* fill with bg color */
1354 if (width <= SFBSTIPPLEBITS) {
1355 /* never happens */;
1356 }
1357 else {
1358 caddr_t q = p;
1359 while (height > 0) {
1360 *(u_int32_t *)p = lmask;
1361 WRITE_MB();
1362 width -= 2 * SFBSTIPPLEBITS;
1363 while (width > 0) {
1364 p += SFBSTIPPLEBYTESDONE;
1365 *(u_int32_t *)p = SFBSTIPPLEALL1;
1366 WRITE_MB();
1367 width -= SFBSTIPPLEBITS;
1368 }
1369 p += SFBSTIPPLEBYTESDONE;
1370 *(u_int32_t *)p = rmask;
1371 WRITE_MB();
1372
1373 p = (q += scanspan);
1374 width = w + align;
1375 height--;
1376 }
1377 }
1378 SFBMODE(sfb, MODE_SIMPLE);
1379 }
1380
1381 int
1382 sfb_alloc_attr(id, fg, bg, flags, attrp)
1383 void *id;
1384 int fg, bg, flags;
1385 long *attrp;
1386 {
1387 if (flags & (WSATTR_HILIT | WSATTR_BLINK |
1388 WSATTR_UNDERLINE | WSATTR_WSCOLORS))
1389 return (EINVAL);
1390 if (flags & WSATTR_REVERSE)
1391 *attrp = 1;
1392 else
1393 *attrp = 0;
1394 return (0);
1395 }
1396