Deleted Added
full compact
ofwfb.c (259016) ofwfb.c (262861)
1/*-
2 * Copyright (c) 2011 Nathan Whitehorn
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2011 Nathan Whitehorn
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: user/ed/newcons/sys/dev/vt/hw/ofwfb/ofwfb.c 219888 2011-03-22 21:31:31Z ed $");
28__FBSDID("$FreeBSD: stable/10/sys/dev/vt/hw/ofwfb/ofwfb.c 262861 2014-03-06 18:30:56Z jhb $");
29
30#include <sys/param.h>
31#include <sys/kernel.h>
32#include <sys/systm.h>
33
34#include <dev/vt/vt.h>
35#include <dev/vt/colors/vt_termcolors.h>
36
37#include <vm/vm.h>
38#include <vm/pmap.h>
39
40#include <machine/bus.h>
41#ifdef __sparc64__
42#include <machine/bus_private.h>
43#endif
44
45#include <dev/ofw/openfirm.h>
46#include <dev/ofw/ofw_bus.h>
47#include <dev/ofw/ofw_pci.h>
48
49struct ofwfb_softc {
50 phandle_t sc_node;
51
52 intptr_t sc_addr;
53 int sc_depth;
54 int sc_stride;
55
56 bus_space_tag_t sc_memt;
57
58 uint32_t sc_colormap[16];
59};
60
61static vd_init_t ofwfb_init;
62static vd_blank_t ofwfb_blank;
63static vd_bitbltchr_t ofwfb_bitbltchr;
64
65static const struct vt_driver vt_ofwfb_driver = {
66 .vd_init = ofwfb_init,
67 .vd_blank = ofwfb_blank,
68 .vd_bitbltchr = ofwfb_bitbltchr,
69 .vd_priority = VD_PRIORITY_GENERIC+1,
70};
71
72static struct ofwfb_softc ofwfb_conssoftc;
73VT_CONSDEV_DECLARE(vt_ofwfb_driver, PIXEL_WIDTH(1920), PIXEL_HEIGHT(1200),
74 &ofwfb_conssoftc);
75/* XXX: hardcoded max size */
76
77static void
78ofwfb_blank(struct vt_device *vd, term_color_t color)
79{
80 struct ofwfb_softc *sc = vd->vd_softc;
29
30#include <sys/param.h>
31#include <sys/kernel.h>
32#include <sys/systm.h>
33
34#include <dev/vt/vt.h>
35#include <dev/vt/colors/vt_termcolors.h>
36
37#include <vm/vm.h>
38#include <vm/pmap.h>
39
40#include <machine/bus.h>
41#ifdef __sparc64__
42#include <machine/bus_private.h>
43#endif
44
45#include <dev/ofw/openfirm.h>
46#include <dev/ofw/ofw_bus.h>
47#include <dev/ofw/ofw_pci.h>
48
49struct ofwfb_softc {
50 phandle_t sc_node;
51
52 intptr_t sc_addr;
53 int sc_depth;
54 int sc_stride;
55
56 bus_space_tag_t sc_memt;
57
58 uint32_t sc_colormap[16];
59};
60
61static vd_init_t ofwfb_init;
62static vd_blank_t ofwfb_blank;
63static vd_bitbltchr_t ofwfb_bitbltchr;
64
65static const struct vt_driver vt_ofwfb_driver = {
66 .vd_init = ofwfb_init,
67 .vd_blank = ofwfb_blank,
68 .vd_bitbltchr = ofwfb_bitbltchr,
69 .vd_priority = VD_PRIORITY_GENERIC+1,
70};
71
72static struct ofwfb_softc ofwfb_conssoftc;
73VT_CONSDEV_DECLARE(vt_ofwfb_driver, PIXEL_WIDTH(1920), PIXEL_HEIGHT(1200),
74 &ofwfb_conssoftc);
75/* XXX: hardcoded max size */
76
77static void
78ofwfb_blank(struct vt_device *vd, term_color_t color)
79{
80 struct ofwfb_softc *sc = vd->vd_softc;
81 u_int ofs;
81 u_int ofs, size;
82 uint32_t c;
83
82 uint32_t c;
83
84 size = sc->sc_stride * vd->vd_height;
84 switch (sc->sc_depth) {
85 case 8:
85 switch (sc->sc_depth) {
86 case 8:
86 for (ofs = 0; ofs < sc->sc_stride*vd->vd_height; ofs++)
87 *(uint8_t *)(sc->sc_addr + ofs) = color;
87 c = (color << 24) | (color << 16) | (color << 8) | color;
88 for (ofs = 0; ofs < size/4; ofs++)
89 *(uint32_t *)(sc->sc_addr + 4*ofs) = c;
88 break;
89 case 32:
90 c = sc->sc_colormap[color];
90 break;
91 case 32:
92 c = sc->sc_colormap[color];
91 for (ofs = 0; ofs < sc->sc_stride*vd->vd_height; ofs++)
93 for (ofs = 0; ofs < size; ofs++)
92 *(uint32_t *)(sc->sc_addr + 4*ofs) = c;
93 break;
94 default:
95 /* panic? */
96 break;
97 }
98}
99
100static void
101ofwfb_bitbltchr(struct vt_device *vd, const uint8_t *src, const uint8_t *mask,
102 int bpl, vt_axis_t top, vt_axis_t left, unsigned int width,
103 unsigned int height, term_color_t fg, term_color_t bg)
104{
105 struct ofwfb_softc *sc = vd->vd_softc;
106 u_long line;
107 uint32_t fgc, bgc;
108 int c;
109 uint8_t b, m;
110
111 fgc = sc->sc_colormap[fg];
112 bgc = sc->sc_colormap[bg];
113 b = m = 0;
114
115 /* Don't try to put off screen pixels */
116 if (((left + width) > vd->vd_width) || ((top + height) >
117 vd->vd_height))
118 return;
119
120 line = (sc->sc_stride * top) + left * sc->sc_depth/8;
121 for (; height > 0; height--) {
122 for (c = 0; c < width; c++) {
123 if (c % 8 == 0)
124 b = *src++;
125 else
126 b <<= 1;
127 if (mask != NULL) {
128 if (c % 8 == 0)
129 m = *mask++;
130 else
131 m <<= 1;
132 /* Skip pixel write, if mask has no bit set. */
133 if ((m & 0x80) == 0)
134 continue;
135 }
136 switch(sc->sc_depth) {
137 case 8:
138 *(uint8_t *)(sc->sc_addr + line + c) =
139 b & 0x80 ? fg : bg;
140 break;
141 case 32:
142 *(uint32_t *)(sc->sc_addr + line + 4*c) =
143 (b & 0x80) ? fgc : bgc;
144 break;
145 default:
146 /* panic? */
147 break;
148 }
149 }
150 line += sc->sc_stride;
151 }
152}
153
154static void
155ofwfb_initialize(struct vt_device *vd)
156{
157 struct ofwfb_softc *sc = vd->vd_softc;
158 char name[64];
159 ihandle_t ih;
160 int i;
161 cell_t retval;
162 uint32_t oldpix;
163
164 /* Open display device, thereby initializing it */
165 memset(name, 0, sizeof(name));
166 OF_package_to_path(sc->sc_node, name, sizeof(name));
167 ih = OF_open(name);
168
169 /*
170 * Set up the color map
171 */
172
173 switch (sc->sc_depth) {
174 case 8:
175 vt_generate_vga_palette(sc->sc_colormap, COLOR_FORMAT_RGB, 255,
176 0, 255, 8, 255, 16);
177
178 for (i = 0; i < 16; i++) {
179 OF_call_method("color!", ih, 4, 1,
180 (cell_t)((sc->sc_colormap[i] >> 16) & 0xff),
181 (cell_t)((sc->sc_colormap[i] >> 8) & 0xff),
182 (cell_t)((sc->sc_colormap[i] >> 0) & 0xff),
183 (cell_t)i, &retval);
184 }
185 break;
186
187 case 32:
188 /*
189 * We bypass the usual bus_space_() accessors here, mostly
190 * for performance reasons. In particular, we don't want
191 * any barrier operations that may be performed and handle
192 * endianness slightly different. Figure out the host-view
193 * endianness of the frame buffer.
194 */
195 oldpix = bus_space_read_4(sc->sc_memt, sc->sc_addr, 0);
196 bus_space_write_4(sc->sc_memt, sc->sc_addr, 0, 0xff000000);
197 if (*(uint8_t *)(sc->sc_addr) == 0xff)
198 vt_generate_vga_palette(sc->sc_colormap,
199 COLOR_FORMAT_RGB, 255, 16, 255, 8, 255, 0);
200 else
201 vt_generate_vga_palette(sc->sc_colormap,
202 COLOR_FORMAT_RGB, 255, 0, 255, 8, 255, 16);
203 bus_space_write_4(sc->sc_memt, sc->sc_addr, 0, oldpix);
204 break;
205
206 default:
207 panic("Unknown color space depth %d", sc->sc_depth);
208 break;
209 }
210
211 /* Clear the screen. */
212 ofwfb_blank(vd, TC_BLACK);
213}
214
215static int
216ofwfb_init(struct vt_device *vd)
217{
218 struct ofwfb_softc *sc = vd->vd_softc;
219 char type[64];
220 phandle_t chosen;
221 ihandle_t stdout;
222 phandle_t node;
223 uint32_t depth, height, width;
224 struct ofw_pci_register pciaddrs[8];
225 int n_pciaddrs;
226 uint32_t fb_phys;
227 int i, len;
228#ifdef __sparc64__
229 static struct bus_space_tag ofwfb_memt[1];
230 bus_addr_t phys;
231 int space;
232#endif
233
234 chosen = OF_finddevice("/chosen");
235 OF_getprop(chosen, "stdout", &stdout, sizeof(stdout));
236 node = OF_instance_to_package(stdout);
237 if (node == -1) {
238 /*
239 * The "/chosen/stdout" does not exist try
240 * using "screen" directly.
241 */
242 node = OF_finddevice("screen");
243 }
244 OF_getprop(node, "device_type", type, sizeof(type));
245 if (strcmp(type, "display") != 0)
246 return (CN_DEAD);
247
248 /* Keep track of the OF node */
249 sc->sc_node = node;
250
251 /* Make sure we have needed properties */
252 if (OF_getproplen(node, "height") != sizeof(height) ||
253 OF_getproplen(node, "width") != sizeof(width) ||
254 OF_getproplen(node, "depth") != sizeof(depth) ||
255 OF_getproplen(node, "linebytes") != sizeof(sc->sc_stride))
256 return (CN_DEAD);
257
258 /* Only support 8 and 32-bit framebuffers */
259 OF_getprop(node, "depth", &depth, sizeof(depth));
260 if (depth != 8 && depth != 32)
261 return (CN_DEAD);
262 sc->sc_depth = depth;
263
264 OF_getprop(node, "height", &height, sizeof(height));
265 OF_getprop(node, "width", &width, sizeof(width));
266 OF_getprop(node, "linebytes", &sc->sc_stride, sizeof(sc->sc_stride));
267
268 vd->vd_height = height;
269 vd->vd_width = width;
270
271 /*
272 * Get the PCI addresses of the adapter, if present. The node may be the
273 * child of the PCI device: in that case, try the parent for
274 * the assigned-addresses property.
275 */
276 len = OF_getprop(node, "assigned-addresses", pciaddrs,
277 sizeof(pciaddrs));
278 if (len == -1) {
279 len = OF_getprop(OF_parent(node), "assigned-addresses",
280 pciaddrs, sizeof(pciaddrs));
281 }
282 if (len == -1)
283 len = 0;
284 n_pciaddrs = len / sizeof(struct ofw_pci_register);
285
286 /*
287 * Grab the physical address of the framebuffer, and then map it
288 * into our memory space. If the MMU is not yet up, it will be
289 * remapped for us when relocation turns on.
290 */
291 if (OF_getproplen(node, "address") == sizeof(fb_phys)) {
292 /* XXX We assume #address-cells is 1 at this point. */
293 OF_getprop(node, "address", &fb_phys, sizeof(fb_phys));
294
295 #if defined(__powerpc__)
296 sc->sc_memt = &bs_be_tag;
297 bus_space_map(sc->sc_memt, fb_phys, height * sc->sc_stride,
298 BUS_SPACE_MAP_PREFETCHABLE, &sc->sc_addr);
299 #elif defined(__sparc64__)
300 OF_decode_addr(node, 0, &space, &phys);
301 sc->sc_memt = &ofwfb_memt[0];
302 sc->sc_addr = sparc64_fake_bustag(space, fb_phys, sc->sc_memt);
303 #else
304 #error Unsupported platform!
305 #endif
306 } else {
307 /*
308 * Some IBM systems don't have an address property. Try to
309 * guess the framebuffer region from the assigned addresses.
310 * This is ugly, but there doesn't seem to be an alternative.
311 * Linux does the same thing.
312 */
313
314 fb_phys = n_pciaddrs;
315 for (i = 0; i < n_pciaddrs; i++) {
316 /* If it is too small, not the framebuffer */
317 if (pciaddrs[i].size_lo < sc->sc_stride*height)
318 continue;
319 /* If it is not memory, it isn't either */
320 if (!(pciaddrs[i].phys_hi &
321 OFW_PCI_PHYS_HI_SPACE_MEM32))
322 continue;
323
324 /* This could be the framebuffer */
325 fb_phys = i;
326
327 /* If it is prefetchable, it certainly is */
328 if (pciaddrs[i].phys_hi & OFW_PCI_PHYS_HI_PREFETCHABLE)
329 break;
330 }
331
332 if (fb_phys == n_pciaddrs) /* No candidates found */
333 return (CN_DEAD);
334
335 #if defined(__powerpc__)
336 OF_decode_addr(node, fb_phys, &sc->sc_memt, &sc->sc_addr);
337 #elif defined(__sparc64__)
338 OF_decode_addr(node, fb_phys, &space, &phys);
339 sc->sc_memt = &ofwfb_memt[0];
340 sc->sc_addr = sparc64_fake_bustag(space, phys, sc->sc_memt);
341 #endif
342 }
343
344 ofwfb_initialize(vd);
345
346 return (CN_INTERNAL);
347}
348
94 *(uint32_t *)(sc->sc_addr + 4*ofs) = c;
95 break;
96 default:
97 /* panic? */
98 break;
99 }
100}
101
102static void
103ofwfb_bitbltchr(struct vt_device *vd, const uint8_t *src, const uint8_t *mask,
104 int bpl, vt_axis_t top, vt_axis_t left, unsigned int width,
105 unsigned int height, term_color_t fg, term_color_t bg)
106{
107 struct ofwfb_softc *sc = vd->vd_softc;
108 u_long line;
109 uint32_t fgc, bgc;
110 int c;
111 uint8_t b, m;
112
113 fgc = sc->sc_colormap[fg];
114 bgc = sc->sc_colormap[bg];
115 b = m = 0;
116
117 /* Don't try to put off screen pixels */
118 if (((left + width) > vd->vd_width) || ((top + height) >
119 vd->vd_height))
120 return;
121
122 line = (sc->sc_stride * top) + left * sc->sc_depth/8;
123 for (; height > 0; height--) {
124 for (c = 0; c < width; c++) {
125 if (c % 8 == 0)
126 b = *src++;
127 else
128 b <<= 1;
129 if (mask != NULL) {
130 if (c % 8 == 0)
131 m = *mask++;
132 else
133 m <<= 1;
134 /* Skip pixel write, if mask has no bit set. */
135 if ((m & 0x80) == 0)
136 continue;
137 }
138 switch(sc->sc_depth) {
139 case 8:
140 *(uint8_t *)(sc->sc_addr + line + c) =
141 b & 0x80 ? fg : bg;
142 break;
143 case 32:
144 *(uint32_t *)(sc->sc_addr + line + 4*c) =
145 (b & 0x80) ? fgc : bgc;
146 break;
147 default:
148 /* panic? */
149 break;
150 }
151 }
152 line += sc->sc_stride;
153 }
154}
155
156static void
157ofwfb_initialize(struct vt_device *vd)
158{
159 struct ofwfb_softc *sc = vd->vd_softc;
160 char name[64];
161 ihandle_t ih;
162 int i;
163 cell_t retval;
164 uint32_t oldpix;
165
166 /* Open display device, thereby initializing it */
167 memset(name, 0, sizeof(name));
168 OF_package_to_path(sc->sc_node, name, sizeof(name));
169 ih = OF_open(name);
170
171 /*
172 * Set up the color map
173 */
174
175 switch (sc->sc_depth) {
176 case 8:
177 vt_generate_vga_palette(sc->sc_colormap, COLOR_FORMAT_RGB, 255,
178 0, 255, 8, 255, 16);
179
180 for (i = 0; i < 16; i++) {
181 OF_call_method("color!", ih, 4, 1,
182 (cell_t)((sc->sc_colormap[i] >> 16) & 0xff),
183 (cell_t)((sc->sc_colormap[i] >> 8) & 0xff),
184 (cell_t)((sc->sc_colormap[i] >> 0) & 0xff),
185 (cell_t)i, &retval);
186 }
187 break;
188
189 case 32:
190 /*
191 * We bypass the usual bus_space_() accessors here, mostly
192 * for performance reasons. In particular, we don't want
193 * any barrier operations that may be performed and handle
194 * endianness slightly different. Figure out the host-view
195 * endianness of the frame buffer.
196 */
197 oldpix = bus_space_read_4(sc->sc_memt, sc->sc_addr, 0);
198 bus_space_write_4(sc->sc_memt, sc->sc_addr, 0, 0xff000000);
199 if (*(uint8_t *)(sc->sc_addr) == 0xff)
200 vt_generate_vga_palette(sc->sc_colormap,
201 COLOR_FORMAT_RGB, 255, 16, 255, 8, 255, 0);
202 else
203 vt_generate_vga_palette(sc->sc_colormap,
204 COLOR_FORMAT_RGB, 255, 0, 255, 8, 255, 16);
205 bus_space_write_4(sc->sc_memt, sc->sc_addr, 0, oldpix);
206 break;
207
208 default:
209 panic("Unknown color space depth %d", sc->sc_depth);
210 break;
211 }
212
213 /* Clear the screen. */
214 ofwfb_blank(vd, TC_BLACK);
215}
216
217static int
218ofwfb_init(struct vt_device *vd)
219{
220 struct ofwfb_softc *sc = vd->vd_softc;
221 char type[64];
222 phandle_t chosen;
223 ihandle_t stdout;
224 phandle_t node;
225 uint32_t depth, height, width;
226 struct ofw_pci_register pciaddrs[8];
227 int n_pciaddrs;
228 uint32_t fb_phys;
229 int i, len;
230#ifdef __sparc64__
231 static struct bus_space_tag ofwfb_memt[1];
232 bus_addr_t phys;
233 int space;
234#endif
235
236 chosen = OF_finddevice("/chosen");
237 OF_getprop(chosen, "stdout", &stdout, sizeof(stdout));
238 node = OF_instance_to_package(stdout);
239 if (node == -1) {
240 /*
241 * The "/chosen/stdout" does not exist try
242 * using "screen" directly.
243 */
244 node = OF_finddevice("screen");
245 }
246 OF_getprop(node, "device_type", type, sizeof(type));
247 if (strcmp(type, "display") != 0)
248 return (CN_DEAD);
249
250 /* Keep track of the OF node */
251 sc->sc_node = node;
252
253 /* Make sure we have needed properties */
254 if (OF_getproplen(node, "height") != sizeof(height) ||
255 OF_getproplen(node, "width") != sizeof(width) ||
256 OF_getproplen(node, "depth") != sizeof(depth) ||
257 OF_getproplen(node, "linebytes") != sizeof(sc->sc_stride))
258 return (CN_DEAD);
259
260 /* Only support 8 and 32-bit framebuffers */
261 OF_getprop(node, "depth", &depth, sizeof(depth));
262 if (depth != 8 && depth != 32)
263 return (CN_DEAD);
264 sc->sc_depth = depth;
265
266 OF_getprop(node, "height", &height, sizeof(height));
267 OF_getprop(node, "width", &width, sizeof(width));
268 OF_getprop(node, "linebytes", &sc->sc_stride, sizeof(sc->sc_stride));
269
270 vd->vd_height = height;
271 vd->vd_width = width;
272
273 /*
274 * Get the PCI addresses of the adapter, if present. The node may be the
275 * child of the PCI device: in that case, try the parent for
276 * the assigned-addresses property.
277 */
278 len = OF_getprop(node, "assigned-addresses", pciaddrs,
279 sizeof(pciaddrs));
280 if (len == -1) {
281 len = OF_getprop(OF_parent(node), "assigned-addresses",
282 pciaddrs, sizeof(pciaddrs));
283 }
284 if (len == -1)
285 len = 0;
286 n_pciaddrs = len / sizeof(struct ofw_pci_register);
287
288 /*
289 * Grab the physical address of the framebuffer, and then map it
290 * into our memory space. If the MMU is not yet up, it will be
291 * remapped for us when relocation turns on.
292 */
293 if (OF_getproplen(node, "address") == sizeof(fb_phys)) {
294 /* XXX We assume #address-cells is 1 at this point. */
295 OF_getprop(node, "address", &fb_phys, sizeof(fb_phys));
296
297 #if defined(__powerpc__)
298 sc->sc_memt = &bs_be_tag;
299 bus_space_map(sc->sc_memt, fb_phys, height * sc->sc_stride,
300 BUS_SPACE_MAP_PREFETCHABLE, &sc->sc_addr);
301 #elif defined(__sparc64__)
302 OF_decode_addr(node, 0, &space, &phys);
303 sc->sc_memt = &ofwfb_memt[0];
304 sc->sc_addr = sparc64_fake_bustag(space, fb_phys, sc->sc_memt);
305 #else
306 #error Unsupported platform!
307 #endif
308 } else {
309 /*
310 * Some IBM systems don't have an address property. Try to
311 * guess the framebuffer region from the assigned addresses.
312 * This is ugly, but there doesn't seem to be an alternative.
313 * Linux does the same thing.
314 */
315
316 fb_phys = n_pciaddrs;
317 for (i = 0; i < n_pciaddrs; i++) {
318 /* If it is too small, not the framebuffer */
319 if (pciaddrs[i].size_lo < sc->sc_stride*height)
320 continue;
321 /* If it is not memory, it isn't either */
322 if (!(pciaddrs[i].phys_hi &
323 OFW_PCI_PHYS_HI_SPACE_MEM32))
324 continue;
325
326 /* This could be the framebuffer */
327 fb_phys = i;
328
329 /* If it is prefetchable, it certainly is */
330 if (pciaddrs[i].phys_hi & OFW_PCI_PHYS_HI_PREFETCHABLE)
331 break;
332 }
333
334 if (fb_phys == n_pciaddrs) /* No candidates found */
335 return (CN_DEAD);
336
337 #if defined(__powerpc__)
338 OF_decode_addr(node, fb_phys, &sc->sc_memt, &sc->sc_addr);
339 #elif defined(__sparc64__)
340 OF_decode_addr(node, fb_phys, &space, &phys);
341 sc->sc_memt = &ofwfb_memt[0];
342 sc->sc_addr = sparc64_fake_bustag(space, phys, sc->sc_memt);
343 #endif
344 }
345
346 ofwfb_initialize(vd);
347
348 return (CN_INTERNAL);
349}
350