1 /* $NetBSD: ffb.c,v 1.36 2008/11/16 05:10:46 macallan Exp $ */
2 /* $OpenBSD: creator.c,v 1.20 2002/07/30 19:48:15 jason Exp $ */
5 * Copyright (c) 2002 Jason L. Wright (jason@thought.net)
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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.
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.
35 #include <sys/cdefs.h>
36 __KERNEL_RCSID(0, "$NetBSD: ffb.c,v 1.36 2008/11/16 05:10:46 macallan Exp $");
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>
44 #include <sys/ioctl.h>
45 #include <sys/malloc.h>
48 #include <machine/bus.h>
49 #include <machine/autoconf.h>
50 #include <machine/openfirm.h>
51 #include <machine/vmparam.h>
53 #include <dev/wscons/wsconsio.h>
54 #include <dev/sun/fbio.h>
55 #include <dev/sun/fbvar.h>
57 #include <dev/wsfont/wsfont.h>
58 #include <dev/wscons/wsdisplay_vconsvar.h>
60 #include <sparc64/dev/ffbreg.h>
61 #include <sparc64/dev/ffbvar.h>
64 /* Sun -> background should be white */
65 #define WS_DEFAULT_BG 0xf
68 extern struct cfdriver ffb_cd
;
70 struct wsscreen_descr ffb_stdscreen
= {
72 0, 0, /* will be filled in -- XXX shouldn't, it's global. */
75 WSSCREEN_REVERSE
| WSSCREEN_WSCOLORS
,
79 const struct wsscreen_descr
*ffb_scrlist
[] = {
81 /* XXX other formats? */
84 struct wsscreen_list ffb_screenlist
= {
85 sizeof(ffb_scrlist
) / sizeof(struct wsscreen_descr
*),
89 static struct vcons_screen ffb_console_screen
;
91 int ffb_ioctl(void *, void *, u_long
, void *, int, struct lwp
*);
92 static int ffb_blank(struct ffb_softc
*, u_long
, u_int
*);
93 paddr_t
ffb_mmap(void *, void *, off_t
, int);
94 void ffb_ras_fifo_wait(struct ffb_softc
*, int);
95 void ffb_ras_wait(struct ffb_softc
*);
96 void ffb_ras_init(struct ffb_softc
*);
97 void ffb_ras_copyrows(void *, int, int, int);
98 void ffb_ras_erasecols(void *, int, int, int, long int);
99 void ffb_ras_eraserows(void *, int, int, long int);
100 void ffb_ras_do_cursor(struct rasops_info
*);
101 void ffb_ras_fill(struct ffb_softc
*);
102 void ffb_ras_setfg(struct ffb_softc
*, int32_t);
104 void ffb_clearscreen(struct ffb_softc
*);
105 int ffb_load_font(void *, void *, struct wsdisplay_font
*);
106 void ffb_init_screen(void *, struct vcons_screen
*, int,
108 int ffb_allocattr(void *, int, int, int, long *);
109 void ffb_putchar(void *, int, int, u_int
, long);
110 void ffb_cursor(void *, int, int, int);
112 /* frame buffer generic driver */
113 static void ffbfb_unblank(struct device
*);
114 dev_type_open(ffbfb_open
);
115 dev_type_close(ffbfb_close
);
116 dev_type_ioctl(ffbfb_ioctl
);
117 dev_type_mmap(ffbfb_mmap
);
119 static struct fbdriver ffb_fbdriver
= {
120 ffbfb_unblank
, ffbfb_open
, ffbfb_close
, ffbfb_ioctl
, nopoll
,
121 ffbfb_mmap
, nokqfilter
124 struct wsdisplay_accessops ffb_accessops
= {
130 ffb_attach(struct ffb_softc
*sc
)
132 struct wsemuldisplaydev_attach_args waa
;
133 struct rasops_info
*ri
;
139 u_int blank
= WSDISPLAYIO_VIDEO_ON
;
146 if (sc
->sc_type
== FFB_CREATOR
) {
147 btype
= prom_getpropint(sc
->sc_node
, "board_type", 0);
148 if ((btype
& 7) == 3)
149 printf(" Creator3D");
155 model
= prom_getpropstring(sc
->sc_node
, "model");
156 if (model
== NULL
|| strlen(model
) == 0)
160 sc
->sc_linebytes
= 8192;
161 sc
->sc_height
= prom_getpropint(sc
->sc_node
, "height", 0);
162 sc
->sc_width
= prom_getpropint(sc
->sc_node
, "width", 0);
165 sc
->sc_mode
= WSDISPLAYIO_MODE_EMUL
;
167 maxcol
= (prom_getoption("screen-#columns", buf
, sizeof buf
) == 0)
168 ? strtoul(buf
, NULL
, 10)
171 maxrow
= (prom_getoption("screen-#rows", buf
, sizeof buf
) != 0)
172 ? strtoul(buf
, NULL
, 10)
177 /* collect DAC version, as Elite3D cursor enable bit is reversed */
178 DAC_WRITE(sc
, FFB_DAC_TYPE
, FFB_DAC_GVERS
);
179 dac
= DAC_READ(sc
, FFB_DAC_VALUE
);
180 sc
->sc_dacrev
= (dac
>> 28) & 0xf;
182 if (sc
->sc_type
== FFB_AFB
) {
184 sc
->sc_needredraw
= 0;
186 /* see what kind of DAC we have */
187 int pnum
= (dac
& 0x0ffff000) >> 12;
188 if (pnum
== 0x236e) {
189 sc
->sc_needredraw
= 0;
191 sc
->sc_needredraw
= 1;
194 printf(", model %s, dac %u\n", model
, sc
->sc_dacrev
);
195 if (sc
->sc_needredraw
)
196 printf("%s: found old DAC, enabling redraw on unblank\n",
197 device_xname(&sc
->sc_dv
));
199 ffb_blank(sc
, WSDISPLAYIO_SVIDEO
, &blank
);
201 sc
->sc_accel
= ((device_cfdata(&sc
->sc_dv
)->cf_flags
&
202 FFB_CFFLAG_NOACCEL
) == 0);
206 vcons_init(&sc
->vd
, sc
, &ffb_stdscreen
, &ffb_accessops
);
207 sc
->vd
.init_screen
= ffb_init_screen
;
209 /* we mess with ffb_console_screen only once */
210 if (sc
->sc_console
) {
211 vcons_init_screen(&sc
->vd
, &ffb_console_screen
, 1, &defattr
);
212 SCREEN_VISIBLE((&ffb_console_screen
));
214 * XXX we shouldn't use a global variable for the console
217 sc
->vd
.active
= &ffb_console_screen
;
218 ffb_console_screen
.scr_flags
= VCONS_SCREEN_IS_STATIC
;
220 if (ffb_console_screen
.scr_ri
.ri_rows
== 0) {
221 /* do some minimal setup to avoid weirdnesses later */
222 vcons_init_screen(&sc
->vd
, &ffb_console_screen
, 1, &defattr
);
225 ri
= &ffb_console_screen
.scr_ri
;
227 ffb_stdscreen
.nrows
= ri
->ri_rows
;
228 ffb_stdscreen
.ncols
= ri
->ri_cols
;
229 ffb_stdscreen
.textops
= &ri
->ri_ops
;
230 ffb_stdscreen
.capabilities
= ri
->ri_caps
;
232 sc
->sc_fb
.fb_driver
= &ffb_fbdriver
;
233 sc
->sc_fb
.fb_type
.fb_cmsize
= 0;
234 sc
->sc_fb
.fb_type
.fb_size
= maxrow
* sc
->sc_linebytes
;
235 sc
->sc_fb
.fb_type
.fb_type
= FBTYPE_CREATOR
;
236 sc
->sc_fb
.fb_type
.fb_width
= sc
->sc_width
;
237 sc
->sc_fb
.fb_type
.fb_depth
= sc
->sc_depth
;
238 sc
->sc_fb
.fb_type
.fb_height
= sc
->sc_height
;
239 sc
->sc_fb
.fb_device
= &sc
->sc_dv
;
240 fb_attach(&sc
->sc_fb
, sc
->sc_console
);
244 if (sc
->sc_console
) {
245 wsdisplay_cnattach(&ffb_stdscreen
, ri
, 0, 0, defattr
);
246 vcons_replay_msgbuf(&ffb_console_screen
);
249 waa
.console
= sc
->sc_console
;
250 waa
.scrdata
= &ffb_screenlist
;
251 waa
.accessops
= &ffb_accessops
;
252 waa
.accesscookie
= &sc
->vd
;
253 config_found(&sc
->sc_dv
, &waa
, wsemuldisplaydevprint
);
257 ffb_ioctl(void *v
, void *vs
, u_long cmd
, void *data
, int flags
, struct lwp
*l
)
259 struct vcons_data
*vd
= v
;
260 struct ffb_softc
*sc
= vd
->cookie
;
261 struct wsdisplay_fbinfo
*wdf
;
262 struct vcons_screen
*ms
= vd
->active
;
265 printf("ffb_ioctl: %s cmd _IO%s%s('%c', %lu)\n",
266 device_xname(&sc
->sc_dv
),
267 (cmd
& IOC_IN
) ? "W" : "", (cmd
& IOC_OUT
) ? "R" : "",
268 (char)IOCGROUP(cmd
), cmd
& 0xff);
273 *(struct fbtype
*)data
= sc
->sc_fb
.fb_type
;
276 #define fba ((struct fbgattr *)data)
277 fba
->real_type
= sc
->sc_fb
.fb_type
.fb_type
;
278 fba
->owner
= 0; /* XXX ??? */
279 fba
->fbtype
= sc
->sc_fb
.fb_type
;
280 fba
->sattr
.flags
= 0;
281 fba
->sattr
.emu_type
= sc
->sc_fb
.fb_type
.fb_type
;
282 fba
->sattr
.dev_specific
[0] = -1;
283 fba
->emu_types
[0] = sc
->sc_fb
.fb_type
.fb_type
;
284 fba
->emu_types
[1] = -1;
294 return ffb_blank(sc
, cmd
== FBIOGVIDEO
?
295 WSDISPLAYIO_GVIDEO
: WSDISPLAYIO_SVIDEO
,
300 /* the console driver is not using the hardware cursor */
303 printf("%s: FBIOGCURPOS not implemented\n", device_xname(&sc
->sc_dv
));
306 printf("%s: FBIOSCURPOS not implemented\n", device_xname(&sc
->sc_dv
));
309 printf("%s: FBIOGCURMAX not implemented\n", device_xname(&sc
->sc_dv
));
312 case WSDISPLAYIO_GTYPE
:
313 *(u_int
*)data
= WSDISPLAY_TYPE_SUNFFB
;
315 case WSDISPLAYIO_SMODE
:
317 if (sc
->sc_mode
!= *(u_int
*)data
) {
318 sc
->sc_mode
= *(u_int
*)data
;
319 if ((sc
->sc_mode
== WSDISPLAYIO_MODE_EMUL
) &&
320 (sc
->sc_locked
== 0)) {
322 vcons_redraw_screen(ms
);
327 case WSDISPLAYIO_GINFO
:
329 wdf
->height
= sc
->sc_height
;
330 wdf
->width
= sc
->sc_width
;
332 wdf
->cmsize
= 256; /* XXX */
334 #ifdef WSDISPLAYIO_LINEBYTES
335 case WSDISPLAYIO_LINEBYTES
:
336 *(u_int
*)data
= sc
->sc_linebytes
;
339 case WSDISPLAYIO_GETCMAP
:
342 case WSDISPLAYIO_PUTCMAP
:
345 case WSDISPLAYIO_SVIDEO
:
346 case WSDISPLAYIO_GVIDEO
:
347 return(ffb_blank(sc
, cmd
, (u_int
*)data
));
349 case WSDISPLAYIO_GCURPOS
:
350 case WSDISPLAYIO_SCURPOS
:
351 case WSDISPLAYIO_GCURMAX
:
352 case WSDISPLAYIO_GCURSOR
:
353 case WSDISPLAYIO_SCURSOR
:
354 return EIO
; /* not supported yet */
362 /* blank/unblank the screen */
364 ffb_blank(struct ffb_softc
*sc
, u_long cmd
, u_int
*data
)
366 struct vcons_screen
*ms
= sc
->vd
.active
;
369 DAC_WRITE(sc
, FFB_DAC_TYPE
, FFB_DAC_GSBLANK
);
370 val
= DAC_READ(sc
, FFB_DAC_VALUE
);
373 case WSDISPLAYIO_GVIDEO
:
377 case WSDISPLAYIO_SVIDEO
:
378 if (*data
== WSDISPLAYIO_VIDEO_OFF
)
380 else if (*data
== WSDISPLAYIO_VIDEO_ON
)
389 DAC_WRITE(sc
, FFB_DAC_TYPE
, FFB_DAC_GSBLANK
);
390 DAC_WRITE(sc
, FFB_DAC_VALUE
, val
);
392 if ((val
& 1) && sc
->sc_needredraw
) {
394 if ((sc
->sc_mode
== WSDISPLAYIO_MODE_EMUL
) &&
395 (sc
->sc_locked
== 0)) {
397 vcons_redraw_screen(ms
);
406 ffb_mmap(void *vsc
, void *vs
, off_t off
, int prot
)
408 struct vcons_data
*vd
= vsc
;
409 struct ffb_softc
*sc
= vd
->cookie
;
412 switch (sc
->sc_mode
) {
413 case WSDISPLAYIO_MODE_MAPPED
:
414 for (i
= 0; i
< sc
->sc_nreg
; i
++) {
415 /* Before this set? */
416 if (off
< sc
->sc_addrs
[i
])
418 /* After this set? */
419 if (off
>= (sc
->sc_addrs
[i
] + sc
->sc_sizes
[i
]))
422 return (bus_space_mmap(sc
->sc_bt
, sc
->sc_addrs
[i
],
423 off
- sc
->sc_addrs
[i
], prot
, BUS_SPACE_MAP_LINEAR
));
426 #ifdef WSDISPLAYIO_MODE_DUMBFB
427 case WSDISPLAYIO_MODE_DUMBFB
:
428 if (sc
->sc_nreg
< FFB_REG_DFB24
)
430 if (off
>= 0 && off
< sc
->sc_sizes
[FFB_REG_DFB24
])
431 return (bus_space_mmap(sc
->sc_bt
,
432 sc
->sc_addrs
[FFB_REG_DFB24
], off
, prot
,
433 BUS_SPACE_MAP_LINEAR
));
441 ffb_ras_fifo_wait(struct ffb_softc
*sc
, int n
)
443 int32_t cache
= sc
->sc_fifo_cache
;
447 cache
= FBC_READ(sc
, FFB_FBC_UCSR
);
448 cache
= (cache
& FBC_UCSR_FIFO_MASK
) - 8;
451 sc
->sc_fifo_cache
= cache
- n
;
455 ffb_ras_wait(struct ffb_softc
*sc
)
460 ucsr
= FBC_READ(sc
, FFB_FBC_UCSR
);
461 if ((ucsr
& (FBC_UCSR_FB_BUSY
|FBC_UCSR_RP_BUSY
)) == 0)
463 r
= ucsr
& (FBC_UCSR_READ_ERR
| FBC_UCSR_FIFO_OVFL
);
465 FBC_WRITE(sc
, FFB_FBC_UCSR
, r
);
470 ffb_ras_init(struct ffb_softc
*sc
)
472 ffb_ras_fifo_wait(sc
, 7);
473 FBC_WRITE(sc
, FFB_FBC_PPC
,
474 FBC_PPC_VCE_DIS
| FBC_PPC_TBE_OPAQUE
|
475 FBC_PPC_APE_DIS
| FBC_PPC_CS_CONST
);
476 FBC_WRITE(sc
, FFB_FBC_FBC
,
477 FFB_FBC_WB_A
| FFB_FBC_RB_A
| FFB_FBC_SB_BOTH
|
478 FFB_FBC_XE_OFF
| FFB_FBC_RGBE_MASK
);
479 FBC_WRITE(sc
, FFB_FBC_ROP
, FBC_ROP_NEW
);
480 FBC_WRITE(sc
, FFB_FBC_DRAWOP
, FBC_DRAWOP_RECTANGLE
);
481 FBC_WRITE(sc
, FFB_FBC_PMASK
, 0xffffffff);
482 FBC_WRITE(sc
, FFB_FBC_FONTINC
, 0x10000);
484 FBC_WRITE(sc
, FFB_FBC_FG
, sc
->sc_fg_cache
);
489 ffb_ras_eraserows(void *cookie
, int row
, int n
, long attr
)
491 struct rasops_info
*ri
= cookie
;
492 struct vcons_screen
*scr
= ri
->ri_hw
;
493 struct ffb_softc
*sc
= scr
->scr_cookie
;
499 if (row
+ n
> ri
->ri_rows
)
500 n
= ri
->ri_rows
- row
;
505 ffb_ras_setfg(sc
, ri
->ri_devcmap
[(attr
>> 16) & 0xf]);
506 ffb_ras_fifo_wait(sc
, 4);
507 if ((n
== ri
->ri_rows
) && (ri
->ri_flg
& RI_FULLCLEAR
)) {
508 FBC_WRITE(sc
, FFB_FBC_BY
, 0);
509 FBC_WRITE(sc
, FFB_FBC_BX
, 0);
510 FBC_WRITE(sc
, FFB_FBC_BH
, ri
->ri_height
);
511 FBC_WRITE(sc
, FFB_FBC_BW
, ri
->ri_width
);
513 row
*= ri
->ri_font
->fontheight
;
514 FBC_WRITE(sc
, FFB_FBC_BY
, ri
->ri_yorigin
+ row
);
515 FBC_WRITE(sc
, FFB_FBC_BX
, ri
->ri_xorigin
);
516 FBC_WRITE(sc
, FFB_FBC_BH
, n
* ri
->ri_font
->fontheight
);
517 FBC_WRITE(sc
, FFB_FBC_BW
, ri
->ri_emuwidth
);
523 ffb_ras_erasecols(void *cookie
, int row
, int col
, int n
, long attr
)
525 struct rasops_info
*ri
= cookie
;
526 struct vcons_screen
*scr
= ri
->ri_hw
;
527 struct ffb_softc
*sc
= scr
->scr_cookie
;
529 if ((row
< 0) || (row
>= ri
->ri_rows
))
535 if (col
+ n
> ri
->ri_cols
)
536 n
= ri
->ri_cols
- col
;
539 n
*= ri
->ri_font
->fontwidth
;
540 col
*= ri
->ri_font
->fontwidth
;
541 row
*= ri
->ri_font
->fontheight
;
544 ffb_ras_setfg(sc
, ri
->ri_devcmap
[(attr
>> 16) & 0xf]);
545 ffb_ras_fifo_wait(sc
, 4);
546 FBC_WRITE(sc
, FFB_FBC_BY
, ri
->ri_yorigin
+ row
);
547 FBC_WRITE(sc
, FFB_FBC_BX
, ri
->ri_xorigin
+ col
);
548 FBC_WRITE(sc
, FFB_FBC_BH
, ri
->ri_font
->fontheight
);
549 FBC_WRITE(sc
, FFB_FBC_BW
, n
- 1);
554 ffb_ras_fill(struct ffb_softc
*sc
)
556 ffb_ras_fifo_wait(sc
, 2);
557 FBC_WRITE(sc
, FFB_FBC_ROP
, FBC_ROP_NEW
);
558 FBC_WRITE(sc
, FFB_FBC_DRAWOP
, FBC_DRAWOP_RECTANGLE
);
563 ffb_ras_copyrows(void *cookie
, int src
, int dst
, int n
)
565 struct rasops_info
*ri
= cookie
;
566 struct vcons_screen
*scr
= ri
->ri_hw
;
567 struct ffb_softc
*sc
= scr
->scr_cookie
;
575 if ((src
+ n
) > ri
->ri_rows
)
576 n
= ri
->ri_rows
- src
;
581 if ((dst
+ n
) > ri
->ri_rows
)
582 n
= ri
->ri_rows
- dst
;
585 n
*= ri
->ri_font
->fontheight
;
586 src
*= ri
->ri_font
->fontheight
;
587 dst
*= ri
->ri_font
->fontheight
;
589 ffb_ras_fifo_wait(sc
, 8);
590 FBC_WRITE(sc
, FFB_FBC_ROP
, FBC_ROP_OLD
| (FBC_ROP_OLD
<< 8));
591 FBC_WRITE(sc
, FFB_FBC_DRAWOP
, FBC_DRAWOP_VSCROLL
);
592 FBC_WRITE(sc
, FFB_FBC_BY
, ri
->ri_yorigin
+ src
);
593 FBC_WRITE(sc
, FFB_FBC_BX
, ri
->ri_xorigin
);
594 FBC_WRITE(sc
, FFB_FBC_DY
, ri
->ri_yorigin
+ dst
);
595 FBC_WRITE(sc
, FFB_FBC_DX
, ri
->ri_xorigin
);
596 FBC_WRITE(sc
, FFB_FBC_BH
, n
);
597 FBC_WRITE(sc
, FFB_FBC_BW
, ri
->ri_emuwidth
);
602 ffb_ras_setfg(struct ffb_softc
*sc
, int32_t fg
)
604 ffb_ras_fifo_wait(sc
, 1);
605 if (fg
== sc
->sc_fg_cache
)
607 sc
->sc_fg_cache
= fg
;
608 FBC_WRITE(sc
, FFB_FBC_FG
, fg
);
612 /* frame buffer generic driver support functions */
614 ffbfb_unblank(struct device
*dev
)
616 struct ffb_softc
*sc
= device_private(dev
);
617 struct vcons_screen
*ms
= sc
->vd
.active
;
627 ffb_blank(sc
, WSDISPLAYIO_SVIDEO
, &on
);
629 if ((sc
->vd
.active
!= &ffb_console_screen
) &&
630 (ffb_console_screen
.scr_flags
& VCONS_SCREEN_IS_STATIC
)) {
632 * force-switch to the console screen.
633 * Caveat: the higher layer will think we're still on the
637 SCREEN_INVISIBLE(sc
->vd
.active
);
638 sc
->vd
.active
= &ffb_console_screen
;
639 SCREEN_VISIBLE(sc
->vd
.active
);
645 vcons_redraw_screen(ms
);
650 ffbfb_open(dev_t dev
, int flags
, int mode
, struct lwp
*l
)
652 struct ffb_softc
*sc
;
654 sc
= device_lookup_private(&ffb_cd
, minor(dev
));
663 ffbfb_close(dev_t dev
, int flags
, int mode
, struct lwp
*l
)
665 struct ffb_softc
*sc
= device_lookup_private(&ffb_cd
, minor(dev
));
666 struct vcons_screen
*ms
= sc
->vd
.active
;
670 if ((sc
->sc_mode
== WSDISPLAYIO_MODE_EMUL
) &&
671 (sc
->sc_locked
== 0)) {
673 vcons_redraw_screen(ms
);
680 ffbfb_ioctl(dev_t dev
, u_long cmd
, void *data
, int flags
, struct lwp
*l
)
682 struct ffb_softc
*sc
= device_lookup_private(&ffb_cd
, minor(dev
));
684 return ffb_ioctl(&sc
->vd
, NULL
, cmd
, data
, flags
, l
);
688 ffbfb_mmap(dev_t dev
, off_t off
, int prot
)
690 struct ffb_softc
*sc
= device_lookup_private(&ffb_cd
, minor(dev
));
696 * off is a magic cookie (see xfree86/drivers/sunffb/ffb.h),
697 * which we map to an index into the "reg" property, and use
698 * our copy of the firmware data as arguments for the real
701 static struct { unsigned long voff
; int reg
; } map
[] = {
702 { 0x00000000, FFB_REG_SFB8R
},
703 { 0x00400000, FFB_REG_SFB8G
},
704 { 0x00800000, FFB_REG_SFB8B
},
705 { 0x00c00000, FFB_REG_SFB8X
},
706 { 0x01000000, FFB_REG_SFB32
},
707 { 0x02000000, FFB_REG_SFB64
},
708 { 0x04000000, FFB_REG_FBC
},
709 { 0x04004000, FFB_REG_DFB8R
},
710 { 0x04404000, FFB_REG_DFB8G
},
711 { 0x04804000, FFB_REG_DFB8B
},
712 { 0x04c04000, FFB_REG_DFB8X
},
713 { 0x05004000, FFB_REG_DFB24
},
714 { 0x06004000, FFB_REG_DFB32
},
715 { 0x07004000, FFB_REG_DFB422A
},
716 { 0x0bc06000, FFB_REG_DAC
},
717 { 0x0bc08000, FFB_REG_PROM
},
721 /* special value "FFB_EXP_VOFF" - not backed by any "reg" entry */
722 if (off
== 0x0bc18000)
723 return bus_space_mmap(sc
->sc_bt
, sc
->sc_addrs
[FFB_REG_PROM
],
724 0x00200000, prot
, BUS_SPACE_MAP_LINEAR
);
727 * FFB_VOFF_FBC_KREGS - used by afbinit to upload firmware. We should
728 * probably mmap them only on afb boards
730 if ((off
>= 0x0bc04000) && (off
< 0x0bc06000))
731 return bus_space_mmap(sc
->sc_bt
, sc
->sc_addrs
[FFB_REG_PROM
],
732 0x00610000 + (off
- 0x0bc04000), prot
,
733 BUS_SPACE_MAP_LINEAR
);
735 #define NELEMS(arr) (sizeof(arr)/sizeof((arr)[0]))
737 /* the map is ordered by voff */
738 for (i
= 0; i
< NELEMS(map
)-1; i
++) {
740 /* the number of entries in reg seems to vary */
741 if (reg
< sc
->sc_nreg
) {
742 size
= min((map
[i
+ 1].voff
- map
[i
].voff
),
744 if ((off
>= map
[i
].voff
) &&
745 (off
< (map
[i
].voff
+ size
))) {
746 o
= off
- map
[i
].voff
;
747 return bus_space_mmap(sc
->sc_bt
,
748 sc
->sc_addrs
[reg
], o
, prot
,
749 BUS_SPACE_MAP_LINEAR
);
758 ffb_clearscreen(struct ffb_softc
*sc
)
760 struct rasops_info
*ri
= &ffb_console_screen
.scr_ri
;
762 ffb_ras_setfg(sc
, ri
->ri_devcmap
[WS_DEFAULT_BG
]);
763 ffb_ras_fifo_wait(sc
, 4);
764 FBC_WRITE(sc
, FFB_FBC_BY
, 0);
765 FBC_WRITE(sc
, FFB_FBC_BX
, 0);
766 FBC_WRITE(sc
, FFB_FBC_BH
, sc
->sc_height
);
767 FBC_WRITE(sc
, FFB_FBC_BW
, sc
->sc_width
);
771 ffb_cursor(void *cookie
, int on
, int row
, int col
)
773 struct rasops_info
*ri
= cookie
;
774 struct vcons_screen
*scr
;
775 struct ffb_softc
*sc
;
776 int x
, y
, wi
, he
, coffset
;
778 if (cookie
!= NULL
) {
780 sc
= scr
->scr_cookie
;
782 wi
= ri
->ri_font
->fontwidth
;
783 he
= ri
->ri_font
->fontheight
;
785 if (sc
->sc_mode
== WSDISPLAYIO_MODE_EMUL
) {
786 x
= ri
->ri_ccol
* wi
+ ri
->ri_xorigin
;
787 y
= ri
->ri_crow
* he
+ ri
->ri_yorigin
;
789 if (ri
->ri_flg
& RI_CURSOR
) {
791 coffset
= ri
->ri_ccol
+ (ri
->ri_crow
*
793 #ifdef WSDISPLAY_SCROLLSUPPORT
794 coffset
+= scr
->scr_offset_to_zero
;
797 sc
->putchar(cookie
, ri
->ri_crow
,
798 ri
->ri_ccol
, scr
->scr_chars
[coffset
],
799 scr
->scr_attrs
[coffset
]);
800 ri
->ri_flg
&= ~RI_CURSOR
;
807 x
= ri
->ri_ccol
* wi
+ ri
->ri_xorigin
;
808 y
= ri
->ri_crow
* he
+ ri
->ri_yorigin
;
809 coffset
= col
+ (row
* ri
->ri_cols
);
810 #ifdef WSDISPLAY_SCROLLSUPPORT
811 coffset
+= scr
->scr_offset_to_zero
;
813 attr
= scr
->scr_attrs
[coffset
];
814 #ifdef FFB_CURSOR_SWAP_COLOURS
815 revattr
=((attr
>> 8 ) & 0x000f0000) | ((attr
&
816 0x000f0000)<<8) | (attr
& 0x0000ffff);
818 revattr
= attr
^ 0xffff0000;
821 sc
->putchar(cookie
, ri
->ri_crow
, ri
->ri_ccol
,
822 scr
->scr_chars
[coffset
], revattr
);
823 ri
->ri_flg
|= RI_CURSOR
;
828 ri
->ri_flg
&= ~RI_CURSOR
;
834 ffb_putchar(void *cookie
, int row
, int col
, u_int c
, long attr
)
836 struct rasops_info
*ri
= cookie
;
837 struct vcons_screen
*scr
= ri
->ri_hw
;
838 struct ffb_softc
*sc
= scr
->scr_cookie
;
840 if (sc
->putchar
!= NULL
) {
842 * the only reason why we need to hook putchar - wait for
843 * the drawing engine to be idle so we don't interfere
844 * ( and we should really use the colour expansion hardware )
847 sc
->putchar(cookie
, row
, col
, c
, attr
);
852 ffb_allocattr(void *cookie
, int fg
, int bg
, int flags
, long *attrp
)
854 if ((fg
== 0) && (bg
== 0))
859 if (flags
& WSATTR_REVERSE
) {
860 *attrp
= (bg
& 0xff) << 24 | (fg
& 0xff) << 16 |
863 *attrp
= (fg
& 0xff) << 24 | (bg
& 0xff) << 16 |
869 ffb_init_screen(void *cookie
, struct vcons_screen
*scr
,
870 int existing
, long *defattr
)
872 struct ffb_softc
*sc
= cookie
;
873 struct rasops_info
*ri
= &scr
->scr_ri
;
876 ri
->ri_width
= sc
->sc_width
;
877 ri
->ri_height
= sc
->sc_height
;
878 ri
->ri_stride
= sc
->sc_linebytes
;
879 ri
->ri_flg
= RI_CENTER
;
881 ri
->ri_bits
= bus_space_vaddr(sc
->sc_bt
, sc
->sc_pixel_h
);
884 printf("addr: %08lx\n",(ulong
)ri
->ri_bits
);
886 rasops_init(ri
, sc
->sc_height
/8, sc
->sc_width
/8);
887 ri
->ri_caps
= WSSCREEN_WSCOLORS
;
888 rasops_reconfig(ri
, sc
->sc_height
/ ri
->ri_font
->fontheight
,
889 sc
->sc_width
/ ri
->ri_font
->fontwidth
);
891 /* enable acceleration */
892 ri
->ri_ops
.copyrows
= ffb_ras_copyrows
;
893 ri
->ri_ops
.eraserows
= ffb_ras_eraserows
;
894 ri
->ri_ops
.erasecols
= ffb_ras_erasecols
;
895 ri
->ri_ops
.cursor
= ffb_cursor
;
896 ri
->ri_ops
.allocattr
= ffb_allocattr
;
897 if (sc
->putchar
== NULL
)
898 sc
->putchar
= ri
->ri_ops
.putchar
;
899 ri
->ri_ops
.putchar
= ffb_putchar
;