1 /*
2 * CDDL HEADER START
3 *
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.
7 *
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.
12 *
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]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #pragma ident "%Z%%M% %I% %E% SMI"
28
29 #include <sys/promif_impl.h>
30 #include <sys/systm.h>
31 #include <sys/hypervisor_api.h>
32 #include <sys/consdev.h>
33 #ifndef _KMDB
34 #include <sys/kmem.h>
35 #endif
36
37 /*
38 * Definitions for using Polled I/O.
39 *
40 * The usage of Polled I/O is different when we are in kmdb. In that case,
41 * we can not directly invoke the polled I/O functions and we have to use
42 * the kmdb DPI interface. Also we don't need to enter/exit the polled I/O
43 * mode because this is already managed by kmdb when entering/exiting the
44 * debugger.
45 *
46 * When we are not in kmdb then we can directly call the polled I/O functions
47 * but we have to enter the polled I/O mode first. After using polled I/O
48 * functions we have to exit the polled I/O mode. Note that entering/exiting
49 * the polled I/O mode is time consuming so this should be avoided when
50 * possible.
51 */
52 #ifdef _KMDB
53 extern struct cons_polledio *kmdb_kdi_get_polled_io(void);
54 extern uintptr_t kmdb_dpi_call(uintptr_t, uint_t, const uintptr_t *);
55
56 #define PROMIF_PIO (kmdb_kdi_get_polled_io())
57
58 #define PROMIF_PIO_CALL1(fn, arg) \
59 (kmdb_dpi_call((uintptr_t)fn, 1, (uintptr_t *)&arg))
60
61 #define PROMIF_PIO_CALL2(fn, arg1, arg2) \
62 { \
63 uintptr_t args[2]; \
64 args[0] = (uintptr_t)arg1; \
65 args[1] = (uintptr_t)arg2; \
66 (void) (kmdb_dpi_call((uintptr_t)fn, 2, (uintptr_t *)args)); \
67 }
68
69 #define PROMIF_PIO_ENTER(pio)
70 #define PROMIF_PIO_EXIT(pio)
71
72 #else /* _KMDB */
73
74 #define PROMIF_PIO (cons_polledio)
75 #define PROMIF_PIO_CALL1(fn, arg) (fn(arg))
76 #define PROMIF_PIO_CALL2(fn, arg1, arg2) (fn(arg1, arg2))
77
78 #define PROMIF_PIO_ENTER(pio) \
79 if (pio->cons_polledio_enter != NULL) { \
80 pio->cons_polledio_enter(pio->cons_polledio_argument); \
81 }
82
83 #define PROMIF_PIO_EXIT(pio) \
84 if (pio->cons_polledio_exit != NULL) { \
85 pio->cons_polledio_exit(pio->cons_polledio_argument); \
86 }
87
88 #endif /* _KMDB */
89
90 #define PROM_REG_TO_UNIT_ADDR(r) ((r) & ~(0xful << 28))
91
92 static pnode_t instance_to_package(ihandle_t ih);
93
94 /* cached copies of IO params */
95 static phandle_t pstdin;
96 static phandle_t pstdout;
97
98 static ihandle_t istdin;
99 static ihandle_t istdout;
100
101 static struct cons_polledio *promif_polledio = NULL;
102
103 int
promif_instance_to_package(void * p)104 promif_instance_to_package(void *p)
105 {
106 cell_t *ci = (cell_t *)p;
107 ihandle_t ih;
108 phandle_t ph;
109
110 ih = p1275_cell2ihandle(ci[3]);
111
112 ph = instance_to_package(ih);
113
114 ci[4] = p1275_phandle2cell(ph);
115
116 return (0);
117 }
118
119 /* This function is not used but it is convenient for debugging I/O problems */
120 static void
121 /* LINTED */
promif_hv_print(char * str)122 promif_hv_print(char *str)
123 {
124 size_t i, len = strlen(str);
125
126 for (i = 0; i < len; i++) {
127 while (hv_cnputchar((uint8_t)str[i]) == H_EWOULDBLOCK)
128 /* try forever */;
129 }
130 }
131
132 static void
promif_pio_enter(void)133 promif_pio_enter(void)
134 {
135 ASSERT(promif_polledio == NULL);
136
137 promif_polledio = PROMIF_PIO;
138 ASSERT(promif_polledio != NULL);
139
140 PROMIF_PIO_ENTER(promif_polledio);
141 }
142
143 static void
promif_pio_exit(void)144 promif_pio_exit(void)
145 {
146 ASSERT(promif_polledio != NULL);
147
148 PROMIF_PIO_EXIT(promif_polledio);
149 promif_polledio = NULL;
150 }
151
152 static int
promif_do_read(char * buf,size_t len,boolean_t wait)153 promif_do_read(char *buf, size_t len, boolean_t wait)
154 {
155 int rlen;
156 int (*getchar)(cons_polledio_arg_t);
157 boolean_t (*ischar)(cons_polledio_arg_t);
158 cons_polledio_arg_t arg;
159
160 promif_pio_enter();
161
162 if ((ischar = promif_polledio->cons_polledio_ischar) == NULL)
163 return (0);
164 if ((getchar = promif_polledio->cons_polledio_getchar) == NULL)
165 return (0);
166
167 arg = promif_polledio->cons_polledio_argument;
168
169 for (rlen = 0; rlen < len; ) {
170 if (PROMIF_PIO_CALL1(ischar, arg)) {
171 buf[rlen] = PROMIF_PIO_CALL1(getchar, arg);
172 rlen++;
173 continue;
174 }
175
176 if (!wait)
177 break;
178 }
179
180 promif_pio_exit();
181
182 return (rlen);
183 }
184
185 static int
promif_do_write(char * buf,size_t len)186 promif_do_write(char *buf, size_t len)
187 {
188 int rlen;
189 void (*putchar)(cons_polledio_arg_t, uchar_t);
190 cons_polledio_arg_t arg;
191
192 promif_pio_enter();
193
194 if ((putchar = promif_polledio->cons_polledio_putchar) == NULL)
195 return (0);
196
197 arg = promif_polledio->cons_polledio_argument;
198
199 for (rlen = 0; rlen < len; rlen++)
200 PROMIF_PIO_CALL2(putchar, arg, buf[rlen]);
201
202 promif_pio_exit();
203
204 return (rlen);
205 }
206
207 char
promif_getchar(void)208 promif_getchar(void)
209 {
210 char c;
211
212 (void) promif_do_read(&c, 1, B_TRUE);
213 return (c);
214 }
215
216 int
promif_write(void * p)217 promif_write(void *p)
218 {
219 cell_t *ci = (cell_t *)p;
220 uint_t fd;
221 char *buf;
222 size_t len;
223 size_t rlen;
224
225 ASSERT(ci[1] == 3);
226
227 fd = p1275_cell2uint(ci[3]);
228 buf = p1275_cell2ptr(ci[4]);
229 len = p1275_cell2size(ci[5]);
230
231 /* only support stdout (console) */
232 ASSERT(fd == istdout);
233
234 rlen = promif_do_write(buf, len);
235
236 /* return the length written */
237 ci[6] = p1275_size2cell(rlen);
238
239 return (0);
240 }
241
242 int
promif_read(void * p)243 promif_read(void *p)
244 {
245 cell_t *ci = (cell_t *)p;
246 uint_t fd;
247 char *buf;
248 size_t len;
249 size_t rlen;
250
251 ASSERT(ci[1] == 3);
252
253 /* unpack arguments */
254 fd = p1275_cell2uint(ci[3]);
255 buf = p1275_cell2ptr(ci[4]);
256 len = p1275_cell2size(ci[5]);
257
258 /* only support stdin (console) */
259 ASSERT(fd == istdin);
260
261 rlen = promif_do_read(buf, len, B_FALSE);
262
263 /* return the length read */
264 ci[6] = p1275_size2cell(rlen);
265
266 return (0);
267 }
268
269 static pnode_t
instance_to_package(ihandle_t ih)270 instance_to_package(ihandle_t ih)
271 {
272 /* only support stdin and stdout */
273 ASSERT((ih == istdin) || (ih == istdout));
274
275 if (ih == istdin)
276 return (pstdin);
277
278 if (ih == istdout)
279 return (pstdout);
280
281 return (OBP_BADNODE);
282 }
283
284 #ifdef _KMDB
285
286 void
promif_io_init(ihandle_t in,ihandle_t out,phandle_t pin,phandle_t pout)287 promif_io_init(ihandle_t in, ihandle_t out, phandle_t pin, phandle_t pout)
288 {
289 istdin = in;
290 istdout = out;
291 pstdin = pin;
292 pstdout = pout;
293 }
294
295 #else
296
297 void
promif_io_init(void)298 promif_io_init(void)
299 {
300 /*
301 * Cache the mapping between the stdin and stdout
302 * ihandles and their respective phandles.
303 */
304 pstdin = prom_stdin_node();
305 pstdout = prom_stdout_node();
306
307 istdin = prom_stdin_ihandle();
308 istdout = prom_stdout_ihandle();
309 }
310
311 int
promif_instance_to_path(void * p)312 promif_instance_to_path(void *p)
313 {
314 cell_t *ci = (cell_t *)p;
315 pnode_t node;
316 ihandle_t ih;
317 char *buf;
318 int rlen;
319 char *regval;
320 uint_t *csaddr;
321 char name[OBP_MAXPROPNAME];
322 char scratch[OBP_MAXPATHLEN];
323 int rvlen;
324
325 ih = p1275_cell2ihandle(ci[3]);
326 buf = p1275_cell2ptr(ci[4]);
327
328 ci[6] = p1275_uint2cell(0);
329
330 node = instance_to_package(ih);
331
332 *buf = '\0';
333
334 while (node != prom_rootnode()) {
335 if (prom_getprop(node, OBP_NAME, name) == -1) {
336 prom_printf("instance_to_path: no name property "
337 "node=0x%x\n", node);
338 return (-1);
339 }
340
341 /* construct the unit address from the 'reg' property */
342 if ((rlen = prom_getproplen(node, OBP_REG)) == -1)
343 return (-1);
344
345 /*
346 * Make sure we don't get dispatched onto a different
347 * cpu if we happen to sleep. See kern_postprom().
348 */
349 thread_affinity_set(curthread, CPU->cpu_id);
350 regval = kmem_zalloc(rlen, KM_SLEEP);
351
352 (void) prom_getprop(node, OBP_REG, regval);
353
354 csaddr = (uint_t *)regval;
355
356 (void) prom_sprintf(scratch, "/%s@%lx%s", name,
357 PROM_REG_TO_UNIT_ADDR(*csaddr), buf);
358
359 kmem_free(regval, rlen);
360 thread_affinity_clear(curthread);
361
362 (void) prom_strcpy(buf, scratch);
363
364 node = prom_parentnode(node);
365 }
366
367 rvlen = prom_strlen(buf);
368 ci[6] = p1275_uint2cell(rvlen);
369
370 return (0);
371 }
372
373 #endif /* _KMDB */
374