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