2 * Copyright (C) 2005 Martin Decky
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
46 ofw_chosen
= ofw_find_device("/chosen");
50 if (ofw_get_property(ofw_chosen
, "stdout", &ofw_stdout
, sizeof(ofw_stdout
)) <= 0)
53 ofw_root
= ofw_find_device("/");
55 puts("\r\nError: Unable to find / device, halted.\r\n");
59 if (ofw_get_property(ofw_chosen
, "mmu", &ofw_mmu
, sizeof(ofw_mmu
)) <= 0) {
60 puts("\r\nError: Unable to get mmu property, halted.\r\n");
64 ofw_memory
= ofw_find_device("/memory");
65 if (ofw_memory
== -1) {
66 puts("\r\nError: Unable to find /memory device, halted.\r\n");
70 ofw_aliases
= ofw_find_device("/aliases");
71 if (ofw_aliases
== -1) {
72 puts("\r\nError: Unable to find /aliases device, halted.\r\n");
77 /** Perform a call to OpenFirmware client interface.
79 * @param service String identifying the service requested.
80 * @param nargs Number of input arguments.
81 * @param nret Number of output arguments. This includes the return value.
82 * @param rets Buffer for output arguments or NULL. The buffer must accommodate nret - 1 items.
84 * @return Return value returned by the client interface.
86 unsigned long ofw_call(const char *service
, const int nargs
, const int nret
, ofw_arg_t
*rets
, ...)
92 args
.service
= (ofw_arg_t
) service
;
97 for (i
= 0; i
< nargs
; i
++)
98 args
.args
[i
] = va_arg(list
, ofw_arg_t
);
101 for (i
= 0; i
< nret
; i
++)
102 args
.args
[i
+ nargs
] = 0;
106 for (i
= 1; i
< nret
; i
++)
107 rets
[i
- 1] = args
.args
[i
+ nargs
];
109 return args
.args
[nargs
];
112 phandle
ofw_find_device(const char *name
)
114 return ofw_call("finddevice", 1, 1, NULL
, name
);
117 int ofw_get_property(const phandle device
, const char *name
, void *buf
, const int buflen
)
119 return ofw_call("getprop", 4, 1, NULL
, device
, name
, buf
, buflen
);
122 int ofw_get_proplen(const phandle device
, const char *name
)
124 return ofw_call("getproplen", 2, 1, NULL
, device
, name
);
127 int ofw_next_property(const phandle device
, char *previous
, char *buf
)
129 return ofw_call("nextprop", 3, 1, NULL
, device
, previous
, buf
);
132 int ofw_package_to_path(const phandle device
, char *buf
, const int buflen
)
134 return ofw_call("package-to-path", 3, 1, NULL
, device
, buf
, buflen
);
137 unsigned int ofw_get_address_cells(const phandle device
)
139 unsigned int ret
= 1;
141 if (ofw_get_property(device
, "#address-cells", &ret
, sizeof(ret
)) <= 0)
142 if (ofw_get_property(ofw_root
, "#address-cells", &ret
, sizeof(ret
)) <= 0)
143 ret
= OFW_ADDRESS_CELLS
;
149 unsigned int ofw_get_size_cells(const phandle device
)
153 if (ofw_get_property(device
, "#size-cells", &ret
, sizeof(ret
)) <= 0)
154 if (ofw_get_property(ofw_root
, "#size-cells", &ret
, sizeof(ret
)) <= 0)
155 ret
= OFW_SIZE_CELLS
;
160 phandle
ofw_get_child_node(const phandle node
)
162 return ofw_call("child", 1, 1, NULL
, node
);
165 phandle
ofw_get_peer_node(const phandle node
)
167 return ofw_call("peer", 1, 1, NULL
, node
);
170 static ihandle
ofw_open(const char *name
)
172 return ofw_call("open", 1, 1, NULL
, name
);
176 void ofw_write(const char *str
, const int len
)
181 ofw_call("write", 3, 1, NULL
, ofw_stdout
, str
, len
);
185 void *ofw_translate(const void *virt
)
190 if (ofw_call("call-method", 3, 5, result
, "translate", ofw_mmu
, virt
) != 0) {
191 puts("Error: MMU method translate() failed, halting.\n");
195 if (ofw_translate_failed(result
[0]))
198 if (sizeof(unative_t
) == 8)
203 return (void *) ((result
[2]<<shift
)|result
[3]);
206 void *ofw_claim(const void *virt
, const int len
)
211 if (ofw_call("call-method", 5, 2, &retaddr
, "claim", ofw_mmu
, 0, len
, virt
) != 0) {
212 puts("Error: MMU method claim() failed, halting.\n");
216 return (void *) retaddr
;
219 int ofw_map(const void *phys
, const void *virt
, const int size
, const int mode
)
221 uintptr_t phys_hi
, phys_lo
;
223 if (sizeof(unative_t
) == 8) {
225 phys_hi
= (uintptr_t) phys
>> shift
;
226 phys_lo
= (uintptr_t) phys
& 0xffffffff;
229 phys_lo
= (uintptr_t) phys
;
232 return ofw_call("call-method", 7, 1, NULL
, "map", ofw_mmu
, mode
, size
, virt
,
237 int ofw_memmap(memmap_t
*map
)
239 unsigned int ac
= ofw_get_address_cells(ofw_memory
);
240 unsigned int sc
= ofw_get_size_cells(ofw_memory
);
242 uint32_t buf
[((ac
+sc
)*MEMMAP_MAX_RECORDS
)];
243 int ret
= ofw_get_property(ofw_memory
, "reg", buf
, sizeof(buf
));
244 if (ret
<= 0) /* ret is the number of written bytes */
250 for (pos
= 0; (pos
< ret
/ sizeof(uint32_t)) && (map
->count
< MEMMAP_MAX_RECORDS
); pos
+= ac
+ sc
) {
251 void * start
= (void *) ((uintptr_t) buf
[pos
+ ac
- 1]);
252 unsigned int size
= buf
[pos
+ ac
+ sc
- 1];
255 map
->zones
[map
->count
].start
= start
;
256 map
->zones
[map
->count
].size
= size
;
266 int ofw_screen(screen_t
*screen
)
268 char device_name
[BUF_SIZE
];
271 if (ofw_get_property(ofw_aliases
, "screen", device_name
, sizeof(device_name
)) <= 0)
274 phandle device
= ofw_find_device(device_name
);
278 if (ofw_get_property(device
, "address", &virtaddr
, sizeof(virtaddr
)) <= 0)
281 screen
->addr
= (void *) ((uintptr_t) virtaddr
);
283 if (ofw_get_property(device
, "width", &screen
->width
, sizeof(screen
->width
)) <= 0)
286 if (ofw_get_property(device
, "height", &screen
->height
, sizeof(screen
->height
)) <= 0)
289 if (ofw_get_property(device
, "depth", &screen
->bpp
, sizeof(screen
->bpp
)) <= 0)
292 if (ofw_get_property(device
, "linebytes", &screen
->scanline
, sizeof(screen
->scanline
)) <= 0)
299 void ofw_quiesce(void)
301 ofw_call("quiesce", 0, 0, NULL
);