4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
26 #include <sys/promif.h>
27 #include <sys/promimpl.h>
30 * Returns 0 on error. Otherwise returns a handle.
37 #ifdef PROM_32BIT_ADDRS
41 if ((uintptr_t)path
> (uint32_t)-1) {
43 len
= prom_strlen(opath
) + 1; /* include terminating NUL */
44 path
= promplat_alloc(len
);
47 (void) prom_strcpy(path
, opath
);
53 ci
[0] = p1275_ptr2cell("open"); /* Service name */
54 ci
[1] = (cell_t
)1; /* #argument cells */
55 ci
[2] = (cell_t
)1; /* #result cells */
56 ci
[3] = p1275_ptr2cell(path
); /* Arg1: Pathname */
57 ci
[4] = (cell_t
)0; /* Res1: Prime result */
59 (void) p1275_cif_handler(&ci
);
64 #ifdef PROM_32BIT_ADDRS
66 promplat_free(path
, len
);
69 return (p1275_cell2int(ci
[4])); /* Res1: ihandle */
74 prom_seek(int fd
, unsigned long long offset
)
78 ci
[0] = p1275_ptr2cell("seek"); /* Service name */
79 ci
[1] = (cell_t
)3; /* #argument cells */
80 ci
[2] = (cell_t
)1; /* #result cells */
81 ci
[3] = p1275_uint2cell((uint_t
)fd
); /* Arg1: ihandle */
82 ci
[4] = p1275_ull2cell_high(offset
); /* Arg2: pos.hi */
83 ci
[5] = p1275_ull2cell_low(offset
); /* Arg3: pos.lo */
84 ci
[6] = (cell_t
)-1; /* Res1: Prime result */
87 (void) p1275_cif_handler(&ci
);
90 return (p1275_cell2int(ci
[6])); /* Res1: actual */
95 prom_read(ihandle_t fd
, caddr_t buf
, size_t len
, uint_t startblk
, char devtype
)
99 #ifdef PROM_32BIT_ADDRS
102 if ((uintptr_t)buf
> (uint32_t)-1) {
104 buf
= promplat_alloc(len
);
110 ow
= promif_preout();
113 ci
[0] = p1275_ptr2cell("read"); /* Service name */
114 ci
[1] = (cell_t
)3; /* #argument cells */
115 ci
[2] = (cell_t
)1; /* #result cells */
116 ci
[3] = p1275_size2cell((uint_t
)fd
); /* Arg1: ihandle */
117 ci
[4] = p1275_ptr2cell(buf
); /* Arg2: buffer address */
118 ci
[5] = p1275_uint2cell(len
); /* Arg3: buffer length */
119 ci
[6] = (cell_t
)-1; /* Res1: Prime result */
121 (void) p1275_cif_handler(&ci
);
126 #ifdef PROM_32BIT_ADDRS
128 promplat_bcopy(buf
, obuf
, len
);
129 promplat_free(buf
, len
);
133 return (p1275_cell2size(ci
[6])); /* Res1: actual length */
137 * prom_write is the only prom_*() function we have to intercept
138 * because all the other prom_*() io interfaces eventually call
143 prom_write(ihandle_t fd
, caddr_t buf
, size_t len
, uint_t startblk
, char devtype
)
149 #ifdef PROM_32BIT_ADDRS
151 static char smallbuf
[256];
157 * If the callback address is set, attempt to redirect
158 * console output back into kernel terminal emulator.
160 if (promif_redirect
!= NULL
&& fd
== prom_stdout_ihandle()) {
161 ow
= promif_preout();
162 rlen
= promif_redirect(promif_redirect_arg
, (uchar_t
*)buf
,
168 #ifdef PROM_32BIT_ADDRS
169 if ((uintptr_t)buf
> (uint32_t)-1) {
171 * This is a hack for kernel message output.
172 * By avoiding calls to promplat_alloc (and
173 * using smallbuf instead) when memory is low
174 * we can print shortish kernel messages without
175 * deadlocking. smallbuf should be at least as
176 * large as the automatic buffer in
177 * prom_printf.c:_doprint()'s stack frame.
178 * promplat_alloc() can block on a mutex and so
179 * is called here before calling promif_preprom().
181 if (len
> sizeof (smallbuf
)) {
183 buf
= promplat_alloc(len
);
187 promplat_bcopy(obuf
, buf
, len
);
193 * Normally we'd call promif_preprom() just before
194 * calling into the prom (to enforce single-threaded
195 * access) but here we need to call it before accessing
196 * smallbuf, since smallbuf is statically allocated and
197 * hence can only be accessed by one thread at a time.
199 ow
= promif_preout();
202 #ifdef PROM_32BIT_ADDRS
203 if ((uintptr_t)buf
> (uint32_t)-1) {
205 * If buf is small enough, use smallbuf
206 * instead of promplat_alloc() (see above)
207 * smallbuf is static, so single thread
208 * access to it by using it only after
211 if (len
<= sizeof (smallbuf
)) {
212 promplat_bcopy(buf
, smallbuf
, len
);
218 ci
[0] = p1275_ptr2cell("write"); /* Service name */
219 ci
[1] = (cell_t
)3; /* #argument cells */
220 ci
[2] = (cell_t
)1; /* #result cells */
221 ci
[3] = p1275_uint2cell((uint_t
)fd
); /* Arg1: ihandle */
222 ci
[4] = p1275_ptr2cell(buf
); /* Arg2: buffer addr */
223 ci
[5] = p1275_size2cell(len
); /* Arg3: buffer len */
224 ci
[6] = (cell_t
)-1; /* Res1: Prime result */
226 (void) p1275_cif_handler(&ci
);
227 rlen
= p1275_cell2size(ci
[6]); /* Res1: actual len */
232 #ifdef PROM_32BIT_ADDRS
234 promplat_free(buf
, len
);
246 ci
[0] = p1275_ptr2cell("close"); /* Service name */
247 ci
[1] = (cell_t
)1; /* #argument cells */
248 ci
[2] = (cell_t
)0; /* #result cells */
249 ci
[3] = p1275_uint2cell((uint_t
)fd
); /* Arg1: ihandle */
251 ow
= promif_preout();
253 (void) p1275_cif_handler(&ci
);