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