sfb.c revision 1.24 1 /* $NetBSD: sfb.c,v 1.24 1999/10/27 04:32:35 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.24 1999/10/27 04:32:35 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, align, shift, w, y;
1080 u_int32_t lmask, rmask;
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 dp = basex + rc->rc_font->width * dstcol;
1089 sp = basex + rc->rc_font->width * srccol;
1090
1091 align = shift = (long)sp & SFBALIGNMASK;
1092 sp -= align;
1093 width = w + align;
1094 align = (long)dp & SFBALIGNMASK;
1095 dp -= align;
1096 shift = align - shift;
1097 #if 1
1098 if (shift < 0) {
1099 align += 8;
1100 dp -= 8;
1101 }
1102 #endif
1103 lmask = SFBCOPYALL1 << align;
1104 rmask = SFBCOPYALL1 >> (-(w + align) & SFBCOPYBITMASK);
1105 sfb = rap->data;
1106
1107 SFBMODE(sfb, MODE_COPY);
1108 SFBPLANEMASK(sfb, ~0);
1109 SFBPIXELSHIFT(sfb, shift);
1110 if (width <= SFBCOPYBITS) {
1111 lmask = lmask & rmask;
1112 while (height > 0) {
1113 *(u_int32_t *)sp = SFBCOPYALL1;
1114 WRITE_MB();
1115 *(u_int32_t *)dp = lmask;
1116 WRITE_MB();
1117 sp += scanspan;
1118 dp += scanspan;
1119 height--;
1120 }
1121 }
1122 /* copy forward (left-to-right) */
1123 else if (dstcol < srccol || srccol + ncols < dstcol) {
1124 caddr_t sq = sp, dq = dp;
1125
1126 w = width;
1127 while (height > 0) {
1128 *(u_int32_t *)sp = SFBCOPYALL1;
1129 WRITE_MB();
1130 *(u_int32_t *)dp = lmask;
1131 WRITE_MB();
1132 width -= 2 * SFBCOPYBITS;
1133 while (width > 0) {
1134 sp += SFBCOPYBYTESDONE;
1135 dp += SFBCOPYBYTESDONE;
1136 *(u_int32_t *)sp = SFBCOPYALL1;
1137 WRITE_MB();
1138 *(u_int32_t *)dp = SFBCOPYALL1;
1139 WRITE_MB();
1140 width -= SFBCOPYBITS;
1141 }
1142 sp += SFBCOPYBYTESDONE;
1143 dp += SFBCOPYBYTESDONE;
1144 *(u_int32_t *)sp = SFBCOPYALL1;
1145 WRITE_MB();
1146 *(u_int32_t *)dp = rmask;
1147 WRITE_MB();
1148
1149 sp = (sq += scanspan);
1150 dp = (dq += scanspan);
1151 width = w;
1152 height--;
1153 }
1154 }
1155 /* copy backward (right-to-left) */
1156 else {
1157 caddr_t sq = (sp += width), dq = (dp += width);
1158
1159 w = width;
1160 while (height > 0) {
1161 *(u_int32_t *)sp = SFBCOPYALL1;
1162 WRITE_MB();
1163 *(u_int32_t *)dp = rmask;
1164 WRITE_MB();
1165 width -= 2 * SFBCOPYBITS;
1166 while (width > 0) {
1167 sp -= SFBCOPYBYTESDONE;
1168 dp -= SFBCOPYBYTESDONE;
1169 *(u_int32_t *)sp = SFBCOPYALL1;
1170 WRITE_MB();
1171 *(u_int32_t *)dp = SFBCOPYALL1;
1172 WRITE_MB();
1173 width -= SFBCOPYBITS;
1174 }
1175 sp -= SFBCOPYBYTESDONE;
1176 dp -= SFBCOPYBYTESDONE;
1177 *(u_int32_t *)sp = SFBCOPYALL1;
1178 WRITE_MB();
1179 *(u_int32_t *)dp = lmask;
1180 WRITE_MB();
1181
1182 sp = (sq += scanspan);
1183 dp = (dq += scanspan);
1184 width = w;
1185 height--;
1186 }
1187 }
1188 SFBMODE(sfb, MODE_SIMPLE);
1189 }
1190
1191 /*
1192 * Clear characters in a line.
1193 */
1194 void
1195 sfb_erasecols(id, row, startcol, ncols, attr)
1196 void *id;
1197 int row, startcol, ncols;
1198 long attr;
1199 {
1200 struct rcons *rc = id;
1201 struct raster *rap = rc->rc_sp;
1202 caddr_t sfb, p;
1203 int scanspan, startx, height, width, align, w, y;
1204 u_int32_t lmask, rmask;
1205
1206 scanspan = rap->linelongs * 4;
1207 y = rc->rc_yorigin + rc->rc_font->height * row;
1208 startx = rc->rc_xorigin + rc->rc_font->width * startcol;
1209 height = rc->rc_font->height;
1210 w = rc->rc_font->width * ncols;
1211
1212 p = (caddr_t)rap->pixels + y * scanspan + startx;
1213 align = (long)p & SFBALIGNMASK;
1214 p -= align;
1215 width = w + align;
1216 lmask = SFBSTIPPLEALL1 << align;
1217 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
1218 sfb = rap->data;
1219
1220 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
1221 SFBPLANEMASK(sfb, ~0);
1222 SFBFG(sfb, 0); /* fill with bg color */
1223 if (width <= SFBSTIPPLEBITS) {
1224 lmask = lmask & rmask;
1225 while (height > 0) {
1226 SFBADDRESS(sfb, (long)p);
1227 SFBSTART(sfb, lmask);
1228 p += scanspan;
1229 height--;
1230 }
1231 }
1232 else {
1233 caddr_t q = p;
1234 while (height > 0) {
1235 *(u_int32_t *)p = lmask;
1236 WRITE_MB();
1237 width -= 2 * SFBSTIPPLEBITS;
1238 while (width > 0) {
1239 p += SFBSTIPPLEBYTESDONE;
1240 *(u_int32_t *)p = SFBSTIPPLEALL1;
1241 WRITE_MB();
1242 width -= SFBSTIPPLEBITS;
1243 }
1244 p += SFBSTIPPLEBYTESDONE;
1245 *(u_int32_t *)p = rmask;
1246 WRITE_MB();
1247
1248 p = (q += scanspan);
1249 width = w + align;
1250 height--;
1251 }
1252 }
1253 SFBMODE(sfb, MODE_SIMPLE);
1254 }
1255
1256 /*
1257 * Copy lines.
1258 */
1259 void
1260 sfb_copyrows(id, srcrow, dstrow, nrows)
1261 void *id;
1262 int srcrow, dstrow, nrows;
1263 {
1264 struct rcons *rc = id;
1265 struct raster *rap = rc->rc_sp;
1266 caddr_t sfb, p;
1267 int scanspan, offset, srcy, height, width, align, w;
1268 u_int32_t lmask, rmask;
1269
1270 scanspan = rap->linelongs * 4;
1271 height = rc->rc_font->height * nrows;
1272 offset = (dstrow - srcrow) * scanspan * rc->rc_font->height;
1273 srcy = rc->rc_yorigin + rc->rc_font->height * srcrow;
1274 if (srcrow < dstrow && srcrow + nrows > dstrow) {
1275 scanspan = -scanspan;
1276 srcy += height;
1277 }
1278
1279 p = (caddr_t)(rap->pixels + srcy * rap->linelongs) + rc->rc_xorigin;
1280 align = (long)p & SFBALIGNMASK;
1281 p -= align;
1282 w = rc->rc_font->width * rc->rc_maxcol;
1283 width = w + align;
1284 lmask = SFBCOPYALL1 << align;
1285 rmask = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
1286 sfb = rap->data;
1287
1288 SFBMODE(sfb, MODE_COPY);
1289 SFBPLANEMASK(sfb, ~0);
1290 SFBPIXELSHIFT(sfb, 0);
1291 if (width <= SFBCOPYBITS) {
1292 /* never happens */;
1293 }
1294 else {
1295 caddr_t q = p;
1296 while (height > 0) {
1297 *(u_int32_t *)p = lmask;
1298 *(u_int32_t *)(p + offset) = lmask;
1299 width -= 2 * SFBCOPYBITS;
1300 while (width > 0) {
1301 p += SFBCOPYBYTESDONE;
1302 *(u_int32_t *)p = SFBCOPYALL1;
1303 *(u_int32_t *)(p + offset) = SFBCOPYALL1;
1304 width -= SFBCOPYBITS;
1305 }
1306 p += SFBCOPYBYTESDONE;
1307 *(u_int32_t *)p = rmask;
1308 *(u_int32_t *)(p + offset) = rmask;
1309
1310 p = (q += scanspan);
1311 width = w + align;
1312 height--;
1313 }
1314 }
1315 SFBMODE(sfb, MODE_SIMPLE);
1316 }
1317
1318 /*
1319 * Erase lines.
1320 */
1321 void
1322 sfb_eraserows(id, startrow, nrows, attr)
1323 void *id;
1324 int startrow, nrows;
1325 long attr;
1326 {
1327 struct rcons *rc = id;
1328 struct raster *rap = rc->rc_sp;
1329 caddr_t sfb, p;
1330 int scanspan, starty, height, width, align, w;
1331 u_int32_t lmask, rmask;
1332
1333 scanspan = rap->linelongs * 4;
1334 starty = rc->rc_yorigin + rc->rc_font->height * startrow;
1335 height = rc->rc_font->height * nrows;
1336
1337 p = (caddr_t)rap->pixels + starty * scanspan + rc->rc_xorigin;
1338 align = (long)p & SFBALIGNMASK;
1339 p -= align;
1340 w = rc->rc_font->width * rc->rc_maxcol;
1341 width = w + align;
1342 lmask = SFBSTIPPLEALL1 << align;
1343 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
1344 sfb = rap->data;
1345
1346 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
1347 SFBPLANEMASK(sfb, ~0);
1348 SFBFG(sfb, 0); /* fill with bg color */
1349 if (width <= SFBSTIPPLEBITS) {
1350 /* never happens */;
1351 }
1352 else {
1353 caddr_t q = p;
1354 while (height > 0) {
1355 *(u_int32_t *)p = lmask;
1356 WRITE_MB();
1357 width -= 2 * SFBSTIPPLEBITS;
1358 while (width > 0) {
1359 p += SFBSTIPPLEBYTESDONE;
1360 *(u_int32_t *)p = SFBSTIPPLEALL1;
1361 WRITE_MB();
1362 width -= SFBSTIPPLEBITS;
1363 }
1364 p += SFBSTIPPLEBYTESDONE;
1365 *(u_int32_t *)p = rmask;
1366 WRITE_MB();
1367
1368 p = (q += scanspan);
1369 width = w + align;
1370 height--;
1371 }
1372 }
1373 SFBMODE(sfb, MODE_SIMPLE);
1374 }
1375
1376 int
1377 sfb_alloc_attr(id, fg, bg, flags, attrp)
1378 void *id;
1379 int fg, bg, flags;
1380 long *attrp;
1381 {
1382 if (flags & (WSATTR_HILIT | WSATTR_BLINK |
1383 WSATTR_UNDERLINE | WSATTR_WSCOLORS))
1384 return (EINVAL);
1385 if (flags & WSATTR_REVERSE)
1386 *attrp = 1;
1387 else
1388 *attrp = 0;
1389 return (0);
1390 }
1391