1 /* $NetBSD: genfb_sbus.c,v 1.8 2009/09/17 16:28:12 tsutsui Exp $ */
4 * Copyright (c) 2007 Michael Lorenz
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
29 /* an SBus frontend for the generic fb console driver */
31 #include <sys/cdefs.h>
32 __KERNEL_RCSID(0, "$NetBSD: genfb_sbus.c,v 1.8 2009/09/17 16:28:12 tsutsui Exp $");
34 #include <sys/param.h>
35 #include <sys/systm.h>
37 #include <sys/device.h>
38 #include <sys/ioctl.h>
44 #include <machine/autoconf.h>
45 #include <machine/pmap.h>
47 #include <dev/sbus/sbusvar.h>
48 #include <dev/sun/fbio.h>
49 #include <dev/sun/fbvar.h>
51 #include <dev/wsfb/genfbvar.h>
53 struct genfb_sbus_softc
{
54 struct genfb_softc sc_gen
;
55 bus_space_tag_t sc_tag
;
59 static int genfb_match_sbus(device_t
, cfdata_t
, void *);
60 static void genfb_attach_sbus(device_t
, device_t
, void *);
61 static int genfb_ioctl_sbus(void *, void *, u_long
, void *, int,
63 static paddr_t
genfb_mmap_sbus(void *, void *, off_t
, int);
65 CFATTACH_DECL(genfb_sbus
, sizeof(struct genfb_sbus_softc
),
66 genfb_match_sbus
, genfb_attach_sbus
, NULL
, NULL
);
69 * Match a graphics device.
72 genfb_match_sbus(device_t parent
, cfdata_t cf
, void *aux
)
74 struct sbus_attach_args
*sa
= aux
;
76 /* if there's no address property we can't use the device */
77 if (prom_getpropint(sa
->sa_node
, "address", -1) == -1)
79 if (strcmp("display", prom_getpropstring(sa
->sa_node
, "device_type"))
87 * Attach a display. We need to notice if it is the console, too.
90 genfb_attach_sbus(device_t parent
, device_t self
, void *args
)
92 struct genfb_sbus_softc
*sc
= device_private(self
);
93 struct sbus_attach_args
*sa
= args
;
95 prop_dictionary_t dict
;
96 bus_space_handle_t bh
;
99 int node
= sa
->sa_node
;
103 /* Remember cookies for genfb_mmap_sbus() */
104 sc
->sc_tag
= sa
->sa_bustag
;
105 sc
->sc_paddr
= sbus_bus_addr(sa
->sa_bustag
, sa
->sa_slot
, sa
->sa_offset
);
107 /* read geometry information from the device tree */
108 sc
->sc_gen
.sc_width
= prom_getpropint(sa
->sa_node
, "width", 1152);
109 sc
->sc_gen
.sc_height
= prom_getpropint(sa
->sa_node
, "height", 900);
110 sc
->sc_gen
.sc_depth
= prom_getpropint(sa
->sa_node
, "depth", 8);
111 sc
->sc_gen
.sc_stride
= prom_getpropint(sa
->sa_node
, "linebytes",
112 (sc
->sc_gen
.sc_width
* sc
->sc_gen
.sc_depth
+ 7) >> 3 );
113 sc
->sc_gen
.sc_fbsize
= sc
->sc_gen
.sc_height
* sc
->sc_gen
.sc_stride
;
114 fbva
= (uint32_t)prom_getpropint(sa
->sa_node
, "address", 0);
116 panic("this fb has no address property\n");
117 aprint_normal_dev(self
, "%d x %d at %d bit\n",
118 sc
->sc_gen
.sc_width
, sc
->sc_gen
.sc_height
, sc
->sc_gen
.sc_depth
);
120 pmap_extract(pmap_kernel(), fbva
, &fbpa
);
121 sc
->sc_gen
.sc_fboffset
= (fbpa
& 0x01ffffff) -
122 (sc
->sc_paddr
& 0x01ffffff);
123 aprint_normal_dev(self
, "framebuffer at offset 0x%x\n",
124 (uint32_t)sc
->sc_gen
.sc_fboffset
);
127 if (sc
->sc_gen
.sc_depth
<= 8) {
128 /* setup some ANSIish colour map */
130 snprintf(boo
, 256, "\" pal!\" %x %x %x %x %x call",
131 sa
->sa_node
, 0, 0xa0, 0xa0, 0);
136 isconsole
= fb_is_console(node
);
137 dict
= device_properties(self
);
138 prop_dictionary_set_bool(dict
, "is_console", isconsole
);
140 if (sbus_bus_map(sa
->sa_bustag
,
142 sa
->sa_offset
+ sc
->sc_gen
.sc_fboffset
,
143 sc
->sc_gen
.sc_fbsize
,
144 BUS_SPACE_MAP_LINEAR
, &bh
) != 0) {
145 aprint_error_dev(self
, "cannot map framebuffer\n");
148 sc
->sc_gen
.sc_fbaddr
= (void *)bus_space_vaddr(sa
->sa_bustag
, bh
);
150 ops
.genfb_ioctl
= genfb_ioctl_sbus
;
151 ops
.genfb_mmap
= genfb_mmap_sbus
;
153 genfb_attach(&sc
->sc_gen
, &ops
);
157 genfb_ioctl_sbus(void *v
, void *vs
, u_long cmd
, void *data
, int flag
,
162 case WSDISPLAYIO_GTYPE
:
163 *(u_int
*)data
= WSDISPLAY_TYPE_GENFB
;
171 genfb_mmap_sbus(void *v
, void *vs
, off_t offset
, int prot
)
173 struct genfb_sbus_softc
*sc
= v
;
175 /* regular fb mapping at 0 */
176 if ((offset
>= 0) && (offset
< sc
->sc_gen
.sc_fbsize
)) {
178 return bus_space_mmap(sc
->sc_tag
, sc
->sc_paddr
,
179 sc
->sc_gen
.sc_fboffset
+ offset
, prot
,
180 BUS_SPACE_MAP_LINEAR
);