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