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 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 */ 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 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 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 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 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 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 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 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 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 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 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 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