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 #ifndef _KMDB 33 #include <sys/kmem.h> 34 #endif 35 36 #define PROM_REG_TO_UNIT_ADDR(r) ((r) & ~(0xful << 28)) 37 38 static pnode_t instance_to_package(ihandle_t ih); 39 40 /* cached copies of IO params */ 41 static phandle_t pstdin; 42 static phandle_t pstdout; 43 44 static ihandle_t istdin; 45 static ihandle_t istdout; 46 47 int 48 promif_instance_to_package(void *p) 49 { 50 cell_t *ci = (cell_t *)p; 51 ihandle_t ih; 52 phandle_t ph; 53 54 ih = p1275_cell2ihandle(ci[3]); 55 56 ph = instance_to_package(ih); 57 58 ci[4] = p1275_phandle2cell(ph); 59 60 return (0); 61 } 62 63 int 64 promif_write(void *p) 65 { 66 cell_t *ci = (cell_t *)p; 67 uint_t fd; 68 char *buf; 69 size_t len; 70 size_t rlen; 71 72 ASSERT(ci[1] == 3); 73 74 fd = p1275_cell2uint(ci[3]); 75 buf = p1275_cell2ptr(ci[4]); 76 len = p1275_cell2size(ci[5]); 77 78 /* only support stdout (console) */ 79 ASSERT(fd == istdout); 80 81 for (rlen = 0; rlen < len; rlen++) { 82 while (hv_cnputchar((uint8_t)buf[rlen]) == H_EWOULDBLOCK) 83 /* try forever */; 84 } 85 86 /* return the length written */ 87 ci[6] = p1275_size2cell(rlen); 88 89 return (0); 90 } 91 92 int 93 promif_read(void *p) 94 { 95 cell_t *ci = (cell_t *)p; 96 uint_t fd; 97 char *buf; 98 size_t len; 99 size_t rlen; 100 101 ASSERT(ci[1] == 3); 102 103 /* unpack arguments */ 104 fd = p1275_cell2uint(ci[3]); 105 buf = p1275_cell2ptr(ci[4]); 106 len = p1275_cell2size(ci[5]); 107 108 /* only support stdin (console) */ 109 ASSERT(fd == istdin); 110 111 for (rlen = 0; rlen < len; rlen++) { 112 if (hv_cngetchar((uint8_t *)&buf[rlen]) != H_EOK) 113 break; 114 } 115 116 /* return the length read */ 117 ci[6] = p1275_size2cell(rlen); 118 119 return (0); 120 } 121 122 static pnode_t 123 instance_to_package(ihandle_t ih) 124 { 125 /* only support stdin and stdout */ 126 ASSERT((ih == istdin) || (ih == istdout)); 127 128 if (ih == istdin) 129 return (pstdin); 130 131 if (ih == istdout) 132 return (pstdout); 133 134 return (OBP_BADNODE); 135 } 136 137 #ifdef _KMDB 138 139 void 140 promif_io_init(ihandle_t in, ihandle_t out, phandle_t pin, phandle_t pout) 141 { 142 istdin = in; 143 istdout = out; 144 pstdin = pin; 145 pstdout = pout; 146 } 147 148 #else 149 150 void 151 promif_io_init(void) 152 { 153 /* 154 * Cache the mapping between the stdin and stdout 155 * ihandles and their respective phandles. 156 */ 157 pstdin = prom_stdin_node(); 158 pstdout = prom_stdout_node(); 159 160 istdin = prom_stdin_ihandle(); 161 istdout = prom_stdout_ihandle(); 162 } 163 164 int 165 promif_instance_to_path(void *p) 166 { 167 cell_t *ci = (cell_t *)p; 168 pnode_t node; 169 ihandle_t ih; 170 char *buf; 171 int rlen; 172 char *regval; 173 uint_t *csaddr; 174 char name[OBP_MAXPROPNAME]; 175 char scratch[OBP_MAXPATHLEN]; 176 int rvlen; 177 178 ih = p1275_cell2ihandle(ci[3]); 179 buf = p1275_cell2ptr(ci[4]); 180 181 ci[6] = p1275_uint2cell(0); 182 183 node = instance_to_package(ih); 184 185 *buf = '\0'; 186 187 while (node != prom_rootnode()) { 188 if (prom_getprop(node, OBP_NAME, name) == -1) { 189 prom_printf("instance_to_path: no name property " 190 "node=0x%x\n", node); 191 return (-1); 192 } 193 194 /* construct the unit address from the 'reg' property */ 195 if ((rlen = prom_getproplen(node, OBP_REG)) == -1) 196 return (-1); 197 198 /* 199 * Make sure we don't get dispatched onto a different 200 * cpu if we happen to sleep. See kern_postprom(). 201 */ 202 thread_affinity_set(curthread, CPU->cpu_id); 203 regval = kmem_zalloc(rlen, KM_SLEEP); 204 205 (void) prom_getprop(node, OBP_REG, regval); 206 207 csaddr = (uint_t *)regval; 208 209 (void) prom_sprintf(scratch, "/%s@%lx%s", name, 210 PROM_REG_TO_UNIT_ADDR(*csaddr), buf); 211 212 kmem_free(regval, rlen); 213 thread_affinity_clear(curthread); 214 215 (void) prom_strcpy(buf, scratch); 216 217 node = prom_parentnode(node); 218 } 219 220 rvlen = prom_strlen(buf); 221 ci[6] = p1275_uint2cell(rvlen); 222 223 return (0); 224 } 225 226 #endif /* _KMDB */ 227