sfb.c revision 1.21 1 /* $NetBSD: sfb.c,v 1.21 1999/10/19 09:51:17 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.21 1999/10/19 09:51:17 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_SIMPLE);
942 SFBPLANEMASK(sfb, 0x01010101); /* LSB only */
943 SFBROP(sfb, 10); /* ROP_INVERT */
944 if (width <= SFBSTIPPLEBITS) {
945 lmask = lmask & rmask;
946 while (height > 0) {
947 SFBADDRESS(sfb, (long)p);
948 SFBSTART(sfb, lmask);
949 p += scanspan;
950 height--;
951 }
952 }
953 else {
954 caddr_t q = p;
955 while (height > 0) {
956 *(u_int32_t *)p = lmask;
957 WRITE_MB();
958 p += SFBSTIPPLEBYTESDONE;
959 *(u_int32_t *)p = rmask;
960 WRITE_MB();
961
962 p = (q += scanspan);
963 height--;
964 }
965 }
966 SFBPLANEMASK(sfb, ~0); /* entire pixel */
967 SFBROP(sfb, 3); /* ROP_COPY */
968
969 rc->rc_bits ^= RC_CURSOR;
970 }
971
972 /*
973 * Actually write a string to the frame buffer.
974 */
975 int
976 sfb_mapchar(id, uni, index)
977 void *id;
978 int uni;
979 unsigned int *index;
980 {
981 if (uni < 128) {
982 *index = uni;
983 return (5);
984 }
985 *index = ' ';
986 return (0);
987 }
988
989 /*
990 * Actually write a string to the frame buffer.
991 */
992 void
993 sfb_putchar(id, row, col, uc, attr)
994 void *id;
995 int row, col;
996 u_int uc;
997 long attr;
998 {
999 struct rcons *rc = id;
1000 struct raster *rap = rc->rc_sp;
1001 caddr_t sfb, p;
1002 int scanspan, height, width, align, x, y;
1003 u_int32_t lmask, rmask, glyph;
1004 u_int32_t *g;
1005
1006 if (uc < 0x20 || uc >= 127) return; /* XXX why \033 is creaping in !? XXX */
1007
1008 x = col * rc->rc_font->width + rc->rc_xorigin;
1009 y = row * rc->rc_font->height + rc->rc_yorigin;
1010 scanspan = rap->linelongs * 4;
1011 height = rc->rc_font->height;
1012 g = rc->rc_font->chars[uc].r->pixels;
1013
1014 p = (caddr_t)rap->pixels + y * scanspan + x;
1015 align = (long)p & SFBALIGNMASK;
1016 p -= align;
1017 width = rc->rc_font->width + align;
1018 lmask = SFBSTIPPLEALL1 << align;
1019 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
1020 sfb = rap->data;
1021 attr = (attr != 0) ^ (rc->rc_bits & RC_INVERT);
1022
1023 SFBMODE(sfb, MODE_OPAQUESTIPPLE);
1024 SFBPLANEMASK(sfb, ~0);
1025 SFBFG(sfb, (attr == 0) ? 0x01010101 : 0);
1026 SFBBG(sfb, (attr == 0) ? 0 : 0x01010101);
1027 if (width <= SFBSTIPPLEBITS) {
1028 lmask = lmask & rmask;
1029 while (height > 0) {
1030 glyph = *g;
1031 SFBPIXELMASK(sfb, lmask);
1032 SFBADDRESS(sfb, (long)p);
1033 SFBSTART(sfb, glyph << align);
1034 p += scanspan;
1035 g += 1;
1036 height--;
1037 }
1038 }
1039 else {
1040 caddr_t q = p;
1041 while (height > 0) {
1042 glyph = *g;
1043 SFBPIXELMASK(sfb, lmask);
1044 WRITE_MB();
1045 *(u_int32_t *)p = glyph << align;
1046 WRITE_MB();
1047 p += SFBSTIPPLEBYTESDONE;
1048 SFBPIXELMASK(sfb, rmask);
1049 WRITE_MB();
1050 *(u_int32_t *)p = glyph >> (-width & SFBSTIPPLEBITMASK);
1051 WRITE_MB();
1052
1053 p = (q += scanspan);
1054 g += 1;
1055 height--;
1056 }
1057 }
1058 SFBMODE(sfb, MODE_SIMPLE);
1059 SFBPIXELMASK(sfb, ~0);
1060 }
1061
1062 /*
1063 * Copy characters in a line.
1064 */
1065 void
1066 sfb_copycols(id, row, srccol, dstcol, ncols)
1067 void *id;
1068 int row, srccol, dstcol, ncols;
1069 {
1070 struct rcons *rc = id;
1071 struct raster *rap = rc->rc_sp;
1072 caddr_t sp, dp, basex, sfb;
1073 int scanspan, height, width, align, shift, w, y;
1074 u_int32_t lmask, rmask;
1075
1076 scanspan = rap->linelongs * 4;
1077 y = rc->rc_yorigin + rc->rc_font->height * row;
1078 basex = (caddr_t)rap->pixels + y * scanspan + rc->rc_xorigin;
1079 height = rc->rc_font->height;
1080 w = rc->rc_font->width * ncols;
1081
1082 dp = basex + rc->rc_font->width * dstcol;
1083 sp = basex + rc->rc_font->width * srccol;
1084
1085 align = shift = (long)sp & SFBALIGNMASK;
1086 sp -= align;
1087 width = w + align;
1088 align = (long)dp & SFBALIGNMASK;
1089 dp -= align;
1090 lmask = SFBCOPYALL1 << align;
1091 rmask = SFBCOPYALL1 >> (-(w + align) & SFBCOPYBITMASK);
1092 shift = align - shift;
1093 sfb = rap->data;
1094
1095 SFBMODE(sfb, MODE_COPY);
1096 SFBPLANEMASK(sfb, ~0);
1097 SFBPIXELSHIFT(sfb, shift);
1098 if (width <= SFBCOPYBITS) {
1099 lmask = lmask & rmask;
1100 while (height > 0) {
1101 *(u_int32_t *)sp = SFBCOPYALL1;
1102 WRITE_MB();
1103 *(u_int32_t *)dp = lmask;
1104 WRITE_MB();
1105 sp += scanspan;
1106 dp += scanspan;
1107 height--;
1108 }
1109 }
1110 /* copy forward (left-to-right) */
1111 else if (dstcol < srccol || srccol + ncols < dstcol) {
1112 caddr_t sq = sp, dq = dp;
1113
1114 w = width;
1115 while (height > 0) {
1116 *(u_int32_t *)sp = SFBCOPYALL1;
1117 WRITE_MB();
1118 *(u_int32_t *)dp = lmask;
1119 WRITE_MB();
1120 width -= 2 * SFBCOPYBITS;
1121 while (width > 0) {
1122 sp += SFBCOPYBYTESDONE;
1123 dp += SFBCOPYBYTESDONE;
1124 *(u_int32_t *)sp = SFBCOPYALL1;
1125 WRITE_MB();
1126 *(u_int32_t *)dp = SFBCOPYALL1;
1127 WRITE_MB();
1128 width -= SFBCOPYBITS;
1129 }
1130 sp += SFBCOPYBYTESDONE;
1131 dp += SFBCOPYBYTESDONE;
1132 *(u_int32_t *)sp = SFBCOPYALL1;
1133 WRITE_MB();
1134 *(u_int32_t *)dp = rmask;
1135 WRITE_MB();
1136
1137 sp = (sq += scanspan);
1138 dp = (dq += scanspan);
1139 width = w;
1140 height--;
1141 }
1142 }
1143 /* copy backward (right-to-left) */
1144 else {
1145 caddr_t sq = (sp += width), dq = (dp += width);
1146
1147 w = width;
1148 while (height > 0) {
1149 *(u_int32_t *)sp = SFBCOPYALL1;
1150 WRITE_MB();
1151 *(u_int32_t *)dp = rmask;
1152 WRITE_MB();
1153 width -= 2 * SFBCOPYBITS;
1154 while (width > 0) {
1155 sp -= SFBCOPYBYTESDONE;
1156 dp -= SFBCOPYBYTESDONE;
1157 *(u_int32_t *)sp = SFBCOPYALL1;
1158 WRITE_MB();
1159 *(u_int32_t *)dp = SFBCOPYALL1;
1160 WRITE_MB();
1161 width -= SFBCOPYBITS;
1162 }
1163 sp -= SFBCOPYBYTESDONE;
1164 dp -= SFBCOPYBYTESDONE;
1165 *(u_int32_t *)sp = SFBCOPYALL1;
1166 WRITE_MB();
1167 *(u_int32_t *)dp = lmask;
1168 WRITE_MB();
1169
1170 sp = (sq += scanspan);
1171 dp = (dq += scanspan);
1172 width = w;
1173 height--;
1174 }
1175 }
1176 SFBMODE(sfb, MODE_SIMPLE);
1177 }
1178
1179 /*
1180 * Clear characters in a line.
1181 */
1182 void
1183 sfb_erasecols(id, row, startcol, ncols, attr)
1184 void *id;
1185 int row, startcol, ncols;
1186 long attr;
1187 {
1188 struct rcons *rc = id;
1189 struct raster *rap = rc->rc_sp;
1190 caddr_t sfb, p;
1191 int scanspan, startx, height, width, align, w, y;
1192 u_int32_t lmask, rmask;
1193
1194 scanspan = rap->linelongs * 4;
1195 y = rc->rc_yorigin + rc->rc_font->height * row;
1196 startx = rc->rc_xorigin + rc->rc_font->width * startcol;
1197 height = rc->rc_font->height;
1198 w = rc->rc_font->width * ncols;
1199
1200 p = (caddr_t)rap->pixels + y * scanspan + startx;
1201 align = (long)p & SFBALIGNMASK;
1202 p -= align;
1203 width = w + align;
1204 lmask = SFBSTIPPLEALL1 << align;
1205 rmask = SFBSTIPPLEALL1 >> (-width & SFBSTIPPLEBITMASK);
1206 sfb = rap->data;
1207 attr = (attr != 0) ^ (rc->rc_bits & RC_INVERT);
1208
1209 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
1210 SFBPLANEMASK(sfb, ~0);
1211 SFBFG(sfb, (attr == 0) ? 0 : 0x01010101);
1212 if (width <= SFBSTIPPLEBITS) {
1213 lmask = lmask & rmask;
1214 while (height > 0) {
1215 SFBADDRESS(sfb, (long)p);
1216 SFBSTART(sfb, lmask);
1217 p += scanspan;
1218 height--;
1219 }
1220 }
1221 else {
1222 caddr_t q = p;
1223 while (height > 0) {
1224 *(u_int32_t *)p = lmask;
1225 WRITE_MB();
1226 width -= 2 * SFBSTIPPLEBITS;
1227 while (width > 0) {
1228 p += SFBSTIPPLEBYTESDONE;
1229 *(u_int32_t *)p = SFBSTIPPLEALL1;
1230 WRITE_MB();
1231 width -= SFBSTIPPLEBITS;
1232 }
1233 p += SFBSTIPPLEBYTESDONE;
1234 *(u_int32_t *)p = rmask;
1235 WRITE_MB();
1236
1237 p = (q += scanspan);
1238 width = w + align;
1239 height--;
1240 }
1241 }
1242 SFBMODE(sfb, MODE_SIMPLE);
1243 }
1244
1245 /*
1246 * Copy lines.
1247 */
1248 void
1249 sfb_copyrows(id, srcrow, dstrow, nrows)
1250 void *id;
1251 int srcrow, dstrow, nrows;
1252 {
1253 struct rcons *rc = id;
1254 struct raster *rap = rc->rc_sp;
1255 caddr_t sfb, p;
1256 int scanspan, offset, srcy, height, width, align, w;
1257 u_int32_t lmask, rmask;
1258
1259 scanspan = rap->linelongs * 4;
1260 height = rc->rc_font->height * nrows;
1261 offset = (dstrow - srcrow) * scanspan * rc->rc_font->height;
1262 srcy = rc->rc_yorigin + rc->rc_font->height * srcrow;
1263 if (srcrow < dstrow && srcrow + nrows > dstrow) {
1264 scanspan = -scanspan;
1265 srcy += height;
1266 }
1267
1268 p = (caddr_t)(rap->pixels + srcy * rap->linelongs) + rc->rc_xorigin;
1269 align = (long)p & SFBALIGNMASK;
1270 p -= align;
1271 w = rc->rc_font->width * rc->rc_maxcol;
1272 width = w + align;
1273 lmask = SFBCOPYALL1 << align;
1274 rmask = SFBCOPYALL1 >> (-width & SFBCOPYBITMASK);
1275 sfb = rap->data;
1276
1277 SFBMODE(sfb, MODE_COPY);
1278 SFBPLANEMASK(sfb, ~0);
1279 SFBPIXELSHIFT(sfb, 0);
1280 if (width <= SFBCOPYBITS) {
1281 /* never happens */;
1282 }
1283 else {
1284 caddr_t q = p;
1285 while (height > 0) {
1286 *(u_int32_t *)p = lmask;
1287 WRITE_MB();
1288 *(u_int32_t *)(p + offset) = lmask;
1289 WRITE_MB();
1290 width -= 2 * SFBCOPYBITS;
1291 while (width > 0) {
1292 p += SFBCOPYBYTESDONE;
1293 *(u_int32_t *)p = SFBCOPYALL1;
1294 WRITE_MB();
1295 *(u_int32_t *)(p + offset) = SFBCOPYALL1;
1296 WRITE_MB();
1297 width -= SFBCOPYBITS;
1298 }
1299 p += SFBCOPYBYTESDONE;
1300 *(u_int32_t *)p = rmask;
1301 WRITE_MB();
1302 *(u_int32_t *)(p + offset) = rmask;
1303 WRITE_MB();
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 attr = (attr != 0) ^ (rc->rc_bits & RC_INVERT);
1341
1342 SFBMODE(sfb, MODE_TRANSPARENTSTIPPLE);
1343 SFBPLANEMASK(sfb, ~0);
1344 SFBFG(sfb, (attr == 0) ? 0 : 0x01010101);
1345 if (width <= SFBSTIPPLEBITS) {
1346 /* never happens */;
1347 }
1348 else {
1349 caddr_t q = p;
1350 while (height > 0) {
1351 *(u_int32_t *)p = lmask;
1352 WRITE_MB();
1353 width -= 2 * SFBSTIPPLEBITS;
1354 while (width > 0) {
1355 p += SFBSTIPPLEBYTESDONE;
1356 *(u_int32_t *)p = SFBSTIPPLEALL1;
1357 WRITE_MB();
1358 width -= SFBSTIPPLEBITS;
1359 }
1360 p += SFBSTIPPLEBYTESDONE;
1361 *(u_int32_t *)p = rmask;
1362 WRITE_MB();
1363
1364 p = (q += scanspan);
1365 width = w + align;
1366 height--;
1367 }
1368 }
1369 SFBMODE(sfb, MODE_SIMPLE);
1370 }
1371
1372 int
1373 sfb_alloc_attr(id, fg, bg, flags, attrp)
1374 void *id;
1375 int fg, bg, flags;
1376 long *attrp;
1377 {
1378 if (flags & (WSATTR_HILIT | WSATTR_BLINK |
1379 WSATTR_UNDERLINE | WSATTR_WSCOLORS))
1380 return (EINVAL);
1381 if (flags & WSATTR_REVERSE)
1382 *attrp = 1;
1383 else
1384 *attrp = 0;
1385 return (0);
1386 }
1387