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