ffb.c revision 1.13 1 /* $NetBSD: ffb.c,v 1.13 2005/05/15 16:41:25 martin Exp $ */
2 /* $OpenBSD: creator.c,v 1.20 2002/07/30 19:48:15 jason Exp $ */
3
4 /*
5 * Copyright (c) 2002 Jason L. Wright (jason (at) thought.net)
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by Jason L. Wright
19 * 4. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
26 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
30 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 */
34
35 #include <sys/cdefs.h>
36 __KERNEL_RCSID(0, "$NetBSD: ffb.c,v 1.13 2005/05/15 16:41:25 martin Exp $");
37
38 #include <sys/types.h>
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/kernel.h>
42 #include <sys/device.h>
43 #include <sys/conf.h>
44
45 #include <machine/bus.h>
46 #include <machine/autoconf.h>
47 #include <machine/openfirm.h>
48 #include <machine/vmparam.h>
49
50 #include <dev/wscons/wsconsio.h>
51 #include <dev/sun/fbio.h>
52 #include <dev/sun/fbvar.h>
53
54 #include <sparc64/dev/ffbreg.h>
55 #include <sparc64/dev/ffbvar.h>
56
57 extern struct cfdriver ffb_cd;
58
59 struct wsscreen_descr ffb_stdscreen = {
60 "sunffb",
61 0, 0, /* will be filled in -- XXX shouldn't, it's global. */
62 0,
63 0, 0,
64 WSSCREEN_REVERSE | WSSCREEN_WSCOLORS
65 };
66
67 const struct wsscreen_descr *ffb_scrlist[] = {
68 &ffb_stdscreen,
69 /* XXX other formats? */
70 };
71
72 struct wsscreen_list ffb_screenlist = {
73 sizeof(ffb_scrlist) / sizeof(struct wsscreen_descr *),
74 ffb_scrlist
75 };
76
77 int ffb_ioctl(void *, u_long, caddr_t, int, struct proc *);
78 int ffb_alloc_screen(void *, const struct wsscreen_descr *, void **,
79 int *, int *, long *);
80 static int ffb_blank(struct ffb_softc *, u_long, u_int *);
81 void ffb_free_screen(void *, void *);
82 int ffb_show_screen(void *, void *, int, void (*cb)(void *, int, int),
83 void *);
84 paddr_t ffb_mmap(void *, off_t, int);
85 void ffb_ras_fifo_wait(struct ffb_softc *, int);
86 void ffb_ras_wait(struct ffb_softc *);
87 void ffb_ras_init(struct ffb_softc *);
88 void ffb_ras_copyrows(void *, int, int, int);
89 void ffb_ras_erasecols(void *, int, int, int, long int);
90 void ffb_ras_eraserows(void *, int, int, long int);
91 void ffb_ras_do_cursor(struct rasops_info *);
92 void ffb_ras_fill(struct ffb_softc *);
93 void ffb_ras_setfg(struct ffb_softc *, int32_t);
94
95 /* frame buffer generic driver */
96 static void ffbfb_unblank(struct device*);
97 dev_type_open(ffbfb_open);
98 dev_type_close(ffbfb_close);
99 dev_type_ioctl(ffbfb_ioctl);
100 dev_type_mmap(ffbfb_mmap);
101 static struct fbdriver ffb_fbdriver = {
102 ffbfb_unblank, ffbfb_open, ffbfb_close, ffbfb_ioctl, nopoll,
103 ffbfb_mmap, nokqfilter
104 };
105
106 struct wsdisplay_accessops ffb_accessops = {
107 ffb_ioctl,
108 ffb_mmap,
109 ffb_alloc_screen,
110 ffb_free_screen,
111 ffb_show_screen,
112 NULL, /* load font */
113 NULL, /* pollc */
114 NULL, /* getwschar */
115 NULL, /* putwschar */
116 NULL, /* scroll */
117 };
118
119 void
120 ffb_attach(struct ffb_softc *sc)
121 {
122 struct wsemuldisplaydev_attach_args waa;
123 char *model;
124 int btype;
125 int maxrow, maxcol;
126 u_int blank = WSDISPLAYIO_VIDEO_ON;
127 char buf[6+1];
128
129 printf(":");
130
131 if (sc->sc_type == FFB_CREATOR) {
132 btype = prom_getpropint(sc->sc_node, "board_type", 0);
133 if ((btype & 7) == 3)
134 printf(" Creator3D");
135 else
136 printf(" Creator");
137 } else
138 printf(" Elite3D");
139
140 model = prom_getpropstring(sc->sc_node, "model");
141 if (model == NULL || strlen(model) == 0)
142 model = "unknown";
143
144 sc->sc_depth = 24;
145 sc->sc_linebytes = 8192;
146 sc->sc_height = prom_getpropint(sc->sc_node, "height", 0);
147 sc->sc_width = prom_getpropint(sc->sc_node, "width", 0);
148
149 sc->sc_fb.fb_rinfo.ri_depth = 32;
150 sc->sc_fb.fb_rinfo.ri_stride = sc->sc_linebytes;
151 sc->sc_fb.fb_rinfo.ri_flg = RI_CENTER;
152 sc->sc_fb.fb_rinfo.ri_bits = (void *)bus_space_vaddr(sc->sc_bt,
153 sc->sc_pixel_h);
154
155 sc->sc_fb.fb_rinfo.ri_width = sc->sc_width;
156 sc->sc_fb.fb_rinfo.ri_height = sc->sc_height;
157 sc->sc_fb.fb_rinfo.ri_hw = sc;
158
159 maxcol = (prom_getoption("screen-#columns", buf, sizeof buf) == 0)
160 ? strtoul(buf, NULL, 10)
161 : 80;
162
163 maxrow = (prom_getoption("screen-#rows", buf, sizeof buf) != 0)
164 ? strtoul(buf, NULL, 10)
165 : 34;
166
167 rasops_init(&sc->sc_fb.fb_rinfo, maxrow, maxcol);
168
169 if ((sc->sc_dv.dv_cfdata->cf_flags & FFB_CFFLAG_NOACCEL) == 0) {
170 sc->sc_fb.fb_rinfo.ri_hw = sc;
171 sc->sc_fb.fb_rinfo.ri_ops.eraserows = ffb_ras_eraserows;
172 sc->sc_fb.fb_rinfo.ri_ops.erasecols = ffb_ras_erasecols;
173 sc->sc_fb.fb_rinfo.ri_ops.copyrows = ffb_ras_copyrows;
174 ffb_ras_init(sc);
175 }
176
177 ffb_stdscreen.nrows = sc->sc_fb.fb_rinfo.ri_rows;
178 ffb_stdscreen.ncols = sc->sc_fb.fb_rinfo.ri_cols;
179 ffb_stdscreen.textops = &sc->sc_fb.fb_rinfo.ri_ops;
180
181 /* collect DAC version, as Elite3D cursor enable bit is reversed */
182 DAC_WRITE(sc, FFB_DAC_TYPE, FFB_DAC_GVERS);
183 sc->sc_dacrev = DAC_READ(sc, FFB_DAC_VALUE) >> 28;
184
185 if (sc->sc_type == FFB_AFB)
186 sc->sc_dacrev = 10;
187 printf(", model %s, dac %u\n", model, sc->sc_dacrev);
188
189 ffb_blank(sc, WSDISPLAYIO_SVIDEO, &blank);
190
191 sc->sc_fb.fb_driver = &ffb_fbdriver;
192 sc->sc_fb.fb_type.fb_cmsize = 0;
193 sc->sc_fb.fb_type.fb_size = maxrow * sc->sc_linebytes;
194 sc->sc_fb.fb_type.fb_type = FBTYPE_CREATOR;
195 sc->sc_fb.fb_type.fb_width = sc->sc_width;
196 sc->sc_fb.fb_type.fb_depth = sc->sc_depth;
197 sc->sc_fb.fb_type.fb_height = sc->sc_height;
198 sc->sc_fb.fb_device = &sc->sc_dv;
199 fb_attach(&sc->sc_fb, sc->sc_console);
200
201 if (sc->sc_console) {
202 int *ccolp, *crowp;
203 long defattr;
204
205 if (romgetcursoraddr(&crowp, &ccolp))
206 ccolp = crowp = NULL;
207 if (ccolp != NULL)
208 sc->sc_fb.fb_rinfo.ri_ccol = *ccolp;
209 if (crowp != NULL)
210 sc->sc_fb.fb_rinfo.ri_crow = *crowp;
211
212 sc->sc_fb.fb_rinfo.ri_ops.allocattr(&sc->sc_fb.fb_rinfo,
213 0, 0, 0, &defattr);
214
215 wsdisplay_cnattach(&ffb_stdscreen, &sc->sc_fb.fb_rinfo,
216 sc->sc_fb.fb_rinfo.ri_ccol, sc->sc_fb.fb_rinfo.ri_crow, defattr);
217 }
218
219 waa.console = sc->sc_console;
220 waa.scrdata = &ffb_screenlist;
221 waa.accessops = &ffb_accessops;
222 waa.accesscookie = sc;
223 config_found(&sc->sc_dv, &waa, wsemuldisplaydevprint);
224 }
225
226 int
227 ffb_ioctl(void *v, u_long cmd, caddr_t data, int flags, struct proc *p)
228 {
229 struct ffb_softc *sc = v;
230 struct wsdisplay_fbinfo *wdf;
231
232 #ifdef FFBDEBUG
233 printf("ffb_ioctl: %s cmd _IO%s%s('%c', %lu)\n",
234 sc->sc_dv.dv_xname,
235 (cmd & IOC_IN) ? "W" : "", (cmd & IOC_OUT) ? "R" : "",
236 (char)IOCGROUP(cmd), cmd & 0xff);
237 #endif
238
239 switch (cmd) {
240 case FBIOGTYPE:
241 *(struct fbtype *)data = sc->sc_fb.fb_type;
242 break;
243 case FBIOGATTR:
244 #define fba ((struct fbgattr *)data)
245 fba->real_type = sc->sc_fb.fb_type.fb_type;
246 fba->owner = 0; /* XXX ??? */
247 fba->fbtype = sc->sc_fb.fb_type;
248 fba->sattr.flags = 0;
249 fba->sattr.emu_type = sc->sc_fb.fb_type.fb_type;
250 fba->sattr.dev_specific[0] = -1;
251 fba->emu_types[0] = sc->sc_fb.fb_type.fb_type;
252 fba->emu_types[1] = -1;
253 #undef fba
254 break;
255
256 case FBIOGETCMAP:
257 case FBIOPUTCMAP:
258 return EIO;
259
260 case FBIOGVIDEO:
261 case FBIOSVIDEO:
262 return ffb_blank(sc, cmd == FBIOGVIDEO?
263 WSDISPLAYIO_GVIDEO : WSDISPLAYIO_SVIDEO,
264 (u_int *)data);
265 break;
266 case FBIOGCURSOR:
267 case FBIOSCURSOR:
268 /* the console driver is not using the hardware cursor */
269 break;
270 case FBIOGCURPOS:
271 printf("%s: FBIOGCURPOS not implemented\n", sc->sc_dv.dv_xname);
272 return EIO;
273 case FBIOSCURPOS:
274 printf("%s: FBIOSCURPOS not implemented\n", sc->sc_dv.dv_xname);
275 return EIO;
276 case FBIOGCURMAX:
277 printf("%s: FBIOGCURMAX not implemented\n", sc->sc_dv.dv_xname);
278 return EIO;
279
280 case WSDISPLAYIO_GTYPE:
281 *(u_int *)data = WSDISPLAY_TYPE_SUNFFB;
282 break;
283 case WSDISPLAYIO_SMODE:
284 sc->sc_mode = *(u_int *)data;
285 break;
286 case WSDISPLAYIO_GINFO:
287 wdf = (void *)data;
288 wdf->height = sc->sc_height;
289 wdf->width = sc->sc_width;
290 wdf->depth = 32;
291 wdf->cmsize = 256; /* XXX */
292 break;
293 #ifdef WSDISPLAYIO_LINEBYTES
294 case WSDISPLAYIO_LINEBYTES:
295 *(u_int *)data = sc->sc_linebytes;
296 break;
297 #endif
298 case WSDISPLAYIO_GETCMAP:
299 break;/* XXX */
300
301 case WSDISPLAYIO_PUTCMAP:
302 break;/* XXX */
303
304 case WSDISPLAYIO_SVIDEO:
305 case WSDISPLAYIO_GVIDEO:
306 return(ffb_blank(sc, cmd, (u_int *)data));
307 break;
308 case WSDISPLAYIO_GCURPOS:
309 case WSDISPLAYIO_SCURPOS:
310 case WSDISPLAYIO_GCURMAX:
311 case WSDISPLAYIO_GCURSOR:
312 case WSDISPLAYIO_SCURSOR:
313 return EIO; /* not supported yet */
314 default:
315 return EPASSTHROUGH;
316 }
317
318 return (0);
319 }
320
321 int
322 ffb_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
323 int *curxp, int *curyp, long *attrp)
324 {
325 struct ffb_softc *sc = v;
326
327 if (sc->sc_nscreens > 0)
328 return (ENOMEM);
329
330 *cookiep = &sc->sc_fb.fb_rinfo;
331 *curyp = 0;
332 *curxp = 0;
333
334 sc->sc_fb.fb_rinfo.ri_ops.allocattr(&sc->sc_fb.fb_rinfo, 0, 0, 0, attrp);
335
336 sc->sc_nscreens++;
337 return (0);
338 }
339
340 /* blank/unblank the screen */
341 static int
342 ffb_blank(struct ffb_softc *sc, u_long cmd, u_int *data)
343 {
344 u_int val;
345
346 DAC_WRITE(sc, FFB_DAC_TYPE, FFB_DAC_GSBLANK);
347 val = DAC_READ(sc, FFB_DAC_VALUE);
348
349 switch (cmd) {
350 case WSDISPLAYIO_GVIDEO:
351 *data = val & 1;
352 return(0);
353 break;
354 case WSDISPLAYIO_SVIDEO:
355 if (*data == WSDISPLAYIO_VIDEO_OFF)
356 val &= ~1;
357 else if (*data == WSDISPLAYIO_VIDEO_ON)
358 val |= 1;
359 else
360 return(EINVAL);
361 break;
362 default:
363 return(EINVAL);
364 }
365
366 DAC_WRITE(sc, FFB_DAC_TYPE, FFB_DAC_GSBLANK);
367 DAC_WRITE(sc, FFB_DAC_VALUE, val);
368
369 return(0);
370 }
371
372 void
373 ffb_free_screen(void *v, void *cookie)
374 {
375 struct ffb_softc *sc = v;
376
377 sc->sc_nscreens--;
378 }
379
380 int
381 ffb_show_screen(void *v, void *cookie, int waitok,
382 void (*cb)(void *, int, int), void *cbarg)
383 {
384 return (0);
385 }
386
387 paddr_t
388 ffb_mmap(void *vsc, off_t off, int prot)
389 {
390 struct ffb_softc *sc = vsc;
391 int i;
392
393 switch (sc->sc_mode) {
394 case WSDISPLAYIO_MODE_MAPPED:
395 for (i = 0; i < sc->sc_nreg; i++) {
396 /* Before this set? */
397 if (off < sc->sc_addrs[i])
398 continue;
399 /* After this set? */
400 if (off >= (sc->sc_addrs[i] + sc->sc_sizes[i]))
401 continue;
402
403 return (bus_space_mmap(sc->sc_bt, sc->sc_addrs[i],
404 off - sc->sc_addrs[i], prot, BUS_SPACE_MAP_LINEAR));
405 }
406 break;
407 #ifdef WSDISPLAYIO_MODE_DUMBFB
408 case WSDISPLAYIO_MODE_DUMBFB:
409 if (sc->sc_nreg < FFB_REG_DFB24)
410 break;
411 if (off >= 0 && off < sc->sc_sizes[FFB_REG_DFB24])
412 return (bus_space_mmap(sc->sc_bt,
413 sc->sc_addrs[FFB_REG_DFB24], off, prot,
414 BUS_SPACE_MAP_LINEAR));
415 break;
416 #endif
417 }
418
419 return (-1);
420 }
421
422 void
423 ffb_ras_fifo_wait(struct ffb_softc *sc, int n)
424 {
425 int32_t cache = sc->sc_fifo_cache;
426
427 if (cache < n) {
428 do {
429 cache = FBC_READ(sc, FFB_FBC_UCSR);
430 cache = (cache & FBC_UCSR_FIFO_MASK) - 8;
431 } while (cache < n);
432 }
433 sc->sc_fifo_cache = cache - n;
434 }
435
436 void
437 ffb_ras_wait(struct ffb_softc *sc)
438 {
439 u_int32_t ucsr, r;
440
441 while (1) {
442 ucsr = FBC_READ(sc, FFB_FBC_UCSR);
443 if ((ucsr & (FBC_UCSR_FB_BUSY|FBC_UCSR_RP_BUSY)) == 0)
444 break;
445 r = ucsr & (FBC_UCSR_READ_ERR | FBC_UCSR_FIFO_OVFL);
446 if (r != 0)
447 FBC_WRITE(sc, FFB_FBC_UCSR, r);
448 }
449 }
450
451 void
452 ffb_ras_init(struct ffb_softc *sc)
453 {
454 ffb_ras_fifo_wait(sc, 7);
455 FBC_WRITE(sc, FFB_FBC_PPC,
456 FBC_PPC_VCE_DIS | FBC_PPC_TBE_OPAQUE |
457 FBC_PPC_APE_DIS | FBC_PPC_CS_CONST);
458 FBC_WRITE(sc, FFB_FBC_FBC,
459 FFB_FBC_WB_A | FFB_FBC_RB_A | FFB_FBC_SB_BOTH |
460 FFB_FBC_XE_OFF | FFB_FBC_RGBE_MASK);
461 FBC_WRITE(sc, FFB_FBC_ROP, FBC_ROP_NEW);
462 FBC_WRITE(sc, FFB_FBC_DRAWOP, FBC_DRAWOP_RECTANGLE);
463 FBC_WRITE(sc, FFB_FBC_PMASK, 0xffffffff);
464 FBC_WRITE(sc, FFB_FBC_FONTINC, 0x10000);
465 sc->sc_fg_cache = 0;
466 FBC_WRITE(sc, FFB_FBC_FG, sc->sc_fg_cache);
467 ffb_ras_wait(sc);
468 }
469
470 void
471 ffb_ras_eraserows(void *cookie, int row, int n, long attr)
472 {
473 struct rasops_info *ri = cookie;
474 struct ffb_softc *sc = ri->ri_hw;
475
476 if (row < 0) {
477 n += row;
478 row = 0;
479 }
480 if (row + n > ri->ri_rows)
481 n = ri->ri_rows - row;
482 if (n <= 0)
483 return;
484
485 ffb_ras_fill(sc);
486 ffb_ras_setfg(sc, ri->ri_devcmap[(attr >> 16) & 0xf]);
487 ffb_ras_fifo_wait(sc, 4);
488 if ((n == ri->ri_rows) && (ri->ri_flg & RI_FULLCLEAR)) {
489 FBC_WRITE(sc, FFB_FBC_BY, 0);
490 FBC_WRITE(sc, FFB_FBC_BX, 0);
491 FBC_WRITE(sc, FFB_FBC_BH, ri->ri_height);
492 FBC_WRITE(sc, FFB_FBC_BW, ri->ri_width);
493 } else {
494 row *= ri->ri_font->fontheight;
495 FBC_WRITE(sc, FFB_FBC_BY, ri->ri_yorigin + row);
496 FBC_WRITE(sc, FFB_FBC_BX, ri->ri_xorigin);
497 FBC_WRITE(sc, FFB_FBC_BH, n * ri->ri_font->fontheight);
498 FBC_WRITE(sc, FFB_FBC_BW, ri->ri_emuwidth);
499 }
500 ffb_ras_wait(sc);
501 }
502
503 void
504 ffb_ras_erasecols(void *cookie, int row, int col, int n, long attr)
505 {
506 struct rasops_info *ri = cookie;
507 struct ffb_softc *sc = ri->ri_hw;
508
509 if ((row < 0) || (row >= ri->ri_rows))
510 return;
511 if (col < 0) {
512 n += col;
513 col = 0;
514 }
515 if (col + n > ri->ri_cols)
516 n = ri->ri_cols - col;
517 if (n <= 0)
518 return;
519 n *= ri->ri_font->fontwidth;
520 col *= ri->ri_font->fontwidth;
521 row *= ri->ri_font->fontheight;
522
523 ffb_ras_fill(sc);
524 ffb_ras_setfg(sc, ri->ri_devcmap[(attr >> 16) & 0xf]);
525 ffb_ras_fifo_wait(sc, 4);
526 FBC_WRITE(sc, FFB_FBC_BY, ri->ri_yorigin + row);
527 FBC_WRITE(sc, FFB_FBC_BX, ri->ri_xorigin + col);
528 FBC_WRITE(sc, FFB_FBC_BH, ri->ri_font->fontheight);
529 FBC_WRITE(sc, FFB_FBC_BW, n - 1);
530 ffb_ras_wait(sc);
531 }
532
533 void
534 ffb_ras_fill(struct ffb_softc *sc)
535 {
536 ffb_ras_fifo_wait(sc, 2);
537 FBC_WRITE(sc, FFB_FBC_ROP, FBC_ROP_NEW);
538 FBC_WRITE(sc, FFB_FBC_DRAWOP, FBC_DRAWOP_RECTANGLE);
539 ffb_ras_wait(sc);
540 }
541
542 void
543 ffb_ras_copyrows(void *cookie, int src, int dst, int n)
544 {
545 struct rasops_info *ri = cookie;
546 struct ffb_softc *sc = ri->ri_hw;
547
548 if (dst == src)
549 return;
550 if (src < 0) {
551 n += src;
552 src = 0;
553 }
554 if ((src + n) > ri->ri_rows)
555 n = ri->ri_rows - src;
556 if (dst < 0) {
557 n += dst;
558 dst = 0;
559 }
560 if ((dst + n) > ri->ri_rows)
561 n = ri->ri_rows - dst;
562 if (n <= 0)
563 return;
564 n *= ri->ri_font->fontheight;
565 src *= ri->ri_font->fontheight;
566 dst *= ri->ri_font->fontheight;
567
568 ffb_ras_fifo_wait(sc, 8);
569 FBC_WRITE(sc, FFB_FBC_ROP, FBC_ROP_OLD | (FBC_ROP_OLD << 8));
570 FBC_WRITE(sc, FFB_FBC_DRAWOP, FBC_DRAWOP_VSCROLL);
571 FBC_WRITE(sc, FFB_FBC_BY, ri->ri_yorigin + src);
572 FBC_WRITE(sc, FFB_FBC_BX, ri->ri_xorigin);
573 FBC_WRITE(sc, FFB_FBC_DY, ri->ri_yorigin + dst);
574 FBC_WRITE(sc, FFB_FBC_DX, ri->ri_xorigin);
575 FBC_WRITE(sc, FFB_FBC_BH, n);
576 FBC_WRITE(sc, FFB_FBC_BW, ri->ri_emuwidth);
577 ffb_ras_wait(sc);
578 }
579
580 void
581 ffb_ras_setfg(struct ffb_softc *sc, int32_t fg)
582 {
583 ffb_ras_fifo_wait(sc, 1);
584 if (fg == sc->sc_fg_cache)
585 return;
586 sc->sc_fg_cache = fg;
587 FBC_WRITE(sc, FFB_FBC_FG, fg);
588 ffb_ras_wait(sc);
589 }
590
591 /* frame buffer generic driver support functions */
592 static void
593 ffbfb_unblank(struct device *dev)
594 {
595 /* u_int on = 1; */
596
597 if (dev && dev->dv_xname)
598 printf("%s: ffbfb_unblank\n", dev->dv_xname);
599 else
600 printf("ffbfb_unblank(%p)n", dev);
601 /* ffb_blank((struct ffb_softc*)dev, WSDISPLAYIO_SVIDEO, &on); */
602 }
603
604 int
605 ffbfb_open(dev_t dev, int flags, int mode, struct proc *p)
606 {
607 int unit = minor(dev);
608
609 if (unit >= ffb_cd.cd_ndevs || ffb_cd.cd_devs[unit] == NULL)
610 return ENXIO;
611
612 return 0;
613 }
614
615 int
616 ffbfb_close(dev_t dev, int flags, int mode, struct proc *p)
617 {
618 return 0;
619 }
620
621 int
622 ffbfb_ioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p)
623 {
624 struct ffb_softc *sc = ffb_cd.cd_devs[minor(dev)];
625
626 return ffb_ioctl(sc, cmd, data, flags, p);
627 }
628
629 paddr_t
630 ffbfb_mmap(dev_t dev, off_t off, int prot)
631 {
632 struct ffb_softc *sc = ffb_cd.cd_devs[minor(dev)];
633 int i, reg;
634 off_t o;
635
636 /*
637 * off is a magic cookie (see xfree86/drivers/sunffb/ffb.h),
638 * which we map to an index into the "reg" property, and use
639 * our copy of the firmware data as arguments for the real
640 * mapping.
641 */
642 static struct { unsigned long voff; int reg; } map[] = {
643 { 0x00000000, FFB_REG_SFB8R },
644 { 0x00400000, FFB_REG_SFB8G },
645 { 0x00800000, FFB_REG_SFB8B },
646 { 0x00c00000, FFB_REG_SFB8X },
647 { 0x01000000, FFB_REG_SFB32 },
648 { 0x02000000, FFB_REG_SFB64 },
649 { 0x04000000, FFB_REG_FBC },
650 { 0x04004000, FFB_REG_DFB8R },
651 { 0x04404000, FFB_REG_DFB8G },
652 { 0x04804000, FFB_REG_DFB8B },
653 { 0x04c04000, FFB_REG_DFB8X },
654 { 0x05004000, FFB_REG_DFB24 },
655 { 0x06004000, FFB_REG_DFB32 },
656 { 0x07004000, FFB_REG_DFB422A },
657 { 0x0bc06000, FFB_REG_DAC },
658 { 0x0bc08000, FFB_REG_PROM },
659 };
660
661 /* special value "FFB_EXP_VOFF" - not backed by any "reg" entry */
662 if (off == 0x0bc18000)
663 return bus_space_mmap(sc->sc_bt, sc->sc_addrs[FFB_REG_PROM],
664 0x00200000, prot, BUS_SPACE_MAP_LINEAR);
665
666 #define NELEMS(arr) (sizeof(arr)/sizeof((arr)[0]))
667
668 /* the map is ordered by voff */
669 for (i = 0; i < NELEMS(map); i++) {
670 if (map[i].voff > off)
671 break; /* beyound */
672 reg = map[i].reg;
673 if (map[i].voff + sc->sc_sizes[reg] < off)
674 continue; /* not there yet */
675 if (off > map[i].voff + sc->sc_sizes[reg])
676 break; /* out of range */
677 o = off - map[i].voff;
678 return bus_space_mmap(sc->sc_bt, sc->sc_addrs[reg], o, prot,
679 BUS_SPACE_MAP_LINEAR);
680 }
681
682 return -1;
683 }
684