sfb.c revision 1.20 1 /* $NetBSD: sfb.c,v 1.20 1999/10/08 02:08:15 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.20 1999/10/08 02:08:15 nisimura Exp $");
36
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/kernel.h>
40 #include <sys/device.h>
41 #include <sys/malloc.h>
42 #include <sys/buf.h>
43 #include <sys/ioctl.h>
44 #include <vm/vm.h>
45
46 #include <machine/bus.h>
47 #include <machine/intr.h>
48
49 #include <dev/rcons/raster.h>
50 #include <dev/wscons/wsconsio.h>
51 #include <dev/wscons/wscons_raster.h>
52 #include <dev/wscons/wsdisplayvar.h>
53
54 #include <dev/tc/tcvar.h>
55 #include <dev/ic/bt459reg.h>
56 #include <dev/tc/sfbreg.h>
57
58 #include <uvm/uvm_extern.h>
59
60 #if defined(pmax)
61 #define machine_btop(x) mips_btop(x)
62 #define MACHINE_KSEG0_TO_PHYS(x) MIPS_KSEG1_TO_PHYS(x)
63 #endif
64
65 #if defined(__alpha__) || defined(alpha)
66 #define machine_btop(x) alpha_btop(x)
67 #define MACHINE_KSEG0_TO_PHYS(x) ALPHA_K0SEG_TO_PHYS(x)
68 #endif
69
70 /*
71 * N.B., Bt459 registers are 8bit width. Some of TC framebuffers have
72 * obscure register layout such as 2nd and 3rd Bt459 registers are
73 * adjacent each other in a word, i.e.,
74 * struct bt459triplet {
75 * struct {
76 * u_int8_t u0;
77 * u_int8_t u1;
78 * u_int8_t u2;
79 * unsigned :8;
80 * } bt_lo;
81 * struct {
82 *
83 * Although HX has single Bt459, 32bit R/W can be done w/o any trouble.
84 * struct bt459reg {
85 * u_int32_t bt_lo;
86 * u_int32_t bt_hi;
87 * u_int32_t bt_reg;
88 * u_int32_t bt_cmap;
89 * };
90 *
91 */
92
93 /* Bt459 hardware registers */
94 #define bt_lo 0
95 #define bt_hi 1
96 #define bt_reg 2
97 #define bt_cmap 3
98
99 #define REG(base, index) *((u_int32_t *)(base) + (index))
100 #define SELECT(vdac, regno) do { \
101 REG(vdac, bt_lo) = ((regno) & 0x00ff); \
102 REG(vdac, bt_hi) = ((regno) & 0x0f00) >> 8; \
103 tc_wmb(); \
104 } while (0)
105
106 struct fb_devconfig {
107 vaddr_t dc_vaddr; /* memory space virtual base address */
108 paddr_t dc_paddr; /* memory space physical base address */
109 vsize_t dc_size; /* size of slot memory */
110 int dc_wid; /* width of frame buffer */
111 int dc_ht; /* height of frame buffer */
112 int dc_depth; /* depth, bits per pixel */
113 int dc_rowbytes; /* bytes in a FB scan line */
114 vaddr_t dc_videobase; /* base of flat frame buffer */
115 struct raster dc_raster; /* raster description */
116 struct rcons dc_rcons; /* raster blitter control info */
117 int dc_blanked; /* currently has video disabled */
118 };
119
120 struct hwcmap256 {
121 #define CMAP_SIZE 256 /* 256 R/G/B entries */
122 u_int8_t r[CMAP_SIZE];
123 u_int8_t g[CMAP_SIZE];
124 u_int8_t b[CMAP_SIZE];
125 };
126
127 struct hwcursor64 {
128 struct wsdisplay_curpos cc_pos;
129 struct wsdisplay_curpos cc_hot;
130 struct wsdisplay_curpos cc_size;
131 struct wsdisplay_curpos cc_magic;
132 #define CURSOR_MAX_SIZE 64
133 u_int8_t cc_color[6];
134 u_int64_t cc_image[64 + 64];
135 };
136
137 struct sfb_softc {
138 struct device sc_dev;
139 struct fb_devconfig *sc_dc; /* device configuration */
140 struct hwcmap256 sc_cmap; /* software copy of colormap */
141 struct hwcursor64 sc_cursor; /* software copy of cursor */
142 int sc_curenb; /* cursor sprite enabled */
143 int sc_changed; /* need update of colormap */
144 #define DATA_ENB_CHANGED 0x01 /* cursor enable changed */
145 #define DATA_CURCMAP_CHANGED 0x02 /* cursor colormap changed */
146 #define DATA_CURSHAPE_CHANGED 0x04 /* cursor size, image, mask changed */
147 #define DATA_CMAP_CHANGED 0x08 /* colormap changed */
148 #define DATA_ALL_CHANGED 0x0f
149 int nscreens;
150 };
151
152 #define HX_MAGIC_X 368
153 #define HX_MAGIC_Y 38
154
155 int sfbmatch __P((struct device *, struct cfdata *, void *));
156 void sfbattach __P((struct device *, struct device *, void *));
157
158 struct cfattach sfb_ca = {
159 sizeof(struct sfb_softc), sfbmatch, sfbattach,
160 };
161
162 void sfb_getdevconfig __P((tc_addr_t, struct fb_devconfig *));
163 struct fb_devconfig sfb_console_dc;
164 tc_addr_t sfb_consaddr;
165
166 void sfb_cursor __P((void *, int, int, int));
167 int sfb_mapchar __P((void *, int, unsigned int *));
168 void sfb_putchar __P((void *, int, int, u_int, long));
169 void sfb_copycols __P((void *, int, int, int, int));
170 void sfb_erasecols __P((void *, int, int, int, long));
171 void sfb_copyrows __P((void *, int, int, int));
172 void sfb_eraserows __P((void *, int, int, long));
173 int sfb_alloc_attr __P((void *, int, int, int, long *));
174
175 struct wsdisplay_emulops sfb_emulops = {
176 sfb_cursor, /* could use hardware cursor; punt */
177 sfb_mapchar,
178 sfb_putchar,
179 sfb_copycols,
180 sfb_erasecols,
181 sfb_copyrows,
182 sfb_eraserows,
183 sfb_alloc_attr
184 };
185
186 struct wsscreen_descr sfb_stdscreen = {
187 "std", 0, 0,
188 &sfb_emulops,
189 0, 0,
190 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 *(u_int32_t *)(sfbasic + SFB_ASIC_VIDEO_BASE) = vbase = 1;
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 #if 0 /* XXX later XXX */
424 To turn off, assign value 0 in ASIC_VIDEO_VALID register.
425 #endif /* XXX XXX XXX */
426 }
427 return (0);
428
429 case WSDISPLAYIO_GVIDEO:
430 *(u_int *)data = dc->dc_blanked ?
431 WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON;
432 return (0);
433
434 case WSDISPLAYIO_GCURPOS:
435 *(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos;
436 return (0);
437
438 case WSDISPLAYIO_SCURPOS:
439 set_curpos(sc, (struct wsdisplay_curpos *)data);
440 bt459_set_curpos(sc);
441 return (0);
442
443 case WSDISPLAYIO_GCURMAX:
444 ((struct wsdisplay_curpos *)data)->x =
445 ((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE;
446 return (0);
447
448 case WSDISPLAYIO_GCURSOR:
449 return get_cursor(sc, (struct wsdisplay_cursor *)data);
450
451 case WSDISPLAYIO_SCURSOR:
452 return set_cursor(sc, (struct wsdisplay_cursor *)data);
453 }
454 return ENOTTY;
455 }
456
457 int
458 sfbmmap(v, offset, prot)
459 void *v;
460 off_t offset;
461 int prot;
462 {
463 struct sfb_softc *sc = v;
464
465 if (offset >= SFB_SIZE || offset < 0)
466 return (-1);
467 return machine_btop(sc->sc_dc->dc_paddr + offset);
468 }
469
470 int
471 sfb_alloc_screen(v, type, cookiep, curxp, curyp, attrp)
472 void *v;
473 const struct wsscreen_descr *type;
474 void **cookiep;
475 int *curxp, *curyp;
476 long *attrp;
477 {
478 struct sfb_softc *sc = v;
479 long defattr;
480
481 if (sc->nscreens > 0)
482 return (ENOMEM);
483
484 *cookiep = &sc->sc_dc->dc_rcons; /* one and only for now */
485 *curxp = 0;
486 *curyp = 0;
487 sfb_alloc_attr(&sc->sc_dc->dc_rcons, 0, 0, 0, &defattr);
488 *attrp = defattr;
489 sc->nscreens++;
490 return (0);
491 }
492
493 void
494 sfb_free_screen(v, cookie)
495 void *v;
496 void *cookie;
497 {
498 struct sfb_softc *sc = v;
499
500 if (sc->sc_dc == &sfb_console_dc)
501 panic("sfb_free_screen: console");
502
503 sc->nscreens--;
504 }
505
506 void
507 sfb_show_screen(v, cookie)
508 void *v;
509 void *cookie;
510 {
511 }
512
513 int
514 sfb_cnattach(addr)
515 tc_addr_t addr;
516 {
517 struct fb_devconfig *dcp = &sfb_console_dc;
518 long defattr;
519
520 sfb_getdevconfig(addr, dcp);
521
522 sfb_alloc_attr(&dcp->dc_rcons, 0, 0, 0, &defattr);
523
524 wsdisplay_cnattach(&sfb_stdscreen, &dcp->dc_rcons,
525 0, 0, defattr);
526 sfb_consaddr = addr;
527 return(0);
528 }
529
530 int
531 sfbintr(arg)
532 void *arg;
533 {
534 struct sfb_softc *sc = arg;
535 caddr_t sfbbase = (caddr_t)sc->sc_dc->dc_vaddr;
536 caddr_t sfbasic = sfbbase + SFB_ASIC_OFFSET;
537 caddr_t vdac;
538 int v;
539
540 *(u_int32_t *)(sfbasic + SFB_ASIC_CLEAR_INTR) = 0;
541 /* *(u_int32_t *)(sfbasic + SFB_ASIC_ENABLE_INTR) = 1; */
542
543 if (sc->sc_changed == 0)
544 return (1);
545
546 vdac = (void *)(sfbbase + SFB_RAMDAC_OFFSET);
547 v = sc->sc_changed;
548 sc->sc_changed = 0;
549
550 if (v & DATA_ENB_CHANGED) {
551 SELECT(vdac, BT459_REG_CCR);
552 REG(vdac, bt_reg) = (sc->sc_curenb) ? 0xc0 : 0x00;
553 }
554 if (v & DATA_CURCMAP_CHANGED) {
555 u_int8_t *cp = sc->sc_cursor.cc_color;
556
557 SELECT(vdac, BT459_REG_CCOLOR_2);
558 REG(vdac, bt_reg) = cp[1]; tc_wmb();
559 REG(vdac, bt_reg) = cp[3]; tc_wmb();
560 REG(vdac, bt_reg) = cp[5]; tc_wmb();
561
562 REG(vdac, bt_reg) = cp[0]; tc_wmb();
563 REG(vdac, bt_reg) = cp[2]; tc_wmb();
564 REG(vdac, bt_reg) = cp[4]; tc_wmb();
565 }
566 if (v & DATA_CURSHAPE_CHANGED) {
567 u_int8_t *ip, *mp, img, msk;
568 u_int8_t u;
569 int bcnt;
570
571 ip = (u_int8_t *)sc->sc_cursor.cc_image;
572 mp = (u_int8_t *)(sc->sc_cursor.cc_image + CURSOR_MAX_SIZE);
573
574 bcnt = 0;
575 SELECT(vdac, BT459_REG_CRAM_BASE+0);
576 /* 64 pixel scan line is consisted with 16 byte cursor ram */
577 while (bcnt < sc->sc_cursor.cc_size.y * 16) {
578 /* pad right half 32 pixel when smaller than 33 */
579 if ((bcnt & 0x8) && sc->sc_cursor.cc_size.x < 33) {
580 REG(vdac, bt_reg) = 0; tc_wmb();
581 REG(vdac, bt_reg) = 0; tc_wmb();
582 }
583 else {
584 img = *ip++;
585 msk = *mp++;
586 img &= msk; /* cookie off image */
587 u = (msk & 0x0f) << 4 | (img & 0x0f);
588 REG(vdac, bt_reg) = shuffle[u]; tc_wmb();
589 u = (msk & 0xf0) | (img & 0xf0) >> 4;
590 REG(vdac, bt_reg) = shuffle[u]; tc_wmb();
591 }
592 bcnt += 2;
593 }
594 /* pad unoccupied scan lines */
595 while (bcnt < CURSOR_MAX_SIZE * 16) {
596 REG(vdac, bt_reg) = 0; tc_wmb();
597 REG(vdac, bt_reg) = 0; tc_wmb();
598 bcnt += 2;
599 }
600 }
601 if (v & DATA_CMAP_CHANGED) {
602 struct hwcmap256 *cm = &sc->sc_cmap;
603 int index;
604
605 SELECT(vdac, 0);
606 for (index = 0; index < CMAP_SIZE; index++) {
607 REG(vdac, bt_cmap) = cm->r[index]; tc_wmb();
608 REG(vdac, bt_cmap) = cm->g[index]; tc_wmb();
609 REG(vdac, bt_cmap) = cm->b[index]; tc_wmb();
610 }
611 }
612 return (1);
613 }
614
615 void
616 sfbinit(dc)
617 struct fb_devconfig *dc;
618 {
619 caddr_t sfbasic = (caddr_t)(dc->dc_vaddr + SFB_ASIC_OFFSET);
620 caddr_t vdac = (void *)(dc->dc_vaddr + SFB_RAMDAC_OFFSET);
621 int i;
622
623 *(u_int32_t *)(sfbasic + SFB_ASIC_VIDEO_VALID) = 0;
624 *(u_int32_t *)(sfbasic + SFB_ASIC_PLANEMASK) = ~0;
625 *(u_int32_t *)(sfbasic + SFB_ASIC_PIXELMASK) = ~0;
626 *(u_int32_t *)(sfbasic + SFB_ASIC_MODE) = 0;
627 *(u_int32_t *)(sfbasic + SFB_ASIC_ROP) = 3;
628
629 *(u_int32_t *)(sfbasic + 0x180000) = 0; /* Bt459 reset */
630
631 SELECT(vdac, BT459_REG_COMMAND_0);
632 REG(vdac, bt_reg) = 0x40; /* CMD0 */ tc_wmb();
633 REG(vdac, bt_reg) = 0x0; /* CMD1 */ tc_wmb();
634 REG(vdac, bt_reg) = 0xc0; /* CMD2 */ tc_wmb();
635 REG(vdac, bt_reg) = 0xff; /* PRM */ tc_wmb();
636 REG(vdac, bt_reg) = 0; /* 205 */ tc_wmb();
637 REG(vdac, bt_reg) = 0x0; /* PBM */ tc_wmb();
638 REG(vdac, bt_reg) = 0; /* 207 */ tc_wmb();
639 REG(vdac, bt_reg) = 0x0; /* ORM */ tc_wmb();
640 REG(vdac, bt_reg) = 0x0; /* OBM */ tc_wmb();
641 REG(vdac, bt_reg) = 0x0; /* ILV */ tc_wmb();
642 REG(vdac, bt_reg) = 0x0; /* TEST */ tc_wmb();
643
644 SELECT(vdac, BT459_REG_CCR);
645 REG(vdac, bt_reg) = 0x0; tc_wmb();
646 REG(vdac, bt_reg) = 0x0; tc_wmb();
647 REG(vdac, bt_reg) = 0x0; tc_wmb();
648 REG(vdac, bt_reg) = 0x0; tc_wmb();
649 REG(vdac, bt_reg) = 0x0; tc_wmb();
650 REG(vdac, bt_reg) = 0x0; tc_wmb();
651 REG(vdac, bt_reg) = 0x0; tc_wmb();
652 REG(vdac, bt_reg) = 0x0; tc_wmb();
653 REG(vdac, bt_reg) = 0x0; tc_wmb();
654 REG(vdac, bt_reg) = 0x0; tc_wmb();
655 REG(vdac, bt_reg) = 0x0; tc_wmb();
656 REG(vdac, bt_reg) = 0x0; tc_wmb();
657 REG(vdac, bt_reg) = 0x0; tc_wmb();
658
659 /* build sane colormap */
660 SELECT(vdac, 0);
661 REG(vdac, bt_cmap) = 0; tc_wmb();
662 REG(vdac, bt_cmap) = 0; tc_wmb();
663 REG(vdac, bt_cmap) = 0; tc_wmb();
664 for (i = 1; i < CMAP_SIZE; i++) {
665 REG(vdac, bt_cmap) = 0xff; tc_wmb();
666 REG(vdac, bt_cmap) = 0xff; tc_wmb();
667 REG(vdac, bt_cmap) = 0xff; tc_wmb();
668 }
669
670 /* clear out cursor image */
671 SELECT(vdac, BT459_REG_CRAM_BASE);
672 for (i = 0; i < 1024; i++)
673 REG(vdac, bt_reg) = 0xff; tc_wmb();
674
675 /*
676 * 2 bit/pixel cursor. Assign MSB for cursor mask and LSB for
677 * cursor image. CCOLOR_2 for mask color, while CCOLOR_3 for
678 * image color. CCOLOR_1 will be never used.
679 */
680 SELECT(vdac, BT459_REG_CCOLOR_1);
681 REG(vdac, bt_reg) = 0xff; tc_wmb();
682 REG(vdac, bt_reg) = 0xff; tc_wmb();
683 REG(vdac, bt_reg) = 0xff; tc_wmb();
684
685 REG(vdac, bt_reg) = 0; tc_wmb();
686 REG(vdac, bt_reg) = 0; tc_wmb();
687 REG(vdac, bt_reg) = 0; tc_wmb();
688
689 REG(vdac, bt_reg) = 0xff; tc_wmb();
690 REG(vdac, bt_reg) = 0xff; tc_wmb();
691 REG(vdac, bt_reg) = 0xff; tc_wmb();
692 }
693
694 static int
695 get_cmap(sc, p)
696 struct sfb_softc *sc;
697 struct wsdisplay_cmap *p;
698 {
699 u_int index = p->index, count = p->count;
700
701 if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE)
702 return (EINVAL);
703
704 if (!uvm_useracc(p->red, count, B_WRITE) ||
705 !uvm_useracc(p->green, count, B_WRITE) ||
706 !uvm_useracc(p->blue, count, B_WRITE))
707 return (EFAULT);
708
709 copyout(&sc->sc_cmap.r[index], p->red, count);
710 copyout(&sc->sc_cmap.g[index], p->green, count);
711 copyout(&sc->sc_cmap.b[index], p->blue, count);
712
713 return (0);
714 }
715
716 static int
717 set_cmap(sc, p)
718 struct sfb_softc *sc;
719 struct wsdisplay_cmap *p;
720 {
721 u_int index = p->index, count = p->count;
722
723 if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE)
724 return (EINVAL);
725
726 if (!uvm_useracc(p->red, count, B_READ) ||
727 !uvm_useracc(p->green, count, B_READ) ||
728 !uvm_useracc(p->blue, count, B_READ))
729 return (EFAULT);
730
731 copyin(p->red, &sc->sc_cmap.r[index], count);
732 copyin(p->green, &sc->sc_cmap.g[index], count);
733 copyin(p->blue, &sc->sc_cmap.b[index], count);
734
735 sc->sc_changed |= DATA_CMAP_CHANGED;
736
737 return (0);
738 }
739
740
741 static int
742 set_cursor(sc, p)
743 struct sfb_softc *sc;
744 struct wsdisplay_cursor *p;
745 {
746 #define cc (&sc->sc_cursor)
747 int v, index, count, icount;
748
749 v = p->which;
750 if (v & WSDISPLAY_CURSOR_DOCMAP) {
751 index = p->cmap.index;
752 count = p->cmap.count;
753 if (index >= 2 || (index + count) > 2)
754 return (EINVAL);
755 if (!uvm_useracc(p->cmap.red, count, B_READ) ||
756 !uvm_useracc(p->cmap.green, count, B_READ) ||
757 !uvm_useracc(p->cmap.blue, count, B_READ))
758 return (EFAULT);
759 }
760 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
761 if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE)
762 return (EINVAL);
763 icount = ((p->size.x < 33) ? 4 : 8) * p->size.y;
764 if (!uvm_useracc(p->image, icount, B_READ) ||
765 !uvm_useracc(p->mask, icount, B_READ))
766 return (EFAULT);
767 }
768 if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOCUR)) {
769 if (v & WSDISPLAY_CURSOR_DOCUR)
770 cc->cc_hot = p->hot;
771 if (v & WSDISPLAY_CURSOR_DOPOS)
772 set_curpos(sc, &p->pos);
773 bt459_set_curpos(sc);
774 }
775
776 sc->sc_changed = 0;
777 if (v & WSDISPLAY_CURSOR_DOCUR) {
778 sc->sc_curenb = p->enable;
779 sc->sc_changed |= DATA_ENB_CHANGED;
780 }
781 if (v & WSDISPLAY_CURSOR_DOCMAP) {
782 copyin(p->cmap.red, &cc->cc_color[index], count);
783 copyin(p->cmap.green, &cc->cc_color[index + 2], count);
784 copyin(p->cmap.blue, &cc->cc_color[index + 4], count);
785 sc->sc_changed |= DATA_CURCMAP_CHANGED;
786 }
787 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
788 cc->cc_size = p->size;
789 memset(cc->cc_image, 0, sizeof cc->cc_image);
790 copyin(p->image, cc->cc_image, icount);
791 copyin(p->mask, cc->cc_image+CURSOR_MAX_SIZE, icount);
792 sc->sc_changed |= DATA_CURSHAPE_CHANGED;
793 }
794
795 return (0);
796 #undef cc
797 }
798
799 static int
800 get_cursor(sc, p)
801 struct sfb_softc *sc;
802 struct wsdisplay_cursor *p;
803 {
804 return (ENOTTY); /* XXX */
805 }
806
807 static void
808 set_curpos(sc, curpos)
809 struct sfb_softc *sc;
810 struct wsdisplay_curpos *curpos;
811 {
812 struct fb_devconfig *dc = sc->sc_dc;
813 int x = curpos->x, y = curpos->y;
814
815 if (y < 0)
816 y = 0;
817 else if (y > dc->dc_ht)
818 y = dc->dc_ht;
819 if (x < 0)
820 x = 0;
821 else if (x > dc->dc_wid)
822 x = dc->dc_wid;
823 sc->sc_cursor.cc_pos.x = x;
824 sc->sc_cursor.cc_pos.y = y;
825 }
826
827 static void
828 bt459_set_curpos(sc)
829 struct sfb_softc *sc;
830 {
831 caddr_t sfbbase = (caddr_t)sc->sc_dc->dc_vaddr;
832 caddr_t vdac = (void *)(sfbbase + SFB_RAMDAC_OFFSET);
833 int x, y, s;
834
835 x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x;
836 y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y;
837
838 x += sc->sc_cursor.cc_magic.x;
839 y += sc->sc_cursor.cc_magic.y;
840
841 s = spltty();
842
843 SELECT(vdac, BT459_REG_CURSOR_X_LOW);
844 REG(vdac, bt_reg) = x; tc_wmb();
845 REG(vdac, bt_reg) = x >> 8; tc_wmb();
846 REG(vdac, bt_reg) = y; tc_wmb();
847 REG(vdac, bt_reg) = y >> 8; tc_wmb();
848
849 splx(s);
850 }
851
852 #define MODE_SIMPLE 0
853 #define MODE_OPAQUESTIPPLE 1
854 #define MODE_OPAQUELINE 2
855 #define MODE_TRANSPARENTSTIPPLE 5
856 #define MODE_TRANSPARENTLINE 6
857 #define MODE_COPY 7
858
859 #define SFBALIGNMASK 0x7
860 #define SFBSTIPPLEALL1 0xffffffff
861 #define SFBSTIPPLEBITS 32
862 #define SFBSTIPPLEBITMASK 0x1f
863 #define SFBSTIPPLEBYTESDONE 32
864
865 /*
866 * Paint (or unpaint) the cursor.
867 */
868 void
869 sfb_cursor(id, on, row, col)
870 void *id;
871 int on, row, col;
872 {
873 struct rcons *rc = id;
874 int x, y;
875
876 /* turn the cursor off */
877 if (!on) {
878 /* make sure it's on */
879 if ((rc->rc_bits & RC_CURSOR) == 0)
880 return;
881
882 row = *rc->rc_crowp;
883 col = *rc->rc_ccolp;
884 } else {
885 /* unpaint the old copy. */
886 *rc->rc_crowp = row;
887 *rc->rc_ccolp = col;
888 }
889
890 x = col * rc->rc_font->width + rc->rc_xorigin;
891 y = row * rc->rc_font->height + rc->rc_yorigin;
892
893 raster_op(rc->rc_sp, x, y,
894 rc->rc_font->width, rc->rc_font->height,
895 RAS_INVERT,
896 (struct raster *) 0, 0, 0);
897
898 rc->rc_bits ^= RC_CURSOR;
899 }
900
901 /*
902 * Actually write a string to the frame buffer.
903 */
904 int
905 sfb_mapchar(id, uni, index)
906 void *id;
907 int uni;
908 unsigned int *index;
909 {
910 if (uni < 128) {
911 *index = uni;
912 return (5);
913 }
914 *index = ' ';
915 return (0);
916 }
917
918 /*
919 * Actually write a string to the frame buffer.
920 */
921 void
922 sfb_putchar(id, row, col, uc, attr)
923 void *id;
924 int row, col;
925 u_int uc;
926 long attr;
927 {
928 struct rcons *rc = id;
929 int x, y, op;
930 u_char help;
931
932 x = col * rc->rc_font->width + rc->rc_xorigin;
933 y = row * rc->rc_font->height + rc->rc_font_ascent + rc->rc_yorigin;
934
935 op = RAS_SRC;
936 if ((attr != 0) ^ ((rc->rc_bits & RC_INVERT) != 0))
937 op = RAS_NOT(op);
938 help = uc & 0xff;
939 raster_textn(rc->rc_sp, x, y, op, rc->rc_font, &help, 1);
940 }
941
942 /*
943 * Copy characters in a line.
944 */
945 void
946 sfb_copycols(id, row, srccol, dstcol, ncols)
947 void *id;
948 int row, srccol, dstcol, ncols;
949 {
950 struct rcons *rc = id;
951 struct raster *rap = rc->rc_sp;
952 caddr_t sp, dp, basex, sfb;
953 int scanspan, height, width, aligns, alignd, w, y;
954 u_int32_t lmasks, rmasks, lmaskd, rmaskd;
955
956 scanspan = rap->linelongs * 4;
957 y = rc->rc_yorigin + rc->rc_font->height * row;
958 basex = (caddr_t)rap->pixels + y * scanspan + rc->rc_xorigin;
959 height = rc->rc_font->height;
960 w = rc->rc_font->width * ncols;
961
962 dp = basex + rc->rc_font->width * dstcol;
963 alignd = (long)dp & SFBALIGNMASK;
964 dp -= alignd;
965 width = w + alignd;
966 lmaskd = SFBSTIPPLEALL1 << alignd;
967 rmaskd = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
968
969 sp = basex + rc->rc_font->width * srccol;
970 aligns = (long)sp & SFBALIGNMASK;
971 sp -= aligns;
972 width = w + aligns;
973 lmasks = SFBSTIPPLEALL1 << aligns;
974 rmasks = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
975
976 width += (-width & SFBSTIPPLEBITMASK);
977 sfb = rap->data;
978 *(u_int32_t *)(sfb + SFB_ASIC_MODE) = MODE_COPY;
979 *(u_int32_t *)(sfb + SFB_ASIC_PLANEMASK) = ~0;
980 *(u_int32_t *)(sfb + SFB_ASIC_PIXELSHIFT) = alignd - aligns;
981
982 if (width <= SFBSTIPPLEBITS) {
983 lmasks = lmasks & rmasks;
984 lmaskd = lmaskd & rmaskd;
985 while (height > 0) {
986 *(u_int32_t *)sp = lmasks;
987 *(u_int32_t *)dp = lmaskd;
988 sp += scanspan;
989 dp += scanspan;
990 height--;
991 }
992 }
993 /* copy forward (left-to-right) */
994 else if (dstcol < srccol || srccol + ncols < dstcol) {
995 caddr_t sq = sp, dq = dp;
996
997 w = width;
998 while (height > 0) {
999 *(u_int32_t *)sp = lmasks;
1000 *(u_int32_t *)dp = lmaskd;
1001 width -= 2 * SFBSTIPPLEBITS;
1002 while (width > 0) {
1003 sp += SFBSTIPPLEBYTESDONE;
1004 dp += SFBSTIPPLEBYTESDONE;
1005 *(u_int32_t *)sp = SFBSTIPPLEALL1;
1006 *(u_int32_t *)dp = SFBSTIPPLEALL1;
1007 width -= SFBSTIPPLEBITS;
1008 }
1009 sp += SFBSTIPPLEBYTESDONE;
1010 dp += SFBSTIPPLEBYTESDONE;
1011 *(u_int32_t *)sp = rmasks;
1012 *(u_int32_t *)dp = rmaskd;
1013
1014 sp = (sq += scanspan);
1015 dp = (dq += scanspan);
1016 width = w;
1017 height--;
1018 }
1019 }
1020 /* copy backward (right-to-left) */
1021 else {
1022 caddr_t sq = (sp += width), dq = (dp += width);
1023
1024 w = width;
1025 while (height > 0) {
1026 *(u_int32_t *)sp = rmasks;
1027 *(u_int32_t *)dp = rmaskd;
1028 width -= 2 * SFBSTIPPLEBITS;
1029 while (width > 0) {
1030 sp -= SFBSTIPPLEBYTESDONE;
1031 dp -= SFBSTIPPLEBYTESDONE;
1032 *(u_int32_t *)sp = SFBSTIPPLEALL1;
1033 *(u_int32_t *)dp = SFBSTIPPLEALL1;
1034 width -= SFBSTIPPLEBITS;
1035 }
1036 sp -= SFBSTIPPLEBYTESDONE;
1037 dp -= SFBSTIPPLEBYTESDONE;
1038 *(u_int32_t *)sp = lmasks;
1039 *(u_int32_t *)dp = lmaskd;
1040
1041 sp = (sq += scanspan);
1042 dp = (dq += scanspan);
1043 width = w;
1044 height--;
1045 }
1046 }
1047 *(u_int32_t *)(sfb + SFB_ASIC_MODE) = MODE_SIMPLE;
1048 }
1049
1050 /*
1051 * Clear characters in a line.
1052 */
1053 void
1054 sfb_erasecols(id, row, startcol, ncols, fillattr)
1055 void *id;
1056 int row, startcol, ncols;
1057 long fillattr;
1058 {
1059 struct rcons *rc = id;
1060 struct raster *rap = rc->rc_sp;
1061 caddr_t sfb, p;
1062 int scanspan, startx, height, width, align, w, y;
1063 u_int32_t lmask, rmask;
1064
1065 scanspan = rap->linelongs * 4;
1066 y = rc->rc_yorigin + rc->rc_font->height * row;
1067 startx = rc->rc_xorigin + rc->rc_font->width * startcol;
1068 height = rc->rc_font->height;
1069 w = rc->rc_font->width * ncols;
1070
1071 p = (caddr_t)rap->pixels + y * scanspan + startx;
1072 align = (long)p & SFBALIGNMASK;
1073 p -= align;
1074 width = w + align;
1075 lmask = SFBSTIPPLEALL1 << align;
1076 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
1077 sfb = rap->data;
1078 *(u_int32_t *)(sfb + SFB_ASIC_MODE) = MODE_TRANSPARENTSTIPPLE;
1079 *(u_int32_t *)(sfb + SFB_ASIC_PLANEMASK) = ~0;
1080 *(u_int32_t *)(sfb + SFB_ASIC_FG) = (fillattr == 0) ? 0 : 0x01010101;
1081 if (width <= SFBSTIPPLEBITS) {
1082 lmask = lmask & rmask;
1083 while (height > 0) {
1084 *(u_int32_t *)(sfb + SFB_ASIC_ADDRESS) = (long)p;
1085 *(u_int32_t *)(sfb + SFB_ASIC_START) = lmask;
1086 p += scanspan;
1087 height--;
1088 }
1089 }
1090 else {
1091 caddr_t q = p;
1092 while (height > 0) {
1093 *(u_int32_t *)p = lmask;
1094 width -= 2 * SFBSTIPPLEBITS;
1095 while (width > 0) {
1096 p += SFBSTIPPLEBYTESDONE;
1097 *(u_int32_t *)p = SFBSTIPPLEALL1;
1098 width -= SFBSTIPPLEBITS;
1099 }
1100 p += SFBSTIPPLEBYTESDONE;
1101 *(u_int32_t *)p = rmask;
1102
1103 p = (q += scanspan);
1104 width = w + align;
1105 height--;
1106 }
1107 }
1108 *(u_int32_t *)(sfb + SFB_ASIC_MODE) = MODE_SIMPLE;
1109 }
1110
1111 /*
1112 * Copy lines.
1113 */
1114 void
1115 sfb_copyrows(id, srcrow, dstrow, nrows)
1116 void *id;
1117 int srcrow, dstrow, nrows;
1118 {
1119 struct rcons *rc = id;
1120 struct raster *rap = rc->rc_sp;
1121 caddr_t sfb, p;
1122 int scanspan, offset, srcy, height, width, align, w;
1123 u_int32_t lmask, rmask;
1124
1125 scanspan = rap->linelongs * 4;
1126 height = rc->rc_font->height * nrows;
1127 offset = (dstrow - srcrow) * scanspan * rc->rc_font->height;
1128 srcy = rc->rc_yorigin + rc->rc_font->height * srcrow;
1129 if (srcrow < dstrow && srcrow + nrows > dstrow) {
1130 scanspan = -scanspan;
1131 srcy += height;
1132 }
1133
1134 p = (caddr_t)(rap->pixels + srcy * rap->linelongs) + rc->rc_xorigin;
1135 align = (long)p & SFBALIGNMASK;
1136 p -= align;
1137 w = rc->rc_font->width * rc->rc_maxcol;
1138 width = w + align;
1139 lmask = SFBSTIPPLEALL1 << align;
1140 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
1141 sfb = rap->data;
1142 *(u_int32_t *)(sfb + SFB_ASIC_MODE) = MODE_COPY;
1143 *(u_int32_t *)(sfb + SFB_ASIC_PLANEMASK) = ~0;
1144 *(u_int32_t *)(sfb + SFB_ASIC_PIXELSHIFT) = 0;
1145 if (width <= SFBSTIPPLEBITS) {
1146 /* never happens */;
1147 }
1148 else {
1149 caddr_t q = p;
1150 while (height > 0) {
1151 *(u_int32_t *)p = lmask;
1152 *(u_int32_t *)(p + offset) = lmask;
1153 width -= 2 * SFBSTIPPLEBITS;
1154 while (width > 0) {
1155 p += SFBSTIPPLEBYTESDONE;
1156 *(u_int32_t *)p = SFBSTIPPLEALL1;
1157 *(u_int32_t *)(p + offset) = SFBSTIPPLEALL1;
1158 width -= SFBSTIPPLEBITS;
1159 }
1160 p += SFBSTIPPLEBYTESDONE;
1161 *(u_int32_t *)p = rmask;
1162 *(u_int32_t *)(p + offset) = rmask;
1163
1164 p = (q += scanspan);
1165 width = w + align;
1166 height--;
1167 }
1168 }
1169 *(u_int32_t *)(sfb + SFB_ASIC_MODE) = MODE_SIMPLE;
1170 }
1171
1172 /*
1173 * Erase lines.
1174 */
1175 void
1176 sfb_eraserows(id, startrow, nrows, fillattr)
1177 void *id;
1178 int startrow, nrows;
1179 long fillattr;
1180 {
1181 struct rcons *rc = id;
1182 struct raster *rap = rc->rc_sp;
1183 caddr_t sfb, p;
1184 int scanspan, starty, height, width, align, w;
1185 u_int32_t lmask, rmask;
1186
1187 scanspan = rap->linelongs * 4;
1188 starty = rc->rc_yorigin + rc->rc_font->height * startrow;
1189 height = rc->rc_font->height * nrows;
1190
1191 p = (caddr_t)rap->pixels + starty * scanspan + rc->rc_xorigin;
1192 align = (long)p & SFBALIGNMASK;
1193 p -= align;
1194 w = rc->rc_font->width * rc->rc_maxcol;
1195 width = w + align;
1196 lmask = SFBSTIPPLEALL1 << align;
1197 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
1198 sfb = rap->data;
1199 *(u_int32_t *)(sfb + SFB_ASIC_MODE) = MODE_TRANSPARENTSTIPPLE;
1200 *(u_int32_t *)(sfb + SFB_ASIC_PLANEMASK) = ~0;
1201 *(u_int32_t *)(sfb + SFB_ASIC_FG) = (fillattr == 0) ? 0 : 0x01010101;
1202 if (width <= SFBSTIPPLEBITS) {
1203 /* never happens */;
1204 }
1205 else {
1206 caddr_t q = p;
1207 while (height > 0) {
1208 *(u_int32_t *)p = lmask;
1209 width -= 2 * SFBSTIPPLEBITS;
1210 while (width > 0) {
1211 p += SFBSTIPPLEBYTESDONE;
1212 *(u_int32_t *)p = SFBSTIPPLEALL1;
1213 width -= SFBSTIPPLEBITS;
1214 }
1215 p += SFBSTIPPLEBYTESDONE;
1216 *(u_int32_t *)p = rmask;
1217
1218 p = (q += scanspan);
1219 width = w + align;
1220 height--;
1221 }
1222 }
1223 *(u_int32_t *)(sfb + SFB_ASIC_MODE) = MODE_SIMPLE;
1224 }
1225
1226 int
1227 sfb_alloc_attr(id, fg, bg, flags, attrp)
1228 void *id;
1229 int fg, bg, flags;
1230 long *attrp;
1231 {
1232 if (flags & (WSATTR_HILIT | WSATTR_BLINK |
1233 WSATTR_UNDERLINE | WSATTR_WSCOLORS))
1234 return (EINVAL);
1235 if (flags & WSATTR_REVERSE)
1236 *attrp = 1;
1237 else
1238 *attrp = 0;
1239 return (0);
1240 }
1241