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