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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 1994,1998,2001-2002 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.h> 30 #include <sys/promimpl.h> 31 32 /* 33 * Returns 0 on error. Otherwise returns a handle. 34 */ 35 int 36 prom_open(char *path) 37 { 38 cell_t ci[5]; 39 promif_owrap_t *ow; 40 #ifdef PROM_32BIT_ADDRS 41 char *opath = NULL; 42 size_t len; 43 44 if ((uintptr_t)path > (uint32_t)-1) { 45 opath = path; 46 len = prom_strlen(opath) + 1; /* include terminating NUL */ 47 path = promplat_alloc(len); 48 if (path == NULL) 49 return (0); 50 (void) prom_strcpy(path, opath); 51 } 52 #endif 53 54 ow = promif_preout(); 55 promif_preprom(); 56 ci[0] = p1275_ptr2cell("open"); /* Service name */ 57 ci[1] = (cell_t)1; /* #argument cells */ 58 ci[2] = (cell_t)1; /* #result cells */ 59 ci[3] = p1275_ptr2cell(path); /* Arg1: Pathname */ 60 ci[4] = (cell_t)0; /* Res1: Prime result */ 61 62 (void) p1275_cif_handler(&ci); 63 64 promif_postprom(); 65 promif_postout(ow); 66 67 #ifdef PROM_32BIT_ADDRS 68 if (opath != NULL) 69 promplat_free(path, len); 70 #endif 71 72 return (p1275_cell2int(ci[4])); /* Res1: ihandle */ 73 } 74 75 76 int 77 prom_seek(int fd, unsigned long long offset) 78 { 79 cell_t ci[7]; 80 81 ci[0] = p1275_ptr2cell("seek"); /* Service name */ 82 ci[1] = (cell_t)3; /* #argument cells */ 83 ci[2] = (cell_t)1; /* #result cells */ 84 ci[3] = p1275_uint2cell((uint_t)fd); /* Arg1: ihandle */ 85 ci[4] = p1275_ull2cell_high(offset); /* Arg2: pos.hi */ 86 ci[5] = p1275_ull2cell_low(offset); /* Arg3: pos.lo */ 87 ci[6] = (cell_t)-1; /* Res1: Prime result */ 88 89 promif_preprom(); 90 (void) p1275_cif_handler(&ci); 91 promif_postprom(); 92 93 return (p1275_cell2int(ci[6])); /* Res1: actual */ 94 } 95 96 /*ARGSUSED3*/ 97 ssize_t 98 prom_read(ihandle_t fd, caddr_t buf, size_t len, uint_t startblk, char devtype) 99 { 100 cell_t ci[7]; 101 promif_owrap_t *ow; 102 #ifdef PROM_32BIT_ADDRS 103 caddr_t obuf = NULL; 104 105 if ((uintptr_t)buf > (uint32_t)-1) { 106 obuf = buf; 107 buf = promplat_alloc(len); 108 if (buf == NULL) 109 return (-1); 110 } 111 #endif 112 113 ow = promif_preout(); 114 promif_preprom(); 115 116 ci[0] = p1275_ptr2cell("read"); /* Service name */ 117 ci[1] = (cell_t)3; /* #argument cells */ 118 ci[2] = (cell_t)1; /* #result cells */ 119 ci[3] = p1275_size2cell((uint_t)fd); /* Arg1: ihandle */ 120 ci[4] = p1275_ptr2cell(buf); /* Arg2: buffer address */ 121 ci[5] = p1275_uint2cell(len); /* Arg3: buffer length */ 122 ci[6] = (cell_t)-1; /* Res1: Prime result */ 123 124 (void) p1275_cif_handler(&ci); 125 126 promif_postprom(); 127 promif_postout(ow); 128 129 #ifdef PROM_32BIT_ADDRS 130 if (obuf != NULL) { 131 promplat_bcopy(buf, obuf, len); 132 promplat_free(buf, len); 133 } 134 #endif 135 136 return (p1275_cell2size(ci[6])); /* Res1: actual length */ 137 } 138 139 /*ARGSUSED3*/ 140 ssize_t 141 prom_write(ihandle_t fd, caddr_t buf, size_t len, uint_t startblk, char devtype) 142 { 143 cell_t ci[7]; 144 promif_owrap_t *ow; 145 #ifdef PROM_32BIT_ADDRS 146 caddr_t obuf = NULL; 147 static char smallbuf[256]; 148 149 ASSERT(buf); 150 151 if ((uintptr_t)buf > (uint32_t)-1) { 152 /* 153 * This is a hack for kernel message output. 154 * By avoiding calls to promplat_alloc (and 155 * using smallbuf instead) when memory is low 156 * we can print shortish kernel messages without 157 * deadlocking. smallbuf should be at least as 158 * large as the automatic buffer in 159 * prom_printf.c:_doprint()'s stack frame. 160 * promplat_alloc() can block on a mutex and so 161 * is called here before calling promif_preprom(). 162 */ 163 if (len > sizeof (smallbuf)) { 164 obuf = buf; 165 buf = promplat_alloc(len); 166 if (buf == NULL) { 167 return (-1); 168 } 169 promplat_bcopy(obuf, buf, len); 170 } 171 } 172 #endif 173 174 ow = promif_preout(); 175 promif_preprom(); 176 177 #ifdef PROM_32BIT_ADDRS 178 179 if ((uintptr_t)buf > (uint32_t)-1) { 180 /* 181 * If buf is small enough, use smallbuf 182 * instead of promplat_alloc() (see above) 183 * smallbuf is static, so single thread 184 * access to it by using it only after 185 * promif_preprom() 186 */ 187 if (len <= sizeof (smallbuf)) { 188 promplat_bcopy(buf, smallbuf, len); 189 buf = smallbuf; 190 } 191 } 192 #endif 193 194 ci[0] = p1275_ptr2cell("write"); /* Service name */ 195 ci[1] = (cell_t)3; /* #argument cells */ 196 ci[2] = (cell_t)1; /* #result cells */ 197 ci[3] = p1275_uint2cell((uint_t)fd); /* Arg1: ihandle */ 198 ci[4] = p1275_ptr2cell(buf); /* Arg2: buffer address */ 199 ci[5] = p1275_size2cell(len); /* Arg3: buffer length */ 200 ci[6] = (cell_t)-1; /* Res1: Prime result */ 201 202 (void) p1275_cif_handler(&ci); 203 204 promif_postprom(); 205 promif_postout(ow); 206 207 #ifdef PROM_32BIT_ADDRS 208 if (obuf != NULL) 209 promplat_free(buf, len); 210 #endif 211 212 return (p1275_cell2size(ci[6])); /* Res1: actual length */ 213 } 214 215 int 216 prom_close(int fd) 217 { 218 cell_t ci[4]; 219 promif_owrap_t *ow; 220 221 ci[0] = p1275_ptr2cell("close"); /* Service name */ 222 ci[1] = (cell_t)1; /* #argument cells */ 223 ci[2] = (cell_t)0; /* #result cells */ 224 ci[3] = p1275_uint2cell((uint_t)fd); /* Arg1: ihandle */ 225 226 ow = promif_preout(); 227 promif_preprom(); 228 (void) p1275_cif_handler(&ci); 229 promif_postprom(); 230 promif_postout(ow); 231 232 return (0); 233 } 234