sfb.c revision 1.43 1 /* $NetBSD: sfb.c,v 1.43 2001/01/19 05:43:43 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.43 2001/01/19 05:43:43 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 == 0) ^ turnoff) {
431 dc->dc_blanked = turnoff;
432 #if 0 /* XXX later XXX */
433 To turn off, assign value 0 in ASIC_VIDEO_VALID register.
434 #endif /* XXX XXX XXX */
435 }
436 return (0);
437
438 case WSDISPLAYIO_GVIDEO:
439 *(u_int *)data = dc->dc_blanked ?
440 WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON;
441 return (0);
442
443 case WSDISPLAYIO_GCURPOS:
444 *(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos;
445 return (0);
446
447 case WSDISPLAYIO_SCURPOS:
448 set_curpos(sc, (struct wsdisplay_curpos *)data);
449 sc->sc_changed = WSDISPLAY_CURSOR_DOPOS;
450 return (0);
451
452 case WSDISPLAYIO_GCURMAX:
453 ((struct wsdisplay_curpos *)data)->x =
454 ((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE;
455 return (0);
456
457 case WSDISPLAYIO_GCURSOR:
458 return get_cursor(sc, (struct wsdisplay_cursor *)data);
459
460 case WSDISPLAYIO_SCURSOR:
461 return set_cursor(sc, (struct wsdisplay_cursor *)data);
462 }
463 return (ENOTTY);
464 }
465
466 static paddr_t
467 sfbmmap(v, offset, prot)
468 void *v;
469 off_t offset;
470 int prot;
471 {
472 struct sfb_softc *sc = v;
473
474 if (offset >= SFB_SIZE || offset < 0)
475 return (-1);
476 return machine_btop(sc->sc_dc->dc_paddr + offset);
477 }
478
479 static int
480 sfb_alloc_screen(v, type, cookiep, curxp, curyp, attrp)
481 void *v;
482 const struct wsscreen_descr *type;
483 void **cookiep;
484 int *curxp, *curyp;
485 long *attrp;
486 {
487 struct sfb_softc *sc = v;
488 long defattr;
489
490 if (sc->nscreens > 0)
491 return (ENOMEM);
492
493 *cookiep = &sc->sc_dc->rinfo; /* one and only for now */
494 *curxp = 0;
495 *curyp = 0;
496 (*sc->sc_dc->rinfo.ri_ops.alloc_attr)(&sc->sc_dc->rinfo, 0, 0, 0, &defattr);
497 *attrp = defattr;
498 sc->nscreens++;
499 return (0);
500 }
501
502 static void
503 sfb_free_screen(v, cookie)
504 void *v;
505 void *cookie;
506 {
507 struct sfb_softc *sc = v;
508
509 if (sc->sc_dc == &sfb_console_dc)
510 panic("sfb_free_screen: console");
511
512 sc->nscreens--;
513 }
514
515 static int
516 sfb_show_screen(v, cookie, waitok, cb, cbarg)
517 void *v;
518 void *cookie;
519 int waitok;
520 void (*cb) __P((void *, int, int));
521 void *cbarg;
522 {
523
524 return (0);
525 }
526
527 /* EXPORT */ int
528 sfb_cnattach(addr)
529 tc_addr_t addr;
530 {
531 struct fb_devconfig *dcp = &sfb_console_dc;
532 long defattr;
533
534 sfb_getdevconfig(addr, dcp);
535
536 (*dcp->rinfo.ri_ops.alloc_attr)(&dcp->rinfo, 0, 0, 0, &defattr);
537
538 wsdisplay_cnattach(&sfb_stdscreen, &dcp->rinfo, 0, 0, defattr);
539 sfb_consaddr = addr;
540 return(0);
541 }
542
543 static int
544 sfbintr(arg)
545 void *arg;
546 {
547 struct sfb_softc *sc = arg;
548 caddr_t sfbasic = (caddr_t)sc->sc_dc->dc_vaddr + SFB_ASIC_OFFSET;
549 caddr_t vdac;
550 int v;
551
552 *(u_int32_t *)(sfbasic + SFB_ASIC_CLEAR_INTR) = 0;
553 /* *(u_int32_t *)(sfbasic + SFB_ASIC_ENABLE_INTR) = 1; */
554
555 if (sc->sc_changed == 0)
556 goto finish;
557
558 vdac = (caddr_t)sc->sc_dc->dc_vaddr + SFB_RAMDAC_OFFSET;
559 v = sc->sc_changed;
560 if (v & WSDISPLAY_CURSOR_DOCUR) {
561 SELECT(vdac, BT459_IREG_CCR);
562 REG(vdac, bt_reg) = (sc->sc_curenb) ? 0xc0 : 0x00;
563 }
564 if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT)) {
565 int x, y;
566
567 x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x;
568 y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y;
569 x += sc->sc_cursor.cc_magic.x;
570 y += sc->sc_cursor.cc_magic.y;
571
572 SELECT(vdac, BT459_IREG_CURSOR_X_LOW);
573 REG(vdac, bt_reg) = x; tc_wmb();
574 REG(vdac, bt_reg) = x >> 8; tc_wmb();
575 REG(vdac, bt_reg) = y; tc_wmb();
576 REG(vdac, bt_reg) = y >> 8; tc_wmb();
577 }
578 if (v & WSDISPLAY_CURSOR_DOCMAP) {
579 u_int8_t *cp = sc->sc_cursor.cc_color;
580
581 SELECT(vdac, BT459_IREG_CCOLOR_2);
582 REG(vdac, bt_reg) = cp[1]; tc_wmb();
583 REG(vdac, bt_reg) = cp[3]; tc_wmb();
584 REG(vdac, bt_reg) = cp[5]; tc_wmb();
585
586 REG(vdac, bt_reg) = cp[0]; tc_wmb();
587 REG(vdac, bt_reg) = cp[2]; tc_wmb();
588 REG(vdac, bt_reg) = cp[4]; tc_wmb();
589 }
590 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
591 u_int8_t *ip, *mp, img, msk;
592 u_int8_t u;
593 int bcnt;
594
595 ip = (u_int8_t *)sc->sc_cursor.cc_image;
596 mp = (u_int8_t *)(sc->sc_cursor.cc_image + CURSOR_MAX_SIZE);
597
598 bcnt = 0;
599 SELECT(vdac, BT459_IREG_CRAM_BASE+0);
600 /* 64 pixel scan line is consisted with 16 byte cursor ram */
601 while (bcnt < sc->sc_cursor.cc_size.y * 16) {
602 /* pad right half 32 pixel when smaller than 33 */
603 if ((bcnt & 0x8) && sc->sc_cursor.cc_size.x < 33) {
604 REG(vdac, bt_reg) = 0; tc_wmb();
605 REG(vdac, bt_reg) = 0; tc_wmb();
606 }
607 else {
608 img = *ip++;
609 msk = *mp++;
610 img &= msk; /* cookie off image */
611 u = (msk & 0x0f) << 4 | (img & 0x0f);
612 REG(vdac, bt_reg) = shuffle[u]; tc_wmb();
613 u = (msk & 0xf0) | (img & 0xf0) >> 4;
614 REG(vdac, bt_reg) = shuffle[u]; tc_wmb();
615 }
616 bcnt += 2;
617 }
618 /* pad unoccupied scan lines */
619 while (bcnt < CURSOR_MAX_SIZE * 16) {
620 REG(vdac, bt_reg) = 0; tc_wmb();
621 REG(vdac, bt_reg) = 0; tc_wmb();
622 bcnt += 2;
623 }
624 }
625 if (v & WSDISPLAY_CMAP_DOLUT) {
626 struct hwcmap256 *cm = &sc->sc_cmap;
627 int index;
628
629 SELECT(vdac, 0);
630 for (index = 0; index < CMAP_SIZE; index++) {
631 REG(vdac, bt_cmap) = cm->r[index]; tc_wmb();
632 REG(vdac, bt_cmap) = cm->g[index]; tc_wmb();
633 REG(vdac, bt_cmap) = cm->b[index]; tc_wmb();
634 }
635 }
636 sc->sc_changed = 0;
637 finish:
638 return (1);
639 }
640
641 static void
642 sfbinit(dc)
643 struct fb_devconfig *dc;
644 {
645 caddr_t vdac = (caddr_t)dc->dc_vaddr + SFB_RAMDAC_OFFSET;
646 const u_int8_t *p;
647 int i;
648
649 SELECT(vdac, BT459_IREG_COMMAND_0);
650 REG(vdac, bt_reg) = 0x40; /* CMD0 */ tc_wmb();
651 REG(vdac, bt_reg) = 0x0; /* CMD1 */ tc_wmb();
652 REG(vdac, bt_reg) = 0xc0; /* CMD2 */ tc_wmb();
653 REG(vdac, bt_reg) = 0xff; /* PRM */ tc_wmb();
654 REG(vdac, bt_reg) = 0; /* 205 */ tc_wmb();
655 REG(vdac, bt_reg) = 0x0; /* PBM */ tc_wmb();
656 REG(vdac, bt_reg) = 0; /* 207 */ tc_wmb();
657 REG(vdac, bt_reg) = 0x0; /* ORM */ tc_wmb();
658 REG(vdac, bt_reg) = 0x0; /* OBM */ tc_wmb();
659 REG(vdac, bt_reg) = 0x0; /* ILV */ tc_wmb();
660 REG(vdac, bt_reg) = 0x0; /* TEST */ tc_wmb();
661
662 SELECT(vdac, BT459_IREG_CCR);
663 REG(vdac, bt_reg) = 0x0; tc_wmb();
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
677 /* build sane colormap */
678 SELECT(vdac, 0);
679 p = rasops_cmap;
680 for (i = 0; i < CMAP_SIZE; i++, p += 3) {
681 REG(vdac, bt_cmap) = p[0]; tc_wmb();
682 REG(vdac, bt_cmap) = p[1]; tc_wmb();
683 REG(vdac, bt_cmap) = p[2]; tc_wmb();
684 }
685
686 /* clear out cursor image */
687 SELECT(vdac, BT459_IREG_CRAM_BASE);
688 for (i = 0; i < 1024; i++)
689 REG(vdac, bt_reg) = 0xff; tc_wmb();
690
691 /*
692 * 2 bit/pixel cursor. Assign MSB for cursor mask and LSB for
693 * cursor image. CCOLOR_2 for mask color, while CCOLOR_3 for
694 * image color. CCOLOR_1 will be never used.
695 */
696 SELECT(vdac, BT459_IREG_CCOLOR_1);
697 REG(vdac, bt_reg) = 0xff; tc_wmb();
698 REG(vdac, bt_reg) = 0xff; tc_wmb();
699 REG(vdac, bt_reg) = 0xff; tc_wmb();
700
701 REG(vdac, bt_reg) = 0; tc_wmb();
702 REG(vdac, bt_reg) = 0; tc_wmb();
703 REG(vdac, bt_reg) = 0; tc_wmb();
704
705 REG(vdac, bt_reg) = 0xff; tc_wmb();
706 REG(vdac, bt_reg) = 0xff; tc_wmb();
707 REG(vdac, bt_reg) = 0xff; tc_wmb();
708 }
709
710 static int
711 get_cmap(sc, p)
712 struct sfb_softc *sc;
713 struct wsdisplay_cmap *p;
714 {
715 u_int index = p->index, count = p->count;
716
717 if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE)
718 return (EINVAL);
719
720 if (!uvm_useracc(p->red, count, B_WRITE) ||
721 !uvm_useracc(p->green, count, B_WRITE) ||
722 !uvm_useracc(p->blue, count, B_WRITE))
723 return (EFAULT);
724
725 copyout(&sc->sc_cmap.r[index], p->red, count);
726 copyout(&sc->sc_cmap.g[index], p->green, count);
727 copyout(&sc->sc_cmap.b[index], p->blue, count);
728
729 return (0);
730 }
731
732 static int
733 set_cmap(sc, p)
734 struct sfb_softc *sc;
735 struct wsdisplay_cmap *p;
736 {
737 u_int index = p->index, count = p->count;
738
739 if (index >= CMAP_SIZE || (index + count) > CMAP_SIZE)
740 return (EINVAL);
741
742 if (!uvm_useracc(p->red, count, B_READ) ||
743 !uvm_useracc(p->green, count, B_READ) ||
744 !uvm_useracc(p->blue, count, B_READ))
745 return (EFAULT);
746
747 copyin(p->red, &sc->sc_cmap.r[index], count);
748 copyin(p->green, &sc->sc_cmap.g[index], count);
749 copyin(p->blue, &sc->sc_cmap.b[index], count);
750 sc->sc_changed |= WSDISPLAY_CMAP_DOLUT;
751 return (0);
752 }
753
754 static int
755 set_cursor(sc, p)
756 struct sfb_softc *sc;
757 struct wsdisplay_cursor *p;
758 {
759 #define cc (&sc->sc_cursor)
760 int v, index, count, icount;
761
762 v = p->which;
763 if (v & WSDISPLAY_CURSOR_DOCMAP) {
764 index = p->cmap.index;
765 count = p->cmap.count;
766 if (index >= 2 || (index + count) > 2)
767 return (EINVAL);
768 if (!uvm_useracc(p->cmap.red, count, B_READ) ||
769 !uvm_useracc(p->cmap.green, count, B_READ) ||
770 !uvm_useracc(p->cmap.blue, count, B_READ))
771 return (EFAULT);
772 }
773 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
774 if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE)
775 return (EINVAL);
776 icount = ((p->size.x < 33) ? 4 : 8) * p->size.y;
777 if (!uvm_useracc(p->image, icount, B_READ) ||
778 !uvm_useracc(p->mask, icount, B_READ))
779 return (EFAULT);
780 }
781
782 if (v & WSDISPLAY_CURSOR_DOCUR)
783 sc->sc_curenb = p->enable;
784 if (v & WSDISPLAY_CURSOR_DOPOS)
785 set_curpos(sc, &p->pos);
786 if (v & WSDISPLAY_CURSOR_DOHOT)
787 cc->cc_hot = p->hot;
788 if (v & WSDISPLAY_CURSOR_DOCMAP) {
789 copyin(p->cmap.red, &cc->cc_color[index], count);
790 copyin(p->cmap.green, &cc->cc_color[index + 2], count);
791 copyin(p->cmap.blue, &cc->cc_color[index + 4], count);
792 }
793 if (v & WSDISPLAY_CURSOR_DOSHAPE) {
794 cc->cc_size = p->size;
795 memset(cc->cc_image, 0, sizeof cc->cc_image);
796 copyin(p->image, cc->cc_image, icount);
797 copyin(p->mask, cc->cc_image+CURSOR_MAX_SIZE, icount);
798 }
799 sc->sc_changed = v;
800
801 return (0);
802 #undef cc
803 }
804
805 static int
806 get_cursor(sc, p)
807 struct sfb_softc *sc;
808 struct wsdisplay_cursor *p;
809 {
810
811 return (ENOTTY); /* XXX */
812 }
813
814 static void
815 set_curpos(sc, curpos)
816 struct sfb_softc *sc;
817 struct wsdisplay_curpos *curpos;
818 {
819 struct fb_devconfig *dc = sc->sc_dc;
820 int x = curpos->x, y = curpos->y;
821
822 if (y < 0)
823 y = 0;
824 else if (y > dc->dc_ht)
825 y = dc->dc_ht;
826 if (x < 0)
827 x = 0;
828 else if (x > dc->dc_wid)
829 x = dc->dc_wid;
830 sc->sc_cursor.cc_pos.x = x;
831 sc->sc_cursor.cc_pos.y = y;
832 }
833
834 #define MODE_SIMPLE 0
835 #define MODE_OPAQUESTIPPLE 1
836 #define MODE_OPAQUELINE 2
837 #define MODE_TRANSPARENTSTIPPLE 5
838 #define MODE_TRANSPARENTLINE 6
839 #define MODE_COPY 7
840
841 /* parameters for 8bpp configuration */
842 #define SFBALIGNMASK 0x7
843 #define SFBSTIPPLEALL1 0xffffffff
844 #define SFBSTIPPLEBITS 32
845 #define SFBSTIPPLEBITMASK 0x1f
846 #define SFBSTIPPLEBYTESDONE 32
847 #define SFBCOPYALL1 0xffffffff
848 #define SFBCOPYBITS 32
849 #define SFBCOPYBITMASK 0x1f
850 #define SFBCOPYBYTESDONE 32
851
852 #if defined(pmax)
853 #define WRITE_MB()
854 #define BUMP(p) (p)
855 #endif
856
857 #if defined(alpha)
858 #define WRITE_MB() tc_wmb()
859 /* SFB registers replicated in 128B stride; cycle after eight iterations */
860 #define BUMP(p) ((p) = (caddr_t)(((long)(p) + 0x80) & ~0x400))
861 #endif
862
863 #define SFBMODE(p, v) \
864 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_MODE) = (v))
865 #define SFBROP(p, v) \
866 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_ROP) = (v))
867 #define SFBPLANEMASK(p, v) \
868 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_PLANEMASK) = (v))
869 #define SFBPIXELMASK(p, v) \
870 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELMASK) = (v))
871 #define SFBADDRESS(p, v) \
872 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_ADDRESS) = (v))
873 #define SFBSTART(p, v) \
874 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_START) = (v))
875 #define SFBPIXELSHIFT(p, v) \
876 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_PIXELSHIFT) = (v))
877 #define SFBFG(p, v) \
878 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_FG) = (v))
879 #define SFBBG(p, v) \
880 (*(u_int32_t *)(BUMP(p) + SFB_ASIC_BG) = (v))
881
882 /*
883 * Paint the cursor.
884 */
885 static void
886 sfb_do_cursor(ri)
887 struct rasops_info *ri;
888 {
889 caddr_t sfb, p;
890 int scanspan, height, width, align, x, y;
891 u_int32_t lmask, rmask;
892
893 x = ri->ri_ccol * ri->ri_font->fontwidth;
894 y = ri->ri_crow * ri->ri_font->fontheight;
895 scanspan = ri->ri_stride;
896 height = ri->ri_font->fontheight;
897
898 p = ri->ri_bits + y * scanspan + x;
899 align = (long)p & SFBALIGNMASK;
900 p -= align;
901 width = ri->ri_font->fontwidth + align;
902 lmask = SFBSTIPPLEALL1 << align;
903 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
904 sfb = ri->ri_hw;
905
906 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
907 SFBPLANEMASK(sfb, ~0);
908 SFBROP(sfb, 6); /* ROP_XOR */
909 SFBFG(sfb, ~0);
910
911 lmask = lmask & rmask;
912 while (height > 0) {
913 SFBADDRESS(sfb, (long)p);
914 SFBSTART(sfb, lmask);
915 p += scanspan;
916 height--;
917 }
918 SFBMODE(sfb, MODE_SIMPLE);
919 SFBROP(sfb, 3); /* ROP_COPY */
920 }
921
922 /*
923 * Paint a character.
924 */
925 static void
926 sfb_putchar(id, row, col, uc, attr)
927 void *id;
928 int row, col;
929 u_int uc;
930 long attr;
931 {
932 struct rasops_info *ri = id;
933 caddr_t sfb, p;
934 int scanspan, height, width, align, x, y;
935 u_int32_t lmask, rmask, glyph;
936 u_int8_t *g;
937
938 x = col * ri->ri_font->fontwidth;
939 y = row * ri->ri_font->fontheight;
940 scanspan = ri->ri_stride;
941 height = ri->ri_font->fontheight;
942 uc -= ri->ri_font->firstchar;
943 g = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
944
945 p = ri->ri_bits + y * scanspan + x;
946 align = (long)p & SFBALIGNMASK;
947 p -= align;
948 width = ri->ri_font->fontwidth + align;
949 lmask = SFBSTIPPLEALL1 << align;
950 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
951 sfb = ri->ri_hw;
952
953 SFBMODE(sfb, MODE_OPAQUESTIPPLE);
954 SFBPLANEMASK(sfb, ~0);
955 SFBFG(sfb, ri->ri_devcmap[(attr >> 24) & 15]);
956 SFBBG(sfb, ri->ri_devcmap[(attr >> 16) & 15]);
957
958 /* XXX 2B stride fonts only XXX */
959 lmask = lmask & rmask;
960 while (height > 0) {
961 glyph = *(u_int16_t *)g; /* XXX */
962 SFBPIXELMASK(sfb, lmask);
963 SFBADDRESS(sfb, (long)p);
964 SFBSTART(sfb, glyph << align);
965 p += scanspan;
966 g += 2; /* XXX */
967 height--;
968 }
969 if (attr & 1 /* UNDERLINE */) {
970 p -= scanspan * 2;
971 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
972 SFBADDRESS(sfb, (long)p);
973 SFBSTART(sfb, lmask);
974 }
975
976 SFBMODE(sfb, MODE_SIMPLE);
977 SFBPIXELMASK(sfb, ~0); /* entire pixel */
978 }
979
980 #if 0
981 /*
982 * Copy characters in a line.
983 */
984 static void
985 sfb_copycols(id, row, srccol, dstcol, ncols)
986 void *id;
987 int row, srccol, dstcol, ncols;
988 {
989 struct rasops_info *ri = id;
990 caddr_t sp, dp, basex, sfb;
991 int scanspan, height, width, aligns, alignd, shift, w, y;
992 u_int32_t lmaskd, rmaskd;
993
994 scanspan = ri->ri_stride;
995 y = row * ri->ri_font->fontheight;
996 basex = ri->ri_bits + y * scanspan;
997 height = ri->ri_font->fontheight;
998 w = ri->ri_font->fontwidth * ncols;
999
1000 sp = basex + ri->ri_font->fontwidth * srccol;
1001 aligns = (long)sp & SFBALIGNMASK;
1002 dp = basex + ri->ri_font->fontwidth * dstcol;
1003 alignd = (long)dp & SFBALIGNMASK;
1004 sfb = ri->ri_hw;
1005
1006 SFBMODE(sfb, MODE_COPY);
1007 SFBPLANEMASK(sfb, ~0);
1008 /* small enough to fit in a single 32bit */
1009 if ((aligns + w) <= SFBCOPYBITS && (alignd + w) <= SFBCOPYBITS) {
1010 SFBPIXELSHIFT(sfb, alignd - aligns);
1011 lmaskd = SFBCOPYALL1 << alignd;
1012 rmaskd = SFBCOPYALL1 >> (-(alignd + w) & SFBCOPYBITMASK);
1013 lmaskd = lmaskd & rmaskd;
1014 sp -= aligns;
1015 dp -= alignd;
1016 while (height > 0) {
1017 *(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB();
1018 *(u_int32_t *)dp = lmaskd; WRITE_MB();
1019 sp += scanspan;
1020 dp += scanspan;
1021 height--;
1022 }
1023 }
1024 /* copy forward (left-to-right) */
1025 else if (dstcol < srccol || srccol + ncols < dstcol) {
1026 caddr_t sq, dq;
1027
1028 shift = alignd - aligns;
1029 if (shift < 0) {
1030 shift = 8 + shift; /* enforce right rotate */
1031 alignd += 8; /* bearing on left edge */
1032 }
1033 width = alignd + w;
1034 lmaskd = SFBCOPYALL1 << alignd;
1035 rmaskd = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
1036 sp -= aligns;
1037 dp -= alignd;
1038
1039 SFBPIXELSHIFT(sfb, shift);
1040 w = width;
1041 sq = sp;
1042 dq = dp;
1043 while (height > 0) {
1044 *(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB();
1045 *(u_int32_t *)dp = lmaskd; WRITE_MB();
1046 width -= 2 * SFBCOPYBITS;
1047 while (width > 0) {
1048 sp += SFBCOPYBYTESDONE;
1049 dp += SFBCOPYBYTESDONE;
1050 *(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB();
1051 *(u_int32_t *)dp = SFBCOPYALL1; WRITE_MB();
1052 width -= SFBCOPYBITS;
1053 }
1054 sp += SFBCOPYBYTESDONE;
1055 dp += SFBCOPYBYTESDONE;
1056 *(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB();
1057 *(u_int32_t *)dp = rmaskd; WRITE_MB();
1058 sp = (sq += scanspan);
1059 dp = (dq += scanspan);
1060 width = w;
1061 height--;
1062 }
1063 }
1064 /* copy backward (right-to-left) */
1065 else {
1066 caddr_t sq, dq;
1067
1068 shift = alignd - aligns;
1069 if (shift > 0) {
1070 shift = shift - 8; /* force left rotate */
1071 alignd += 24;
1072 }
1073 width = alignd + w;
1074 lmaskd = SFBCOPYALL1 << alignd;
1075 rmaskd = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
1076 sp -= aligns;
1077 dp -= alignd;
1078
1079 SFBPIXELSHIFT(sfb, shift);
1080 w = width;
1081 sq = sp += (((aligns + w) - 1) & ~31);
1082 dq = dp += (((alignd + w) - 1) & ~31);
1083 while (height > 0) {
1084 *(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB();
1085 *(u_int32_t *)dp = rmaskd; WRITE_MB();
1086 width -= 2 * SFBCOPYBITS;
1087 while (width > 0) {
1088 sp -= SFBCOPYBYTESDONE;
1089 dp -= SFBCOPYBYTESDONE;
1090 *(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB();
1091 *(u_int32_t *)dp = SFBCOPYALL1; WRITE_MB();
1092 width -= SFBCOPYBITS;
1093 }
1094 sp -= SFBCOPYBYTESDONE;
1095 dp -= SFBCOPYBYTESDONE;
1096 *(u_int32_t *)sp = SFBCOPYALL1; WRITE_MB();
1097 *(u_int32_t *)dp = lmaskd; WRITE_MB();
1098
1099 sp = (sq += scanspan);
1100 dp = (dq += scanspan);
1101 width = w;
1102 height--;
1103 }
1104 }
1105 SFBMODE(sfb, MODE_SIMPLE);
1106 SFBPIXELSHIFT(sfb, 0);
1107 }
1108 #endif
1109
1110 /*
1111 * Clear characters in a line.
1112 */
1113 static void
1114 sfb_erasecols(id, row, startcol, ncols, attr)
1115 void *id;
1116 int row, startcol, ncols;
1117 long attr;
1118 {
1119 struct rasops_info *ri = id;
1120 caddr_t sfb, p;
1121 int scanspan, startx, height, width, align, w, y;
1122 u_int32_t lmask, rmask;
1123
1124 scanspan = ri->ri_stride;
1125 y = row * ri->ri_font->fontheight;
1126 startx = startcol * ri->ri_font->fontwidth;
1127 height = ri->ri_font->fontheight;
1128 w = ri->ri_font->fontwidth * ncols;
1129
1130 p = ri->ri_bits + y * scanspan + startx;
1131 align = (long)p & SFBALIGNMASK;
1132 p -= align;
1133 width = w + align;
1134 lmask = SFBSTIPPLEALL1 << align;
1135 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
1136 sfb = ri->ri_hw;
1137
1138 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
1139 SFBPLANEMASK(sfb, ~0);
1140 SFBFG(sfb, ri->ri_devcmap[(attr >> 16) & 15]); /* fill with bg */
1141 if (width <= SFBSTIPPLEBITS) {
1142 lmask = lmask & rmask;
1143 while (height > 0) {
1144 SFBADDRESS(sfb, (long)p);
1145 SFBSTART(sfb, lmask);
1146 p += scanspan;
1147 height--;
1148 }
1149 }
1150 else {
1151 caddr_t q = p;
1152 while (height > 0) {
1153 *(u_int32_t *)p = lmask;
1154 WRITE_MB();
1155 width -= 2 * SFBSTIPPLEBITS;
1156 while (width > 0) {
1157 p += SFBSTIPPLEBYTESDONE;
1158 *(u_int32_t *)p = SFBSTIPPLEALL1;
1159 WRITE_MB();
1160 width -= SFBSTIPPLEBITS;
1161 }
1162 p += SFBSTIPPLEBYTESDONE;
1163 *(u_int32_t *)p = rmask;
1164 WRITE_MB();
1165
1166 p = (q += scanspan);
1167 width = w + align;
1168 height--;
1169 }
1170 }
1171 SFBMODE(sfb, MODE_SIMPLE);
1172 }
1173
1174 /*
1175 * Copy lines.
1176 */
1177 static void
1178 sfb_copyrows(id, srcrow, dstrow, nrows)
1179 void *id;
1180 int srcrow, dstrow, nrows;
1181 {
1182 struct rasops_info *ri = id;
1183 caddr_t sfb, p;
1184 int scanspan, offset, srcy, height, width, align, w;
1185 u_int32_t lmask, rmask;
1186
1187 scanspan = ri->ri_stride;
1188 height = ri->ri_font->fontheight * nrows;
1189 offset = (dstrow - srcrow) * ri->ri_yscale;
1190 srcy = ri->ri_font->fontheight * srcrow;
1191 if (srcrow < dstrow && srcrow + nrows > dstrow) {
1192 scanspan = -scanspan;
1193 srcy += height;
1194 }
1195
1196 p = ri->ri_bits + srcy * ri->ri_stride;
1197 align = (long)p & SFBALIGNMASK;
1198 p -= align;
1199 w = ri->ri_emuwidth;
1200 width = w + align;
1201 lmask = SFBCOPYALL1 << align;
1202 rmask = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
1203 sfb = ri->ri_hw;
1204
1205 SFBMODE(sfb, MODE_COPY);
1206 SFBPLANEMASK(sfb, ~0);
1207 SFBPIXELSHIFT(sfb, 0);
1208 if (width <= SFBCOPYBITS) {
1209 /* never happens */;
1210 }
1211 else {
1212 caddr_t q = p;
1213 while (height > 0) {
1214 *(u_int32_t *)p = lmask;
1215 *(u_int32_t *)(p + offset) = lmask;
1216 width -= 2 * SFBCOPYBITS;
1217 while (width > 0) {
1218 p += SFBCOPYBYTESDONE;
1219 *(u_int32_t *)p = SFBCOPYALL1;
1220 *(u_int32_t *)(p + offset) = SFBCOPYALL1;
1221 width -= SFBCOPYBITS;
1222 }
1223 p += SFBCOPYBYTESDONE;
1224 *(u_int32_t *)p = rmask;
1225 *(u_int32_t *)(p + offset) = rmask;
1226
1227 p = (q += scanspan);
1228 width = w + align;
1229 height--;
1230 }
1231 }
1232 SFBMODE(sfb, MODE_SIMPLE);
1233 }
1234
1235 /*
1236 * Erase lines.
1237 */
1238 void
1239 sfb_eraserows(id, startrow, nrows, attr)
1240 void *id;
1241 int startrow, nrows;
1242 long attr;
1243 {
1244 struct rasops_info *ri = id;
1245 caddr_t sfb, p;
1246 int scanspan, starty, height, width, align, w;
1247 u_int32_t lmask, rmask;
1248
1249 scanspan = ri->ri_stride;
1250 starty = ri->ri_font->fontheight * startrow;
1251 height = ri->ri_font->fontheight * nrows;
1252
1253 p = ri->ri_bits + starty * scanspan;
1254 align = (long)p & SFBALIGNMASK;
1255 p -= align;
1256 w = ri->ri_emuwidth;
1257 width = w + align;
1258 lmask = SFBSTIPPLEALL1 << align;
1259 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
1260 sfb = ri->ri_hw;
1261
1262 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
1263 SFBPLANEMASK(sfb, ~0);
1264 SFBFG(sfb, ri->ri_devcmap[(attr >> 16) & 15]); /* fill with bg */
1265 if (width <= SFBSTIPPLEBITS) {
1266 /* never happens */;
1267 }
1268 else {
1269 caddr_t q = p;
1270 while (height > 0) {
1271 *(u_int32_t *)p = lmask;
1272 WRITE_MB();
1273 width -= 2 * SFBSTIPPLEBITS;
1274 while (width > 0) {
1275 p += SFBSTIPPLEBYTESDONE;
1276 *(u_int32_t *)p = SFBSTIPPLEALL1;
1277 WRITE_MB();
1278 width -= SFBSTIPPLEBITS;
1279 }
1280 p += SFBSTIPPLEBYTESDONE;
1281 *(u_int32_t *)p = rmask;
1282 WRITE_MB();
1283
1284 p = (q += scanspan);
1285 width = w + align;
1286 height--;
1287 }
1288 }
1289 SFBMODE(sfb, MODE_SIMPLE);
1290 }
1291