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