1 0 stevel /* 2 0 stevel * CDDL HEADER START 3 0 stevel * 4 0 stevel * The contents of this file are subject to the terms of the 5 1106 mrj * Common Development and Distribution License (the "License"). 6 1106 mrj * You may not use this file except in compliance with the License. 7 0 stevel * 8 0 stevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 0 stevel * or http://www.opensolaris.org/os/licensing. 10 0 stevel * See the License for the specific language governing permissions 11 0 stevel * and limitations under the License. 12 0 stevel * 13 0 stevel * When distributing Covered Code, include this CDDL HEADER in each 14 0 stevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 0 stevel * If applicable, add the following below this CDDL HEADER, with the 16 0 stevel * fields enclosed by brackets "[]" replaced with your own identifying 17 0 stevel * information: Portions Copyright [yyyy] [name of copyright owner] 18 0 stevel * 19 0 stevel * CDDL HEADER END 20 0 stevel */ 21 1106 mrj 22 0 stevel /* 23 8561 Scott * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 0 stevel * Use is subject to license terms. 25 0 stevel */ 26 0 stevel 27 0 stevel #include <sys/note.h> 28 0 stevel #include <sys/types.h> 29 0 stevel #include <sys/param.h> 30 0 stevel #include <sys/systm.h> 31 0 stevel #include <sys/buf.h> 32 0 stevel #include <sys/uio.h> 33 0 stevel #include <sys/cred.h> 34 0 stevel #include <sys/poll.h> 35 0 stevel #include <sys/mman.h> 36 0 stevel #include <sys/kmem.h> 37 0 stevel #include <sys/model.h> 38 0 stevel #include <sys/file.h> 39 0 stevel #include <sys/proc.h> 40 0 stevel #include <sys/open.h> 41 0 stevel #include <sys/user.h> 42 0 stevel #include <sys/t_lock.h> 43 0 stevel #include <sys/vm.h> 44 0 stevel #include <sys/stat.h> 45 0 stevel #include <vm/hat.h> 46 0 stevel #include <vm/seg.h> 47 0 stevel #include <vm/seg_vn.h> 48 0 stevel #include <vm/seg_dev.h> 49 0 stevel #include <vm/as.h> 50 0 stevel #include <sys/cmn_err.h> 51 0 stevel #include <sys/cpuvar.h> 52 0 stevel #include <sys/debug.h> 53 0 stevel #include <sys/autoconf.h> 54 0 stevel #include <sys/sunddi.h> 55 0 stevel #include <sys/esunddi.h> 56 0 stevel #include <sys/sunndi.h> 57 0 stevel #include <sys/kstat.h> 58 0 stevel #include <sys/conf.h> 59 0 stevel #include <sys/ddi_impldefs.h> /* include implementation structure defs */ 60 0 stevel #include <sys/ndi_impldefs.h> /* include prototypes */ 61 5107 eota #include <sys/ddi_timer.h> 62 0 stevel #include <sys/hwconf.h> 63 0 stevel #include <sys/pathname.h> 64 0 stevel #include <sys/modctl.h> 65 0 stevel #include <sys/epm.h> 66 0 stevel #include <sys/devctl.h> 67 0 stevel #include <sys/callb.h> 68 0 stevel #include <sys/cladm.h> 69 0 stevel #include <sys/sysevent.h> 70 0 stevel #include <sys/dacf_impl.h> 71 0 stevel #include <sys/ddidevmap.h> 72 0 stevel #include <sys/bootconf.h> 73 0 stevel #include <sys/disp.h> 74 0 stevel #include <sys/atomic.h> 75 0 stevel #include <sys/promif.h> 76 0 stevel #include <sys/instance.h> 77 0 stevel #include <sys/sysevent/eventdefs.h> 78 0 stevel #include <sys/task.h> 79 0 stevel #include <sys/project.h> 80 0 stevel #include <sys/taskq.h> 81 0 stevel #include <sys/devpolicy.h> 82 0 stevel #include <sys/ctype.h> 83 0 stevel #include <net/if.h> 84 2768 sl108498 #include <sys/rctl.h> 85 8662 Jordan #include <sys/zone.h> 86 11066 rafael #include <sys/clock_impl.h> 87 10696 David #include <sys/ddi.h> 88 0 stevel 89 0 stevel extern pri_t minclsyspri; 90 0 stevel 91 2768 sl108498 extern rctl_hndl_t rc_project_locked_mem; 92 2768 sl108498 extern rctl_hndl_t rc_zone_locked_mem; 93 0 stevel 94 0 stevel #ifdef DEBUG 95 0 stevel static int sunddi_debug = 0; 96 0 stevel #endif /* DEBUG */ 97 0 stevel 98 0 stevel /* ddi_umem_unlock miscellaneous */ 99 0 stevel 100 0 stevel static void i_ddi_umem_unlock_thread_start(void); 101 0 stevel 102 0 stevel static kmutex_t ddi_umem_unlock_mutex; /* unlock list mutex */ 103 0 stevel static kcondvar_t ddi_umem_unlock_cv; /* unlock list block/unblock */ 104 0 stevel static kthread_t *ddi_umem_unlock_thread; 105 0 stevel /* 106 0 stevel * The ddi_umem_unlock FIFO list. NULL head pointer indicates empty list. 107 0 stevel */ 108 0 stevel static struct ddi_umem_cookie *ddi_umem_unlock_head = NULL; 109 0 stevel static struct ddi_umem_cookie *ddi_umem_unlock_tail = NULL; 110 0 stevel 111 0 stevel /* 112 0 stevel * DDI(Sun) Function and flag definitions: 113 0 stevel */ 114 0 stevel 115 0 stevel #if defined(__x86) 116 0 stevel /* 117 0 stevel * Used to indicate which entries were chosen from a range. 118 0 stevel */ 119 0 stevel char *chosen_reg = "chosen-reg"; 120 0 stevel #endif 121 0 stevel 122 0 stevel /* 123 0 stevel * Function used to ring system console bell 124 0 stevel */ 125 0 stevel void (*ddi_console_bell_func)(clock_t duration); 126 0 stevel 127 0 stevel /* 128 0 stevel * Creating register mappings and handling interrupts: 129 0 stevel */ 130 0 stevel 131 0 stevel /* 132 0 stevel * Generic ddi_map: Call parent to fulfill request... 133 0 stevel */ 134 0 stevel 135 0 stevel int 136 0 stevel ddi_map(dev_info_t *dp, ddi_map_req_t *mp, off_t offset, 137 0 stevel off_t len, caddr_t *addrp) 138 0 stevel { 139 0 stevel dev_info_t *pdip; 140 0 stevel 141 0 stevel ASSERT(dp); 142 0 stevel pdip = (dev_info_t *)DEVI(dp)->devi_parent; 143 0 stevel return ((DEVI(pdip)->devi_ops->devo_bus_ops->bus_map)(pdip, 144 0 stevel dp, mp, offset, len, addrp)); 145 0 stevel } 146 0 stevel 147 0 stevel /* 148 0 stevel * ddi_apply_range: (Called by nexi only.) 149 0 stevel * Apply ranges in parent node dp, to child regspec rp... 150 0 stevel */ 151 0 stevel 152 0 stevel int 153 0 stevel ddi_apply_range(dev_info_t *dp, dev_info_t *rdip, struct regspec *rp) 154 0 stevel { 155 0 stevel return (i_ddi_apply_range(dp, rdip, rp)); 156 0 stevel } 157 0 stevel 158 0 stevel int 159 0 stevel ddi_map_regs(dev_info_t *dip, uint_t rnumber, caddr_t *kaddrp, off_t offset, 160 0 stevel off_t len) 161 0 stevel { 162 0 stevel ddi_map_req_t mr; 163 0 stevel #if defined(__x86) 164 0 stevel struct { 165 0 stevel int bus; 166 0 stevel int addr; 167 0 stevel int size; 168 0 stevel } reg, *reglist; 169 0 stevel uint_t length; 170 0 stevel int rc; 171 0 stevel 172 0 stevel /* 173 0 stevel * get the 'registers' or the 'reg' property. 174 0 stevel * We look up the reg property as an array of 175 0 stevel * int's. 176 0 stevel */ 177 0 stevel rc = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 178 0 stevel DDI_PROP_DONTPASS, "registers", (int **)®list, &length); 179 0 stevel if (rc != DDI_PROP_SUCCESS) 180 0 stevel rc = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 181 0 stevel DDI_PROP_DONTPASS, "reg", (int **)®list, &length); 182 0 stevel if (rc == DDI_PROP_SUCCESS) { 183 0 stevel /* 184 0 stevel * point to the required entry. 185 0 stevel */ 186 0 stevel reg = reglist[rnumber]; 187 0 stevel reg.addr += offset; 188 0 stevel if (len != 0) 189 0 stevel reg.size = len; 190 0 stevel /* 191 0 stevel * make a new property containing ONLY the required tuple. 192 0 stevel */ 193 0 stevel if (ddi_prop_update_int_array(DDI_DEV_T_NONE, dip, 194 0 stevel chosen_reg, (int *)®, (sizeof (reg)/sizeof (int))) 195 0 stevel != DDI_PROP_SUCCESS) { 196 0 stevel cmn_err(CE_WARN, "%s%d: cannot create '%s' " 197 0 stevel "property", DEVI(dip)->devi_name, 198 0 stevel DEVI(dip)->devi_instance, chosen_reg); 199 0 stevel } 200 0 stevel /* 201 0 stevel * free the memory allocated by 202 0 stevel * ddi_prop_lookup_int_array (). 203 0 stevel */ 204 0 stevel ddi_prop_free((void *)reglist); 205 0 stevel } 206 0 stevel #endif 207 0 stevel mr.map_op = DDI_MO_MAP_LOCKED; 208 0 stevel mr.map_type = DDI_MT_RNUMBER; 209 0 stevel mr.map_obj.rnumber = rnumber; 210 0 stevel mr.map_prot = PROT_READ | PROT_WRITE; 211 0 stevel mr.map_flags = DDI_MF_KERNEL_MAPPING; 212 0 stevel mr.map_handlep = NULL; 213 0 stevel mr.map_vers = DDI_MAP_VERSION; 214 0 stevel 215 0 stevel /* 216 0 stevel * Call my parent to map in my regs. 217 0 stevel */ 218 0 stevel 219 0 stevel return (ddi_map(dip, &mr, offset, len, kaddrp)); 220 0 stevel } 221 0 stevel 222 0 stevel void 223 0 stevel ddi_unmap_regs(dev_info_t *dip, uint_t rnumber, caddr_t *kaddrp, off_t offset, 224 0 stevel off_t len) 225 0 stevel { 226 0 stevel ddi_map_req_t mr; 227 0 stevel 228 0 stevel mr.map_op = DDI_MO_UNMAP; 229 0 stevel mr.map_type = DDI_MT_RNUMBER; 230 0 stevel mr.map_flags = DDI_MF_KERNEL_MAPPING; 231 0 stevel mr.map_prot = PROT_READ | PROT_WRITE; /* who cares? */ 232 0 stevel mr.map_obj.rnumber = rnumber; 233 0 stevel mr.map_handlep = NULL; 234 0 stevel mr.map_vers = DDI_MAP_VERSION; 235 0 stevel 236 0 stevel /* 237 0 stevel * Call my parent to unmap my regs. 238 0 stevel */ 239 0 stevel 240 0 stevel (void) ddi_map(dip, &mr, offset, len, kaddrp); 241 0 stevel *kaddrp = (caddr_t)0; 242 0 stevel #if defined(__x86) 243 0 stevel (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, chosen_reg); 244 0 stevel #endif 245 0 stevel } 246 0 stevel 247 0 stevel int 248 0 stevel ddi_bus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp, 249 0 stevel off_t offset, off_t len, caddr_t *vaddrp) 250 0 stevel { 251 0 stevel return (i_ddi_bus_map(dip, rdip, mp, offset, len, vaddrp)); 252 0 stevel } 253 0 stevel 254 0 stevel /* 255 0 stevel * nullbusmap: The/DDI default bus_map entry point for nexi 256 0 stevel * not conforming to the reg/range paradigm (i.e. scsi, etc.) 257 0 stevel * with no HAT/MMU layer to be programmed at this level. 258 0 stevel * 259 0 stevel * If the call is to map by rnumber, return an error, 260 0 stevel * otherwise pass anything else up the tree to my parent. 261 0 stevel */ 262 0 stevel int 263 0 stevel nullbusmap(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp, 264 0 stevel off_t offset, off_t len, caddr_t *vaddrp) 265 0 stevel { 266 0 stevel _NOTE(ARGUNUSED(rdip)) 267 0 stevel if (mp->map_type == DDI_MT_RNUMBER) 268 0 stevel return (DDI_ME_UNSUPPORTED); 269 0 stevel 270 0 stevel return (ddi_map(dip, mp, offset, len, vaddrp)); 271 0 stevel } 272 0 stevel 273 0 stevel /* 274 0 stevel * ddi_rnumber_to_regspec: Not for use by leaf drivers. 275 0 stevel * Only for use by nexi using the reg/range paradigm. 276 0 stevel */ 277 0 stevel struct regspec * 278 0 stevel ddi_rnumber_to_regspec(dev_info_t *dip, int rnumber) 279 0 stevel { 280 0 stevel return (i_ddi_rnumber_to_regspec(dip, rnumber)); 281 0 stevel } 282 0 stevel 283 0 stevel 284 0 stevel /* 285 0 stevel * Note that we allow the dip to be nil because we may be called 286 0 stevel * prior even to the instantiation of the devinfo tree itself - all 287 0 stevel * regular leaf and nexus drivers should always use a non-nil dip! 288 0 stevel * 289 0 stevel * We treat peek in a somewhat cavalier fashion .. assuming that we'll 290 0 stevel * simply get a synchronous fault as soon as we touch a missing address. 291 0 stevel * 292 0 stevel * Poke is rather more carefully handled because we might poke to a write 293 0 stevel * buffer, "succeed", then only find some time later that we got an 294 0 stevel * asynchronous fault that indicated that the address we were writing to 295 0 stevel * was not really backed by hardware. 296 0 stevel */ 297 0 stevel 298 0 stevel static int 299 0 stevel i_ddi_peekpoke(dev_info_t *devi, ddi_ctl_enum_t cmd, size_t size, 300 0 stevel void *addr, void *value_p) 301 0 stevel { 302 0 stevel union { 303 0 stevel uint64_t u64; 304 0 stevel uint32_t u32; 305 0 stevel uint16_t u16; 306 0 stevel uint8_t u8; 307 0 stevel } peekpoke_value; 308 0 stevel 309 0 stevel peekpoke_ctlops_t peekpoke_args; 310 0 stevel uint64_t dummy_result; 311 0 stevel int rval; 312 0 stevel 313 0 stevel /* Note: size is assumed to be correct; it is not checked. */ 314 0 stevel peekpoke_args.size = size; 315 42 agiri peekpoke_args.dev_addr = (uintptr_t)addr; 316 0 stevel peekpoke_args.handle = NULL; 317 0 stevel peekpoke_args.repcount = 1; 318 0 stevel peekpoke_args.flags = 0; 319 0 stevel 320 0 stevel if (cmd == DDI_CTLOPS_POKE) { 321 0 stevel switch (size) { 322 0 stevel case sizeof (uint8_t): 323 0 stevel peekpoke_value.u8 = *(uint8_t *)value_p; 324 0 stevel break; 325 0 stevel case sizeof (uint16_t): 326 0 stevel peekpoke_value.u16 = *(uint16_t *)value_p; 327 0 stevel break; 328 0 stevel case sizeof (uint32_t): 329 0 stevel peekpoke_value.u32 = *(uint32_t *)value_p; 330 0 stevel break; 331 0 stevel case sizeof (uint64_t): 332 0 stevel peekpoke_value.u64 = *(uint64_t *)value_p; 333 0 stevel break; 334 0 stevel } 335 0 stevel } 336 0 stevel 337 42 agiri peekpoke_args.host_addr = (uintptr_t)&peekpoke_value.u64; 338 0 stevel 339 0 stevel if (devi != NULL) 340 0 stevel rval = ddi_ctlops(devi, devi, cmd, &peekpoke_args, 341 0 stevel &dummy_result); 342 0 stevel else 343 0 stevel rval = peekpoke_mem(cmd, &peekpoke_args); 344 0 stevel 345 0 stevel /* 346 0 stevel * A NULL value_p is permitted by ddi_peek(9F); discard the result. 347 0 stevel */ 348 0 stevel if ((cmd == DDI_CTLOPS_PEEK) & (value_p != NULL)) { 349 0 stevel switch (size) { 350 0 stevel case sizeof (uint8_t): 351 0 stevel *(uint8_t *)value_p = peekpoke_value.u8; 352 0 stevel break; 353 0 stevel case sizeof (uint16_t): 354 0 stevel *(uint16_t *)value_p = peekpoke_value.u16; 355 0 stevel break; 356 0 stevel case sizeof (uint32_t): 357 0 stevel *(uint32_t *)value_p = peekpoke_value.u32; 358 0 stevel break; 359 0 stevel case sizeof (uint64_t): 360 0 stevel *(uint64_t *)value_p = peekpoke_value.u64; 361 0 stevel break; 362 0 stevel } 363 0 stevel } 364 0 stevel 365 0 stevel return (rval); 366 0 stevel } 367 0 stevel 368 0 stevel /* 369 0 stevel * Keep ddi_peek() and ddi_poke() in case 3rd parties are calling this. 370 0 stevel * they shouldn't be, but the 9f manpage kind of pseudo exposes it. 371 0 stevel */ 372 0 stevel int 373 0 stevel ddi_peek(dev_info_t *devi, size_t size, void *addr, void *value_p) 374 0 stevel { 375 0 stevel switch (size) { 376 0 stevel case sizeof (uint8_t): 377 0 stevel case sizeof (uint16_t): 378 0 stevel case sizeof (uint32_t): 379 0 stevel case sizeof (uint64_t): 380 0 stevel break; 381 0 stevel default: 382 0 stevel return (DDI_FAILURE); 383 0 stevel } 384 0 stevel 385 0 stevel return (i_ddi_peekpoke(devi, DDI_CTLOPS_PEEK, size, addr, value_p)); 386 0 stevel } 387 0 stevel 388 0 stevel int 389 0 stevel ddi_poke(dev_info_t *devi, size_t size, void *addr, void *value_p) 390 0 stevel { 391 0 stevel switch (size) { 392 0 stevel case sizeof (uint8_t): 393 0 stevel case sizeof (uint16_t): 394 0 stevel case sizeof (uint32_t): 395 0 stevel case sizeof (uint64_t): 396 0 stevel break; 397 0 stevel default: 398 0 stevel return (DDI_FAILURE); 399 0 stevel } 400 0 stevel 401 0 stevel return (i_ddi_peekpoke(devi, DDI_CTLOPS_POKE, size, addr, value_p)); 402 0 stevel } 403 0 stevel 404 0 stevel int 405 0 stevel ddi_peek8(dev_info_t *dip, int8_t *addr, int8_t *val_p) 406 0 stevel { 407 0 stevel return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr, 408 0 stevel val_p)); 409 0 stevel } 410 0 stevel 411 0 stevel int 412 0 stevel ddi_peek16(dev_info_t *dip, int16_t *addr, int16_t *val_p) 413 0 stevel { 414 0 stevel return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr, 415 0 stevel val_p)); 416 0 stevel } 417 0 stevel 418 0 stevel int 419 0 stevel ddi_peek32(dev_info_t *dip, int32_t *addr, int32_t *val_p) 420 0 stevel { 421 0 stevel return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr, 422 0 stevel val_p)); 423 0 stevel } 424 0 stevel 425 0 stevel int 426 0 stevel ddi_peek64(dev_info_t *dip, int64_t *addr, int64_t *val_p) 427 0 stevel { 428 0 stevel return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr, 429 0 stevel val_p)); 430 0 stevel } 431 0 stevel 432 1106 mrj 433 1106 mrj /* 434 1106 mrj * We need to separate the old interfaces from the new ones and leave them 435 1106 mrj * in here for a while. Previous versions of the OS defined the new interfaces 436 1106 mrj * to the old interfaces. This way we can fix things up so that we can 437 1106 mrj * eventually remove these interfaces. 438 1106 mrj * e.g. A 3rd party module/driver using ddi_peek8 and built against S10 439 1106 mrj * or earlier will actually have a reference to ddi_peekc in the binary. 440 1106 mrj */ 441 1106 mrj #ifdef _ILP32 442 1106 mrj int 443 1106 mrj ddi_peekc(dev_info_t *dip, int8_t *addr, int8_t *val_p) 444 1106 mrj { 445 1106 mrj return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr, 446 1106 mrj val_p)); 447 1106 mrj } 448 1106 mrj 449 1106 mrj int 450 1106 mrj ddi_peeks(dev_info_t *dip, int16_t *addr, int16_t *val_p) 451 1106 mrj { 452 1106 mrj return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr, 453 1106 mrj val_p)); 454 1106 mrj } 455 1106 mrj 456 1106 mrj int 457 1106 mrj ddi_peekl(dev_info_t *dip, int32_t *addr, int32_t *val_p) 458 1106 mrj { 459 1106 mrj return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr, 460 1106 mrj val_p)); 461 1106 mrj } 462 1106 mrj 463 1106 mrj int 464 1106 mrj ddi_peekd(dev_info_t *dip, int64_t *addr, int64_t *val_p) 465 1106 mrj { 466 1106 mrj return (i_ddi_peekpoke(dip, DDI_CTLOPS_PEEK, sizeof (*val_p), addr, 467 1106 mrj val_p)); 468 1106 mrj } 469 1106 mrj #endif /* _ILP32 */ 470 1106 mrj 471 0 stevel int 472 0 stevel ddi_poke8(dev_info_t *dip, int8_t *addr, int8_t val) 473 1106 mrj { 474 1106 mrj return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val)); 475 1106 mrj } 476 1106 mrj 477 1106 mrj int 478 1106 mrj ddi_poke16(dev_info_t *dip, int16_t *addr, int16_t val) 479 1106 mrj { 480 1106 mrj return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val)); 481 1106 mrj } 482 1106 mrj 483 1106 mrj int 484 1106 mrj ddi_poke32(dev_info_t *dip, int32_t *addr, int32_t val) 485 1106 mrj { 486 1106 mrj return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val)); 487 1106 mrj } 488 1106 mrj 489 1106 mrj int 490 1106 mrj ddi_poke64(dev_info_t *dip, int64_t *addr, int64_t val) 491 1106 mrj { 492 1106 mrj return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val)); 493 1106 mrj } 494 1106 mrj 495 1106 mrj /* 496 1106 mrj * We need to separate the old interfaces from the new ones and leave them 497 1106 mrj * in here for a while. Previous versions of the OS defined the new interfaces 498 1106 mrj * to the old interfaces. This way we can fix things up so that we can 499 1106 mrj * eventually remove these interfaces. 500 1106 mrj * e.g. A 3rd party module/driver using ddi_poke8 and built against S10 501 1106 mrj * or earlier will actually have a reference to ddi_pokec in the binary. 502 1106 mrj */ 503 1106 mrj #ifdef _ILP32 504 0 stevel int 505 0 stevel ddi_pokec(dev_info_t *dip, int8_t *addr, int8_t val) 506 0 stevel { 507 0 stevel return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val)); 508 0 stevel } 509 0 stevel 510 0 stevel int 511 0 stevel ddi_pokes(dev_info_t *dip, int16_t *addr, int16_t val) 512 0 stevel { 513 0 stevel return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val)); 514 0 stevel } 515 0 stevel 516 0 stevel int 517 0 stevel ddi_pokel(dev_info_t *dip, int32_t *addr, int32_t val) 518 0 stevel { 519 0 stevel return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val)); 520 0 stevel } 521 0 stevel 522 0 stevel int 523 0 stevel ddi_poked(dev_info_t *dip, int64_t *addr, int64_t val) 524 0 stevel { 525 0 stevel return (i_ddi_peekpoke(dip, DDI_CTLOPS_POKE, sizeof (val), addr, &val)); 526 0 stevel } 527 1106 mrj #endif /* _ILP32 */ 528 0 stevel 529 0 stevel /* 530 0 stevel * ddi_peekpokeio() is used primarily by the mem drivers for moving 531 0 stevel * data to and from uio structures via peek and poke. Note that we 532 0 stevel * use "internal" routines ddi_peek and ddi_poke to make this go 533 0 stevel * slightly faster, avoiding the call overhead .. 534 0 stevel */ 535 0 stevel int 536 0 stevel ddi_peekpokeio(dev_info_t *devi, struct uio *uio, enum uio_rw rw, 537 0 stevel caddr_t addr, size_t len, uint_t xfersize) 538 0 stevel { 539 0 stevel int64_t ibuffer; 540 0 stevel int8_t w8; 541 0 stevel size_t sz; 542 0 stevel int o; 543 0 stevel 544 0 stevel if (xfersize > sizeof (long)) 545 0 stevel xfersize = sizeof (long); 546 0 stevel 547 0 stevel while (len != 0) { 548 0 stevel if ((len | (uintptr_t)addr) & 1) { 549 0 stevel sz = sizeof (int8_t); 550 0 stevel if (rw == UIO_WRITE) { 551 0 stevel if ((o = uwritec(uio)) == -1) 552 0 stevel return (DDI_FAILURE); 553 0 stevel if (ddi_poke8(devi, (int8_t *)addr, 554 0 stevel (int8_t)o) != DDI_SUCCESS) 555 0 stevel return (DDI_FAILURE); 556 0 stevel } else { 557 0 stevel if (i_ddi_peekpoke(devi, DDI_CTLOPS_PEEK, sz, 558 0 stevel (int8_t *)addr, &w8) != DDI_SUCCESS) 559 0 stevel return (DDI_FAILURE); 560 0 stevel if (ureadc(w8, uio)) 561 0 stevel return (DDI_FAILURE); 562 0 stevel } 563 0 stevel } else { 564 0 stevel switch (xfersize) { 565 0 stevel case sizeof (int64_t): 566 0 stevel if (((len | (uintptr_t)addr) & 567 0 stevel (sizeof (int64_t) - 1)) == 0) { 568 0 stevel sz = xfersize; 569 0 stevel break; 570 0 stevel } 571 0 stevel /*FALLTHROUGH*/ 572 0 stevel case sizeof (int32_t): 573 0 stevel if (((len | (uintptr_t)addr) & 574 0 stevel (sizeof (int32_t) - 1)) == 0) { 575 0 stevel sz = xfersize; 576 0 stevel break; 577 0 stevel } 578 0 stevel /*FALLTHROUGH*/ 579 0 stevel default: 580 0 stevel /* 581 0 stevel * This still assumes that we might have an 582 0 stevel * I/O bus out there that permits 16-bit 583 0 stevel * transfers (and that it would be upset by 584 0 stevel * 32-bit transfers from such locations). 585 0 stevel */ 586 0 stevel sz = sizeof (int16_t); 587 0 stevel break; 588 0 stevel } 589 0 stevel 590 0 stevel if (rw == UIO_READ) { 591 0 stevel if (i_ddi_peekpoke(devi, DDI_CTLOPS_PEEK, sz, 592 0 stevel addr, &ibuffer) != DDI_SUCCESS) 593 0 stevel return (DDI_FAILURE); 594 0 stevel } 595 0 stevel 596 0 stevel if (uiomove(&ibuffer, sz, rw, uio)) 597 0 stevel return (DDI_FAILURE); 598 0 stevel 599 0 stevel if (rw == UIO_WRITE) { 600 0 stevel if (i_ddi_peekpoke(devi, DDI_CTLOPS_POKE, sz, 601 0 stevel addr, &ibuffer) != DDI_SUCCESS) 602 0 stevel return (DDI_FAILURE); 603 0 stevel } 604 0 stevel } 605 0 stevel addr += sz; 606 0 stevel len -= sz; 607 0 stevel } 608 0 stevel return (DDI_SUCCESS); 609 0 stevel } 610 0 stevel 611 0 stevel /* 612 0 stevel * These routines are used by drivers that do layered ioctls 613 0 stevel * On sparc, they're implemented in assembler to avoid spilling 614 0 stevel * register windows in the common (copyin) case .. 615 0 stevel */ 616 0 stevel #if !defined(__sparc) 617 0 stevel int 618 0 stevel ddi_copyin(const void *buf, void *kernbuf, size_t size, int flags) 619 0 stevel { 620 0 stevel if (flags & FKIOCTL) 621 0 stevel return (kcopy(buf, kernbuf, size) ? -1 : 0); 622 0 stevel return (copyin(buf, kernbuf, size)); 623 0 stevel } 624 0 stevel 625 0 stevel int 626 0 stevel ddi_copyout(const void *buf, void *kernbuf, size_t size, int flags) 627 0 stevel { 628 0 stevel if (flags & FKIOCTL) 629 0 stevel return (kcopy(buf, kernbuf, size) ? -1 : 0); 630 0 stevel return (copyout(buf, kernbuf, size)); 631 0 stevel } 632 0 stevel #endif /* !__sparc */ 633 0 stevel 634 0 stevel /* 635 0 stevel * Conversions in nexus pagesize units. We don't duplicate the 636 0 stevel * 'nil dip' semantics of peek/poke because btopr/btop/ptob are DDI/DKI 637 0 stevel * routines anyway. 638 0 stevel */ 639 0 stevel unsigned long 640 0 stevel ddi_btop(dev_info_t *dip, unsigned long bytes) 641 0 stevel { 642 0 stevel unsigned long pages; 643 0 stevel 644 0 stevel (void) ddi_ctlops(dip, dip, DDI_CTLOPS_BTOP, &bytes, &pages); 645 0 stevel return (pages); 646 0 stevel } 647 0 stevel 648 0 stevel unsigned long 649 0 stevel ddi_btopr(dev_info_t *dip, unsigned long bytes) 650 0 stevel { 651 0 stevel unsigned long pages; 652 0 stevel 653 0 stevel (void) ddi_ctlops(dip, dip, DDI_CTLOPS_BTOPR, &bytes, &pages); 654 0 stevel return (pages); 655 0 stevel } 656 0 stevel 657 0 stevel unsigned long 658 0 stevel ddi_ptob(dev_info_t *dip, unsigned long pages) 659 0 stevel { 660 0 stevel unsigned long bytes; 661 0 stevel 662 0 stevel (void) ddi_ctlops(dip, dip, DDI_CTLOPS_PTOB, &pages, &bytes); 663 0 stevel return (bytes); 664 0 stevel } 665 0 stevel 666 0 stevel unsigned int 667 0 stevel ddi_enter_critical(void) 668 0 stevel { 669 0 stevel return ((uint_t)spl7()); 670 0 stevel } 671 0 stevel 672 0 stevel void 673 0 stevel ddi_exit_critical(unsigned int spl) 674 0 stevel { 675 0 stevel splx((int)spl); 676 0 stevel } 677 0 stevel 678 0 stevel /* 679 0 stevel * Nexus ctlops punter 680 0 stevel */ 681 0 stevel 682 0 stevel #if !defined(__sparc) 683 0 stevel /* 684 0 stevel * Request bus_ctl parent to handle a bus_ctl request 685 0 stevel * 686 0 stevel * (The sparc version is in sparc_ddi.s) 687 0 stevel */ 688 0 stevel int 689 0 stevel ddi_ctlops(dev_info_t *d, dev_info_t *r, ddi_ctl_enum_t op, void *a, void *v) 690 0 stevel { 691 0 stevel int (*fp)(); 692 0 stevel 693 0 stevel if (!d || !r) 694 0 stevel return (DDI_FAILURE); 695 0 stevel 696 0 stevel if ((d = (dev_info_t *)DEVI(d)->devi_bus_ctl) == NULL) 697 0 stevel return (DDI_FAILURE); 698 0 stevel 699 0 stevel fp = DEVI(d)->devi_ops->devo_bus_ops->bus_ctl; 700 0 stevel return ((*fp)(d, r, op, a, v)); 701 0 stevel } 702 0 stevel 703 0 stevel #endif 704 0 stevel 705 0 stevel /* 706 0 stevel * DMA/DVMA setup 707 0 stevel */ 708 0 stevel 709 0 stevel #if defined(__sparc) 710 0 stevel static ddi_dma_lim_t standard_limits = { 711 0 stevel (uint_t)0, /* addr_t dlim_addr_lo */ 712 0 stevel (uint_t)-1, /* addr_t dlim_addr_hi */ 713 0 stevel (uint_t)-1, /* uint_t dlim_cntr_max */ 714 0 stevel (uint_t)1, /* uint_t dlim_burstsizes */ 715 0 stevel (uint_t)1, /* uint_t dlim_minxfer */ 716 0 stevel 0 /* uint_t dlim_dmaspeed */ 717 0 stevel }; 718 0 stevel #elif defined(__x86) 719 0 stevel static ddi_dma_lim_t standard_limits = { 720 0 stevel (uint_t)0, /* addr_t dlim_addr_lo */ 721 0 stevel (uint_t)0xffffff, /* addr_t dlim_addr_hi */ 722 0 stevel (uint_t)0, /* uint_t dlim_cntr_max */ 723 0 stevel (uint_t)0x00000001, /* uint_t dlim_burstsizes */ 724 0 stevel (uint_t)DMA_UNIT_8, /* uint_t dlim_minxfer */ 725 0 stevel (uint_t)0, /* uint_t dlim_dmaspeed */ 726 0 stevel (uint_t)0x86<<24+0, /* uint_t dlim_version */ 727 0 stevel (uint_t)0xffff, /* uint_t dlim_adreg_max */ 728 0 stevel (uint_t)0xffff, /* uint_t dlim_ctreg_max */ 729 0 stevel (uint_t)512, /* uint_t dlim_granular */ 730 0 stevel (int)1, /* int dlim_sgllen */ 731 0 stevel (uint_t)0xffffffff /* uint_t dlim_reqsizes */ 732 0 stevel }; 733 0 stevel 734 0 stevel #endif 735 0 stevel 736 0 stevel int 737 0 stevel ddi_dma_setup(dev_info_t *dip, struct ddi_dma_req *dmareqp, 738 0 stevel ddi_dma_handle_t *handlep) 739 0 stevel { 740 0 stevel int (*funcp)() = ddi_dma_map; 741 0 stevel struct bus_ops *bop; 742 0 stevel #if defined(__sparc) 743 0 stevel auto ddi_dma_lim_t dma_lim; 744 0 stevel 745 0 stevel if (dmareqp->dmar_limits == (ddi_dma_lim_t *)0) { 746 0 stevel dma_lim = standard_limits; 747 0 stevel } else { 748 0 stevel dma_lim = *dmareqp->dmar_limits; 749 0 stevel } 750 0 stevel dmareqp->dmar_limits = &dma_lim; 751 0 stevel #endif 752 0 stevel #if defined(__x86) 753 0 stevel if (dmareqp->dmar_limits == (ddi_dma_lim_t *)0) 754 0 stevel return (DDI_FAILURE); 755 0 stevel #endif 756 0 stevel 757 0 stevel /* 758 0 stevel * Handle the case that the requester is both a leaf 759 0 stevel * and a nexus driver simultaneously by calling the 760 0 stevel * requester's bus_dma_map function directly instead 761 0 stevel * of ddi_dma_map. 762 0 stevel */ 763 0 stevel bop = DEVI(dip)->devi_ops->devo_bus_ops; 764 0 stevel if (bop && bop->bus_dma_map) 765 0 stevel funcp = bop->bus_dma_map; 766 0 stevel return ((*funcp)(dip, dip, dmareqp, handlep)); 767 0 stevel } 768 0 stevel 769 0 stevel int 770 0 stevel ddi_dma_addr_setup(dev_info_t *dip, struct as *as, caddr_t addr, size_t len, 771 0 stevel uint_t flags, int (*waitfp)(), caddr_t arg, 772 0 stevel ddi_dma_lim_t *limits, ddi_dma_handle_t *handlep) 773 0 stevel { 774 0 stevel int (*funcp)() = ddi_dma_map; 775 0 stevel ddi_dma_lim_t dma_lim; 776 0 stevel struct ddi_dma_req dmareq; 777 0 stevel struct bus_ops *bop; 778 0 stevel 779 0 stevel if (len == 0) { 780 0 stevel return (DDI_DMA_NOMAPPING); 781 0 stevel } 782 0 stevel if (limits == (ddi_dma_lim_t *)0) { 783 0 stevel dma_lim = standard_limits; 784 0 stevel } else { 785 0 stevel dma_lim = *limits; 786 0 stevel } 787 0 stevel dmareq.dmar_limits = &dma_lim; 788 0 stevel dmareq.dmar_flags = flags; 789 0 stevel dmareq.dmar_fp = waitfp; 790 0 stevel dmareq.dmar_arg = arg; 791 0 stevel dmareq.dmar_object.dmao_size = len; 792 0 stevel dmareq.dmar_object.dmao_type = DMA_OTYP_VADDR; 793 0 stevel dmareq.dmar_object.dmao_obj.virt_obj.v_as = as; 794 0 stevel dmareq.dmar_object.dmao_obj.virt_obj.v_addr = addr; 795 0 stevel dmareq.dmar_object.dmao_obj.virt_obj.v_priv = NULL; 796 0 stevel 797 0 stevel /* 798 0 stevel * Handle the case that the requester is both a leaf 799 0 stevel * and a nexus driver simultaneously by calling the 800 0 stevel * requester's bus_dma_map function directly instead 801 0 stevel * of ddi_dma_map. 802 0 stevel */ 803 0 stevel bop = DEVI(dip)->devi_ops->devo_bus_ops; 804 0 stevel if (bop && bop->bus_dma_map) 805 0 stevel funcp = bop->bus_dma_map; 806 0 stevel 807 0 stevel return ((*funcp)(dip, dip, &dmareq, handlep)); 808 0 stevel } 809 0 stevel 810 0 stevel int 811 0 stevel ddi_dma_buf_setup(dev_info_t *dip, struct buf *bp, uint_t flags, 812 0 stevel int (*waitfp)(), caddr_t arg, ddi_dma_lim_t *limits, 813 0 stevel ddi_dma_handle_t *handlep) 814 0 stevel { 815 0 stevel int (*funcp)() = ddi_dma_map; 816 0 stevel ddi_dma_lim_t dma_lim; 817 0 stevel struct ddi_dma_req dmareq; 818 0 stevel struct bus_ops *bop; 819 0 stevel 820 0 stevel if (limits == (ddi_dma_lim_t *)0) { 821 0 stevel dma_lim = standard_limits; 822 0 stevel } else { 823 0 stevel dma_lim = *limits; 824 0 stevel } 825 0 stevel dmareq.dmar_limits = &dma_lim; 826 0 stevel dmareq.dmar_flags = flags; 827 0 stevel dmareq.dmar_fp = waitfp; 828 0 stevel dmareq.dmar_arg = arg; 829 0 stevel dmareq.dmar_object.dmao_size = (uint_t)bp->b_bcount; 830 0 stevel 831 1299 cth if (bp->b_flags & B_PAGEIO) { 832 0 stevel dmareq.dmar_object.dmao_type = DMA_OTYP_PAGES; 833 0 stevel dmareq.dmar_object.dmao_obj.pp_obj.pp_pp = bp->b_pages; 834 0 stevel dmareq.dmar_object.dmao_obj.pp_obj.pp_offset = 835 0 stevel (uint_t)(((uintptr_t)bp->b_un.b_addr) & MMU_PAGEOFFSET); 836 0 stevel } else { 837 0 stevel dmareq.dmar_object.dmao_type = DMA_OTYP_BUFVADDR; 838 0 stevel dmareq.dmar_object.dmao_obj.virt_obj.v_addr = bp->b_un.b_addr; 839 1299 cth if (bp->b_flags & B_SHADOW) { 840 0 stevel dmareq.dmar_object.dmao_obj.virt_obj.v_priv = 841 4582 cth bp->b_shadow; 842 0 stevel } else { 843 0 stevel dmareq.dmar_object.dmao_obj.virt_obj.v_priv = NULL; 844 0 stevel } 845 0 stevel 846 0 stevel /* 847 0 stevel * If the buffer has no proc pointer, or the proc 848 0 stevel * struct has the kernel address space, or the buffer has 849 0 stevel * been marked B_REMAPPED (meaning that it is now 850 0 stevel * mapped into the kernel's address space), then 851 0 stevel * the address space is kas (kernel address space). 852 0 stevel */ 853 1299 cth if ((bp->b_proc == NULL) || (bp->b_proc->p_as == &kas) || 854 1299 cth (bp->b_flags & B_REMAPPED)) { 855 0 stevel dmareq.dmar_object.dmao_obj.virt_obj.v_as = 0; 856 0 stevel } else { 857 0 stevel dmareq.dmar_object.dmao_obj.virt_obj.v_as = 858 0 stevel bp->b_proc->p_as; 859 0 stevel } 860 0 stevel } 861 0 stevel 862 0 stevel /* 863 0 stevel * Handle the case that the requester is both a leaf 864 0 stevel * and a nexus driver simultaneously by calling the 865 0 stevel * requester's bus_dma_map function directly instead 866 0 stevel * of ddi_dma_map. 867 0 stevel */ 868 0 stevel bop = DEVI(dip)->devi_ops->devo_bus_ops; 869 0 stevel if (bop && bop->bus_dma_map) 870 0 stevel funcp = bop->bus_dma_map; 871 0 stevel 872 0 stevel return ((*funcp)(dip, dip, &dmareq, handlep)); 873 0 stevel } 874 0 stevel 875 0 stevel #if !defined(__sparc) 876 0 stevel /* 877 0 stevel * Request bus_dma_ctl parent to fiddle with a dma request. 878 0 stevel * 879 0 stevel * (The sparc version is in sparc_subr.s) 880 0 stevel */ 881 0 stevel int 882 0 stevel ddi_dma_mctl(dev_info_t *dip, dev_info_t *rdip, 883 0 stevel ddi_dma_handle_t handle, enum ddi_dma_ctlops request, 884 0 stevel off_t *offp, size_t *lenp, caddr_t *objp, uint_t flags) 885 0 stevel { 886 0 stevel int (*fp)(); 887 0 stevel 888 10216 Vikram if (dip != ddi_root_node()) 889 10216 Vikram dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_ctl; 890 0 stevel fp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_ctl; 891 0 stevel return ((*fp) (dip, rdip, handle, request, offp, lenp, objp, flags)); 892 0 stevel } 893 0 stevel #endif 894 0 stevel 895 0 stevel /* 896 0 stevel * For all DMA control functions, call the DMA control 897 0 stevel * routine and return status. 898 0 stevel * 899 0 stevel * Just plain assume that the parent is to be called. 900 0 stevel * If a nexus driver or a thread outside the framework 901 0 stevel * of a nexus driver or a leaf driver calls these functions, 902 0 stevel * it is up to them to deal with the fact that the parent's 903 0 stevel * bus_dma_ctl function will be the first one called. 904 0 stevel */ 905 0 stevel 906 0 stevel #define HD ((ddi_dma_impl_t *)h)->dmai_rdip 907 0 stevel 908 0 stevel int 909 0 stevel ddi_dma_kvaddrp(ddi_dma_handle_t h, off_t off, size_t len, caddr_t *kp) 910 0 stevel { 911 0 stevel return (ddi_dma_mctl(HD, HD, h, DDI_DMA_KVADDR, &off, &len, kp, 0)); 912 0 stevel } 913 0 stevel 914 0 stevel int 915 0 stevel ddi_dma_htoc(ddi_dma_handle_t h, off_t o, ddi_dma_cookie_t *c) 916 0 stevel { 917 0 stevel return (ddi_dma_mctl(HD, HD, h, DDI_DMA_HTOC, &o, 0, (caddr_t *)c, 0)); 918 0 stevel } 919 0 stevel 920 0 stevel int 921 0 stevel ddi_dma_coff(ddi_dma_handle_t h, ddi_dma_cookie_t *c, off_t *o) 922 0 stevel { 923 0 stevel return (ddi_dma_mctl(HD, HD, h, DDI_DMA_COFF, 924 0 stevel (off_t *)c, 0, (caddr_t *)o, 0)); 925 0 stevel } 926 0 stevel 927 0 stevel int 928 0 stevel ddi_dma_movwin(ddi_dma_handle_t h, off_t *o, size_t *l, ddi_dma_cookie_t *c) 929 0 stevel { 930 0 stevel return (ddi_dma_mctl(HD, HD, h, DDI_DMA_MOVWIN, o, 931 0 stevel l, (caddr_t *)c, 0)); 932 0 stevel } 933 0 stevel 934 0 stevel int 935 0 stevel ddi_dma_curwin(ddi_dma_handle_t h, off_t *o, size_t *l) 936 0 stevel { 937 0 stevel if ((((ddi_dma_impl_t *)h)->dmai_rflags & DDI_DMA_PARTIAL) == 0) 938 0 stevel return (DDI_FAILURE); 939 0 stevel return (ddi_dma_mctl(HD, HD, h, DDI_DMA_REPWIN, o, l, 0, 0)); 940 0 stevel } 941 0 stevel 942 0 stevel int 943 0 stevel ddi_dma_nextwin(ddi_dma_handle_t h, ddi_dma_win_t win, 944 0 stevel ddi_dma_win_t *nwin) 945 0 stevel { 946 0 stevel return (ddi_dma_mctl(HD, HD, h, DDI_DMA_NEXTWIN, (off_t *)&win, 0, 947 0 stevel (caddr_t *)nwin, 0)); 948 0 stevel } 949 0 stevel 950 0 stevel int 951 0 stevel ddi_dma_nextseg(ddi_dma_win_t win, ddi_dma_seg_t seg, ddi_dma_seg_t *nseg) 952 0 stevel { 953 0 stevel ddi_dma_handle_t h = (ddi_dma_handle_t)win; 954 0 stevel 955 0 stevel return (ddi_dma_mctl(HD, HD, h, DDI_DMA_NEXTSEG, (off_t *)&win, 956 0 stevel (size_t *)&seg, (caddr_t *)nseg, 0)); 957 0 stevel } 958 0 stevel 959 0 stevel #if (defined(__i386) && !defined(__amd64)) || defined(__sparc) 960 0 stevel /* 961 0 stevel * This routine is Obsolete and should be removed from ALL architectures 962 0 stevel * in a future release of Solaris. 963 0 stevel * 964 0 stevel * It is deliberately NOT ported to amd64; please fix the code that 965 0 stevel * depends on this routine to use ddi_dma_nextcookie(9F). 966 509 mrj * 967 509 mrj * NOTE: even though we fixed the pointer through a 32-bit param issue (the fix 968 509 mrj * is a side effect to some other cleanup), we're still not going to support 969 509 mrj * this interface on x64. 970 0 stevel */ 971 0 stevel int 972 0 stevel ddi_dma_segtocookie(ddi_dma_seg_t seg, off_t *o, off_t *l, 973 0 stevel ddi_dma_cookie_t *cookiep) 974 0 stevel { 975 0 stevel ddi_dma_handle_t h = (ddi_dma_handle_t)seg; 976 0 stevel 977 0 stevel return (ddi_dma_mctl(HD, HD, h, DDI_DMA_SEGTOC, o, (size_t *)l, 978 0 stevel (caddr_t *)cookiep, 0)); 979 0 stevel } 980 0 stevel #endif /* (__i386 && !__amd64) || __sparc */ 981 0 stevel 982 0 stevel #if !defined(__sparc) 983 0 stevel 984 0 stevel /* 985 0 stevel * The SPARC versions of these routines are done in assembler to 986 0 stevel * save register windows, so they're in sparc_subr.s. 987 0 stevel */ 988 0 stevel 989 0 stevel int 990 0 stevel ddi_dma_map(dev_info_t *dip, dev_info_t *rdip, 991 0 stevel struct ddi_dma_req *dmareqp, ddi_dma_handle_t *handlep) 992 0 stevel { 993 0 stevel int (*funcp)(dev_info_t *, dev_info_t *, struct ddi_dma_req *, 994 0 stevel ddi_dma_handle_t *); 995 0 stevel 996 10216 Vikram if (dip != ddi_root_node()) 997 10216 Vikram dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_map; 998 10216 Vikram 999 10216 Vikram funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_map; 1000 10216 Vikram return ((*funcp)(dip, rdip, dmareqp, handlep)); 1001 0 stevel } 1002 0 stevel 1003 0 stevel int 1004 0 stevel ddi_dma_allochdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_attr_t *attr, 1005 0 stevel int (*waitfp)(caddr_t), caddr_t arg, ddi_dma_handle_t *handlep) 1006 0 stevel { 1007 0 stevel int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_attr_t *, 1008 0 stevel int (*)(caddr_t), caddr_t, ddi_dma_handle_t *); 1009 0 stevel 1010 10216 Vikram if (dip != ddi_root_node()) 1011 10216 Vikram dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_allochdl; 1012 10216 Vikram 1013 10216 Vikram funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_allochdl; 1014 10216 Vikram return ((*funcp)(dip, rdip, attr, waitfp, arg, handlep)); 1015 0 stevel } 1016 0 stevel 1017 0 stevel int 1018 0 stevel ddi_dma_freehdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_handle_t handlep) 1019 0 stevel { 1020 0 stevel int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t); 1021 0 stevel 1022 10216 Vikram if (dip != ddi_root_node()) 1023 10216 Vikram dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_allochdl; 1024 10216 Vikram 1025 10216 Vikram funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_freehdl; 1026 10216 Vikram return ((*funcp)(dip, rdip, handlep)); 1027 0 stevel } 1028 0 stevel 1029 0 stevel int 1030 0 stevel ddi_dma_bindhdl(dev_info_t *dip, dev_info_t *rdip, 1031 0 stevel ddi_dma_handle_t handle, struct ddi_dma_req *dmareq, 1032 0 stevel ddi_dma_cookie_t *cp, uint_t *ccountp) 1033 0 stevel { 1034 0 stevel int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t, 1035 0 stevel struct ddi_dma_req *, ddi_dma_cookie_t *, uint_t *); 1036 0 stevel 1037 10216 Vikram if (dip != ddi_root_node()) 1038 10216 Vikram dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_bindhdl; 1039 10216 Vikram 1040 10216 Vikram funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_bindhdl; 1041 10216 Vikram return ((*funcp)(dip, rdip, handle, dmareq, cp, ccountp)); 1042 0 stevel } 1043 0 stevel 1044 0 stevel int 1045 0 stevel ddi_dma_unbindhdl(dev_info_t *dip, dev_info_t *rdip, 1046 0 stevel ddi_dma_handle_t handle) 1047 0 stevel { 1048 0 stevel int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t); 1049 0 stevel 1050 10216 Vikram if (dip != ddi_root_node()) 1051 10216 Vikram dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_unbindhdl; 1052 10216 Vikram 1053 10216 Vikram funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_unbindhdl; 1054 10216 Vikram return ((*funcp)(dip, rdip, handle)); 1055 0 stevel } 1056 0 stevel 1057 0 stevel 1058 0 stevel int 1059 0 stevel ddi_dma_flush(dev_info_t *dip, dev_info_t *rdip, 1060 0 stevel ddi_dma_handle_t handle, off_t off, size_t len, 1061 0 stevel uint_t cache_flags) 1062 0 stevel { 1063 0 stevel int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t, 1064 0 stevel off_t, size_t, uint_t); 1065 0 stevel 1066 10216 Vikram if (dip != ddi_root_node()) 1067 10216 Vikram dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_flush; 1068 10216 Vikram 1069 10216 Vikram funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_flush; 1070 10216 Vikram return ((*funcp)(dip, rdip, handle, off, len, cache_flags)); 1071 0 stevel } 1072 0 stevel 1073 0 stevel int 1074 0 stevel ddi_dma_win(dev_info_t *dip, dev_info_t *rdip, 1075 0 stevel ddi_dma_handle_t handle, uint_t win, off_t *offp, 1076 0 stevel size_t *lenp, ddi_dma_cookie_t *cookiep, uint_t *ccountp) 1077 0 stevel { 1078 0 stevel int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t, 1079 0 stevel uint_t, off_t *, size_t *, ddi_dma_cookie_t *, uint_t *); 1080 0 stevel 1081 10216 Vikram if (dip != ddi_root_node()) 1082 10216 Vikram dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_win; 1083 10216 Vikram 1084 10216 Vikram funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_win; 1085 10216 Vikram return ((*funcp)(dip, rdip, handle, win, offp, lenp, 1086 0 stevel cookiep, ccountp)); 1087 0 stevel } 1088 0 stevel 1089 0 stevel int 1090 0 stevel ddi_dma_sync(ddi_dma_handle_t h, off_t o, size_t l, uint_t whom) 1091 0 stevel { 1092 0 stevel ddi_dma_impl_t *hp = (ddi_dma_impl_t *)h; 1093 10216 Vikram dev_info_t *dip, *rdip; 1094 0 stevel int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t, off_t, 1095 4582 cth size_t, uint_t); 1096 0 stevel 1097 0 stevel /* 1098 0 stevel * the DMA nexus driver will set DMP_NOSYNC if the 1099 0 stevel * platform does not require any sync operation. For 1100 0 stevel * example if the memory is uncached or consistent 1101 0 stevel * and without any I/O write buffers involved. 1102 0 stevel */ 1103 0 stevel if ((hp->dmai_rflags & DMP_NOSYNC) == DMP_NOSYNC) 1104 0 stevel return (DDI_SUCCESS); 1105 0 stevel 1106 10216 Vikram dip = rdip = hp->dmai_rdip; 1107 10216 Vikram if (dip != ddi_root_node()) 1108 10216 Vikram dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_flush; 1109 10216 Vikram funcp = DEVI(dip)->devi_ops->devo_bus_ops->bus_dma_flush; 1110 10216 Vikram return ((*funcp)(dip, rdip, h, o, l, whom)); 1111 0 stevel } 1112 0 stevel 1113 0 stevel int 1114 0 stevel ddi_dma_unbind_handle(ddi_dma_handle_t h) 1115 0 stevel { 1116 0 stevel ddi_dma_impl_t *hp = (ddi_dma_impl_t *)h; 1117 10216 Vikram dev_info_t *dip, *rdip; 1118 0 stevel int (*funcp)(dev_info_t *, dev_info_t *, ddi_dma_handle_t); 1119 0 stevel 1120 10216 Vikram dip = rdip = hp->dmai_rdip; 1121 10216 Vikram if (dip != ddi_root_node()) 1122 10216 Vikram dip = (dev_info_t *)DEVI(dip)->devi_bus_dma_unbindhdl; 1123 10216 Vikram funcp = DEVI(rdip)->devi_bus_dma_unbindfunc; 1124 10216 Vikram return ((*funcp)(dip, rdip, h)); 1125 0 stevel } 1126 0 stevel 1127 0 stevel #endif /* !__sparc */ 1128 0 stevel 1129 0 stevel int 1130 0 stevel ddi_dma_free(ddi_dma_handle_t h) 1131 0 stevel { 1132 0 stevel return (ddi_dma_mctl(HD, HD, h, DDI_DMA_FREE, 0, 0, 0, 0)); 1133 0 stevel } 1134 0 stevel 1135 0 stevel int 1136 0 stevel ddi_iopb_alloc(dev_info_t *dip, ddi_dma_lim_t *limp, uint_t len, caddr_t *iopbp) 1137 0 stevel { 1138 0 stevel ddi_dma_lim_t defalt; 1139 0 stevel size_t size = len; 1140 0 stevel 1141 0 stevel if (!limp) { 1142 0 stevel defalt = standard_limits; 1143 0 stevel limp = &defalt; 1144 0 stevel } 1145 0 stevel return (i_ddi_mem_alloc_lim(dip, limp, size, 0, 0, 0, 1146 0 stevel iopbp, NULL, NULL)); 1147 0 stevel } 1148 0 stevel 1149 0 stevel void 1150 0 stevel ddi_iopb_free(caddr_t iopb) 1151 0 stevel { 1152 1900 eota i_ddi_mem_free(iopb, NULL); 1153 0 stevel } 1154 0 stevel 1155 0 stevel int 1156 0 stevel ddi_mem_alloc(dev_info_t *dip, ddi_dma_lim_t *limits, uint_t length, 1157 0 stevel uint_t flags, caddr_t *kaddrp, uint_t *real_length) 1158 0 stevel { 1159 0 stevel ddi_dma_lim_t defalt; 1160 0 stevel size_t size = length; 1161 0 stevel 1162 0 stevel if (!limits) { 1163 0 stevel defalt = standard_limits; 1164 0 stevel limits = &defalt; 1165 0 stevel } 1166 0 stevel return (i_ddi_mem_alloc_lim(dip, limits, size, flags & 0x1, 1167 0 stevel 1, 0, kaddrp, real_length, NULL)); 1168 0 stevel } 1169 0 stevel 1170 0 stevel void 1171 0 stevel ddi_mem_free(caddr_t kaddr) 1172 0 stevel { 1173 1900 eota i_ddi_mem_free(kaddr, NULL); 1174 0 stevel } 1175 0 stevel 1176 0 stevel /* 1177 0 stevel * DMA attributes, alignment, burst sizes, and transfer minimums 1178 0 stevel */ 1179 0 stevel int 1180 0 stevel ddi_dma_get_attr(ddi_dma_handle_t handle, ddi_dma_attr_t *attrp) 1181 0 stevel { 1182 0 stevel ddi_dma_impl_t *dimp = (ddi_dma_impl_t *)handle; 1183 0 stevel 1184 0 stevel if (attrp == NULL) 1185 0 stevel return (DDI_FAILURE); 1186 0 stevel *attrp = dimp->dmai_attr; 1187 0 stevel return (DDI_SUCCESS); 1188 0 stevel } 1189 0 stevel 1190 0 stevel int 1191 0 stevel ddi_dma_burstsizes(ddi_dma_handle_t handle) 1192 0 stevel { 1193 0 stevel ddi_dma_impl_t *dimp = (ddi_dma_impl_t *)handle; 1194 0 stevel 1195 0 stevel if (!dimp) 1196 0 stevel return (0); 1197 0 stevel else 1198 0 stevel return (dimp->dmai_burstsizes); 1199 0 stevel } 1200 0 stevel 1201 0 stevel int 1202 0 stevel ddi_dma_devalign(ddi_dma_handle_t handle, uint_t *alignment, uint_t *mineffect) 1203 0 stevel { 1204 0 stevel ddi_dma_impl_t *dimp = (ddi_dma_impl_t *)handle; 1205 0 stevel 1206 0 stevel if (!dimp || !alignment || !mineffect) 1207 0 stevel return (DDI_FAILURE); 1208 0 stevel if (!(dimp->dmai_rflags & DDI_DMA_SBUS_64BIT)) { 1209 0 stevel *alignment = 1 << ddi_ffs(dimp->dmai_burstsizes); 1210 0 stevel } else { 1211 0 stevel if (dimp->dmai_burstsizes & 0xff0000) { 1212 0 stevel *alignment = 1 << ddi_ffs(dimp->dmai_burstsizes >> 16); 1213 0 stevel } else { 1214 0 stevel *alignment = 1 << ddi_ffs(dimp->dmai_burstsizes); 1215 0 stevel } 1216 0 stevel } 1217 0 stevel *mineffect = dimp->dmai_minxfer; 1218 0 stevel return (DDI_SUCCESS); 1219 0 stevel } 1220 0 stevel 1221 0 stevel int 1222 0 stevel ddi_iomin(dev_info_t *a, int i, int stream) 1223 0 stevel { 1224 0 stevel int r; 1225 0 stevel 1226 0 stevel /* 1227 0 stevel * Make sure that the initial value is sane 1228 0 stevel */ 1229 0 stevel if (i & (i - 1)) 1230 0 stevel return (0); 1231 0 stevel if (i == 0) 1232 0 stevel i = (stream) ? 4 : 1; 1233 0 stevel 1234 0 stevel r = ddi_ctlops(a, a, 1235 0 stevel DDI_CTLOPS_IOMIN, (void *)(uintptr_t)stream, (void *)&i); 1236 0 stevel if (r != DDI_SUCCESS || (i & (i - 1))) 1237 0 stevel return (0); 1238 0 stevel return (i); 1239 0 stevel } 1240 0 stevel 1241 0 stevel /* 1242 0 stevel * Given two DMA attribute structures, apply the attributes 1243 0 stevel * of one to the other, following the rules of attributes 1244 0 stevel * and the wishes of the caller. 1245 0 stevel * 1246 0 stevel * The rules of DMA attribute structures are that you cannot 1247 0 stevel * make things *less* restrictive as you apply one set 1248 0 stevel * of attributes to another. 1249 0 stevel * 1250 0 stevel */ 1251 0 stevel void 1252 0 stevel ddi_dma_attr_merge(ddi_dma_attr_t *attr, ddi_dma_attr_t *mod) 1253 0 stevel { 1254 0 stevel attr->dma_attr_addr_lo = 1255 0 stevel MAX(attr->dma_attr_addr_lo, mod->dma_attr_addr_lo); 1256 0 stevel attr->dma_attr_addr_hi = 1257 0 stevel MIN(attr->dma_attr_addr_hi, mod->dma_attr_addr_hi); 1258 0 stevel attr->dma_attr_count_max = 1259 0 stevel MIN(attr->dma_attr_count_max, mod->dma_attr_count_max); 1260 0 stevel attr->dma_attr_align = 1261 0 stevel MAX(attr->dma_attr_align, mod->dma_attr_align); 1262 0 stevel attr->dma_attr_burstsizes = 1263 0 stevel (uint_t)(attr->dma_attr_burstsizes & mod->dma_attr_burstsizes); 1264 0 stevel attr->dma_attr_minxfer = 1265 0 stevel maxbit(attr->dma_attr_minxfer, mod->dma_attr_minxfer); 1266 0 stevel attr->dma_attr_maxxfer = 1267 0 stevel MIN(attr->dma_attr_maxxfer, mod->dma_attr_maxxfer); 1268 0 stevel attr->dma_attr_seg = MIN(attr->dma_attr_seg, mod->dma_attr_seg); 1269 0 stevel attr->dma_attr_sgllen = MIN((uint_t)attr->dma_attr_sgllen, 1270 0 stevel (uint_t)mod->dma_attr_sgllen); 1271 0 stevel attr->dma_attr_granular = 1272 0 stevel MAX(attr->dma_attr_granular, mod->dma_attr_granular); 1273 0 stevel } 1274 0 stevel 1275 0 stevel /* 1276 0 stevel * mmap/segmap interface: 1277 0 stevel */ 1278 0 stevel 1279 0 stevel /* 1280 0 stevel * ddi_segmap: setup the default segment driver. Calls the drivers 1281 0 stevel * XXmmap routine to validate the range to be mapped. 1282 0 stevel * Return ENXIO of the range is not valid. Create 1283 0 stevel * a seg_dev segment that contains all of the 1284 0 stevel * necessary information and will reference the 1285 0 stevel * default segment driver routines. It returns zero 1286 0 stevel * on success or non-zero on failure. 1287 0 stevel */ 1288 0 stevel int 1289 0 stevel ddi_segmap(dev_t dev, off_t offset, struct as *asp, caddr_t *addrp, off_t len, 1290 0 stevel uint_t prot, uint_t maxprot, uint_t flags, cred_t *credp) 1291 0 stevel { 1292 0 stevel extern int spec_segmap(dev_t, off_t, struct as *, caddr_t *, 1293 0 stevel off_t, uint_t, uint_t, uint_t, struct cred *); 1294 0 stevel 1295 0 stevel return (spec_segmap(dev, offset, asp, addrp, len, 1296 0 stevel prot, maxprot, flags, credp)); 1297 0 stevel } 1298 0 stevel 1299 0 stevel /* 1300 0 stevel * ddi_map_fault: Resolve mappings at fault time. Used by segment 1301 0 stevel * drivers. Allows each successive parent to resolve 1302 0 stevel * address translations and add its mappings to the 1303 0 stevel * mapping list supplied in the page structure. It 1304 0 stevel * returns zero on success or non-zero on failure. 1305 0 stevel */ 1306 0 stevel 1307 0 stevel int 1308 0 stevel ddi_map_fault(dev_info_t *dip, struct hat *hat, struct seg *seg, 1309 0 stevel caddr_t addr, struct devpage *dp, pfn_t pfn, uint_t prot, uint_t lock) 1310 0 stevel { 1311 0 stevel return (i_ddi_map_fault(dip, dip, hat, seg, addr, dp, pfn, prot, lock)); 1312 0 stevel } 1313 0 stevel 1314 0 stevel /* 1315 0 stevel * ddi_device_mapping_check: Called from ddi_segmap_setup. 1316 0 stevel * Invokes platform specific DDI to determine whether attributes specified 1317 0 stevel * in attr(9s) are valid for the region of memory that will be made 1318 0 stevel * available for direct access to user process via the mmap(2) system call. 1319 0 stevel */ 1320 0 stevel int 1321 0 stevel ddi_device_mapping_check(dev_t dev, ddi_device_acc_attr_t *accattrp, 1322 0 stevel uint_t rnumber, uint_t *hat_flags) 1323 0 stevel { 1324 0 stevel ddi_acc_handle_t handle; 1325 0 stevel ddi_map_req_t mr; 1326 0 stevel ddi_acc_hdl_t *hp; 1327 0 stevel int result; 1328 0 stevel dev_info_t *dip; 1329 0 stevel 1330 0 stevel /* 1331 0 stevel * we use e_ddi_hold_devi_by_dev to search for the devi. We 1332 0 stevel * release it immediately since it should already be held by 1333 0 stevel * a devfs vnode. 1334 0 stevel */ 1335 0 stevel if ((dip = 1336 0 stevel e_ddi_hold_devi_by_dev(dev, E_DDI_HOLD_DEVI_NOATTACH)) == NULL) 1337 0 stevel return (-1); 1338 0 stevel ddi_release_devi(dip); /* for e_ddi_hold_devi_by_dev() */ 1339 0 stevel 1340 0 stevel /* 1341 0 stevel * Allocate and initialize the common elements of data 1342 0 stevel * access handle. 1343 0 stevel */ 1344 0 stevel handle = impl_acc_hdl_alloc(KM_SLEEP, NULL); 1345 0 stevel if (handle == NULL) 1346 0 stevel return (-1); 1347 0 stevel 1348 0 stevel hp = impl_acc_hdl_get(handle); 1349 0 stevel hp->ah_vers = VERS_ACCHDL; 1350 0 stevel hp->ah_dip = dip; 1351 0 stevel hp->ah_rnumber = rnumber; 1352 0 stevel hp->ah_offset = 0; 1353 0 stevel hp->ah_len = 0; 1354 0 stevel hp->ah_acc = *accattrp; 1355 0 stevel 1356 0 stevel /* 1357 0 stevel * Set up the mapping request and call to parent. 1358 0 stevel */ 1359 0 stevel mr.map_op = DDI_MO_MAP_HANDLE; 1360 0 stevel mr.map_type = DDI_MT_RNUMBER; 1361 0 stevel mr.map_obj.rnumber = rnumber; 1362 0 stevel mr.map_prot = PROT_READ | PROT_WRITE; 1363 0 stevel mr.map_flags = DDI_MF_KERNEL_MAPPING; 1364 0 stevel mr.map_handlep = hp; 1365 0 stevel mr.map_vers = DDI_MAP_VERSION; 1366 0 stevel result = ddi_map(dip, &mr, 0, 0, NULL); 1367 0 stevel 1368 0 stevel /* 1369 0 stevel * Region must be mappable, pick up flags from the framework. 1370 0 stevel */ 1371 0 stevel *hat_flags = hp->ah_hat_flags; 1372 0 stevel 1373 0 stevel impl_acc_hdl_free(handle); 1374 0 stevel 1375 0 stevel /* 1376 0 stevel * check for end result. 1377 0 stevel */ 1378 0 stevel if (result != DDI_SUCCESS) 1379 0 stevel return (-1); 1380 0 stevel return (0); 1381 0 stevel } 1382 0 stevel 1383 0 stevel 1384 0 stevel /* 1385 0 stevel * Property functions: See also, ddipropdefs.h. 1386 0 stevel * 1387 0 stevel * These functions are the framework for the property functions, 1388 0 stevel * i.e. they support software defined properties. All implementation 1389 0 stevel * specific property handling (i.e.: self-identifying devices and 1390 0 stevel * PROM defined properties are handled in the implementation specific 1391 0 stevel * functions (defined in ddi_implfuncs.h). 1392 0 stevel */ 1393 0 stevel 1394 0 stevel /* 1395 0 stevel * nopropop: Shouldn't be called, right? 1396 0 stevel */ 1397 0 stevel int 1398 0 stevel nopropop(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int mod_flags, 1399 0 stevel char *name, caddr_t valuep, int *lengthp) 1400 0 stevel { 1401 0 stevel _NOTE(ARGUNUSED(dev, dip, prop_op, mod_flags, name, valuep, lengthp)) 1402 0 stevel return (DDI_PROP_NOT_FOUND); 1403 0 stevel } 1404 0 stevel 1405 0 stevel #ifdef DDI_PROP_DEBUG 1406 0 stevel int ddi_prop_debug_flag = 0; 1407 0 stevel 1408 0 stevel int 1409 0 stevel ddi_prop_debug(int enable) 1410 0 stevel { 1411 0 stevel int prev = ddi_prop_debug_flag; 1412 0 stevel 1413 0 stevel if ((enable != 0) || (prev != 0)) 1414 0 stevel printf("ddi_prop_debug: debugging %s\n", 1415 0 stevel enable ? "enabled" : "disabled"); 1416 0 stevel ddi_prop_debug_flag = enable; 1417 0 stevel return (prev); 1418 0 stevel } 1419 0 stevel 1420 0 stevel #endif /* DDI_PROP_DEBUG */ 1421 0 stevel 1422 0 stevel /* 1423 0 stevel * Search a property list for a match, if found return pointer 1424 0 stevel * to matching prop struct, else return NULL. 1425 0 stevel */ 1426 0 stevel 1427 0 stevel ddi_prop_t * 1428 0 stevel i_ddi_prop_search(dev_t dev, char *name, uint_t flags, ddi_prop_t **list_head) 1429 0 stevel { 1430 0 stevel ddi_prop_t *propp; 1431 0 stevel 1432 0 stevel /* 1433 0 stevel * find the property in child's devinfo: 1434 168 cth * Search order defined by this search function is first matching 1435 168 cth * property with input dev == DDI_DEV_T_ANY matching any dev or 1436 168 cth * dev == propp->prop_dev, name == propp->name, and the correct 1437 168 cth * data type as specified in the flags. If a DDI_DEV_T_NONE dev 1438 168 cth * value made it this far then it implies a DDI_DEV_T_ANY search. 1439 168 cth */ 1440 168 cth if (dev == DDI_DEV_T_NONE) 1441 168 cth dev = DDI_DEV_T_ANY; 1442 0 stevel 1443 0 stevel for (propp = *list_head; propp != NULL; propp = propp->prop_next) { 1444 0 stevel 1445 164 cth if (!DDI_STRSAME(propp->prop_name, name)) 1446 0 stevel continue; 1447 0 stevel 1448 0 stevel if ((dev != DDI_DEV_T_ANY) && (propp->prop_dev != dev)) 1449 0 stevel continue; 1450 0 stevel 1451 0 stevel if (((propp->prop_flags & flags) & DDI_PROP_TYPE_MASK) == 0) 1452 0 stevel continue; 1453 0 stevel 1454 0 stevel return (propp); 1455 0 stevel } 1456 0 stevel 1457 0 stevel return ((ddi_prop_t *)0); 1458 0 stevel } 1459 0 stevel 1460 0 stevel /* 1461 0 stevel * Search for property within devnames structures 1462 0 stevel */ 1463 0 stevel ddi_prop_t * 1464 0 stevel i_ddi_search_global_prop(dev_t dev, char *name, uint_t flags) 1465 0 stevel { 1466 0 stevel major_t major; 1467 0 stevel struct devnames *dnp; 1468 0 stevel ddi_prop_t *propp; 1469 0 stevel 1470 0 stevel /* 1471 0 stevel * Valid dev_t value is needed to index into the 1472 0 stevel * correct devnames entry, therefore a dev_t 1473 0 stevel * value of DDI_DEV_T_ANY is not appropriate. 1474 0 stevel */ 1475 0 stevel ASSERT(dev != DDI_DEV_T_ANY); 1476 0 stevel if (dev == DDI_DEV_T_ANY) { 1477 0 stevel return ((ddi_prop_t *)0); 1478 0 stevel } 1479 0 stevel 1480 0 stevel major = getmajor(dev); 1481 0 stevel dnp = &(devnamesp[major]); 1482 0 stevel 1483 0 stevel if (dnp->dn_global_prop_ptr == NULL) 1484 0 stevel return ((ddi_prop_t *)0); 1485 0 stevel 1486 0 stevel LOCK_DEV_OPS(&dnp->dn_lock); 1487 0 stevel 1488 0 stevel for (propp = dnp->dn_global_prop_ptr->prop_list; 1489 0 stevel propp != NULL; 1490 0 stevel propp = (ddi_prop_t *)propp->prop_next) { 1491 0 stevel 1492 164 cth if (!DDI_STRSAME(propp->prop_name, name)) 1493 0 stevel continue; 1494 0 stevel 1495 8371 Vikram if ((!(flags & DDI_PROP_ROOTNEX_GLOBAL)) && 1496 8371 Vikram (!(flags & LDI_DEV_T_ANY)) && (propp->prop_dev != dev)) 1497 0 stevel continue; 1498 0 stevel 1499 0 stevel if (((propp->prop_flags & flags) & DDI_PROP_TYPE_MASK) == 0) 1500 0 stevel continue; 1501 0 stevel 1502 0 stevel /* Property found, return it */ 1503 0 stevel UNLOCK_DEV_OPS(&dnp->dn_lock); 1504 0 stevel return (propp); 1505 0 stevel } 1506 0 stevel 1507 0 stevel UNLOCK_DEV_OPS(&dnp->dn_lock); 1508 0 stevel return ((ddi_prop_t *)0); 1509 0 stevel } 1510 0 stevel 1511 0 stevel static char prop_no_mem_msg[] = "can't allocate memory for ddi property <%s>"; 1512 0 stevel 1513 0 stevel /* 1514 0 stevel * ddi_prop_search_global: 1515 0 stevel * Search the global property list within devnames 1516 0 stevel * for the named property. Return the encoded value. 1517 0 stevel */ 1518 0 stevel static int 1519 0 stevel i_ddi_prop_search_global(dev_t dev, uint_t flags, char *name, 1520 0 stevel void *valuep, uint_t *lengthp) 1521 0 stevel { 1522 0 stevel ddi_prop_t *propp; 1523 0 stevel caddr_t buffer; 1524 0 stevel 1525 0 stevel propp = i_ddi_search_global_prop(dev, name, flags); 1526 0 stevel 1527 0 stevel /* Property NOT found, bail */ 1528 0 stevel if (propp == (ddi_prop_t *)0) 1529 0 stevel return (DDI_PROP_NOT_FOUND); 1530 0 stevel 1531 0 stevel if (propp->prop_flags & DDI_PROP_UNDEF_IT) 1532 0 stevel return (DDI_PROP_UNDEFINED); 1533 0 stevel 1534 497 cth if ((buffer = kmem_alloc(propp->prop_len, 1535 497 cth (flags & DDI_PROP_CANSLEEP) ? KM_SLEEP : KM_NOSLEEP)) == NULL) { 1536 0 stevel cmn_err(CE_CONT, prop_no_mem_msg, name); 1537 0 stevel return (DDI_PROP_NO_MEMORY); 1538 0 stevel } 1539 0 stevel 1540 0 stevel /* 1541 0 stevel * Return the encoded data 1542 0 stevel */ 1543 0 stevel *(caddr_t *)valuep = buffer; 1544 0 stevel *lengthp = propp->prop_len; 1545 0 stevel bcopy(propp->prop_val, buffer, propp->prop_len); 1546 0 stevel 1547 0 stevel return (DDI_PROP_SUCCESS); 1548 0 stevel } 1549 0 stevel 1550 0 stevel /* 1551 0 stevel * ddi_prop_search_common: Lookup and return the encoded value 1552 0 stevel */ 1553 0 stevel int 1554 0 stevel ddi_prop_search_common(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, 1555 0 stevel uint_t flags, char *name, void *valuep, uint_t *lengthp) 1556 0 stevel { 1557 0 stevel ddi_prop_t *propp; 1558 0 stevel int i; 1559 0 stevel caddr_t buffer; 1560 0 stevel caddr_t prealloc = NULL; 1561 0 stevel int plength = 0; 1562 0 stevel dev_info_t *pdip; 1563 0 stevel int (*bop)(); 1564 0 stevel 1565 0 stevel /*CONSTANTCONDITION*/ 1566 0 stevel while (1) { 1567 0 stevel 1568 0 stevel mutex_enter(&(DEVI(dip)->devi_lock)); 1569 0 stevel 1570 0 stevel 1571 0 stevel /* 1572 0 stevel * find the property in child's devinfo: 1573 0 stevel * Search order is: 1574 0 stevel * 1. driver defined properties 1575 0 stevel * 2. system defined properties 1576 0 stevel * 3. driver global properties 1577 0 stevel * 4. boot defined properties 1578 0 stevel */ 1579 0 stevel 1580 0 stevel propp = i_ddi_prop_search(dev, name, flags, 1581 0 stevel &(DEVI(dip)->devi_drv_prop_ptr)); 1582 0 stevel if (propp == NULL) { 1583 0 stevel propp = i_ddi_prop_search(dev, name, flags, 1584 0 stevel &(DEVI(dip)->devi_sys_prop_ptr)); 1585 0 stevel } 1586 0 stevel if ((propp == NULL) && DEVI(dip)->devi_global_prop_list) { 1587 0 stevel propp = i_ddi_prop_search(dev, name, flags, 1588 0 stevel &DEVI(dip)->devi_global_prop_list->prop_list); 1589 0 stevel } 1590 0 stevel 1591 0 stevel if (propp == NULL) { 1592 0 stevel propp = i_ddi_prop_search(dev, name, flags, 1593 0 stevel &(DEVI(dip)->devi_hw_prop_ptr)); 1594 0 stevel } 1595 0 stevel 1596 0 stevel /* 1597 0 stevel * Software property found? 1598 0 stevel */ 1599 0 stevel if (propp != (ddi_prop_t *)0) { 1600 0 stevel 1601 0 stevel /* 1602 0 stevel * If explicit undefine, return now. 1603 0 stevel */ 1604 0 stevel if (propp->prop_flags & DDI_PROP_UNDEF_IT) { 1605 0 stevel mutex_exit(&(DEVI(dip)->devi_lock)); 1606 0 stevel if (prealloc) 1607 0 stevel kmem_free(prealloc, plength); 1608 0 stevel return (DDI_PROP_UNDEFINED); 1609 0 stevel } 1610 0 stevel 1611 0 stevel /* 1612 0 stevel * If we only want to know if it exists, return now 1613 0 stevel */ 1614 0 stevel if (prop_op == PROP_EXISTS) { 1615 0 stevel mutex_exit(&(DEVI(dip)->devi_lock)); 1616 0 stevel ASSERT(prealloc == NULL); 1617 0 stevel return (DDI_PROP_SUCCESS); 1618 0 stevel } 1619 0 stevel 1620 0 stevel /* 1621 0 stevel * If length only request or prop length == 0, 1622 0 stevel * service request and return now. 1623 0 stevel */ 1624 0 stevel if ((prop_op == PROP_LEN) ||(propp->prop_len == 0)) { 1625 0 stevel *lengthp = propp->prop_len; 1626 0 stevel 1627 0 stevel /* 1628 0 stevel * if prop_op is PROP_LEN_AND_VAL_ALLOC 1629 0 stevel * that means prop_len is 0, so set valuep 1630 0 stevel * also to NULL 1631 0 stevel */ 1632 0 stevel if (prop_op == PROP_LEN_AND_VAL_ALLOC) 1633 0 stevel *(caddr_t *)valuep = NULL; 1634 0 stevel 1635 0 stevel mutex_exit(&(DEVI(dip)->devi_lock)); 1636 0 stevel if (prealloc) 1637 0 stevel kmem_free(prealloc, plength); 1638 0 stevel return (DDI_PROP_SUCCESS); 1639 0 stevel } 1640 0 stevel 1641 0 stevel /* 1642 0 stevel * If LEN_AND_VAL_ALLOC and the request can sleep, 1643 0 stevel * drop the mutex, allocate the buffer, and go 1644 0 stevel * through the loop again. If we already allocated 1645 0 stevel * the buffer, and the size of the property changed, 1646 0 stevel * keep trying... 1647 0 stevel */ 1648 0 stevel if ((prop_op == PROP_LEN_AND_VAL_ALLOC) && 1649 0 stevel (flags & DDI_PROP_CANSLEEP)) { 1650 0 stevel if (prealloc && (propp->prop_len != plength)) { 1651 0 stevel kmem_free(prealloc, plength); 1652 0 stevel prealloc = NULL; 1653 0 stevel } 1654 0 stevel if (prealloc == NULL) { 1655 0 stevel plength = propp->prop_len; 1656 0 stevel mutex_exit(&(DEVI(dip)->devi_lock)); 1657 0 stevel prealloc = kmem_alloc(plength, 1658 0 stevel KM_SLEEP); 1659 0 stevel continue; 1660 0 stevel } 1661 0 stevel } 1662 0 stevel 1663 0 stevel /* 1664 0 stevel * Allocate buffer, if required. Either way, 1665 0 stevel * set `buffer' variable. 1666 0 stevel */ 1667 0 stevel i = *lengthp; /* Get callers length */ 1668 0 stevel *lengthp = propp->prop_len; /* Set callers length */ 1669 0 stevel 1670 0 stevel switch (prop_op) { 1671 0 stevel 1672 0 stevel case PROP_LEN_AND_VAL_ALLOC: 1673 0 stevel 1674 0 stevel if (prealloc == NULL) { 1675 0 stevel buffer = kmem_alloc(propp->prop_len, 1676 0 stevel KM_NOSLEEP); 1677 0 stevel } else { 1678 0 stevel buffer = prealloc; 1679 0 stevel } 1680 0 stevel 1681 0 stevel if (buffer == NULL) { 1682 0 stevel mutex_exit(&(DEVI(dip)->devi_lock)); 1683 0 stevel cmn_err(CE_CONT, prop_no_mem_msg, name); 1684 0 stevel return (DDI_PROP_NO_MEMORY); 1685 0 stevel } 1686 0 stevel /* Set callers buf ptr */ 1687 0 stevel *(caddr_t *)valuep = buffer; 1688 0 stevel break; 1689 0 stevel 1690 0 stevel case PROP_LEN_AND_VAL_BUF: 1691 0 stevel 1692 0 stevel if (propp->prop_len > (i)) { 1693 0 stevel mutex_exit(&(DEVI(dip)->devi_lock)); 1694 0 stevel return (DDI_PROP_BUF_TOO_SMALL); 1695 0 stevel } 1696 0 stevel 1697 0 stevel buffer = valuep; /* Get callers buf ptr */ 1698 0 stevel break; 1699 0 stevel 1700 0 stevel default: 1701 0 stevel break; 1702 0 stevel } 1703 0 stevel 1704 0 stevel /* 1705 0 stevel * Do the copy. 1706 0 stevel */ 1707 0 stevel bcopy(propp->prop_val, buffer, propp->prop_len); 1708 0 stevel mutex_exit(&(DEVI(dip)->devi_lock)); 1709 0 stevel return (DDI_PROP_SUCCESS); 1710 0 stevel } 1711 0 stevel 1712 0 stevel mutex_exit(&(DEVI(dip)->devi_lock)); 1713 0 stevel if (prealloc) 1714 0 stevel kmem_free(prealloc, plength); 1715 0 stevel prealloc = NULL; 1716 0 stevel 1717 0 stevel /* 1718 0 stevel * Prop not found, call parent bus_ops to deal with possible 1719 0 stevel * h/w layer (possible PROM defined props, etc.) and to 1720 0 stevel * possibly ascend the hierarchy, if allowed by flags. 1721 0 stevel */ 1722 0 stevel pdip = (dev_info_t *)DEVI(dip)->devi_parent; 1723 0 stevel 1724 0 stevel /* 1725 0 stevel * One last call for the root driver PROM props? 1726 0 stevel */ 1727 0 stevel if (dip == ddi_root_node()) { 1728 0 stevel return (ddi_bus_prop_op(dev, dip, dip, prop_op, 1729 0 stevel flags, name, valuep, (int *)lengthp)); 1730 0 stevel } 1731 0 stevel 1732 0 stevel /* 1733 0 stevel * We may have been called to check for properties 1734 0 stevel * within a single devinfo node that has no parent - 1735 0 stevel * see make_prop() 1736 0 stevel */ 1737 0 stevel if (pdip == NULL) { 1738 0 stevel ASSERT((flags & 1739 0 stevel (DDI_PROP_DONTPASS | DDI_PROP_NOTPROM)) == 1740 0 stevel (DDI_PROP_DONTPASS | DDI_PROP_NOTPROM)); 1741 0 stevel return (DDI_PROP_NOT_FOUND); 1742 0 stevel } 1743 0 stevel 1744 0 stevel /* 1745 0 stevel * Instead of recursing, we do iterative calls up the tree. 1746 0 stevel * As a bit of optimization, skip the bus_op level if the 1747 0 stevel * node is a s/w node and if the parent's bus_prop_op function 1748 0 stevel * is `ddi_bus_prop_op', because we know that in this case, 1749 0 stevel * this function does nothing. 1750 0 stevel * 1751 0 stevel * 4225415: If the parent isn't attached, or the child 1752 0 stevel * hasn't been named by the parent yet, use the default 1753 0 stevel * ddi_bus_prop_op as a proxy for the parent. This 1754 0 stevel * allows property lookups in any child/parent state to 1755 0 stevel * include 'prom' and inherited properties, even when 1756 0 stevel * there are no drivers attached to the child or parent. 1757 0 stevel */ 1758 0 stevel 1759 0 stevel bop = ddi_bus_prop_op; 1760 1333 cth if (i_ddi_devi_attached(pdip) && 1761 0 stevel (i_ddi_node_state(dip) >= DS_INITIALIZED)) 1762 0 stevel bop = DEVI(pdip)->devi_ops->devo_bus_ops->bus_prop_op; 1763 0 stevel 1764 0 stevel i = DDI_PROP_NOT_FOUND; 1765 0 stevel 1766 0 stevel if ((bop != ddi_bus_prop_op) || ndi_dev_is_prom_node(dip)) { 1767 0 stevel i = (*bop)(dev, pdip, dip, prop_op, 1768 0 stevel flags | DDI_PROP_DONTPASS, 1769 0 stevel name, valuep, lengthp); 1770 0 stevel } 1771 0 stevel 1772 0 stevel if ((flags & DDI_PROP_DONTPASS) || 1773 0 stevel (i != DDI_PROP_NOT_FOUND)) 1774 0 stevel return (i); 1775 0 stevel 1776 0 stevel dip = pdip; 1777 0 stevel } 1778 0 stevel /*NOTREACHED*/ 1779 0 stevel } 1780 0 stevel 1781 0 stevel 1782 0 stevel /* 1783 0 stevel * ddi_prop_op: The basic property operator for drivers. 1784 0 stevel * 1785 0 stevel * In ddi_prop_op, the type of valuep is interpreted based on prop_op: 1786 0 stevel * 1787 0 stevel * prop_op valuep 1788 0 stevel * ------ ------ 1789 0 stevel * 1790 0 stevel * PROP_LEN <unused> 1791 0 stevel * 1792 0 stevel * PROP_LEN_AND_VAL_BUF Pointer to callers buffer 1793 0 stevel * 1794 0 stevel * PROP_LEN_AND_VAL_ALLOC Address of callers pointer (will be set to 1795 0 stevel * address of allocated buffer, if successful) 1796 0 stevel */ 1797 0 stevel int 1798 0 stevel ddi_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, int mod_flags, 1799 0 stevel char *name, caddr_t valuep, int *lengthp) 1800 0 stevel { 1801 0 stevel int i; 1802 0 stevel 1803 0 stevel ASSERT((mod_flags & DDI_PROP_TYPE_MASK) == 0); 1804 0 stevel 1805 0 stevel /* 1806 0 stevel * If this was originally an LDI prop lookup then we bail here. 1807 0 stevel * The reason is that the LDI property lookup interfaces first call 1808 0 stevel * a drivers prop_op() entry point to allow it to override 1809 0 stevel * properties. But if we've made it here, then the driver hasn't 1810 0 stevel * overriden any properties. We don't want to continue with the 1811 0 stevel * property search here because we don't have any type inforamtion. 1812 0 stevel * When we return failure, the LDI interfaces will then proceed to 1813 0 stevel * call the typed property interfaces to look up the property. 1814 0 stevel */ 1815 0 stevel if (mod_flags & DDI_PROP_DYNAMIC) 1816 0 stevel return (DDI_PROP_NOT_FOUND); 1817 0 stevel 1818 0 stevel /* 1819 0 stevel * check for pre-typed property consumer asking for typed property: 1820 0 stevel * see e_ddi_getprop_int64. 1821 0 stevel */ 1822 0 stevel if (mod_flags & DDI_PROP_CONSUMER_TYPED) 1823 0 stevel mod_flags |= DDI_PROP_TYPE_INT64; 1824 0 stevel mod_flags |= DDI_PROP_TYPE_ANY; 1825 0 stevel 1826 0 stevel i = ddi_prop_search_common(dev, dip, prop_op, 1827 4582 cth mod_flags, name, valuep, (uint_t *)lengthp); 1828 0 stevel if (i == DDI_PROP_FOUND_1275) 1829 0 stevel return (DDI_PROP_SUCCESS); 1830 0 stevel return (i); 1831 0 stevel } 1832 0 stevel 1833 0 stevel /* 1834 4582 cth * ddi_prop_op_nblocks_blksize: The basic property operator for drivers that 1835 4582 cth * maintain size in number of blksize blocks. Provides a dynamic property 1836 4582 cth * implementation for size oriented properties based on nblocks64 and blksize 1837 4582 cth * values passed in by the driver. Fallback to ddi_prop_op if the nblocks64 1838 4582 cth * is too large. This interface should not be used with a nblocks64 that 1839 4582 cth * represents the driver's idea of how to represent unknown, if nblocks is 1840 4582 cth * unknown use ddi_prop_op. 1841 4582 cth */ 1842 4582 cth int 1843 4582 cth ddi_prop_op_nblocks_blksize(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, 1844 4582 cth int mod_flags, char *name, caddr_t valuep, int *lengthp, 1845 4582 cth uint64_t nblocks64, uint_t blksize) 1846 4582 cth { 1847 4582 cth uint64_t size64; 1848 4582 cth int blkshift; 1849 4582 cth 1850 4582 cth /* convert block size to shift value */ 1851 4582 cth ASSERT(BIT_ONLYONESET(blksize)); 1852 4582 cth blkshift = highbit(blksize) - 1; 1853 4582 cth 1854 4582 cth /* 1855 4582 cth * There is no point in supporting nblocks64 values that don't have 1856 4582 cth * an accurate uint64_t byte count representation. 1857 4582 cth */ 1858 4582 cth if (nblocks64 >= (UINT64_MAX >> blkshift)) 1859 4582 cth return (ddi_prop_op(dev, dip, prop_op, mod_flags, 1860 4582 cth name, valuep, lengthp)); 1861 4582 cth 1862 4582 cth size64 = nblocks64 << blkshift; 1863 4582 cth return (ddi_prop_op_size_blksize(dev, dip, prop_op, mod_flags, 1864 4582 cth name, valuep, lengthp, size64, blksize)); 1865 4582 cth } 1866 4582 cth 1867 4582 cth /* 1868 4582 cth * ddi_prop_op_nblocks: ddi_prop_op_nblocks_blksize with DEV_BSIZE blksize. 1869 0 stevel */ 1870 0 stevel int 1871 0 stevel ddi_prop_op_nblocks(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, 1872 0 stevel int mod_flags, char *name, caddr_t valuep, int *lengthp, uint64_t nblocks64) 1873 0 stevel { 1874 4582 cth return (ddi_prop_op_nblocks_blksize(dev, dip, prop_op, 1875 4582 cth mod_flags, name, valuep, lengthp, nblocks64, DEV_BSIZE)); 1876 4582 cth } 1877 4582 cth 1878 4582 cth /* 1879 4582 cth * ddi_prop_op_size_blksize: The basic property operator for block drivers that 1880 4582 cth * maintain size in bytes. Provides a of dynamic property implementation for 1881 4582 cth * size oriented properties based on size64 value and blksize passed in by the 1882 4582 cth * driver. Fallback to ddi_prop_op if the size64 is too large. This interface 1883 4582 cth * should not be used with a size64 that represents the driver's idea of how 1884 4582 cth * to represent unknown, if size is unknown use ddi_prop_op. 1885 0 stevel * 1886 0 stevel * NOTE: the legacy "nblocks"/"size" properties are treated as 32-bit unsigned 1887 0 stevel * integers. While the most likely interface to request them ([bc]devi_size) 1888 0 stevel * is declared int (signed) there is no enforcement of this, which means we 1889 0 stevel * can't enforce limitations here without risking regression. 1890 0 stevel */ 1891 0 stevel int 1892 4582 cth ddi_prop_op_size_blksize(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, 1893 4582 cth int mod_flags, char *name, caddr_t valuep, int *lengthp, uint64_t size64, 1894 4582 cth uint_t blksize) 1895 0 stevel { 1896 0 stevel uint64_t nblocks64; 1897 0 stevel int callers_length; 1898 0 stevel caddr_t buffer; 1899 4582 cth int blkshift; 1900 4582 cth 1901 7224 cth /* 1902 7224 cth * This is a kludge to support capture of size(9P) pure dynamic 1903 7224 cth * properties in snapshots for non-cmlb code (without exposing 1904 7224 cth * i_ddi_prop_dyn changes). When everyone uses cmlb, this code 1905 7224 cth * should be removed. 1906 7224 cth */ 1907 7224 cth if (i_ddi_prop_dyn_driver_get(dip) == NULL) { 1908 7224 cth static i_ddi_prop_dyn_t prop_dyn_size[] = { 1909 7224 cth {"Size", DDI_PROP_TYPE_INT64, S_IFCHR}, 1910 7224 cth {"Nblocks", DDI_PROP_TYPE_INT64, S_IFBLK}, 1911 7224 cth {NULL} 1912 7224 cth }; 1913 7224 cth i_ddi_prop_dyn_driver_set(dip, prop_dyn_size); 1914 7224 cth } 1915 7224 cth 1916 4582 cth /* convert block size to shift value */ 1917 4582 cth ASSERT(BIT_ONLYONESET(blksize)); 1918 4582 cth blkshift = highbit(blksize) - 1; 1919 0 stevel 1920 0 stevel /* compute DEV_BSIZE nblocks value */ 1921 4582 cth nblocks64 = size64 >> blkshift; 1922 0 stevel 1923 0 stevel /* get callers length, establish length of our dynamic properties */ 1924 0 stevel callers_length = *lengthp; 1925 0 stevel 1926 0 stevel if (strcmp(name, "Nblocks") == 0) 1927 0 stevel *lengthp = sizeof (uint64_t); 1928 0 stevel else if (strcmp(name, "Size") == 0) 1929 0 stevel *lengthp = sizeof (uint64_t); 1930 0 stevel else if ((strcmp(name, "nblocks") == 0) && (nblocks64 < UINT_MAX)) 1931 0 stevel *lengthp = sizeof (uint32_t); 1932 0 stevel else if ((strcmp(name, "size") == 0) && (size64 < UINT_MAX)) 1933 4582 cth *lengthp = sizeof (uint32_t); 1934 4582 cth else if ((strcmp(name, "blksize") == 0) && (blksize < UINT_MAX)) 1935 0 stevel *lengthp = sizeof (uint32_t); 1936 0 stevel else { 1937 0 stevel /* fallback to ddi_prop_op */ 1938 0 stevel return (ddi_prop_op(dev, dip, prop_op, mod_flags, 1939 0 stevel name, valuep, lengthp)); 1940 0 stevel } 1941 0 stevel 1942 0 stevel /* service request for the length of the property */ 1943 0 stevel if (prop_op == PROP_LEN) 1944 0 stevel return (DDI_PROP_SUCCESS); 1945 0 stevel 1946 0 stevel switch (prop_op) { 1947 0 stevel case PROP_LEN_AND_VAL_ALLOC: 1948 0 stevel if ((buffer = kmem_alloc(*lengthp, 1949 0 stevel (mod_flags & DDI_PROP_CANSLEEP) ? 1950 0 stevel KM_SLEEP : KM_NOSLEEP)) == NULL) 1951 0 stevel return (DDI_PROP_NO_MEMORY); 1952 0 stevel 1953 0 stevel *(caddr_t *)valuep = buffer; /* set callers buf ptr */ 1954 0 stevel break; 1955 0 stevel 1956 0 stevel case PROP_LEN_AND_VAL_BUF: 1957 7224 cth /* the length of the property and the request must match */ 1958 7224 cth if (callers_length != *lengthp) 1959 7224 cth return (DDI_PROP_INVAL_ARG); 1960 7224 cth 1961 0 stevel buffer = valuep; /* get callers buf ptr */ 1962 0 stevel break; 1963 0 stevel 1964 0 stevel default: 1965 0 stevel return (DDI_PROP_INVAL_ARG); 1966 0 stevel } 1967 0 stevel 1968 0 stevel /* transfer the value into the buffer */ 1969 0 stevel if (strcmp(name, "Nblocks") == 0) 1970 0 stevel *((uint64_t *)buffer) = nblocks64; 1971 0 stevel else if (strcmp(name, "Size") == 0) 1972 0 stevel *((uint64_t *)buffer) = size64; 1973 0 stevel else if (strcmp(name, "nblocks") == 0) 1974 0 stevel *((uint32_t *)buffer) = (uint32_t)nblocks64; 1975 0 stevel else if (strcmp(name, "size") == 0) 1976 0 stevel *((uint32_t *)buffer) = (uint32_t)size64; 1977 4582 cth else if (strcmp(name, "blksize") == 0) 1978 4582 cth *((uint32_t *)buffer) = (uint32_t)blksize; 1979 4582 cth return (DDI_PROP_SUCCESS); 1980 4582 cth } 1981 4582 cth 1982 4582 cth /* 1983 4582 cth * ddi_prop_op_size: ddi_prop_op_size_blksize with DEV_BSIZE block size. 1984 4582 cth */ 1985 4582 cth int 1986 4582 cth ddi_prop_op_size(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op, 1987 4582 cth int mod_flags, char *name, caddr_t valuep, int *lengthp, uint64_t size64) 1988 4582 cth { 1989 4582 cth return (ddi_prop_op_size_blksize(dev, dip, prop_op, 1990 4582 cth mod_flags, name, valuep, lengthp, size64, DEV_BSIZE)); 1991 0 stevel } 1992 0 stevel 1993 0 stevel /* 1994 0 stevel * Variable length props... 1995 0 stevel */ 1996 0 stevel 1997 0 stevel /* 1998 0 stevel * ddi_getlongprop: Get variable length property len+val into a buffer 1999 0 stevel * allocated by property provider via kmem_alloc. Requester 2000 0 stevel * is responsible for freeing returned property via kmem_free. 2001 0 stevel * 2002 0 stevel * Arguments: 2003 0 stevel * 2004 0 stevel * dev_t: Input: dev_t of property. 2005 0 stevel * dip: Input: dev_info_t pointer of child. 2006 0 stevel * flags: Input: Possible flag modifiers are: 2007 0 stevel * DDI_PROP_DONTPASS: Don't pass to parent if prop not found. 2008 0 stevel * DDI_PROP_CANSLEEP: Memory allocation may sleep. 2009 0 stevel * name: Input: name of property. 2010 0 stevel * valuep: Output: Addr of callers buffer pointer. 2011 0 stevel * lengthp:Output: *lengthp will contain prop length on exit. 2012 0 stevel * 2013 0 stevel * Possible Returns: 2014 0 stevel * 2015 0 stevel * DDI_PROP_SUCCESS: Prop found and returned. 2016 0 stevel * DDI_PROP_NOT_FOUND: Prop not found 2017 0 stevel * DDI_PROP_UNDEFINED: Prop explicitly undefined. 2018 0 stevel * DDI_PROP_NO_MEMORY: Prop found, but unable to alloc mem. 2019 0 stevel */ 2020 0 stevel 2021 0 stevel int 2022 0 stevel ddi_getlongprop(dev_t dev, dev_info_t *dip, int flags, 2023 0 stevel char *name, caddr_t valuep, int *lengthp) 2024 0 stevel { 2025 0 stevel return (ddi_prop_op(dev, dip, PROP_LEN_AND_VAL_ALLOC, 2026 0 stevel flags, name, valuep, lengthp)); 2027 0 stevel } 2028 0 stevel 2029 0 stevel /* 2030 0 stevel * 2031 0 stevel * ddi_getlongprop_buf: Get long prop into pre-allocated callers 2032 0 stevel * buffer. (no memory allocation by provider). 2033 0 stevel * 2034 0 stevel * dev_t: Input: dev_t of property. 2035 0 stevel * dip: Input: dev_info_t pointer of child. 2036 0 stevel * flags: Input: DDI_PROP_DONTPASS or NULL 2037 0 stevel * name: Input: name of property 2038 0 stevel * valuep: Input: ptr to callers buffer. 2039 0 stevel * lengthp:I/O: ptr to length of callers buffer on entry, 2040 0 stevel * actual length of property on exit. 2041 0 stevel * 2042 0 stevel * Possible returns: 2043 0 stevel * 2044 0 stevel * DDI_PROP_SUCCESS Prop found and returned 2045 0 stevel * DDI_PROP_NOT_FOUND Prop not found 2046 0 stevel * DDI_PROP_UNDEFINED Prop explicitly undefined. 2047 0 stevel * DDI_PROP_BUF_TOO_SMALL Prop found, callers buf too small, 2048 0 stevel * no value returned, but actual prop 2049 0 stevel * length returned in *lengthp 2050 0 stevel * 2051 0 stevel */ 2052 0 stevel 2053 0 stevel int 2054 0 stevel ddi_getlongprop_buf(dev_t dev, dev_info_t *dip, int flags, 2055 0 stevel char *name, caddr_t valuep, int *lengthp) 2056 0 stevel { 2057 0 stevel return (ddi_prop_op(dev, dip, PROP_LEN_AND_VAL_BUF, 2058 0 stevel flags, name, valuep, lengthp)); 2059 0 stevel } 2060 0 stevel 2061 0 stevel /* 2062 0 stevel * Integer/boolean sized props. 2063 0 stevel * 2064 0 stevel * Call is value only... returns found boolean or int sized prop value or 2065 0 stevel * defvalue if prop not found or is wrong length or is explicitly undefined. 2066 0 stevel * Only flag is DDI_PROP_DONTPASS... 2067 0 stevel * 2068 0 stevel * By convention, this interface returns boolean (0) sized properties 2069 0 stevel * as value (int)1. 2070 0 stevel * 2071 0 stevel * This never returns an error, if property not found or specifically 2072 0 stevel * undefined, the input `defvalue' is returned. 2073 0 stevel */ 2074 0 stevel 2075 0 stevel int 2076 0 stevel ddi_getprop(dev_t dev, dev_info_t *dip, int flags, char *name, int defvalue) 2077 0 stevel { 2078 0 stevel int propvalue = defvalue; 2079 0 stevel int proplength = sizeof (int); 2080 0 stevel int error; 2081 0 stevel 2082 0 stevel error = ddi_prop_op(dev, dip, PROP_LEN_AND_VAL_BUF, 2083 0 stevel flags, name, (caddr_t)&propvalue, &proplength); 2084 0 stevel 2085 0 stevel if ((error == DDI_PROP_SUCCESS) && (proplength == 0)) 2086 0 stevel propvalue = 1; 2087 0 stevel 2088 0 stevel return (propvalue); 2089 0 stevel } 2090 0 stevel 2091 0 stevel /* 2092 0 stevel * Get prop length interface: flags are 0 or DDI_PROP_DONTPASS 2093 0 stevel * if returns DDI_PROP_SUCCESS, length returned in *lengthp. 2094 0 stevel */ 2095 0 stevel 2096 0 stevel int 2097 0 stevel ddi_getproplen(dev_t dev, dev_info_t *dip, int flags, char *name, int *lengthp) 2098 0 stevel { 2099 0 stevel return (ddi_prop_op(dev, dip, PROP_LEN, flags, name, NULL, lengthp)); 2100 0 stevel } 2101 0 stevel 2102 0 stevel /* 2103 0 stevel * Allocate a struct prop_driver_data, along with 'size' bytes 2104 0 stevel * for decoded property data. This structure is freed by 2105 0 stevel * calling ddi_prop_free(9F). 2106 0 stevel */ 2107 0 stevel static void * 2108 0 stevel ddi_prop_decode_alloc(size_t size, void (*prop_free)(struct prop_driver_data *)) 2109 0 stevel { 2110 0 stevel struct prop_driver_data *pdd; 2111 0 stevel 2112 0 stevel /* 2113 0 stevel * Allocate a structure with enough memory to store the decoded data. 2114 0 stevel */ 2115 0 stevel pdd = kmem_zalloc(sizeof (struct prop_driver_data) + size, KM_SLEEP); 2116 0 stevel pdd->pdd_size = (sizeof (struct prop_driver_data) + size); 2117 0 stevel pdd->pdd_prop_free = prop_free; 2118 0 stevel 2119 0 stevel /* 2120 0 stevel * Return a pointer to the location to put the decoded data. 2121 0 stevel */ 2122 0 stevel return ((void *)((caddr_t)pdd + sizeof (struct prop_driver_data))); 2123 0 stevel } 2124 0 stevel 2125 0 stevel /* 2126 0 stevel * Allocated the memory needed to store the encoded data in the property 2127 0 stevel * handle. 2128 0 stevel */ 2129 0 stevel static int 2130 0 stevel ddi_prop_encode_alloc(prop_handle_t *ph, size_t size) 2131 0 stevel { 2132 0 stevel /* 2133 0 stevel * If size is zero, then set data to NULL and size to 0. This 2134 0 stevel * is a boolean property. 2135 0 stevel */ 2136 0 stevel if (size == 0) { 2137 0 stevel ph->ph_size = 0; 2138 0 stevel ph->ph_data = NULL; 2139 0 stevel ph->ph_cur_pos = NULL; 2140 0 stevel ph->ph_save_pos = NULL; 2141 0 stevel } else { 2142 0 stevel if (ph->ph_flags == DDI_PROP_DONTSLEEP) { 2143 0 stevel ph->ph_data = kmem_zalloc(size, KM_NOSLEEP); 2144 0 stevel if (ph->ph_data == NULL) 2145 0 stevel return (DDI_PROP_NO_MEMORY); 2146 0 stevel } else 2147 0 stevel ph->ph_data = kmem_zalloc(size, KM_SLEEP); 2148 0 stevel ph->ph_size = size; 2149 0 stevel ph->ph_cur_pos = ph->ph_data; 2150 0 stevel ph->ph_save_pos = ph->ph_data; 2151 0 stevel } 2152 0 stevel return (DDI_PROP_SUCCESS); 2153 0 stevel } 2154 0 stevel 2155 0 stevel /* 2156 0 stevel * Free the space allocated by the lookup routines. Each lookup routine 2157 0 stevel * returns a pointer to the decoded data to the driver. The driver then 2158 0 stevel * passes this pointer back to us. This data actually lives in a struct 2159 0 stevel * prop_driver_data. We use negative indexing to find the beginning of 2160 0 stevel * the structure and then free the entire structure using the size and 2161 0 stevel * the free routine stored in the structure. 2162 0 stevel */ 2163 0 stevel void 2164 0 stevel ddi_prop_free(void *datap) 2165 0 stevel { 2166 0 stevel struct prop_driver_data *pdd; 2167 0 stevel 2168 0 stevel /* 2169 0 stevel * Get the structure 2170 0 stevel */ 2171 0 stevel pdd = (struct prop_driver_data *) 2172 4582 cth ((caddr_t)datap - sizeof (struct prop_driver_data)); 2173 0 stevel /* 2174 0 stevel * Call the free routine to free it 2175 0 stevel */ 2176 0 stevel (*pdd->pdd_prop_free)(pdd); 2177 0 stevel } 2178 0 stevel 2179 0 stevel /* 2180 0 stevel * Free the data associated with an array of ints, 2181 0 stevel * allocated with ddi_prop_decode_alloc(). 2182 0 stevel */ 2183 0 stevel static void 2184 0 stevel ddi_prop_free_ints(struct prop_driver_data *pdd) 2185 0 stevel { 2186 0 stevel kmem_free(pdd, pdd->pdd_size); 2187 0 stevel } 2188 0 stevel 2189 0 stevel /* 2190 0 stevel * Free a single string property or a single string contained within 2191 0 stevel * the argv style return value of an array of strings. 2192 0 stevel */ 2193 0 stevel static void 2194 0 stevel ddi_prop_free_string(struct prop_driver_data *pdd) 2195 0 stevel { 2196 0 stevel kmem_free(pdd, pdd->pdd_size); 2197 0 stevel 2198 0 stevel } 2199 0 stevel 2200 0 stevel /* 2201 0 stevel * Free an array of strings. 2202 0 stevel */ 2203 0 stevel static void 2204 0 stevel ddi_prop_free_strings(struct prop_driver_data *pdd) 2205 0 stevel { 2206 0 stevel kmem_free(pdd, pdd->pdd_size); 2207 0 stevel } 2208 0 stevel 2209 0 stevel /* 2210 0 stevel * Free the data associated with an array of bytes. 2211 0 stevel */ 2212 0 stevel static void 2213 0 stevel ddi_prop_free_bytes(struct prop_driver_data *pdd) 2214 0 stevel { 2215 0 stevel kmem_free(pdd, pdd->pdd_size); 2216 0 stevel } 2217 0 stevel 2218 0 stevel /* 2219 0 stevel * Reset the current location pointer in the property handle to the 2220 0 stevel * beginning of the data. 2221 0 stevel */ 2222 0 stevel void 2223 0 stevel ddi_prop_reset_pos(prop_handle_t *ph) 2224 0 stevel { 2225 0 stevel ph->ph_cur_pos = ph->ph_data; 2226 0 stevel ph->ph_save_pos = ph->ph_data; 2227 0 stevel } 2228 0 stevel 2229 0 stevel /* 2230 0 stevel * Restore the current location pointer in the property handle to the 2231 0 stevel * saved position. 2232 0 stevel */ 2233 0 stevel void 2234 0 stevel ddi_prop_save_pos(prop_handle_t *ph) 2235 0 stevel { 2236 0 stevel ph->ph_save_pos = ph->ph_cur_pos; 2237 0 stevel } 2238 0 stevel 2239 0 stevel /* 2240 0 stevel * Save the location that the current location pointer is pointing to.. 2241 0 stevel */ 2242 0 stevel void 2243 0 stevel ddi_prop_restore_pos(prop_handle_t *ph) 2244 0 stevel { 2245 0 stevel ph->ph_cur_pos = ph->ph_save_pos; 2246 0 stevel } 2247 0 stevel 2248 0 stevel /* 2249 0 stevel * Property encode/decode functions 2250 0 stevel */ 2251 0 stevel 2252 0 stevel /* 2253 0 stevel * Decode a single integer property 2254 0 stevel */ 2255 0 stevel static int 2256 0 stevel ddi_prop_fm_decode_int(prop_handle_t *ph, void *data, uint_t *nelements) 2257 0 stevel { 2258 0 stevel int i; 2259 0 stevel int tmp; 2260 0 stevel 2261 0 stevel /* 2262 0 stevel * If there is nothing to decode return an error 2263 0 stevel */ 2264 0 stevel if (ph->ph_size == 0) 2265 0 stevel return (DDI_PROP_END_OF_DATA); 2266 0 stevel 2267 0 stevel /* 2268 0 stevel * Decode the property as a single integer and return it 2269 0 stevel * in data if we were able to decode it. 2270 0 stevel */ 2271 0 stevel i = DDI_PROP_INT(ph, DDI_PROP_CMD_DECODE, &tmp); 2272 0 stevel if (i < DDI_PROP_RESULT_OK) { 2273 0 stevel switch (i) { 2274 0 stevel case DDI_PROP_RESULT_EOF: 2275 0 stevel return (DDI_PROP_END_OF_DATA); 2276 0 stevel 2277 0 stevel case DDI_PROP_RESULT_ERROR: 2278 0 stevel return (DDI_PROP_CANNOT_DECODE); 2279 0 stevel } 2280 0 stevel } 2281 0 stevel 2282 0 stevel *(int *)data = tmp; 2283 0 stevel *nelements = 1; 2284 0 stevel return (DDI_PROP_SUCCESS); 2285 0 stevel } 2286 0 stevel 2287 0 stevel /* 2288 0 stevel * Decode a single 64 bit integer property 2289 0 stevel */ 2290 0 stevel static int 2291 0 stevel ddi_prop_fm_decode_int64(prop_handle_t *ph, void *data, uint_t *nelements) 2292 0 stevel { 2293 0 stevel int i; 2294 0 stevel int64_t tmp; 2295 0 stevel 2296 0 stevel /* 2297 0 stevel * If there is nothing to decode return an error 2298 0 stevel */ 2299 0 stevel if (ph->ph_size == 0) 2300 0 stevel return (DDI_PROP_END_OF_DATA); 2301 0 stevel 2302 0 stevel /* 2303 0 stevel * Decode the property as a single integer and return it 2304 0 stevel * in data if we were able to decode it. 2305 0 stevel */ 2306 0 stevel i = DDI_PROP_INT64(ph, DDI_PROP_CMD_DECODE, &tmp); 2307 0 stevel if (i < DDI_PROP_RESULT_OK) { 2308 0 stevel switch (i) { 2309 0 stevel case DDI_PROP_RESULT_EOF: 2310 0 stevel return (DDI_PROP_END_OF_DATA); 2311 0 stevel 2312 0 stevel case DDI_PROP_RESULT_ERROR: 2313 0 stevel return (DDI_PROP_CANNOT_DECODE); 2314 0 stevel } 2315 0 stevel } 2316 0 stevel 2317 0 stevel *(int64_t *)data = tmp; 2318 0 stevel *nelements = 1; 2319 0 stevel return (DDI_PROP_SUCCESS); 2320 0 stevel } 2321 0 stevel 2322 0 stevel /* 2323 0 stevel * Decode an array of integers property 2324 0 stevel */ 2325 0 stevel static int 2326 0 stevel ddi_prop_fm_decode_ints(prop_handle_t *ph, void *data, uint_t *nelements) 2327 0 stevel { 2328 0 stevel int i; 2329 0 stevel int cnt = 0; 2330 0 stevel int *tmp; 2331 0 stevel int *intp; 2332 0 stevel int n; 2333 0 stevel 2334 0 stevel /* 2335 0 stevel * Figure out how many array elements there are by going through the 2336 0 stevel * data without decoding it first and counting. 2337 0 stevel */ 2338 0 stevel for (;;) { 2339 0 stevel i = DDI_PROP_INT(ph, DDI_PROP_CMD_SKIP, NULL); 2340 0 stevel if (i < 0) 2341 0 stevel break; 2342 0 stevel cnt++; 2343 0 stevel } 2344 0 stevel 2345 0 stevel /* 2346 0 stevel * If there are no elements return an error 2347 0 stevel */ 2348 0 stevel if (cnt == 0) 2349 0 stevel return (DDI_PROP_END_OF_DATA); 2350 0 stevel 2351 0 stevel /* 2352 0 stevel * If we cannot skip through the data, we cannot decode it 2353 0 stevel */ 2354 0 stevel if (i == DDI_PROP_RESULT_ERROR) 2355 0 stevel return (DDI_PROP_CANNOT_DECODE); 2356 0 stevel 2357 0 stevel /* 2358 0 stevel * Reset the data pointer to the beginning of the encoded data 2359 0 stevel */ 2360 0 stevel ddi_prop_reset_pos(ph); 2361 0 stevel 2362 0 stevel /* 2363 0 stevel * Allocated memory to store the decoded value in. 2364 0 stevel */ 2365 0 stevel intp = ddi_prop_decode_alloc((cnt * sizeof (int)), 2366 4582 cth ddi_prop_free_ints); 2367 0 stevel 2368 0 stevel /* 2369 0 stevel * Decode each element and place it in the space we just allocated 2370 0 stevel */ 2371 0 stevel tmp = intp; 2372 0 stevel for (n = 0; n < cnt; n++, tmp++) { 2373 0 stevel i = DDI_PROP_INT(ph, DDI_PROP_CMD_DECODE, tmp); 2374 0 stevel if (i < DDI_PROP_RESULT_OK) { 2375 0 stevel /* 2376 0 stevel * Free the space we just allocated 2377 0 stevel * and return an error. 2378 0 stevel */ 2379 0 stevel ddi_prop_free(intp); 2380 0 stevel switch (i) { 2381 0 stevel case DDI_PROP_RESULT_EOF: 2382 0 stevel return (DDI_PROP_END_OF_DATA); 2383 0 stevel 2384 0 stevel case DDI_PROP_RESULT_ERROR: 2385 0 stevel return (DDI_PROP_CANNOT_DECODE); 2386 0 stevel } 2387 0 stevel } 2388 0 stevel } 2389 0 stevel 2390 0 stevel *nelements = cnt; 2391 0 stevel *(int **)data = intp; 2392 0 stevel 2393 0 stevel return (DDI_PROP_SUCCESS); 2394 0 stevel } 2395 0 stevel 2396 0 stevel /* 2397 0 stevel * Decode a 64 bit integer array property 2398 0 stevel */ 2399 0 stevel static int 2400 0 stevel ddi_prop_fm_decode_int64_array(prop_handle_t *ph, void *data, uint_t *nelements) 2401 0 stevel { 2402 0 stevel int i; 2403 0 stevel int n; 2404 0 stevel int cnt = 0; 2405 0 stevel int64_t *tmp; 2406 0 stevel int64_t *intp; 2407 0 stevel 2408 0 stevel /* 2409 0 stevel * Count the number of array elements by going 2410 0 stevel * through the data without decoding it. 2411 0 stevel */ 2412 0 stevel for (;;) { 2413 0 stevel i = DDI_PROP_INT64(ph, DDI_PROP_CMD_SKIP, NULL); 2414 0 stevel if (i < 0) 2415 0 stevel break; 2416 0 stevel cnt++; 2417 0 stevel } 2418 0 stevel 2419 0 stevel /* 2420 0 stevel * If there are no elements return an error 2421 0 stevel */ 2422 0 stevel if (cnt == 0) 2423 0 stevel return (DDI_PROP_END_OF_DATA); 2424 0 stevel 2425 0 stevel /* 2426 0 stevel * If we cannot skip through the data, we cannot decode it 2427 0 stevel */ 2428 0 stevel if (i == DDI_PROP_RESULT_ERROR) 2429 0 stevel return (DDI_PROP_CANNOT_DECODE); 2430 0 stevel 2431 0 stevel /* 2432 0 stevel * Reset the data pointer to the beginning of the encoded data 2433 0 stevel */ 2434 0 stevel ddi_prop_reset_pos(ph); 2435 0 stevel 2436 0 stevel /* 2437 0 stevel * Allocate memory to store the decoded value. 2438 0 stevel */ 2439 0 stevel intp = ddi_prop_decode_alloc((cnt * sizeof (int64_t)), 2440 4582 cth ddi_prop_free_ints); 2441 0 stevel 2442 0 stevel /* 2443 0 stevel * Decode each element and place it in the space allocated 2444 0 stevel */ 2445 0 stevel tmp = intp; 2446 0 stevel for (n = 0; n < cnt; n++, tmp++) { 2447 0 stevel i = DDI_PROP_INT64(ph, DDI_PROP_CMD_DECODE, tmp); 2448 0 stevel if (i < DDI_PROP_RESULT_OK) { 2449 0 stevel /* 2450 0 stevel * Free the space we just allocated 2451 0 stevel * and return an error. 2452 0 stevel */ 2453 0 stevel ddi_prop_free(intp); 2454 0 stevel switch (i) { 2455 0 stevel case DDI_PROP_RESULT_EOF: 2456 0 stevel return (DDI_PROP_END_OF_DATA); 2457 0 stevel 2458 0 stevel case DDI_PROP_RESULT_ERROR: 2459 0 stevel return (DDI_PROP_CANNOT_DECODE); 2460 0 stevel } 2461 0 stevel } 2462 0 stevel } 2463 0 stevel 2464 0 stevel *nelements = cnt; 2465 0 stevel *(int64_t **)data = intp; 2466 0 stevel 2467 0 stevel return (DDI_PROP_SUCCESS); 2468 0 stevel } 2469 0 stevel 2470 0 stevel /* 2471 0 stevel * Encode an array of integers property (Can be one element) 2472 0 stevel */ 2473 0 stevel int 2474 0 stevel ddi_prop_fm_encode_ints(prop_handle_t *ph, void *data, uint_t nelements) 2475 0 stevel { 2476 0 stevel int i; 2477 0 stevel int *tmp; 2478 0 stevel int cnt; 2479 0 stevel int size; 2480 0 stevel 2481 0 stevel /* 2482 0 stevel * If there is no data, we cannot do anything 2483 0 stevel */ 2484 0 stevel if (nelements == 0) 2485 0 stevel return (DDI_PROP_CANNOT_ENCODE); 2486 0 stevel 2487 0 stevel /* 2488 0 stevel * Get the size of an encoded int. 2489 0 stevel */ 2490 0 stevel size = DDI_PROP_INT(ph, DDI_PROP_CMD_GET_ESIZE, NULL); 2491 0 stevel 2492 0 stevel if (size < DDI_PROP_RESULT_OK) { 2493 0 stevel switch (size) { 2494 0 stevel case DDI_PROP_RESULT_EOF: 2495 0 stevel return (DDI_PROP_END_OF_DATA); 2496 0 stevel 2497 0 stevel case DDI_PROP_RESULT_ERROR: 2498 0 stevel return (DDI_PROP_CANNOT_ENCODE); 2499 0 stevel } 2500 0 stevel } 2501 0 stevel 2502 0 stevel /* 2503 0 stevel * Allocate space in the handle to store the encoded int. 2504 0 stevel */ 2505 0 stevel if (ddi_prop_encode_alloc(ph, size * nelements) != 2506 4582 cth DDI_PROP_SUCCESS) 2507 0 stevel return (DDI_PROP_NO_MEMORY); 2508 0 stevel 2509 0 stevel /* 2510 0 stevel * Encode the array of ints. 2511 0 stevel */ 2512 0 stevel tmp = (int *)data; 2513 0 stevel for (cnt = 0; cnt < nelements; cnt++, tmp++) { 2514 0 stevel i = DDI_PROP_INT(ph, DDI_PROP_CMD_ENCODE, tmp); 2515 0 stevel if (i < DDI_PROP_RESULT_OK) { 2516 0 stevel switch (i) { 2517 0 stevel case DDI_PROP_RESULT_EOF: 2518 0 stevel return (DDI_PROP_END_OF_DATA); 2519 0 stevel 2520 0 stevel case DDI_PROP_RESULT_ERROR: 2521 0 stevel return (DDI_PROP_CANNOT_ENCODE); 2522 0 stevel } 2523 0 stevel } 2524 0 stevel } 2525 0 stevel 2526 0 stevel return (DDI_PROP_SUCCESS); 2527 0 stevel } 2528 0 stevel 2529 0 stevel 2530 0 stevel /* 2531 0 stevel * Encode a 64 bit integer array property 2532 0 stevel */ 2533 0 stevel int 2534 0 stevel ddi_prop_fm_encode_int64(prop_handle_t *ph, void *data, uint_t nelements) 2535 0 stevel { 2536 0 stevel int i; 2537 0 stevel int cnt; 2538 0 stevel int size; 2539 0 stevel int64_t *tmp; 2540 0 stevel 2541 0 stevel /* 2542 0 stevel * If there is no data, we cannot do anything 2543 0 stevel */ 2544 0 stevel if (nelements == 0) 2545 0 stevel return (DDI_PROP_CANNOT_ENCODE); 2546 0 stevel 2547 0 stevel /* 2548 0 stevel * Get the size of an encoded 64 bit int. 2549 0 stevel */ 2550 0 stevel size = DDI_PROP_INT64(ph, DDI_PROP_CMD_GET_ESIZE, NULL); 2551 0 stevel 2552 0 stevel if (size < DDI_PROP_RESULT_OK) { 2553 0 stevel switch (size) { 2554 0 stevel case DDI_PROP_RESULT_EOF: 2555 0 stevel return (DDI_PROP_END_OF_DATA); 2556 0 stevel 2557 0 stevel case DDI_PROP_RESULT_ERROR: 2558 0 stevel return (DDI_PROP_CANNOT_ENCODE); 2559 0 stevel } 2560 0 stevel } 2561 0 stevel 2562 0 stevel /* 2563 0 stevel * Allocate space in the handle to store the encoded int. 2564 0 stevel */ 2565 0 stevel if (ddi_prop_encode_alloc(ph, size * nelements) != 2566 0 stevel DDI_PROP_SUCCESS) 2567 0 stevel return (DDI_PROP_NO_MEMORY); 2568 0 stevel 2569 0 stevel /* 2570 0 stevel * Encode the array of ints. 2571 0 stevel */ 2572 0 stevel tmp = (int64_t *)data; 2573 0 stevel for (cnt = 0; cnt < nelements; cnt++, tmp++) { 2574 0 stevel i = DDI_PROP_INT64(ph, DDI_PROP_CMD_ENCODE, tmp); 2575 0 stevel if (i < DDI_PROP_RESULT_OK) { 2576 0 stevel switch (i) { 2577 0 stevel case DDI_PROP_RESULT_EOF: 2578 0 stevel return (DDI_PROP_END_OF_DATA); 2579 0 stevel 2580 0 stevel case DDI_PROP_RESULT_ERROR: 2581 0 stevel return (DDI_PROP_CANNOT_ENCODE); 2582 0 stevel } 2583 0 stevel } 2584 0 stevel } 2585 0 stevel 2586 0 stevel return (DDI_PROP_SUCCESS); 2587 0 stevel } 2588 0 stevel 2589 0 stevel /* 2590 0 stevel * Decode a single string property 2591 0 stevel */ 2592 0 stevel static int 2593 0 stevel ddi_prop_fm_decode_string(prop_handle_t *ph, void *data, uint_t *nelements) 2594 0 stevel { 2595 0 stevel char *tmp; 2596 0 stevel char *str; 2597 0 stevel int i; 2598 0 stevel int size; 2599 0 stevel 2600 0 stevel /* 2601 0 stevel * If there is nothing to decode return an error 2602 0 stevel */ 2603 0 stevel if (ph->ph_size == 0) 2604 0 stevel return (DDI_PROP_END_OF_DATA); 2605 0 stevel 2606 0 stevel /* 2607 0 stevel * Get the decoded size of the encoded string. 2608 0 stevel */ 2609 0 stevel size = DDI_PROP_STR(ph, DDI_PROP_CMD_GET_DSIZE, NULL); 2610 0 stevel if (size < DDI_PROP_RESULT_OK) { 2611 0 stevel switch (size) { 2612 0 stevel case DDI_PROP_RESULT_EOF: 2613 0 stevel return (DDI_PROP_END_OF_DATA); 2614 0 stevel 2615 0 stevel case DDI_PROP_RESULT_ERROR: 2616 0 stevel return (DDI_PROP_CANNOT_DECODE); 2617 0 stevel } 2618 0 stevel } 2619 0 stevel 2620 0 stevel /* 2621 0 stevel * Allocated memory to store the decoded value in. 2622 0 stevel */ 2623 0 stevel str = ddi_prop_decode_alloc((size_t)size, ddi_prop_free_string); 2624 0 stevel 2625 0 stevel ddi_prop_reset_pos(ph); 2626 0 stevel 2627 0 stevel /* 2628 0 stevel * Decode the str and place it in the space we just allocated 2629 0 stevel */ 2630 0 stevel tmp = str; 2631 0 stevel i = DDI_PROP_STR(ph, DDI_PROP_CMD_DECODE, tmp); 2632 0 stevel if (i < DDI_PROP_RESULT_OK) { 2633 0 stevel /* 2634 0 stevel * Free the space we just allocated 2635 0 stevel * and return an error. 2636 0 stevel */ 2637 0 stevel ddi_prop_free(str); 2638 0 stevel switch (i) { 2639 0 stevel case DDI_PROP_RESULT_EOF: 2640 0 stevel return (DDI_PROP_END_OF_DATA); 2641 0 stevel 2642 0 stevel case DDI_PROP_RESULT_ERROR: 2643 0 stevel return (DDI_PROP_CANNOT_DECODE); 2644 0 stevel } 2645 0 stevel } 2646 0 stevel 2647 0 stevel *(char **)data = str; 2648 0 stevel *nelements = 1; 2649 0 stevel 2650 0 stevel return (DDI_PROP_SUCCESS); 2651 0 stevel } 2652 0 stevel 2653 0 stevel /* 2654 0 stevel * Decode an array of strings. 2655 0 stevel */ 2656 0 stevel int 2657 0 stevel ddi_prop_fm_decode_strings(prop_handle_t *ph, void *data, uint_t *nelements) 2658 0 stevel { 2659 0 stevel int cnt = 0; 2660 0 stevel char **strs; 2661 0 stevel char **tmp; 2662 0 stevel char *ptr; 2663 0 stevel int i; 2664 0 stevel int n; 2665 0 stevel int size; 2666 0 stevel size_t nbytes; 2667 0 stevel 2668 0 stevel /* 2669 0 stevel * Figure out how many array elements there are by going through the 2670 0 stevel * data without decoding it first and counting. 2671 0 stevel */ 2672 0 stevel for (;;) { 2673 0 stevel i = DDI_PROP_STR(ph, DDI_PROP_CMD_SKIP, NULL); 2674 0 stevel if (i < 0) 2675 0 stevel break; 2676 0 stevel cnt++; 2677 0 stevel } 2678 0 stevel 2679 0 stevel /* 2680 0 stevel * If there are no elements return an error 2681 0 stevel */ 2682 0 stevel if (cnt == 0) 2683 0 stevel return (DDI_PROP_END_OF_DATA); 2684 0 stevel 2685 0 stevel /* 2686 0 stevel * If we cannot skip through the data, we cannot decode it 2687 0 stevel */ 2688 0 stevel if (i == DDI_PROP_RESULT_ERROR) 2689 0 stevel return (DDI_PROP_CANNOT_DECODE); 2690 0 stevel 2691 0 stevel /* 2692 0 stevel * Reset the data pointer to the beginning of the encoded data 2693 0 stevel */ 2694 0 stevel ddi_prop_reset_pos(ph); 2695 0 stevel 2696 0 stevel /* 2697 0 stevel * Figure out how much memory we need for the sum total 2698 0 stevel */ 2699 0 stevel nbytes = (cnt + 1) * sizeof (char *); 2700 0 stevel 2701 0 stevel for (n = 0; n < cnt; n++) { 2702 0 stevel /* 2703 0 stevel * Get the decoded size of the current encoded string. 2704 0 stevel */ 2705 0 stevel size = DDI_PROP_STR(ph, DDI_PROP_CMD_GET_DSIZE, NULL); 2706 0 stevel if (size < DDI_PROP_RESULT_OK) { 2707 0 stevel switch (size) { 2708 0 stevel case DDI_PROP_RESULT_EOF: 2709 0 stevel return (DDI_PROP_END_OF_DATA); 2710 0 stevel 2711 0 stevel case DDI_PROP_RESULT_ERROR: 2712 0 stevel return (DDI_PROP_CANNOT_DECODE); 2713 0 stevel } 2714 0 stevel } 2715 0 stevel 2716 0 stevel nbytes += size; 2717 0 stevel } 2718 0 stevel 2719 0 stevel /* 2720 0 stevel * Allocate memory in which to store the decoded strings. 2721 0 stevel */ 2722 0 stevel strs = ddi_prop_decode_alloc(nbytes, ddi_prop_free_strings); 2723 0 stevel 2724 0 stevel /* 2725 0 stevel * Set up pointers for each string by figuring out yet 2726 0 stevel * again how long each string is. 2727 0 stevel */ 2728 0 stevel ddi_prop_reset_pos(ph); 2729 0 stevel ptr = (caddr_t)strs + ((cnt + 1) * sizeof (char *)); 2730 0 stevel for (tmp = strs, n = 0; n < cnt; n++, tmp++) { 2731 0 stevel /* 2732 0 stevel * Get the decoded size of the current encoded string. 2733 0 stevel */ 2734 0 stevel size = DDI_PROP_STR(ph, DDI_PROP_CMD_GET_DSIZE, NULL); 2735 0 stevel if (size < DDI_PROP_RESULT_OK) { 2736 0 stevel ddi_prop_free(strs); 2737 0 stevel switch (size) { 2738 0 stevel case DDI_PROP_RESULT_EOF: 2739 0 stevel return (DDI_PROP_END_OF_DATA); 2740 0 stevel 2741 0 stevel case DDI_PROP_RESULT_ERROR: 2742 0 stevel return (DDI_PROP_CANNOT_DECODE); 2743 0 stevel } 2744 0 stevel } 2745 0 stevel 2746 0 stevel *tmp = ptr; 2747 0 stevel ptr += size; 2748 0 stevel } 2749 0 stevel 2750 0 stevel /* 2751 0 stevel * String array is terminated by a NULL 2752 0 stevel */ 2753 0 stevel *tmp = NULL; 2754 0 stevel 2755 0 stevel /* 2756 0 stevel * Finally, we can decode each string 2757 0 stevel */ 2758 0 stevel ddi_prop_reset_pos(ph); 2759 0 stevel for (tmp = strs, n = 0; n < cnt; n++, tmp++) { 2760 0 stevel i = DDI_PROP_STR(ph, DDI_PROP_CMD_DECODE, *tmp); 2761 0 stevel if (i < DDI_PROP_RESULT_OK) { 2762 0 stevel /* 2763 0 stevel * Free the space we just allocated 2764 0 stevel * and return an error 2765 0 stevel */ 2766 0 stevel ddi_prop_free(strs); 2767 0 stevel switch (i) { 2768 0 stevel case DDI_PROP_RESULT_EOF: 2769 0 stevel return (DDI_PROP_END_OF_DATA); 2770 0 stevel 2771 0 stevel case DDI_PROP_RESULT_ERROR: 2772 0 stevel return (DDI_PROP_CANNOT_DECODE); 2773 0 stevel } 2774 0 stevel } 2775 0 stevel } 2776 0 stevel 2777 0 stevel *(char ***)data = strs; 2778 0 stevel *nelements = cnt; 2779 0 stevel 2780 0 stevel return (DDI_PROP_SUCCESS); 2781 0 stevel } 2782 0 stevel 2783 0 stevel /* 2784 0 stevel * Encode a string. 2785 0 stevel */ 2786 0 stevel int 2787 0 stevel ddi_prop_fm_encode_string(prop_handle_t *ph, void *data, uint_t nelements) 2788 0 stevel { 2789 0 stevel char **tmp; 2790 0 stevel int size; 2791 0 stevel int i; 2792 0 stevel 2793 0 stevel /* 2794 0 stevel * If there is no data, we cannot do anything 2795 0 stevel */ 2796 0 stevel if (nelements == 0) 2797 0 stevel return (DDI_PROP_CANNOT_ENCODE); 2798 0 stevel 2799 0 stevel /* 2800 0 stevel * Get the size of the encoded string. 2801 0 stevel */ 2802 0 stevel tmp = (char **)data; 2803 0 stevel size = DDI_PROP_STR(ph, DDI_PROP_CMD_GET_ESIZE, *tmp); 2804 0 stevel if (size < DDI_PROP_RESULT_OK) { 2805 0 stevel switch (size) { 2806 0 stevel case DDI_PROP_RESULT_EOF: 2807 0 stevel return (DDI_PROP_END_OF_DATA); 2808 0 stevel 2809 0 stevel case DDI_PROP_RESULT_ERROR: 2810 0 stevel return (DDI_PROP_CANNOT_ENCODE); 2811 0 stevel } 2812 0 stevel } 2813 0 stevel 2814 0 stevel /* 2815 0 stevel * Allocate space in the handle to store the encoded string. 2816 0 stevel */ 2817 0 stevel if (ddi_prop_encode_alloc(ph, size) != DDI_PROP_SUCCESS) 2818 0 stevel return (DDI_PROP_NO_MEMORY); 2819 0 stevel 2820 0 stevel ddi_prop_reset_pos(ph); 2821 0 stevel 2822 0 stevel /* 2823 0 stevel * Encode the string. 2824 0 stevel */ 2825 0 stevel tmp = (char **)data; 2826 0 stevel i = DDI_PROP_STR(ph, DDI_PROP_CMD_ENCODE, *tmp); 2827 0 stevel if (i < DDI_PROP_RESULT_OK) { 2828 0 stevel switch (i) { 2829 0 stevel case DDI_PROP_RESULT_EOF: 2830 0 stevel return (DDI_PROP_END_OF_DATA); 2831 0 stevel 2832 0 stevel case DDI_PROP_RESULT_ERROR: 2833 0 stevel return (DDI_PROP_CANNOT_ENCODE); 2834 0 stevel } 2835 0 stevel } 2836 0 stevel 2837 0 stevel return (DDI_PROP_SUCCESS); 2838 0 stevel } 2839 0 stevel 2840 0 stevel 2841 0 stevel /* 2842 0 stevel * Encode an array of strings. 2843 0 stevel */ 2844 0 stevel int 2845 0 stevel ddi_prop_fm_encode_strings(prop_handle_t *ph, void *data, uint_t nelements) 2846 0 stevel { 2847 0 stevel int cnt = 0; 2848 0 stevel char **tmp; 2849 0 stevel int size; 2850 0 stevel uint_t total_size; 2851 0 stevel int i; 2852 0 stevel 2853 0 stevel /* 2854 0 stevel * If there is no data, we cannot do anything 2855 0 stevel */ 2856 0 stevel if (nelements == 0) 2857 0 stevel return (DDI_PROP_CANNOT_ENCODE); 2858 0 stevel 2859 0 stevel /* 2860 0 stevel * Get the total size required to encode all the strings. 2861 0 stevel */ 2862 0 stevel total_size = 0; 2863 0 stevel tmp = (char **)data; 2864 0 stevel for (cnt = 0; cnt < nelements; cnt++, tmp++) { 2865 0 stevel size = DDI_PROP_STR(ph, DDI_PROP_CMD_GET_ESIZE, *tmp); 2866 0 stevel if (size < DDI_PROP_RESULT_OK) { 2867 0 stevel switch (size) { 2868 0 stevel case DDI_PROP_RESULT_EOF: 2869 0 stevel return (DDI_PROP_END_OF_DATA); 2870 0 stevel 2871 0 stevel case DDI_PROP_RESULT_ERROR: 2872 0 stevel return (DDI_PROP_CANNOT_ENCODE); 2873 0 stevel } 2874 0 stevel } 2875 0 stevel total_size += (uint_t)size; 2876 0 stevel } 2877 0 stevel 2878 0 stevel /* 2879 0 stevel * Allocate space in the handle to store the encoded strings. 2880 0 stevel */ 2881 0 stevel if (ddi_prop_encode_alloc(ph, total_size) != DDI_PROP_SUCCESS) 2882 0 stevel return (DDI_PROP_NO_MEMORY); 2883 0 stevel 2884 0 stevel ddi_prop_reset_pos(ph); 2885 0 stevel 2886 0 stevel /* 2887 0 stevel * Encode the array of strings. 2888 0 stevel */ 2889 0 stevel tmp = (char **)data; 2890 0 stevel for (cnt = 0; cnt < nelements; cnt++, tmp++) { 2891 0 stevel i = DDI_PROP_STR(ph, DDI_PROP_CMD_ENCODE, *tmp); 2892 0 stevel if (i < DDI_PROP_RESULT_OK) { 2893 0 stevel switch (i) { 2894 0 stevel case DDI_PROP_RESULT_EOF: 2895 0 stevel return (DDI_PROP_END_OF_DATA); 2896 0 stevel 2897 0 stevel case DDI_PROP_RESULT_ERROR: 2898 0 stevel return (DDI_PROP_CANNOT_ENCODE); 2899 0 stevel } 2900 0 stevel } 2901 0 stevel } 2902 0 stevel 2903 0 stevel return (DDI_PROP_SUCCESS); 2904 0 stevel } 2905 0 stevel 2906 0 stevel 2907 0 stevel /* 2908 0 stevel * Decode an array of bytes. 2909 0 stevel */ 2910 0 stevel static int 2911 0 stevel ddi_prop_fm_decode_bytes(prop_handle_t *ph, void *data, uint_t *nelements) 2912 0 stevel { 2913 0 stevel uchar_t *tmp; 2914 0 stevel int nbytes; 2915 0 stevel int i; 2916 0 stevel 2917 0 stevel /* 2918 0 stevel * If there are no elements return an error 2919 0 stevel */ 2920 0 stevel if (ph->ph_size == 0) 2921 0 stevel return (DDI_PROP_END_OF_DATA); 2922 0 stevel 2923 0 stevel /* 2924 0 stevel * Get the size of the encoded array of bytes. 2925 0 stevel */ 2926 0 stevel nbytes = DDI_PROP_BYTES(ph, DDI_PROP_CMD_GET_DSIZE, 2927 4582 cth data, ph->ph_size); 2928 0 stevel if (nbytes < DDI_PROP_RESULT_OK) { 2929 0 stevel switch (nbytes) { 2930 0 stevel case DDI_PROP_RESULT_EOF: 2931 0 stevel return (DDI_PROP_END_OF_DATA); 2932 0 stevel 2933 0 stevel case DDI_PROP_RESULT_ERROR: 2934 0 stevel return (DDI_PROP_CANNOT_DECODE); 2935 0 stevel } 2936 0 stevel } 2937 0 stevel 2938 0 stevel /* 2939 0 stevel * Allocated memory to store the decoded value in. 2940 0 stevel */ 2941 0 stevel tmp = ddi_prop_decode_alloc(nbytes, ddi_prop_free_bytes); 2942 0 stevel 2943 0 stevel /* 2944 0 stevel * Decode each element and place it in the space we just allocated 2945 0 stevel */ 2946 0 stevel i = DDI_PROP_BYTES(ph, DDI_PROP_CMD_DECODE, tmp, nbytes); 2947 0 stevel if (i < DDI_PROP_RESULT_OK) { 2948 0 stevel /* 2949 0 stevel * Free the space we just allocated 2950 0 stevel * and return an error 2951 0 stevel */ 2952 0 stevel ddi_prop_free(tmp); 2953 0 stevel switch (i) { 2954 0 stevel case DDI_PROP_RESULT_EOF: 2955 0 stevel return (DDI_PROP_END_OF_DATA); 2956 0 stevel 2957 0 stevel case DDI_PROP_RESULT_ERROR: 2958 0 stevel return (DDI_PROP_CANNOT_DECODE); 2959 0 stevel } 2960 0 stevel } 2961 0 stevel 2962 0 stevel *(uchar_t **)data = tmp; 2963 0 stevel *nelements = nbytes; 2964 0 stevel 2965 0 stevel return (DDI_PROP_SUCCESS); 2966 0 stevel } 2967 0 stevel 2968 0 stevel /* 2969 0 stevel * Encode an array of bytes. 2970 0 stevel */ 2971 0 stevel int 2972 0 stevel ddi_prop_fm_encode_bytes(prop_handle_t *ph, void *data, uint_t nelements) 2973 0 stevel { 2974 0 stevel int size; 2975 0 stevel int i; 2976 0 stevel 2977 0 stevel /* 2978 0 stevel * If there are no elements, then this is a boolean property, 2979 0 stevel * so just create a property handle with no data and return. 2980 0 stevel */ 2981 0 stevel if (nelements == 0) { 2982 0 stevel (void) ddi_prop_encode_alloc(ph, 0); 2983 0 stevel return (DDI_PROP_SUCCESS); 2984 0 stevel } 2985 0 stevel 2986 0 stevel /* 2987 0 stevel * Get the size of the encoded array of bytes. 2988 0 stevel */ 2989 0 stevel size = DDI_PROP_BYTES(ph, DDI_PROP_CMD_GET_ESIZE, (uchar_t *)data, 2990 4582 cth nelements); 2991 0 stevel if (size < DDI_PROP_RESULT_OK) { 2992 0 stevel switch (size) { 2993 0 stevel case DDI_PROP_RESULT_EOF: 2994 0 stevel return (DDI_PROP_END_OF_DATA); 2995 0 stevel 2996 0 stevel case DDI_PROP_RESULT_ERROR: 2997 0 stevel return (DDI_PROP_CANNOT_DECODE); 2998 0 stevel } 2999 0 stevel } 3000 0 stevel 3001 0 stevel /* 3002 0 stevel * Allocate space in the handle to store the encoded bytes. 3003 0 stevel */ 3004 0 stevel if (ddi_prop_encode_alloc(ph, (uint_t)size) != DDI_PROP_SUCCESS) 3005 0 stevel return (DDI_PROP_NO_MEMORY); 3006 0 stevel 3007 0 stevel /* 3008 0 stevel * Encode the array of bytes. 3009 0 stevel */ 3010 0 stevel i = DDI_PROP_BYTES(ph, DDI_PROP_CMD_ENCODE, (uchar_t *)data, 3011 4582 cth nelements); 3012 0 stevel if (i < DDI_PROP_RESULT_OK) { 3013 0 stevel switch (i) { 3014 0 stevel case DDI_PROP_RESULT_EOF: 3015 0 stevel return (DDI_PROP_END_OF_DATA); 3016 0 stevel 3017 0 stevel case DDI_PROP_RESULT_ERROR: 3018 0 stevel return (DDI_PROP_CANNOT_ENCODE); 3019 0 stevel } 3020 0 stevel } 3021 0 stevel 3022 0 stevel return (DDI_PROP_SUCCESS); 3023 0 stevel } 3024 0 stevel 3025 0 stevel /* 3026 0 stevel * OBP 1275 integer, string and byte operators. 3027 0 stevel * 3028 0 stevel * DDI_PROP_CMD_DECODE: 3029 0 stevel * 3030 0 stevel * DDI_PROP_RESULT_ERROR: cannot decode the data 3031 0 stevel * DDI_PROP_RESULT_EOF: end of data 3032 0 stevel * DDI_PROP_OK: data was decoded 3033 0 stevel * 3034 0 stevel * DDI_PROP_CMD_ENCODE: 3035 0 stevel * 3036 0 stevel * DDI_PROP_RESULT_ERROR: cannot encode the data 3037 0 stevel * DDI_PROP_RESULT_EOF: end of data 3038 0 stevel * DDI_PROP_OK: data was encoded 3039 0 stevel * 3040 0 stevel * DDI_PROP_CMD_SKIP: 3041 0 stevel * 3042 0 stevel * DDI_PROP_RESULT_ERROR: cannot skip the data 3043 0 stevel * DDI_PROP_RESULT_EOF: end of data 3044 0 stevel * DDI_PROP_OK: data was skipped 3045 0 stevel * 3046 0 stevel * DDI_PROP_CMD_GET_ESIZE: 3047 0 stevel * 3048 0 stevel * DDI_PROP_RESULT_ERROR: cannot get encoded size 3049 0 stevel * DDI_PROP_RESULT_EOF: end of data 3050 0 stevel * > 0: the encoded size 3051 0 stevel * 3052 0 stevel * DDI_PROP_CMD_GET_DSIZE: 3053 0 stevel * 3054 0 stevel * DDI_PROP_RESULT_ERROR: cannot get decoded size 3055 0 stevel * DDI_PROP_RESULT_EOF: end of data 3056 0 stevel * > 0: the decoded size 3057 0 stevel */ 3058 0 stevel 3059 0 stevel /* 3060 0 stevel * OBP 1275 integer operator 3061 0 stevel * 3062 0 stevel * OBP properties are a byte stream of data, so integers may not be 3063 0 stevel * properly aligned. Therefore we need to copy them one byte at a time. 3064 0 stevel */ 3065 0 stevel int 3066 0 stevel ddi_prop_1275_int(prop_handle_t *ph, uint_t cmd, int *data) 3067 0 stevel { 3068 0 stevel int i; 3069 0 stevel 3070 0 stevel switch (cmd) { 3071 0 stevel case DDI_PROP_CMD_DECODE: 3072 0 stevel /* 3073 0 stevel * Check that there is encoded data 3074 0 stevel */ 3075 0 stevel if (ph->ph_cur_pos == NULL || ph->ph_size == 0) 3076 0 stevel return (DDI_PROP_RESULT_ERROR); 3077 0 stevel if (ph->ph_flags & PH_FROM_PROM) { 3078 0 stevel i = MIN(ph->ph_size, PROP_1275_INT_SIZE); 3079 0 stevel if ((int *)ph->ph_cur_pos > ((int *)ph->ph_data + 3080 4582 cth ph->ph_size - i)) 3081 0 stevel return (DDI_PROP_RESULT_ERROR); 3082 0 stevel } else { 3083 0 stevel if (ph->ph_size < sizeof (int) || 3084 4582 cth ((int *)ph->ph_cur_pos > ((int *)ph->ph_data + 3085 4582 cth ph->ph_size - sizeof (int)))) 3086 4582 cth return (DDI_PROP_RESULT_ERROR); 3087 0 stevel } 3088 0 stevel 3089 0 stevel /* 3090 0 stevel * Copy the integer, using the implementation-specific 3091 0 stevel * copy function if the property is coming from the PROM. 3092 0 stevel */ 3093 0 stevel if (ph->ph_flags & PH_FROM_PROM) { 3094 0 stevel *data = impl_ddi_prop_int_from_prom( 3095 4582 cth (uchar_t *)ph->ph_cur_pos, 3096 4582 cth (ph->ph_size < PROP_1275_INT_SIZE) ? 3097 4582 cth ph->ph_size : PROP_1275_INT_SIZE); 3098 0 stevel } else { 3099 0 stevel bcopy(ph->ph_cur_pos, data, sizeof (int)); 3100 0 stevel } 3101 0 stevel 3102 0 stevel /* 3103 0 stevel * Move the current location to the start of the next 3104 0 stevel * bit of undecoded data. 3105 0 stevel */ 3106 0 stevel ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos + 3107 4582 cth PROP_1275_INT_SIZE; 3108 0 stevel return (DDI_PROP_RESULT_OK); 3109 0 stevel 3110 0 stevel case DDI_PROP_CMD_ENCODE: 3111 0 stevel /* 3112 0 stevel * Check that there is room to encoded the data 3113 0 stevel */ 3114 0 stevel if (ph->ph_cur_pos == NULL || ph->ph_size == 0 || 3115 4582 cth ph->ph_size < PROP_1275_INT_SIZE || 3116 4582 cth ((int *)ph->ph_cur_pos > ((int *)ph->ph_data + 3117 4582 cth ph->ph_size - sizeof (int)))) 3118 0 stevel return (DDI_PROP_RESULT_ERROR); 3119 0 stevel 3120 0 stevel /* 3121 0 stevel * Encode the integer into the byte stream one byte at a 3122 0 stevel * time. 3123 0 stevel */ 3124 0 stevel bcopy(data, ph->ph_cur_pos, sizeof (int)); 3125 0 stevel 3126 0 stevel /* 3127 0 stevel * Move the current location to the start of the next bit of 3128 0 stevel * space where we can store encoded data. 3129 0 stevel */ 3130 0 stevel ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos + PROP_1275_INT_SIZE; 3131 0 stevel return (DDI_PROP_RESULT_OK); 3132 0 stevel 3133 0 stevel case DDI_PROP_CMD_SKIP: 3134 0 stevel /* 3135 0 stevel * Check that there is encoded data 3136 0 stevel */ 3137 0 stevel if (ph->ph_cur_pos == NULL || ph->ph_size == 0 || 3138 4582 cth ph->ph_size < PROP_1275_INT_SIZE) 3139 4582 cth return (DDI_PROP_RESULT_ERROR); 3140 4582 cth 3141 0 stevel 3142 0 stevel if ((caddr_t)ph->ph_cur_pos == 3143 0 stevel (caddr_t)ph->ph_data + ph->ph_size) { 3144 0 stevel return (DDI_PROP_RESULT_EOF); 3145 0 stevel } else if ((caddr_t)ph->ph_cur_pos > 3146 0 stevel (caddr_t)ph->ph_data + ph->ph_size) { 3147 0 stevel return (DDI_PROP_RESULT_EOF); 3148 0 stevel } 3149 0 stevel 3150 0 stevel /* 3151 4582 cth * Move the current location to the start of the next bit of 3152 4582 cth * undecoded data. 3153 4582 cth */ 3154 4582 cth ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos + PROP_1275_INT_SIZE; 3155 4582 cth return (DDI_PROP_RESULT_OK); 3156 4582 cth 3157 4582 cth case DDI_PROP_CMD_GET_ESIZE: 3158 4582 cth /* 3159 4582 cth * Return the size of an encoded integer on OBP 3160 4582 cth */ 3161 4582 cth return (PROP_1275_INT_SIZE); 3162 4582 cth 3163 4582 cth case DDI_PROP_CMD_GET_DSIZE: 3164 4582 cth /* 3165 4582 cth * Return the size of a decoded integer on the system. 3166 4582 cth */ 3167 4582 cth return (sizeof (int)); 3168 4582 cth 3169 4582 cth default: 3170 4582 cth #ifdef DEBUG 3171 4582 cth panic("ddi_prop_1275_int: %x impossible", cmd); 3172 4582 cth /*NOTREACHED*/ 3173 4582 cth #else 3174 4582 cth return (DDI_PROP_RESULT_ERROR); 3175 4582 cth #endif /* DEBUG */ 3176 4582 cth } 3177 4582 cth } 3178 4582 cth 3179 4582 cth /* 3180 4582 cth * 64 bit integer operator. 3181 4582 cth * 3182 4582 cth * This is an extension, defined by Sun, to the 1275 integer 3183 4582 cth * operator. This routine handles the encoding/decoding of 3184 4582 cth * 64 bit integer properties. 3185 4582 cth */ 3186 4582 cth int 3187 4582 cth ddi_prop_int64_op(prop_handle_t *ph, uint_t cmd, int64_t *data) 3188 4582 cth { 3189 4582 cth 3190 4582 cth switch (cmd) { 3191 4582 cth case DDI_PROP_CMD_DECODE: 3192 4582 cth /* 3193 4582 cth * Check that there is encoded data 3194 4582 cth */ 3195 4582 cth if (ph->ph_cur_pos == NULL || ph->ph_size == 0) 3196 4582 cth return (DDI_PROP_RESULT_ERROR); 3197 4582 cth if (ph->ph_flags & PH_FROM_PROM) { 3198 4582 cth return (DDI_PROP_RESULT_ERROR); 3199 4582 cth } else { 3200 4582 cth if (ph->ph_size < sizeof (int64_t) || 3201 4582 cth ((int64_t *)ph->ph_cur_pos > 3202 4582 cth ((int64_t *)ph->ph_data + 3203 4582 cth ph->ph_size - sizeof (