genfb_sbus.c revision 1.1 1 /* $NetBSD: genfb_sbus.c,v 1.1 2007/04/11 04:45:45 macallan Exp $ */
2
3 /*-
4 * Copyright (c) 2007 Michael Lorenz
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
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.
15 * 3. Neither the name of The NetBSD Foundation nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
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 /* an SBus frontend for the generic fb console driver */
33
34 #include <sys/cdefs.h>
35 __KERNEL_RCSID(0, "$NetBSD: genfb_sbus.c,v 1.1 2007/04/11 04:45:45 macallan Exp $");
36
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/buf.h>
40 #include <sys/device.h>
41 #include <sys/ioctl.h>
42 #include <sys/conf.h>
43
44 #include <uvm/uvm.h>
45
46 #include <machine/bus.h>
47 #include <machine/autoconf.h>
48 #include <machine/pmap.h>
49
50 #include <dev/sbus/sbusvar.h>
51 #include <dev/sun/fbio.h>
52 #include <dev/sun/fbvar.h>
53
54 #include <dev/wsfb/genfbvar.h>
55
56 struct genfb_sbus_softc {
57 struct genfb_softc sc_gen;
58 struct sbusdev sc_sd;
59 bus_space_tag_t sc_tag;
60 paddr_t sc_paddr;
61 };
62
63 static int genfb_match_sbus(struct device *, struct cfdata *, void *);
64 static void genfb_attach_sbus(struct device *, struct device *, void *);
65 static int genfb_ioctl_sbus(void *, void *, u_long, void *, int,
66 struct lwp*);
67 static paddr_t genfb_mmap_sbus(void *, void *, off_t, int);
68
69 CFATTACH_DECL(genfb_sbus, sizeof(struct genfb_sbus_softc),
70 genfb_match_sbus, genfb_attach_sbus, NULL, NULL);
71
72 /*
73 * Match a graphics device.
74 */
75 static int
76 genfb_match_sbus(struct device *parent, struct cfdata *cf, void *aux)
77 {
78 struct sbus_attach_args *sa = aux;
79
80 /* if there's no address property we can't use the device */
81 if (prom_getpropint(sa->sa_node, "address", -1) == -1)
82 return 0;
83 if (strcmp("display", prom_getpropstring(sa->sa_node, "device_type"))
84 == 0)
85 return 1;
86
87 return 0;
88 }
89
90 /*
91 * Attach a display. We need to notice if it is the console, too.
92 */
93 static void
94 genfb_attach_sbus(struct device *parent, struct device *self, void *args)
95 {
96 struct genfb_sbus_softc *sc = (struct genfb_sbus_softc *)self;
97 struct sbusdev *sd = &sc->sc_sd;
98 struct sbus_attach_args *sa = args;
99 struct genfb_ops ops;
100 prop_dictionary_t dict;
101 bus_space_handle_t bh;
102 paddr_t fbpa;
103 vaddr_t fbva;
104 int node = sa->sa_node;
105 int isconsole;
106
107 aprint_normal("\n");
108 /* Remember cookies for genfb_mmap_sbus() */
109 sc->sc_tag = sa->sa_bustag;
110 sc->sc_paddr = sbus_bus_addr(sa->sa_bustag, sa->sa_slot, sa->sa_offset);
111
112 /* read geometry information from the device tree */
113 sc->sc_gen.sc_width = prom_getpropint(sa->sa_node, "width", 1152);
114 sc->sc_gen.sc_height = prom_getpropint(sa->sa_node, "height", 900);
115 sc->sc_gen.sc_depth = prom_getpropint(sa->sa_node, "depth", 8);
116 sc->sc_gen.sc_stride = prom_getpropint(sa->sa_node, "linebytes",
117 (sc->sc_gen.sc_width * sc->sc_gen.sc_depth + 7) >> 3 );
118 sc->sc_gen.sc_fbsize = sc->sc_gen.sc_width * sc->sc_gen.sc_stride;
119 fbva = (uint32_t)prom_getpropint(sa->sa_node, "address", 0);
120 if (fbva == 0)
121 panic("this fb has no address property\n");
122 aprint_normal("%s: %d x %d at %d bit\n", self->dv_xname,
123 sc->sc_gen.sc_width, sc->sc_gen.sc_height, sc->sc_gen.sc_depth);
124
125 pmap_extract(pmap_kernel(), fbva, &fbpa);
126 sc->sc_gen.sc_fboffset = (fbpa & 0x01ffffff) -
127 (sc->sc_paddr & 0x01ffffff);
128 aprint_normal("%s: framebuffer at offset 0x%x\n", self->dv_xname,
129 (uint32_t)sc->sc_gen.sc_fboffset);
130
131 #if notyet
132 if (sc->sc_gen.sc_depth <= 8) {
133 /* setup some ANSIish colour map */
134 char boo[256];
135 snprintf(boo, 256, "\" pal!\" %x %x %x %x %x call",
136 sa->sa_node, 0, 0xa0, 0xa0, 0);
137 prom_interpret(boo);
138 }
139 #endif
140
141 isconsole = fb_is_console(node);
142 dict = device_properties(self);
143 prop_dictionary_set_bool(dict, "is_console", isconsole);
144
145 if (sbus_bus_map(sa->sa_bustag,
146 sa->sa_slot,
147 sa->sa_offset + sc->sc_gen.sc_fboffset,
148 sc->sc_gen.sc_fbsize,
149 BUS_SPACE_MAP_LINEAR, &bh) != 0) {
150 printf("%s: cannot map framebuffer\n", self->dv_xname);
151 return;
152 }
153 sc->sc_gen.sc_fbaddr = (void *)bus_space_vaddr(sa->sa_bustag, bh);
154
155 sbus_establish(sd, self);
156 ops.genfb_ioctl = genfb_ioctl_sbus;
157 ops.genfb_mmap = genfb_mmap_sbus;
158
159 genfb_attach(&sc->sc_gen, &ops);
160 }
161
162 static int
163 genfb_ioctl_sbus(void *v, void *vs, u_long cmd, void *data, int flag,
164 struct lwp *l)
165 {
166
167 switch (cmd) {
168 case WSDISPLAYIO_GTYPE:
169 *(u_int *)data = WSDISPLAY_TYPE_GENFB;
170 return 0;
171 }
172
173 return EPASSTHROUGH;
174 }
175
176 static paddr_t
177 genfb_mmap_sbus(void *v, void *vs, off_t offset, int prot)
178 {
179 struct genfb_sbus_softc *sc = v;
180
181 /* regular fb mapping at 0 */
182 if ((offset >= 0) && (offset < sc->sc_gen.sc_fbsize)) {
183
184 return bus_space_mmap(sc->sc_tag, sc->sc_paddr,
185 sc->sc_gen.sc_fboffset + offset, prot,
186 BUS_SPACE_MAP_LINEAR);
187 }
188
189 return -1;
190 }
191