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