sfb.c revision 1.26 1 /* $NetBSD: sfb.c,v 1.26 1999/11/09 08:25:31 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.26 1999/11/09 08:25:31 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 (strncmp("PMAGB-BA", ta->ta_modname, TC_ROM_LLEN) != 0)
281 return (0);
282 return (1);
283 }
284
285 void
286 sfb_getdevconfig(dense_addr, dc)
287 tc_addr_t dense_addr;
288 struct fb_devconfig *dc;
289 {
290 struct raster *rap;
291 struct rcons *rcp;
292 caddr_t sfbasic;
293 int i, hsetup, vsetup, vbase;
294
295 dc->dc_vaddr = dense_addr;
296 dc->dc_paddr = MACHINE_KSEG0_TO_PHYS(dc->dc_vaddr);
297
298 sfbasic = (caddr_t)(dc->dc_vaddr + SFB_ASIC_OFFSET);
299 hsetup = *(u_int32_t *)(sfbasic + SFB_ASIC_VIDEO_HSETUP);
300 vsetup = *(u_int32_t *)(sfbasic + SFB_ASIC_VIDEO_VSETUP);
301 *(u_int32_t *)(sfbasic + SFB_ASIC_VIDEO_BASE) = vbase = 1;
302
303 dc->dc_wid = (hsetup & 0x1ff) << 2;
304 dc->dc_ht = (vsetup & 0x7ff);
305 dc->dc_depth = 8;
306 dc->dc_rowbytes = dc->dc_wid * (dc->dc_depth / 8);
307 dc->dc_videobase = dc->dc_vaddr + SFB_FB_OFFSET + vbase * 4096;
308 dc->dc_blanked = 0;
309
310 /* initialize colormap and cursor resource */
311 sfbinit(dc);
312
313 /* clear the screen */
314 for (i = 0; i < dc->dc_ht * dc->dc_rowbytes; i += sizeof(u_int32_t))
315 *(u_int32_t *)(dc->dc_videobase + i) = 0x0;
316
317 *(u_int32_t *)(sfbasic + SFB_ASIC_VIDEO_VALID) = 1;
318
319 /* initialize the raster */
320 rap = &dc->dc_raster;
321 rap->width = dc->dc_wid;
322 rap->height = dc->dc_ht;
323 rap->depth = dc->dc_depth;
324 rap->linelongs = dc->dc_rowbytes / sizeof(u_int32_t);
325 rap->pixels = (u_int32_t *)dc->dc_videobase;
326 rap->data = sfbasic;
327
328 /* initialize the raster console blitter */
329 rcp = &dc->dc_rcons;
330 rcp->rc_sp = rap;
331 rcp->rc_crow = rcp->rc_ccol = -1;
332 rcp->rc_crowp = &rcp->rc_crow;
333 rcp->rc_ccolp = &rcp->rc_ccol;
334 rcons_init(rcp, 34, 80);
335
336 sfb_stdscreen.nrows = dc->dc_rcons.rc_maxrow;
337 sfb_stdscreen.ncols = dc->dc_rcons.rc_maxcol;
338 }
339
340 void
341 sfbattach(parent, self, aux)
342 struct device *parent, *self;
343 void *aux;
344 {
345 struct sfb_softc *sc = (struct sfb_softc *)self;
346 struct tc_attach_args *ta = aux;
347 struct wsemuldisplaydev_attach_args waa;
348 struct hwcmap256 *cm;
349 caddr_t sfbasic;
350 int console;
351
352 console = (ta->ta_addr == sfb_consaddr);
353 if (console) {
354 sc->sc_dc = &sfb_console_dc;
355 sc->nscreens = 1;
356 }
357 else {
358 sc->sc_dc = (struct fb_devconfig *)
359 malloc(sizeof(struct fb_devconfig), M_DEVBUF, M_WAITOK);
360 sfb_getdevconfig(ta->ta_addr, sc->sc_dc);
361 }
362 printf(": %d x %d, %dbpp\n", sc->sc_dc->dc_wid, sc->sc_dc->dc_ht,
363 sc->sc_dc->dc_depth);
364
365 cm = &sc->sc_cmap;
366 memset(cm, 255, sizeof(struct hwcmap256)); /* XXX */
367 cm->r[0] = cm->g[0] = cm->b[0] = 0; /* XXX */
368
369 sc->sc_cursor.cc_magic.x = HX_MAGIC_X;
370 sc->sc_cursor.cc_magic.y = HX_MAGIC_Y;
371
372 tc_intr_establish(parent, ta->ta_cookie, TC_IPL_TTY, sfbintr, sc);
373
374 sfbasic = (caddr_t)(sc->sc_dc->dc_vaddr + SFB_ASIC_OFFSET);
375 *(u_int32_t *)(sfbasic + SFB_ASIC_CLEAR_INTR) = 0;
376 *(u_int32_t *)(sfbasic + SFB_ASIC_ENABLE_INTR) = 1;
377
378 waa.console = console;
379 waa.scrdata = &sfb_screenlist;
380 waa.accessops = &sfb_accessops;
381 waa.accesscookie = sc;
382
383 config_found(self, &waa, wsemuldisplaydevprint);
384 }
385
386 int
387 sfbioctl(v, cmd, data, flag, p)
388 void *v;
389 u_long cmd;
390 caddr_t data;
391 int flag;
392 struct proc *p;
393 {
394 struct sfb_softc *sc = v;
395 struct fb_devconfig *dc = sc->sc_dc;
396 int turnoff;
397
398 switch (cmd) {
399 case WSDISPLAYIO_GTYPE:
400 *(u_int *)data = WSDISPLAY_TYPE_SFB;
401 return (0);
402
403 case WSDISPLAYIO_GINFO:
404 #define wsd_fbip ((struct wsdisplay_fbinfo *)data)
405 wsd_fbip->height = sc->sc_dc->dc_ht;
406 wsd_fbip->width = sc->sc_dc->dc_wid;
407 wsd_fbip->depth = sc->sc_dc->dc_depth;
408 wsd_fbip->cmsize = CMAP_SIZE;
409 #undef fbt
410 return (0);
411
412 case WSDISPLAYIO_GETCMAP:
413 return get_cmap(sc, (struct wsdisplay_cmap *)data);
414
415 case WSDISPLAYIO_PUTCMAP:
416 return set_cmap(sc, (struct wsdisplay_cmap *)data);
417
418 case WSDISPLAYIO_SVIDEO:
419 turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF;
420 if ((dc->dc_blanked == 0) ^ turnoff) {
421 dc->dc_blanked = turnoff;
422 #if 0 /* XXX later XXX */
423 To turn off, assign value 0 in ASIC_VIDEO_VALID register.
424 #endif /* XXX XXX XXX */
425 }
426 return (0);
427
428 case WSDISPLAYIO_GVIDEO:
429 *(u_int *)data = dc->dc_blanked ?
430 WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON;
431 return (0);
432
433 case WSDISPLAYIO_GCURPOS:
434 *(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos;
435 return (0);
436
437 case WSDISPLAYIO_SCURPOS:
438 set_curpos(sc, (struct wsdisplay_curpos *)data);
439 bt459_set_curpos(sc);
440 return (0);
441
442 case WSDISPLAYIO_GCURMAX:
443 ((struct wsdisplay_curpos *)data)->x =
444 ((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE;
445 return (0);
446
447 case WSDISPLAYIO_GCURSOR:
448 return get_cursor(sc, (struct wsdisplay_cursor *)data);
449
450 case WSDISPLAYIO_SCURSOR:
451 return set_cursor(sc, (struct wsdisplay_cursor *)data);
452 }
453 return ENOTTY;
454 }
455
456 int
457 sfbmmap(v, offset, prot)
458 void *v;
459 off_t offset;
460 int prot;
461 {
462 struct sfb_softc *sc = v;
463
464 if (offset >= SFB_SIZE || offset < 0)
465 return (-1);
466 return machine_btop(sc->sc_dc->dc_paddr + offset);
467 }
468
469 int
470 sfb_alloc_screen(v, type, cookiep, curxp, curyp, attrp)
471 void *v;
472 const struct wsscreen_descr *type;
473 void **cookiep;
474 int *curxp, *curyp;
475 long *attrp;
476 {
477 struct sfb_softc *sc = v;
478 long defattr;
479
480 if (sc->nscreens > 0)
481 return (ENOMEM);
482
483 *cookiep = &sc->sc_dc->dc_rcons; /* one and only for now */
484 *curxp = 0;
485 *curyp = 0;
486 sfb_alloc_attr(&sc->sc_dc->dc_rcons, 0, 0, 0, &defattr);
487 *attrp = defattr;
488 sc->nscreens++;
489 return (0);
490 }
491
492 void
493 sfb_free_screen(v, cookie)
494 void *v;
495 void *cookie;
496 {
497 struct sfb_softc *sc = v;
498
499 if (sc->sc_dc == &sfb_console_dc)
500 panic("sfb_free_screen: console");
501
502 sc->nscreens--;
503 }
504
505 void
506 sfb_show_screen(v, cookie)
507 void *v;
508 void *cookie;
509 {
510 }
511
512 int
513 sfb_cnattach(addr)
514 tc_addr_t addr;
515 {
516 struct fb_devconfig *dcp = &sfb_console_dc;
517 long defattr;
518
519 sfb_getdevconfig(addr, dcp);
520
521 sfb_alloc_attr(&dcp->dc_rcons, 0, 0, 0, &defattr);
522
523 wsdisplay_cnattach(&sfb_stdscreen, &dcp->dc_rcons,
524 0, 0, defattr);
525 sfb_consaddr = addr;
526 return(0);
527 }
528
529 int
530 sfbintr(arg)
531 void *arg;
532 {
533 struct sfb_softc *sc = arg;
534 caddr_t sfbbase = (caddr_t)sc->sc_dc->dc_vaddr;
535 caddr_t sfbasic = sfbbase + SFB_ASIC_OFFSET;
536 caddr_t vdac;
537 int v;
538
539 *(u_int32_t *)(sfbasic + SFB_ASIC_CLEAR_INTR) = 0;
540 /* *(u_int32_t *)(sfbasic + SFB_ASIC_ENABLE_INTR) = 1; */
541
542 if (sc->sc_changed == 0)
543 return (1);
544
545 vdac = (void *)(sfbbase + SFB_RAMDAC_OFFSET);
546 v = sc->sc_changed;
547 sc->sc_changed = 0;
548
549 if (v & DATA_ENB_CHANGED) {
550 SELECT(vdac, BT459_REG_CCR);
551 REG(vdac, bt_reg) = (sc->sc_curenb) ? 0xc0 : 0x00;
552 }
553 if (v & DATA_CURCMAP_CHANGED) {
554 u_int8_t *cp = sc->sc_cursor.cc_color;
555
556 SELECT(vdac, BT459_REG_CCOLOR_2);
557 REG(vdac, bt_reg) = cp[1]; tc_wmb();
558 REG(vdac, bt_reg) = cp[3]; tc_wmb();
559 REG(vdac, bt_reg) = cp[5]; tc_wmb();
560
561 REG(vdac, bt_reg) = cp[0]; tc_wmb();
562 REG(vdac, bt_reg) = cp[2]; tc_wmb();
563 REG(vdac, bt_reg) = cp[4]; tc_wmb();
564 }
565 if (v & DATA_CURSHAPE_CHANGED) {
566 u_int8_t *ip, *mp, img, msk;
567 u_int8_t u;
568 int bcnt;
569
570 ip = (u_int8_t *)sc->sc_cursor.cc_image;
571 mp = (u_int8_t *)(sc->sc_cursor.cc_image + CURSOR_MAX_SIZE);
572
573 bcnt = 0;
574 SELECT(vdac, BT459_REG_CRAM_BASE+0);
575 /* 64 pixel scan line is consisted with 16 byte cursor ram */
576 while (bcnt < sc->sc_cursor.cc_size.y * 16) {
577 /* pad right half 32 pixel when smaller than 33 */
578 if ((bcnt & 0x8) && sc->sc_cursor.cc_size.x < 33) {
579 REG(vdac, bt_reg) = 0; tc_wmb();
580 REG(vdac, bt_reg) = 0; tc_wmb();
581 }
582 else {
583 img = *ip++;
584 msk = *mp++;
585 img &= msk; /* cookie off image */
586 u = (msk & 0x0f) << 4 | (img & 0x0f);
587 REG(vdac, bt_reg) = shuffle[u]; tc_wmb();
588 u = (msk & 0xf0) | (img & 0xf0) >> 4;
589 REG(vdac, bt_reg) = shuffle[u]; tc_wmb();
590 }
591 bcnt += 2;
592 }
593 /* pad unoccupied scan lines */
594 while (bcnt < CURSOR_MAX_SIZE * 16) {
595 REG(vdac, bt_reg) = 0; tc_wmb();
596 REG(vdac, bt_reg) = 0; tc_wmb();
597 bcnt += 2;
598 }
599 }
600 if (v & DATA_CMAP_CHANGED) {
601 struct hwcmap256 *cm = &sc->sc_cmap;
602 int index;
603
604 SELECT(vdac, 0);
605 for (index = 0; index < CMAP_SIZE; index++) {
606 REG(vdac, bt_cmap) = cm->r[index]; tc_wmb();
607 REG(vdac, bt_cmap) = cm->g[index]; tc_wmb();
608 REG(vdac, bt_cmap) = cm->b[index]; tc_wmb();
609 }
610 }
611 return (1);
612 }
613
614 void
615 sfbinit(dc)
616 struct fb_devconfig *dc;
617 {
618 caddr_t sfbasic = (caddr_t)(dc->dc_vaddr + SFB_ASIC_OFFSET);
619 caddr_t vdac = (void *)(dc->dc_vaddr + SFB_RAMDAC_OFFSET);
620 int i;
621
622 *(u_int32_t *)(sfbasic + SFB_ASIC_VIDEO_VALID) = 0;
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 REG(vdac, bt_cmap) = 0; tc_wmb();
661 REG(vdac, bt_cmap) = 0; tc_wmb();
662 REG(vdac, bt_cmap) = 0; tc_wmb();
663 for (i = 1; i < CMAP_SIZE; i++) {
664 REG(vdac, bt_cmap) = 0xff; tc_wmb();
665 REG(vdac, bt_cmap) = 0xff; tc_wmb();
666 REG(vdac, bt_cmap) = 0xff; 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 sfbbase = (caddr_t)sc->sc_dc->dc_vaddr;
831 caddr_t vdac = (void *)(sfbbase + SFB_RAMDAC_OFFSET);
832 int x, y, s;
833
834 x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x;
835 y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y;
836
837 x += sc->sc_cursor.cc_magic.x;
838 y += sc->sc_cursor.cc_magic.y;
839
840 s = spltty();
841
842 SELECT(vdac, BT459_REG_CURSOR_X_LOW);
843 REG(vdac, bt_reg) = x; tc_wmb();
844 REG(vdac, bt_reg) = x >> 8; tc_wmb();
845 REG(vdac, bt_reg) = y; tc_wmb();
846 REG(vdac, bt_reg) = y >> 8; tc_wmb();
847
848 splx(s);
849 }
850
851 #define MODE_SIMPLE 0
852 #define MODE_OPAQUESTIPPLE 1
853 #define MODE_OPAQUELINE 2
854 #define MODE_TRANSPARENTSTIPPLE 5
855 #define MODE_TRANSPARENTLINE 6
856 #define MODE_COPY 7
857
858 /* parameters for 8bpp configuration */
859 #define SFBALIGNMASK 0x7
860 #define SFBSTIPPLEALL1 0xffffffff
861 #define SFBSTIPPLEBITS 32
862 #define SFBSTIPPLEBITMASK 0x1f
863 #define SFBSTIPPLEBYTESDONE 32
864 #define SFBCOPYALL1 0xffffffff
865 #define SFBCOPYBITS 32
866 #define SFBCOPYBITMASK 0x1f
867 #define SFBCOPYBYTESDONE 32
868
869 #ifdef pmax
870 #define WRITE_MB()
871 #define BUMP(p) (p)
872 #endif
873
874 #ifdef alpha
875 #define WRITE_MB() tc_wmb()
876 #define BUMP(p) ((p) = (caddr_t)(((long)(p) + 128) & ~0x400))
877 #endif
878
879 #define SFBMODE(p, v) \
880 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_MODE) = (v))
881 #define SFBROP(p, v) \
882 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_ROP) = (v))
883 #define SFBPLANEMASK(p, v) \
884 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_PLANEMASK) = (v))
885 #define SFBPIXELMASK(p, v) \
886 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELMASK) = (v))
887 #define SFBADDRESS(p, v) \
888 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_ADDRESS) = (v))
889 #define SFBSTART(p, v) \
890 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_START) = (v))
891 #define SFBPIXELSHIFT(p, v) \
892 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELSHIFT) = (v))
893 #define SFBFG(p, v) \
894 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_FG) = (v))
895 #define SFBBG(p, v) \
896 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_BG) = (v))
897
898
899 /*
900 * Paint (or unpaint) the cursor.
901 */
902 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
972 /*
973 * Actually write a string to the frame buffer.
974 */
975 int
976 sfb_mapchar(id, uni, index)
977 void *id;
978 int uni;
979 unsigned int *index;
980 {
981 if (uni < 128) {
982 *index = uni;
983 return (5);
984 }
985 *index = ' ';
986 return (0);
987 }
988
989 /*
990 * Actually write a string to the frame buffer.
991 */
992 void
993 sfb_putchar(id, row, col, uc, attr)
994 void *id;
995 int row, col;
996 u_int uc;
997 long attr;
998 {
999 struct rcons *rc = id;
1000 struct raster *rap = rc->rc_sp;
1001 caddr_t sfb, p;
1002 int scanspan, height, width, align, x, y;
1003 u_int32_t lmask, rmask, glyph;
1004 u_int32_t *g;
1005
1006 if (uc < 0x20 || uc >= 127) return; /* XXX why \033 is creaping in !? XXX */
1007
1008 x = col * rc->rc_font->width + rc->rc_xorigin;
1009 y = row * rc->rc_font->height + rc->rc_yorigin;
1010 scanspan = rap->linelongs * 4;
1011 height = rc->rc_font->height;
1012 g = rc->rc_font->chars[uc].r->pixels;
1013
1014 p = (caddr_t)rap->pixels + y * scanspan + x;
1015 align = (long)p & SFBALIGNMASK;
1016 p -= align;
1017 width = rc->rc_font->width + align;
1018 lmask = SFBSTIPPLEALL1 << align;
1019 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
1020 sfb = rap->data;
1021 attr = (attr != 0) ^ (rc->rc_bits & RC_INVERT);
1022
1023 SFBMODE(sfb, MODE_OPAQUESTIPPLE);
1024 SFBPLANEMASK(sfb, ~0);
1025 SFBFG(sfb, (attr == 0) ? 0x01010101 : 0);
1026 SFBBG(sfb, (attr == 0) ? 0 : 0x01010101);
1027 if (width <= SFBSTIPPLEBITS) {
1028 lmask = lmask & rmask;
1029 while (height > 0) {
1030 glyph = *g;
1031 SFBPIXELMASK(sfb, lmask);
1032 SFBADDRESS(sfb, (long)p);
1033 SFBSTART(sfb, glyph << align);
1034 p += scanspan;
1035 g += 1;
1036 height--;
1037 }
1038 }
1039 else {
1040 caddr_t q = p;
1041 while (height > 0) {
1042 glyph = *g;
1043 SFBPIXELMASK(sfb, lmask);
1044 WRITE_MB();
1045 *(u_int32_t *)p = glyph << align;
1046 WRITE_MB();
1047 p += SFBSTIPPLEBYTESDONE;
1048 SFBPIXELMASK(sfb, rmask);
1049 WRITE_MB();
1050 *(u_int32_t *)p = glyph >> (-width & SFBSTIPPLEBITMASK);
1051 WRITE_MB();
1052
1053 p = (q += scanspan);
1054 g += 1;
1055 height--;
1056 }
1057 }
1058 SFBMODE(sfb, MODE_SIMPLE);
1059 SFBPIXELMASK(sfb, ~0); /* entire pixel */
1060 }
1061
1062 /*
1063 * Copy characters in a line.
1064 */
1065 void
1066 sfb_copycols(id, row, srccol, dstcol, ncols)
1067 void *id;
1068 int row, srccol, dstcol, ncols;
1069 {
1070 struct rcons *rc = id;
1071 struct raster *rap = rc->rc_sp;
1072 caddr_t sp, dp, basex, sfb;
1073 int scanspan, height, width, aligns, alignd, shift, w, y;
1074 u_int32_t lmasks, rmasks, lmaskd, rmaskd;
1075
1076 scanspan = rap->linelongs * 4;
1077 y = rc->rc_yorigin + rc->rc_font->height * row;
1078 basex = (caddr_t)rap->pixels + y * scanspan + rc->rc_xorigin;
1079 height = rc->rc_font->height;
1080 w = rc->rc_font->width * ncols;
1081
1082 sp = basex + rc->rc_font->width * srccol;
1083 aligns = (long)sp & SFBALIGNMASK;
1084 dp = basex + rc->rc_font->width * dstcol;
1085 alignd = (long)dp & SFBALIGNMASK;
1086 sfb = rap->data;
1087
1088 SFBMODE(sfb, MODE_COPY);
1089 SFBPLANEMASK(sfb, ~0);
1090
1091 /* copy forward (left-to-right) */
1092 if (dstcol < srccol || srccol + ncols < dstcol) {
1093 caddr_t sq, dq;
1094
1095 shift = alignd - aligns;
1096 if (shift < 0) {
1097 dp -= 8; /* prime left edge */
1098 alignd += 8; /* compensate it */
1099 width = aligns + w + 8; /* adjust total width */
1100 shift = 8 + shift; /* enforce right rotate */
1101 }
1102 else if (shift > 0)
1103 width = aligns + w + 8; /* enfore drain at right edge */
1104
1105 lmasks = SFBCOPYALL1 << aligns;
1106 rmasks = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
1107 lmaskd = SFBCOPYALL1 << alignd;
1108 rmaskd = SFBCOPYALL1 >> (-(w + alignd) & SFBCOPYBITMASK);
1109
1110 if (w + alignd <= SFBCOPYBITS)
1111 goto singlewrite;
1112
1113 SFBPIXELSHIFT(sfb, shift);
1114 w = width;
1115 sq = sp;
1116 dq = dp;
1117 while (height > 0) {
1118 *(u_int32_t *)sp = lmasks;
1119 WRITE_MB();
1120 *(u_int32_t *)dp = lmaskd;
1121 WRITE_MB();
1122 width -= 2 * SFBCOPYBITS;
1123 while (width > 0) {
1124 sp += SFBCOPYBYTESDONE;
1125 dp += SFBCOPYBYTESDONE;
1126 *(u_int32_t *)sp = SFBCOPYALL1;
1127 WRITE_MB();
1128 *(u_int32_t *)dp = SFBCOPYALL1;
1129 WRITE_MB();
1130 width -= SFBCOPYBITS;
1131 }
1132 sp += SFBCOPYBYTESDONE;
1133 dp += SFBCOPYBYTESDONE;
1134 *(u_int32_t *)sp = rmasks;
1135 WRITE_MB();
1136 *(u_int32_t *)dp = rmaskd;
1137 WRITE_MB();
1138
1139 sp = (sq += scanspan);
1140 dp = (dq += scanspan);
1141 width = w;
1142 height--;
1143 }
1144 }
1145 /* copy backward (right-to-left) */
1146 else {
1147 caddr_t sq, dq;
1148
1149 shift = alignd - aligns;
1150 if (shift > 0) {
1151 shift = shift - 8;
1152 w += 8;
1153 }
1154 width = w + aligns;
1155 lmasks = SFBCOPYALL1 << aligns;
1156 rmasks = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
1157 lmaskd = SFBCOPYALL1 << alignd;
1158 rmaskd = SFBCOPYALL1 >> (-(w + alignd) & SFBCOPYBITMASK);
1159
1160 if (w + alignd <= SFBCOPYBITS)
1161 goto singlewrite;
1162
1163 SFBPIXELSHIFT(sfb, shift);
1164 w = width;
1165 sq = (sp += width);
1166 dq = (dp += width);
1167 while (height > 0) {
1168 *(u_int32_t *)sp = rmasks;
1169 WRITE_MB();
1170 *(u_int32_t *)dp = rmaskd;
1171 WRITE_MB();
1172 width -= 2 * SFBCOPYBITS;
1173 while (width > 0) {
1174 sp -= SFBCOPYBYTESDONE;
1175 dp -= SFBCOPYBYTESDONE;
1176 *(u_int32_t *)sp = SFBCOPYALL1;
1177 WRITE_MB();
1178 *(u_int32_t *)dp = SFBCOPYALL1;
1179 WRITE_MB();
1180 width -= SFBCOPYBITS;
1181 }
1182 sp -= SFBCOPYBYTESDONE;
1183 dp -= SFBCOPYBYTESDONE;
1184 *(u_int32_t *)sp = lmasks;
1185 WRITE_MB();
1186 *(u_int32_t *)dp = lmaskd;
1187 WRITE_MB();
1188
1189 sp = (sq += scanspan);
1190 dp = (dq += scanspan);
1191 width = w;
1192 height--;
1193 }
1194 }
1195 SFBMODE(sfb, MODE_SIMPLE);
1196 SFBPIXELSHIFT(sfb, 0);
1197 return;
1198
1199 singlewrite:
1200 SFBPIXELSHIFT(sfb, shift);
1201 lmasks = lmasks & rmasks;
1202 lmaskd = lmaskd & rmaskd;
1203 while (height > 0) {
1204 *(u_int32_t *)sp = lmasks;
1205 WRITE_MB();
1206 *(u_int32_t *)dp = lmaskd;
1207 WRITE_MB();
1208 sp += scanspan;
1209 dp += scanspan;
1210 height--;
1211 }
1212 SFBMODE(sfb, MODE_SIMPLE);
1213 SFBPIXELSHIFT(sfb, 0);
1214 }
1215
1216 /*
1217 * Clear characters in a line.
1218 */
1219 void
1220 sfb_erasecols(id, row, startcol, ncols, attr)
1221 void *id;
1222 int row, startcol, ncols;
1223 long attr;
1224 {
1225 struct rcons *rc = id;
1226 struct raster *rap = rc->rc_sp;
1227 caddr_t sfb, p;
1228 int scanspan, startx, height, width, align, w, y;
1229 u_int32_t lmask, rmask;
1230
1231 scanspan = rap->linelongs * 4;
1232 y = rc->rc_yorigin + rc->rc_font->height * row;
1233 startx = rc->rc_xorigin + rc->rc_font->width * startcol;
1234 height = rc->rc_font->height;
1235 w = rc->rc_font->width * ncols;
1236
1237 p = (caddr_t)rap->pixels + y * scanspan + startx;
1238 align = (long)p & SFBALIGNMASK;
1239 p -= align;
1240 width = w + align;
1241 lmask = SFBSTIPPLEALL1 << align;
1242 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
1243 sfb = rap->data;
1244
1245 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
1246 SFBPLANEMASK(sfb, ~0);
1247 SFBFG(sfb, 0); /* fill with bg color */
1248 if (width <= SFBSTIPPLEBITS) {
1249 lmask = lmask & rmask;
1250 while (height > 0) {
1251 SFBADDRESS(sfb, (long)p);
1252 SFBSTART(sfb, lmask);
1253 p += scanspan;
1254 height--;
1255 }
1256 }
1257 else {
1258 caddr_t q = p;
1259 while (height > 0) {
1260 *(u_int32_t *)p = lmask;
1261 WRITE_MB();
1262 width -= 2 * SFBSTIPPLEBITS;
1263 while (width > 0) {
1264 p += SFBSTIPPLEBYTESDONE;
1265 *(u_int32_t *)p = SFBSTIPPLEALL1;
1266 WRITE_MB();
1267 width -= SFBSTIPPLEBITS;
1268 }
1269 p += SFBSTIPPLEBYTESDONE;
1270 *(u_int32_t *)p = rmask;
1271 WRITE_MB();
1272
1273 p = (q += scanspan);
1274 width = w + align;
1275 height--;
1276 }
1277 }
1278 SFBMODE(sfb, MODE_SIMPLE);
1279 }
1280
1281 /*
1282 * Copy lines.
1283 */
1284 void
1285 sfb_copyrows(id, srcrow, dstrow, nrows)
1286 void *id;
1287 int srcrow, dstrow, nrows;
1288 {
1289 struct rcons *rc = id;
1290 struct raster *rap = rc->rc_sp;
1291 caddr_t sfb, p;
1292 int scanspan, offset, srcy, height, width, align, w;
1293 u_int32_t lmask, rmask;
1294
1295 scanspan = rap->linelongs * 4;
1296 height = rc->rc_font->height * nrows;
1297 offset = (dstrow - srcrow) * scanspan * rc->rc_font->height;
1298 srcy = rc->rc_yorigin + rc->rc_font->height * srcrow;
1299 if (srcrow < dstrow && srcrow + nrows > dstrow) {
1300 scanspan = -scanspan;
1301 srcy += height;
1302 }
1303
1304 p = (caddr_t)(rap->pixels + srcy * rap->linelongs) + rc->rc_xorigin;
1305 align = (long)p & SFBALIGNMASK;
1306 p -= align;
1307 w = rc->rc_font->width * rc->rc_maxcol;
1308 width = w + align;
1309 lmask = SFBCOPYALL1 << align;
1310 rmask = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
1311 sfb = rap->data;
1312
1313 SFBMODE(sfb, MODE_COPY);
1314 SFBPLANEMASK(sfb, ~0);
1315 SFBPIXELSHIFT(sfb, 0);
1316 if (width <= SFBCOPYBITS) {
1317 /* never happens */;
1318 }
1319 else {
1320 caddr_t q = p;
1321 while (height > 0) {
1322 *(u_int32_t *)p = lmask;
1323 *(u_int32_t *)(p + offset) = lmask;
1324 width -= 2 * SFBCOPYBITS;
1325 while (width > 0) {
1326 p += SFBCOPYBYTESDONE;
1327 *(u_int32_t *)p = SFBCOPYALL1;
1328 *(u_int32_t *)(p + offset) = SFBCOPYALL1;
1329 width -= SFBCOPYBITS;
1330 }
1331 p += SFBCOPYBYTESDONE;
1332 *(u_int32_t *)p = rmask;
1333 *(u_int32_t *)(p + offset) = rmask;
1334
1335 p = (q += scanspan);
1336 width = w + align;
1337 height--;
1338 }
1339 }
1340 SFBMODE(sfb, MODE_SIMPLE);
1341 }
1342
1343 /*
1344 * Erase lines.
1345 */
1346 void
1347 sfb_eraserows(id, startrow, nrows, attr)
1348 void *id;
1349 int startrow, nrows;
1350 long attr;
1351 {
1352 struct rcons *rc = id;
1353 struct raster *rap = rc->rc_sp;
1354 caddr_t sfb, p;
1355 int scanspan, starty, height, width, align, w;
1356 u_int32_t lmask, rmask;
1357
1358 scanspan = rap->linelongs * 4;
1359 starty = rc->rc_yorigin + rc->rc_font->height * startrow;
1360 height = rc->rc_font->height * nrows;
1361
1362 p = (caddr_t)rap->pixels + starty * scanspan + rc->rc_xorigin;
1363 align = (long)p & SFBALIGNMASK;
1364 p -= align;
1365 w = rc->rc_font->width * rc->rc_maxcol;
1366 width = w + align;
1367 lmask = SFBSTIPPLEALL1 << align;
1368 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
1369 sfb = rap->data;
1370
1371 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
1372 SFBPLANEMASK(sfb, ~0);
1373 SFBFG(sfb, 0); /* fill with bg color */
1374 if (width <= SFBSTIPPLEBITS) {
1375 /* never happens */;
1376 }
1377 else {
1378 caddr_t q = p;
1379 while (height > 0) {
1380 *(u_int32_t *)p = lmask;
1381 WRITE_MB();
1382 width -= 2 * SFBSTIPPLEBITS;
1383 while (width > 0) {
1384 p += SFBSTIPPLEBYTESDONE;
1385 *(u_int32_t *)p = SFBSTIPPLEALL1;
1386 WRITE_MB();
1387 width -= SFBSTIPPLEBITS;
1388 }
1389 p += SFBSTIPPLEBYTESDONE;
1390 *(u_int32_t *)p = rmask;
1391 WRITE_MB();
1392
1393 p = (q += scanspan);
1394 width = w + align;
1395 height--;
1396 }
1397 }
1398 SFBMODE(sfb, MODE_SIMPLE);
1399 }
1400
1401 int
1402 sfb_alloc_attr(id, fg, bg, flags, attrp)
1403 void *id;
1404 int fg, bg, flags;
1405 long *attrp;
1406 {
1407 if (flags & (WSATTR_HILIT | WSATTR_BLINK |
1408 WSATTR_UNDERLINE | WSATTR_WSCOLORS))
1409 return (EINVAL);
1410 if (flags & WSATTR_REVERSE)
1411 *attrp = 1;
1412 else
1413 *attrp = 0;
1414 return (0);
1415 }
1416