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