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