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