1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * PC specific DDI implementation 31 */ 32 #include <sys/types.h> 33 #include <sys/autoconf.h> 34 #include <sys/avintr.h> 35 #include <sys/bootconf.h> 36 #include <sys/conf.h> 37 #include <sys/cpuvar.h> 38 #include <sys/ddi_impldefs.h> 39 #include <sys/ddi_subrdefs.h> 40 #include <sys/ethernet.h> 41 #include <sys/fp.h> 42 #include <sys/instance.h> 43 #include <sys/kmem.h> 44 #include <sys/machsystm.h> 45 #include <sys/modctl.h> 46 #include <sys/promif.h> 47 #include <sys/prom_plat.h> 48 #include <sys/sunndi.h> 49 #include <sys/ndi_impldefs.h> 50 #include <sys/ddi_impldefs.h> 51 #include <sys/sysmacros.h> 52 #include <sys/systeminfo.h> 53 #include <sys/utsname.h> 54 #include <sys/atomic.h> 55 #include <sys/spl.h> 56 #include <sys/archsystm.h> 57 #include <vm/seg_kmem.h> 58 #include <sys/ontrap.h> 59 #include <sys/fm/protocol.h> 60 #include <sys/ramdisk.h> 61 #include <sys/sunndi.h> 62 #include <sys/vmem.h> 63 #include <sys/pci_impl.h> 64 #if defined(__xpv) 65 #include <sys/hypervisor.h> 66 #endif 67 #include <sys/mach_intr.h> 68 #include <vm/hat_i86.h> 69 #include <sys/x86_archext.h> 70 71 /* 72 * DDI Boot Configuration 73 */ 74 75 /* 76 * Platform drivers on this platform 77 */ 78 char *platform_module_list[] = { 79 "acpippm", 80 "ppm", 81 (char *)0 82 }; 83 84 /* pci bus resource maps */ 85 struct pci_bus_resource *pci_bus_res; 86 87 size_t dma_max_copybuf_size = 0x101000; /* 1M + 4K */ 88 89 uint64_t ramdisk_start, ramdisk_end; 90 91 /* 92 * Forward declarations 93 */ 94 static int getlongprop_buf(); 95 static void get_boot_properties(void); 96 static void impl_bus_initialprobe(void); 97 static void impl_bus_reprobe(void); 98 99 static int poke_mem(peekpoke_ctlops_t *in_args); 100 static int peek_mem(peekpoke_ctlops_t *in_args); 101 102 static int kmem_override_cache_attrs(caddr_t, size_t, uint_t); 103 104 #define CTGENTRIES 15 105 106 static struct ctgas { 107 struct ctgas *ctg_next; 108 int ctg_index; 109 void *ctg_addr[CTGENTRIES]; 110 size_t ctg_size[CTGENTRIES]; 111 } ctglist; 112 113 static kmutex_t ctgmutex; 114 #define CTGLOCK() mutex_enter(&ctgmutex) 115 #define CTGUNLOCK() mutex_exit(&ctgmutex) 116 117 /* 118 * Minimum pfn value of page_t's put on the free list. This is to simplify 119 * support of ddi dma memory requests which specify small, non-zero addr_lo 120 * values. 121 * 122 * The default value of 2, which corresponds to the only known non-zero addr_lo 123 * value used, means a single page will be sacrificed (pfn typically starts 124 * at 1). ddiphysmin can be set to 0 to disable. It cannot be set above 0x100 125 * otherwise mp startup panics. 126 */ 127 pfn_t ddiphysmin = 2; 128 129 static void 130 check_driver_disable(void) 131 { 132 int proplen = 128; 133 char *prop_name; 134 char *drv_name, *propval; 135 major_t major; 136 137 prop_name = kmem_alloc(proplen, KM_SLEEP); 138 for (major = 0; major < devcnt; major++) { 139 drv_name = ddi_major_to_name(major); 140 if (drv_name == NULL) 141 continue; 142 (void) snprintf(prop_name, proplen, "disable-%s", drv_name); 143 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_root_node(), 144 DDI_PROP_DONTPASS, prop_name, &propval) == DDI_SUCCESS) { 145 if (strcmp(propval, "true") == 0) { 146 devnamesp[major].dn_flags |= DN_DRIVER_REMOVED; 147 cmn_err(CE_NOTE, "driver %s disabled", 148 drv_name); 149 } 150 ddi_prop_free(propval); 151 } 152 } 153 kmem_free(prop_name, proplen); 154 } 155 156 157 /* 158 * Configure the hardware on the system. 159 * Called before the rootfs is mounted 160 */ 161 void 162 configure(void) 163 { 164 extern void i_ddi_init_root(); 165 166 #if defined(__i386) 167 extern int fpu_pentium_fdivbug; 168 #endif /* __i386 */ 169 extern int fpu_ignored; 170 171 /* 172 * Determine if an FPU is attached 173 */ 174 175 fpu_probe(); 176 177 #if defined(__i386) 178 if (fpu_pentium_fdivbug) { 179 printf("\ 180 FP hardware exhibits Pentium floating point divide problem\n"); 181 } 182 #endif /* __i386 */ 183 184 if (fpu_ignored) { 185 printf("FP hardware will not be used\n"); 186 } else if (!fpu_exists) { 187 printf("No FPU in configuration\n"); 188 } 189 190 /* 191 * Initialize devices on the machine. 192 * Uses configuration tree built by the PROMs to determine what 193 * is present, and builds a tree of prototype dev_info nodes 194 * corresponding to the hardware which identified itself. 195 */ 196 #if !defined(SAS) && !defined(MPSAS) 197 /* 198 * Check for disabled drivers and initialize root node. 199 */ 200 check_driver_disable(); 201 i_ddi_init_root(); 202 203 /* 204 * attach the isa nexus to get ACPI resource usage 205 * isa is "kind of" a pseudo node 206 */ 207 #if defined(__xpv) 208 if (DOMAIN_IS_INITDOMAIN(xen_info)) 209 (void) i_ddi_attach_pseudo_node("isa"); 210 #else 211 (void) i_ddi_attach_pseudo_node("isa"); 212 #endif 213 214 /* reprogram devices not set up by firmware (BIOS) */ 215 impl_bus_reprobe(); 216 #endif /* !SAS && !MPSAS */ 217 } 218 219 /* 220 * The "status" property indicates the operational status of a device. 221 * If this property is present, the value is a string indicating the 222 * status of the device as follows: 223 * 224 * "okay" operational. 225 * "disabled" not operational, but might become operational. 226 * "fail" not operational because a fault has been detected, 227 * and it is unlikely that the device will become 228 * operational without repair. no additional details 229 * are available. 230 * "fail-xxx" not operational because a fault has been detected, 231 * and it is unlikely that the device will become 232 * operational without repair. "xxx" is additional 233 * human-readable information about the particular 234 * fault condition that was detected. 235 * 236 * The absence of this property means that the operational status is 237 * unknown or okay. 238 * 239 * This routine checks the status property of the specified device node 240 * and returns 0 if the operational status indicates failure, and 1 otherwise. 241 * 242 * The property may exist on plug-in cards the existed before IEEE 1275-1994. 243 * And, in that case, the property may not even be a string. So we carefully 244 * check for the value "fail", in the beginning of the string, noting 245 * the property length. 246 */ 247 int 248 status_okay(int id, char *buf, int buflen) 249 { 250 char status_buf[OBP_MAXPROPNAME]; 251 char *bufp = buf; 252 int len = buflen; 253 int proplen; 254 static const char *status = "status"; 255 static const char *fail = "fail"; 256 int fail_len = (int)strlen(fail); 257 258 /* 259 * Get the proplen ... if it's smaller than "fail", 260 * or doesn't exist ... then we don't care, since 261 * the value can't begin with the char string "fail". 262 * 263 * NB: proplen, if it's a string, includes the NULL in the 264 * the size of the property, and fail_len does not. 265 */ 266 proplen = prom_getproplen((pnode_t)id, (caddr_t)status); 267 if (proplen <= fail_len) /* nonexistant or uninteresting len */ 268 return (1); 269 270 /* 271 * if a buffer was provided, use it 272 */ 273 if ((buf == (char *)NULL) || (buflen <= 0)) { 274 bufp = status_buf; 275 len = sizeof (status_buf); 276 } 277 *bufp = (char)0; 278 279 /* 280 * Get the property into the buffer, to the extent of the buffer, 281 * and in case the buffer is smaller than the property size, 282 * NULL terminate the buffer. (This handles the case where 283 * a buffer was passed in and the caller wants to print the 284 * value, but the buffer was too small). 285 */ 286 (void) prom_bounded_getprop((pnode_t)id, (caddr_t)status, 287 (caddr_t)bufp, len); 288 *(bufp + len - 1) = (char)0; 289 290 /* 291 * If the value begins with the char string "fail", 292 * then it means the node is failed. We don't care 293 * about any other values. We assume the node is ok 294 * although it might be 'disabled'. 295 */ 296 if (strncmp(bufp, fail, fail_len) == 0) 297 return (0); 298 299 return (1); 300 } 301 302 /* 303 * Check the status of the device node passed as an argument. 304 * 305 * if ((status is OKAY) || (status is DISABLED)) 306 * return DDI_SUCCESS 307 * else 308 * print a warning and return DDI_FAILURE 309 */ 310 /*ARGSUSED1*/ 311 int 312 check_status(int id, char *name, dev_info_t *parent) 313 { 314 char status_buf[64]; 315 char devtype_buf[OBP_MAXPROPNAME]; 316 int retval = DDI_FAILURE; 317 318 /* 319 * is the status okay? 320 */ 321 if (status_okay(id, status_buf, sizeof (status_buf))) 322 return (DDI_SUCCESS); 323 324 /* 325 * a status property indicating bad memory will be associated 326 * with a node which has a "device_type" property with a value of 327 * "memory-controller". in this situation, return DDI_SUCCESS 328 */ 329 if (getlongprop_buf(id, OBP_DEVICETYPE, devtype_buf, 330 sizeof (devtype_buf)) > 0) { 331 if (strcmp(devtype_buf, "memory-controller") == 0) 332 retval = DDI_SUCCESS; 333 } 334 335 /* 336 * print the status property information 337 */ 338 cmn_err(CE_WARN, "status '%s' for '%s'", status_buf, name); 339 return (retval); 340 } 341 342 /*ARGSUSED*/ 343 uint_t 344 softlevel1(caddr_t arg1, caddr_t arg2) 345 { 346 softint(); 347 return (1); 348 } 349 350 /* 351 * Allow for implementation specific correction of PROM property values. 352 */ 353 354 /*ARGSUSED*/ 355 void 356 impl_fix_props(dev_info_t *dip, dev_info_t *ch_dip, char *name, int len, 357 caddr_t buffer) 358 { 359 /* 360 * There are no adjustments needed in this implementation. 361 */ 362 } 363 364 static int 365 getlongprop_buf(int id, char *name, char *buf, int maxlen) 366 { 367 int size; 368 369 size = prom_getproplen((pnode_t)id, name); 370 if (size <= 0 || (size > maxlen - 1)) 371 return (-1); 372 373 if (-1 == prom_getprop((pnode_t)id, name, buf)) 374 return (-1); 375 376 if (strcmp("name", name) == 0) { 377 if (buf[size - 1] != '\0') { 378 buf[size] = '\0'; 379 size += 1; 380 } 381 } 382 383 return (size); 384 } 385 386 static int 387 get_prop_int_array(dev_info_t *di, char *pname, int **pval, uint_t *plen) 388 { 389 int ret; 390 391 if ((ret = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, di, 392 DDI_PROP_DONTPASS, pname, pval, plen)) 393 == DDI_PROP_SUCCESS) { 394 *plen = (*plen) * (sizeof (int)); 395 } 396 return (ret); 397 } 398 399 400 /* 401 * Node Configuration 402 */ 403 404 struct prop_ispec { 405 uint_t pri, vec; 406 }; 407 408 /* 409 * For the x86, we're prepared to claim that the interrupt string 410 * is in the form of a list of <ipl,vec> specifications. 411 */ 412 413 #define VEC_MIN 1 414 #define VEC_MAX 255 415 416 static int 417 impl_xlate_intrs(dev_info_t *child, int *in, 418 struct ddi_parent_private_data *pdptr) 419 { 420 size_t size; 421 int n; 422 struct intrspec *new; 423 caddr_t got_prop; 424 int *inpri; 425 int got_len; 426 extern int ignore_hardware_nodes; /* force flag from ddi_impl.c */ 427 428 static char bad_intr_fmt[] = 429 "bad interrupt spec from %s%d - ipl %d, irq %d\n"; 430 431 /* 432 * determine if the driver is expecting the new style "interrupts" 433 * property which just contains the IRQ, or the old style which 434 * contains pairs of <IPL,IRQ>. if it is the new style, we always 435 * assign IPL 5 unless an "interrupt-priorities" property exists. 436 * in that case, the "interrupt-priorities" property contains the 437 * IPL values that match, one for one, the IRQ values in the 438 * "interrupts" property. 439 */ 440 inpri = NULL; 441 if ((ddi_getprop(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS, 442 "ignore-hardware-nodes", -1) != -1) || ignore_hardware_nodes) { 443 /* the old style "interrupts" property... */ 444 445 /* 446 * The list consists of <ipl,vec> elements 447 */ 448 if ((n = (*in++ >> 1)) < 1) 449 return (DDI_FAILURE); 450 451 pdptr->par_nintr = n; 452 size = n * sizeof (struct intrspec); 453 new = pdptr->par_intr = kmem_zalloc(size, KM_SLEEP); 454 455 while (n--) { 456 int level = *in++; 457 int vec = *in++; 458 459 if (level < 1 || level > MAXIPL || 460 vec < VEC_MIN || vec > VEC_MAX) { 461 cmn_err(CE_CONT, bad_intr_fmt, 462 DEVI(child)->devi_name, 463 DEVI(child)->devi_instance, level, vec); 464 goto broken; 465 } 466 new->intrspec_pri = level; 467 if (vec != 2) 468 new->intrspec_vec = vec; 469 else 470 /* 471 * irq 2 on the PC bus is tied to irq 9 472 * on ISA, EISA and MicroChannel 473 */ 474 new->intrspec_vec = 9; 475 new++; 476 } 477 478 return (DDI_SUCCESS); 479 } else { 480 /* the new style "interrupts" property... */ 481 482 /* 483 * The list consists of <vec> elements 484 */ 485 if ((n = (*in++)) < 1) 486 return (DDI_FAILURE); 487 488 pdptr->par_nintr = n; 489 size = n * sizeof (struct intrspec); 490 new = pdptr->par_intr = kmem_zalloc(size, KM_SLEEP); 491 492 /* XXX check for "interrupt-priorities" property... */ 493 if (ddi_getlongprop(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS, 494 "interrupt-priorities", (caddr_t)&got_prop, &got_len) 495 == DDI_PROP_SUCCESS) { 496 if (n != (got_len / sizeof (int))) { 497 cmn_err(CE_CONT, 498 "bad interrupt-priorities length" 499 " from %s%d: expected %d, got %d\n", 500 DEVI(child)->devi_name, 501 DEVI(child)->devi_instance, n, 502 (int)(got_len / sizeof (int))); 503 goto broken; 504 } 505 inpri = (int *)got_prop; 506 } 507 508 while (n--) { 509 int level; 510 int vec = *in++; 511 512 if (inpri == NULL) 513 level = 5; 514 else 515 level = *inpri++; 516 517 if (level < 1 || level > MAXIPL || 518 vec < VEC_MIN || vec > VEC_MAX) { 519 cmn_err(CE_CONT, bad_intr_fmt, 520 DEVI(child)->devi_name, 521 DEVI(child)->devi_instance, level, vec); 522 goto broken; 523 } 524 new->intrspec_pri = level; 525 if (vec != 2) 526 new->intrspec_vec = vec; 527 else 528 /* 529 * irq 2 on the PC bus is tied to irq 9 530 * on ISA, EISA and MicroChannel 531 */ 532 new->intrspec_vec = 9; 533 new++; 534 } 535 536 if (inpri != NULL) 537 kmem_free(got_prop, got_len); 538 return (DDI_SUCCESS); 539 } 540 541 broken: 542 kmem_free(pdptr->par_intr, size); 543 pdptr->par_intr = NULL; 544 pdptr->par_nintr = 0; 545 if (inpri != NULL) 546 kmem_free(got_prop, got_len); 547 548 return (DDI_FAILURE); 549 } 550 551 /* 552 * Create a ddi_parent_private_data structure from the ddi properties of 553 * the dev_info node. 554 * 555 * The "reg" and either an "intr" or "interrupts" properties are required 556 * if the driver wishes to create mappings or field interrupts on behalf 557 * of the device. 558 * 559 * The "reg" property is assumed to be a list of at least one triple 560 * 561 * <bustype, address, size>*1 562 * 563 * The "intr" property is assumed to be a list of at least one duple 564 * 565 * <SPARC ipl, vector#>*1 566 * 567 * The "interrupts" property is assumed to be a list of at least one 568 * n-tuples that describes the interrupt capabilities of the bus the device 569 * is connected to. For SBus, this looks like 570 * 571 * <SBus-level>*1 572 * 573 * (This property obsoletes the 'intr' property). 574 * 575 * The "ranges" property is optional. 576 */ 577 void 578 make_ddi_ppd(dev_info_t *child, struct ddi_parent_private_data **ppd) 579 { 580 struct ddi_parent_private_data *pdptr; 581 int n; 582 int *reg_prop, *rng_prop, *intr_prop, *irupts_prop; 583 uint_t reg_len, rng_len, intr_len, irupts_len; 584 585 *ppd = pdptr = kmem_zalloc(sizeof (*pdptr), KM_SLEEP); 586 587 /* 588 * Handle the 'reg' property. 589 */ 590 if ((get_prop_int_array(child, "reg", ®_prop, ®_len) == 591 DDI_PROP_SUCCESS) && (reg_len != 0)) { 592 pdptr->par_nreg = reg_len / (int)sizeof (struct regspec); 593 pdptr->par_reg = (struct regspec *)reg_prop; 594 } 595 596 /* 597 * See if I have a range (adding one where needed - this 598 * means to add one for sbus node in sun4c, when romvec > 0, 599 * if no range is already defined in the PROM node. 600 * (Currently no sun4c PROMS define range properties, 601 * but they should and may in the future.) For the SBus 602 * node, the range is defined by the SBus reg property. 603 */ 604 if (get_prop_int_array(child, "ranges", &rng_prop, &rng_len) 605 == DDI_PROP_SUCCESS) { 606 pdptr->par_nrng = rng_len / (int)(sizeof (struct rangespec)); 607 pdptr->par_rng = (struct rangespec *)rng_prop; 608 } 609 610 /* 611 * Handle the 'intr' and 'interrupts' properties 612 */ 613 614 /* 615 * For backwards compatibility 616 * we first look for the 'intr' property for the device. 617 */ 618 if (get_prop_int_array(child, "intr", &intr_prop, &intr_len) 619 != DDI_PROP_SUCCESS) { 620 intr_len = 0; 621 } 622 623 /* 624 * If we're to support bus adapters and future platforms cleanly, 625 * we need to support the generalized 'interrupts' property. 626 */ 627 if (get_prop_int_array(child, "interrupts", &irupts_prop, 628 &irupts_len) != DDI_PROP_SUCCESS) { 629 irupts_len = 0; 630 } else if (intr_len != 0) { 631 /* 632 * If both 'intr' and 'interrupts' are defined, 633 * then 'interrupts' wins and we toss the 'intr' away. 634 */ 635 ddi_prop_free((void *)intr_prop); 636 intr_len = 0; 637 } 638 639 if (intr_len != 0) { 640 641 /* 642 * Translate the 'intr' property into an array 643 * an array of struct intrspec's. There's not really 644 * very much to do here except copy what's out there. 645 */ 646 647 struct intrspec *new; 648 struct prop_ispec *l; 649 650 n = pdptr->par_nintr = intr_len / sizeof (struct prop_ispec); 651 l = (struct prop_ispec *)intr_prop; 652 pdptr->par_intr = 653 new = kmem_zalloc(n * sizeof (struct intrspec), KM_SLEEP); 654 while (n--) { 655 new->intrspec_pri = l->pri; 656 new->intrspec_vec = l->vec; 657 new++; 658 l++; 659 } 660 ddi_prop_free((void *)intr_prop); 661 662 } else if ((n = irupts_len) != 0) { 663 size_t size; 664 int *out; 665 666 /* 667 * Translate the 'interrupts' property into an array 668 * of intrspecs for the rest of the DDI framework to 669 * toy with. Only our ancestors really know how to 670 * do this, so ask 'em. We massage the 'interrupts' 671 * property so that it is pre-pended by a count of 672 * the number of integers in the argument. 673 */ 674 size = sizeof (int) + n; 675 out = kmem_alloc(size, KM_SLEEP); 676 *out = n / sizeof (int); 677 bcopy(irupts_prop, out + 1, (size_t)n); 678 ddi_prop_free((void *)irupts_prop); 679 if (impl_xlate_intrs(child, out, pdptr) != DDI_SUCCESS) { 680 cmn_err(CE_CONT, 681 "Unable to translate 'interrupts' for %s%d\n", 682 DEVI(child)->devi_binding_name, 683 DEVI(child)->devi_instance); 684 } 685 kmem_free(out, size); 686 } 687 } 688 689 /* 690 * Name a child 691 */ 692 static int 693 impl_sunbus_name_child(dev_info_t *child, char *name, int namelen) 694 { 695 /* 696 * Fill in parent-private data and this function returns to us 697 * an indication if it used "registers" to fill in the data. 698 */ 699 if (ddi_get_parent_data(child) == NULL) { 700 struct ddi_parent_private_data *pdptr; 701 make_ddi_ppd(child, &pdptr); 702 ddi_set_parent_data(child, pdptr); 703 } 704 705 name[0] = '\0'; 706 if (sparc_pd_getnreg(child) > 0) { 707 (void) snprintf(name, namelen, "%x,%x", 708 (uint_t)sparc_pd_getreg(child, 0)->regspec_bustype, 709 (uint_t)sparc_pd_getreg(child, 0)->regspec_addr); 710 } 711 712 return (DDI_SUCCESS); 713 } 714 715 /* 716 * Called from the bus_ctl op of sunbus (sbus, obio, etc) nexus drivers 717 * to implement the DDI_CTLOPS_INITCHILD operation. That is, it names 718 * the children of sun busses based on the reg spec. 719 * 720 * Handles the following properties (in make_ddi_ppd): 721 * Property value 722 * Name type 723 * reg register spec 724 * intr old-form interrupt spec 725 * interrupts new (bus-oriented) interrupt spec 726 * ranges range spec 727 */ 728 int 729 impl_ddi_sunbus_initchild(dev_info_t *child) 730 { 731 char name[MAXNAMELEN]; 732 void impl_ddi_sunbus_removechild(dev_info_t *); 733 734 /* 735 * Name the child, also makes parent private data 736 */ 737 (void) impl_sunbus_name_child(child, name, MAXNAMELEN); 738 ddi_set_name_addr(child, name); 739 740 /* 741 * Attempt to merge a .conf node; if successful, remove the 742 * .conf node. 743 */ 744 if ((ndi_dev_is_persistent_node(child) == 0) && 745 (ndi_merge_node(child, impl_sunbus_name_child) == DDI_SUCCESS)) { 746 /* 747 * Return failure to remove node 748 */ 749 impl_ddi_sunbus_removechild(child); 750 return (DDI_FAILURE); 751 } 752 return (DDI_SUCCESS); 753 } 754 755 void 756 impl_free_ddi_ppd(dev_info_t *dip) 757 { 758 struct ddi_parent_private_data *pdptr; 759 size_t n; 760 761 if ((pdptr = ddi_get_parent_data(dip)) == NULL) 762 return; 763 764 if ((n = (size_t)pdptr->par_nintr) != 0) 765 /* 766 * Note that kmem_free is used here (instead of 767 * ddi_prop_free) because the contents of the 768 * property were placed into a separate buffer and 769 * mucked with a bit before being stored in par_intr. 770 * The actual return value from the prop lookup 771 * was freed with ddi_prop_free previously. 772 */ 773 kmem_free(pdptr->par_intr, n * sizeof (struct intrspec)); 774 775 if ((n = (size_t)pdptr->par_nrng) != 0) 776 ddi_prop_free((void *)pdptr->par_rng); 777 778 if ((n = pdptr->par_nreg) != 0) 779 ddi_prop_free((void *)pdptr->par_reg); 780 781 kmem_free(pdptr, sizeof (*pdptr)); 782 ddi_set_parent_data(dip, NULL); 783 } 784 785 void 786 impl_ddi_sunbus_removechild(dev_info_t *dip) 787 { 788 impl_free_ddi_ppd(dip); 789 ddi_set_name_addr(dip, NULL); 790 /* 791 * Strip the node to properly convert it back to prototype form 792 */ 793 impl_rem_dev_props(dip); 794 } 795 796 /* 797 * DDI Interrupt 798 */ 799 800 /* 801 * turn this on to force isa, eisa, and mca device to ignore the new 802 * hardware nodes in the device tree (normally turned on only for 803 * drivers that need it by setting the property "ignore-hardware-nodes" 804 * in their driver.conf file). 805 * 806 * 7/31/96 -- Turned off globally. Leaving variable in for the moment 807 * as safety valve. 808 */ 809 int ignore_hardware_nodes = 0; 810 811 /* 812 * Local data 813 */ 814 static struct impl_bus_promops *impl_busp; 815 816 817 /* 818 * New DDI interrupt framework 819 */ 820 821 /* 822 * i_ddi_intr_ops: 823 * 824 * This is the interrupt operator function wrapper for the bus function 825 * bus_intr_op. 826 */ 827 int 828 i_ddi_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t op, 829 ddi_intr_handle_impl_t *hdlp, void * result) 830 { 831 dev_info_t *pdip = (dev_info_t *)DEVI(dip)->devi_parent; 832 int ret = DDI_FAILURE; 833 834 /* request parent to process this interrupt op */ 835 if (NEXUS_HAS_INTR_OP(pdip)) 836 ret = (*(DEVI(pdip)->devi_ops->devo_bus_ops->bus_intr_op))( 837 pdip, rdip, op, hdlp, result); 838 else 839 cmn_err(CE_WARN, "Failed to process interrupt " 840 "for %s%d due to down-rev nexus driver %s%d", 841 ddi_get_name(rdip), ddi_get_instance(rdip), 842 ddi_get_name(pdip), ddi_get_instance(pdip)); 843 return (ret); 844 } 845 846 /* 847 * i_ddi_add_softint - allocate and add a soft interrupt to the system 848 */ 849 int 850 i_ddi_add_softint(ddi_softint_hdl_impl_t *hdlp) 851 { 852 int ret; 853 854 /* add soft interrupt handler */ 855 ret = add_avsoftintr((void *)hdlp, hdlp->ih_pri, hdlp->ih_cb_func, 856 DEVI(hdlp->ih_dip)->devi_name, hdlp->ih_cb_arg1, hdlp->ih_cb_arg2); 857 return (ret ? DDI_SUCCESS : DDI_FAILURE); 858 } 859 860 861 void 862 i_ddi_remove_softint(ddi_softint_hdl_impl_t *hdlp) 863 { 864 (void) rem_avsoftintr((void *)hdlp, hdlp->ih_pri, hdlp->ih_cb_func); 865 } 866 867 868 extern void (*setsoftint)(int, struct av_softinfo *); 869 extern boolean_t av_check_softint_pending(struct av_softinfo *, boolean_t); 870 871 int 872 i_ddi_trigger_softint(ddi_softint_hdl_impl_t *hdlp, void *arg2) 873 { 874 if (av_check_softint_pending(hdlp->ih_pending, B_FALSE)) 875 return (DDI_EPENDING); 876 877 update_avsoftintr_args((void *)hdlp, hdlp->ih_pri, arg2); 878 879 (*setsoftint)(hdlp->ih_pri, hdlp->ih_pending); 880 return (DDI_SUCCESS); 881 } 882 883 /* 884 * i_ddi_set_softint_pri: 885 * 886 * The way this works is that it first tries to add a softint vector 887 * at the new priority in hdlp. If that succeeds; then it removes the 888 * existing softint vector at the old priority. 889 */ 890 int 891 i_ddi_set_softint_pri(ddi_softint_hdl_impl_t *hdlp, uint_t old_pri) 892 { 893 int ret; 894 895 /* 896 * If a softint is pending at the old priority then fail the request. 897 */ 898 if (av_check_softint_pending(hdlp->ih_pending, B_TRUE)) 899 return (DDI_FAILURE); 900 901 ret = av_softint_movepri((void *)hdlp, old_pri); 902 return (ret ? DDI_SUCCESS : DDI_FAILURE); 903 } 904 905 void 906 i_ddi_alloc_intr_phdl(ddi_intr_handle_impl_t *hdlp) 907 { 908 hdlp->ih_private = (void *)kmem_zalloc(sizeof (ihdl_plat_t), KM_SLEEP); 909 } 910 911 void 912 i_ddi_free_intr_phdl(ddi_intr_handle_impl_t *hdlp) 913 { 914 kmem_free(hdlp->ih_private, sizeof (ihdl_plat_t)); 915 hdlp->ih_private = NULL; 916 } 917 918 int 919 i_ddi_get_intx_nintrs(dev_info_t *dip) 920 { 921 struct ddi_parent_private_data *pdp; 922 923 if ((pdp = ddi_get_parent_data(dip)) == NULL) 924 return (0); 925 926 return (pdp->par_nintr); 927 } 928 929 /* 930 * DDI Memory/DMA 931 */ 932 933 /* 934 * Support for allocating DMAable memory to implement 935 * ddi_dma_mem_alloc(9F) interface. 936 */ 937 938 #define KA_ALIGN_SHIFT 7 939 #define KA_ALIGN (1 << KA_ALIGN_SHIFT) 940 #define KA_NCACHE (PAGESHIFT + 1 - KA_ALIGN_SHIFT) 941 942 /* 943 * Dummy DMA attribute template for kmem_io[].kmem_io_attr. We only 944 * care about addr_lo, addr_hi, and align. addr_hi will be dynamically set. 945 */ 946 947 static ddi_dma_attr_t kmem_io_attr = { 948 DMA_ATTR_V0, 949 0x0000000000000000ULL, /* dma_attr_addr_lo */ 950 0x0000000000000000ULL, /* dma_attr_addr_hi */ 951 0x00ffffff, 952 0x1000, /* dma_attr_align */ 953 1, 1, 0xffffffffULL, 0xffffffffULL, 0x1, 1, 0 954 }; 955 956 /* kmem io memory ranges and indices */ 957 enum { 958 IO_4P, IO_64G, IO_4G, IO_2G, IO_1G, IO_512M, 959 IO_256M, IO_128M, IO_64M, IO_32M, IO_16M, MAX_MEM_RANGES 960 }; 961 962 static struct { 963 vmem_t *kmem_io_arena; 964 kmem_cache_t *kmem_io_cache[KA_NCACHE]; 965 ddi_dma_attr_t kmem_io_attr; 966 } kmem_io[MAX_MEM_RANGES]; 967 968 static int kmem_io_idx; /* index of first populated kmem_io[] */ 969 970 static page_t * 971 page_create_io_wrapper(void *addr, size_t len, int vmflag, void *arg) 972 { 973 extern page_t *page_create_io(vnode_t *, u_offset_t, uint_t, 974 uint_t, struct as *, caddr_t, ddi_dma_attr_t *); 975 976 return (page_create_io(&kvp, (u_offset_t)(uintptr_t)addr, len, 977 PG_EXCL | ((vmflag & VM_NOSLEEP) ? 0 : PG_WAIT), &kas, addr, arg)); 978 } 979 980 #ifdef __xpv 981 static void 982 segkmem_free_io(vmem_t *vmp, void * ptr, size_t size) 983 { 984 extern void page_destroy_io(page_t *); 985 segkmem_xfree(vmp, ptr, size, page_destroy_io); 986 } 987 #endif 988 989 static void * 990 segkmem_alloc_io_4P(vmem_t *vmp, size_t size, int vmflag) 991 { 992 return (segkmem_xalloc(vmp, NULL, size, vmflag, 0, 993 page_create_io_wrapper, &kmem_io[IO_4P].kmem_io_attr)); 994 } 995 996 static void * 997 segkmem_alloc_io_64G(vmem_t *vmp, size_t size, int vmflag) 998 { 999 return (segkmem_xalloc(vmp, NULL, size, vmflag, 0, 1000 page_create_io_wrapper, &kmem_io[IO_64G].kmem_io_attr)); 1001 } 1002 1003 static void * 1004 segkmem_alloc_io_4G(vmem_t *vmp, size_t size, int vmflag) 1005 { 1006 return (segkmem_xalloc(vmp, NULL, size, vmflag, 0, 1007 page_create_io_wrapper, &kmem_io[IO_4G].kmem_io_attr)); 1008 } 1009 1010 static void * 1011 segkmem_alloc_io_2G(vmem_t *vmp, size_t size, int vmflag) 1012 { 1013 return (segkmem_xalloc(vmp, NULL, size, vmflag, 0, 1014 page_create_io_wrapper, &kmem_io[IO_2G].kmem_io_attr)); 1015 } 1016 1017 static void * 1018 segkmem_alloc_io_1G(vmem_t *vmp, size_t size, int vmflag) 1019 { 1020 return (segkmem_xalloc(vmp, NULL, size, vmflag, 0, 1021 page_create_io_wrapper, &kmem_io[IO_1G].kmem_io_attr)); 1022 } 1023 1024 static void * 1025 segkmem_alloc_io_512M(vmem_t *vmp, size_t size, int vmflag) 1026 { 1027 return (segkmem_xalloc(vmp, NULL, size, vmflag, 0, 1028 page_create_io_wrapper, &kmem_io[IO_512M].kmem_io_attr)); 1029 } 1030 1031 static void * 1032 segkmem_alloc_io_256M(vmem_t *vmp, size_t size, int vmflag) 1033 { 1034 return (segkmem_xalloc(vmp, NULL, size, vmflag, 0, 1035 page_create_io_wrapper, &kmem_io[IO_256M].kmem_io_attr)); 1036 } 1037 1038 static void * 1039 segkmem_alloc_io_128M(vmem_t *vmp, size_t size, int vmflag) 1040 { 1041 return (segkmem_xalloc(vmp, NULL, size, vmflag, 0, 1042 page_create_io_wrapper, &kmem_io[IO_128M].kmem_io_attr)); 1043 } 1044 1045 static void * 1046 segkmem_alloc_io_64M(vmem_t *vmp, size_t size, int vmflag) 1047 { 1048 return (segkmem_xalloc(vmp, NULL, size, vmflag, 0, 1049 page_create_io_wrapper, &kmem_io[IO_64M].kmem_io_attr)); 1050 } 1051 1052 static void * 1053 segkmem_alloc_io_32M(vmem_t *vmp, size_t size, int vmflag) 1054 { 1055 return (segkmem_xalloc(vmp, NULL, size, vmflag, 0, 1056 page_create_io_wrapper, &kmem_io[IO_32M].kmem_io_attr)); 1057 } 1058 1059 static void * 1060 segkmem_alloc_io_16M(vmem_t *vmp, size_t size, int vmflag) 1061 { 1062 return (segkmem_xalloc(vmp, NULL, size, vmflag, 0, 1063 page_create_io_wrapper, &kmem_io[IO_16M].kmem_io_attr)); 1064 } 1065 1066 struct { 1067 uint64_t io_limit; 1068 char *io_name; 1069 void *(*io_alloc)(vmem_t *, size_t, int); 1070 int io_initial; /* kmem_io_init during startup */ 1071 } io_arena_params[MAX_MEM_RANGES] = { 1072 {0x000fffffffffffffULL, "kmem_io_4P", segkmem_alloc_io_4P, 1}, 1073 {0x0000000fffffffffULL, "kmem_io_64G", segkmem_alloc_io_64G, 0}, 1074 {0x00000000ffffffffULL, "kmem_io_4G", segkmem_alloc_io_4G, 1}, 1075 {0x000000007fffffffULL, "kmem_io_2G", segkmem_alloc_io_2G, 1}, 1076 {0x000000003fffffffULL, "kmem_io_1G", segkmem_alloc_io_1G, 0}, 1077 {0x000000001fffffffULL, "kmem_io_512M", segkmem_alloc_io_512M, 0}, 1078 {0x000000000fffffffULL, "kmem_io_256M", segkmem_alloc_io_256M, 0}, 1079 {0x0000000007ffffffULL, "kmem_io_128M", segkmem_alloc_io_128M, 0}, 1080 {0x0000000003ffffffULL, "kmem_io_64M", segkmem_alloc_io_64M, 0}, 1081 {0x0000000001ffffffULL, "kmem_io_32M", segkmem_alloc_io_32M, 0}, 1082 {0x0000000000ffffffULL, "kmem_io_16M", segkmem_alloc_io_16M, 1} 1083 }; 1084 1085 void 1086 kmem_io_init(int a) 1087 { 1088 int c; 1089 char name[40]; 1090 1091 kmem_io[a].kmem_io_arena = vmem_create(io_arena_params[a].io_name, 1092 NULL, 0, PAGESIZE, io_arena_params[a].io_alloc, 1093 #ifdef __xpv 1094 segkmem_free_io, 1095 #else 1096 segkmem_free, 1097 #endif 1098 heap_arena, 0, VM_SLEEP); 1099 1100 for (c = 0; c < KA_NCACHE; c++) { 1101 size_t size = KA_ALIGN << c; 1102 (void) sprintf(name, "%s_%lu", 1103 io_arena_params[a].io_name, size); 1104 kmem_io[a].kmem_io_cache[c] = kmem_cache_create(name, 1105 size, size, NULL, NULL, NULL, NULL, 1106 kmem_io[a].kmem_io_arena, 0); 1107 } 1108 } 1109 1110 /* 1111 * Return the index of the highest memory range for addr. 1112 */ 1113 static int 1114 kmem_io_index(uint64_t addr) 1115 { 1116 int n; 1117 1118 for (n = kmem_io_idx; n < MAX_MEM_RANGES; n++) { 1119 if (kmem_io[n].kmem_io_attr.dma_attr_addr_hi <= addr) { 1120 if (kmem_io[n].kmem_io_arena == NULL) 1121 kmem_io_init(n); 1122 return (n); 1123 } 1124 } 1125 panic("kmem_io_index: invalid addr - must be at least 16m"); 1126 1127 /*NOTREACHED*/ 1128 } 1129 1130 /* 1131 * Return the index of the next kmem_io populated memory range 1132 * after curindex. 1133 */ 1134 static int 1135 kmem_io_index_next(int curindex) 1136 { 1137 int n; 1138 1139 for (n = curindex + 1; n < MAX_MEM_RANGES; n++) { 1140 if (kmem_io[n].kmem_io_arena) 1141 return (n); 1142 } 1143 return (-1); 1144 } 1145 1146 /* 1147 * allow kmem to be mapped in with different PTE cache attribute settings. 1148 * Used by i_ddi_mem_alloc() 1149 */ 1150 int 1151 kmem_override_cache_attrs(caddr_t kva, size_t size, uint_t order) 1152 { 1153 uint_t hat_flags; 1154 caddr_t kva_end; 1155 uint_t hat_attr; 1156 pfn_t pfn; 1157 1158 if (hat_getattr(kas.a_hat, kva, &hat_attr) == -1) { 1159 return (-1); 1160 } 1161 1162 hat_attr &= ~HAT_ORDER_MASK; 1163 hat_attr |= order | HAT_NOSYNC; 1164 hat_flags = HAT_LOAD_LOCK; 1165 1166 kva_end = (caddr_t)(((uintptr_t)kva + size + PAGEOFFSET) & 1167 (uintptr_t)PAGEMASK); 1168 kva = (caddr_t)((uintptr_t)kva & (uintptr_t)PAGEMASK); 1169 1170 while (kva < kva_end) { 1171 pfn = hat_getpfnum(kas.a_hat, kva); 1172 hat_unload(kas.a_hat, kva, PAGESIZE, HAT_UNLOAD_UNLOCK); 1173 hat_devload(kas.a_hat, kva, PAGESIZE, pfn, hat_attr, hat_flags); 1174 kva += MMU_PAGESIZE; 1175 } 1176 1177 return (0); 1178 } 1179 1180 void 1181 ka_init(void) 1182 { 1183 int a; 1184 paddr_t maxphysaddr; 1185 #if !defined(__xpv) 1186 extern pfn_t physmax; 1187 1188 maxphysaddr = mmu_ptob((paddr_t)physmax) + MMU_PAGEOFFSET; 1189 #else 1190 maxphysaddr = mmu_ptob((paddr_t)HYPERVISOR_memory_op( 1191 XENMEM_maximum_ram_page, NULL)) + MMU_PAGEOFFSET; 1192 #endif 1193 1194 ASSERT(maxphysaddr <= io_arena_params[0].io_limit); 1195 1196 for (a = 0; a < MAX_MEM_RANGES; a++) { 1197 if (maxphysaddr >= io_arena_params[a + 1].io_limit) { 1198 if (maxphysaddr > io_arena_params[a + 1].io_limit) 1199 io_arena_params[a].io_limit = maxphysaddr; 1200 else 1201 a++; 1202 break; 1203 } 1204 } 1205 kmem_io_idx = a; 1206 1207 for (; a < MAX_MEM_RANGES; a++) { 1208 kmem_io[a].kmem_io_attr = kmem_io_attr; 1209 kmem_io[a].kmem_io_attr.dma_attr_addr_hi = 1210 io_arena_params[a].io_limit; 1211 /* 1212 * initialize kmem_io[] arena/cache corresponding to 1213 * maxphysaddr and to the "common" io memory ranges that 1214 * have io_initial set to a non-zero value. 1215 */ 1216 if (io_arena_params[a].io_initial || a == kmem_io_idx) 1217 kmem_io_init(a); 1218 } 1219 } 1220 1221 /* 1222 * put contig address/size 1223 */ 1224 static void * 1225 putctgas(void *addr, size_t size) 1226 { 1227 struct ctgas *ctgp = &ctglist; 1228 int i; 1229 1230 CTGLOCK(); 1231 do { 1232 if ((i = ctgp->ctg_index) < CTGENTRIES) { 1233 ctgp->ctg_addr[i] = addr; 1234 ctgp->ctg_size[i] = size; 1235 ctgp->ctg_index++; 1236 break; 1237 } 1238 if (!ctgp->ctg_next) 1239 ctgp->ctg_next = kmem_zalloc(sizeof (struct ctgas), 1240 KM_NOSLEEP); 1241 ctgp = ctgp->ctg_next; 1242 } while (ctgp); 1243 1244 CTGUNLOCK(); 1245 return (ctgp); 1246 } 1247 1248 /* 1249 * get contig size by addr 1250 */ 1251 static size_t 1252 getctgsz(void *addr) 1253 { 1254 struct ctgas *ctgp = &ctglist; 1255 int i, j; 1256 size_t sz; 1257 1258 ASSERT(addr); 1259 CTGLOCK(); 1260 1261 while (ctgp) { 1262 for (i = 0; i < ctgp->ctg_index; i++) { 1263 if (addr != ctgp->ctg_addr[i]) 1264 continue; 1265 1266 sz = ctgp->ctg_size[i]; 1267 j = --ctgp->ctg_index; 1268 if (i != j) { 1269 ctgp->ctg_size[i] = ctgp->ctg_size[j]; 1270 ctgp->ctg_addr[i] = ctgp->ctg_addr[j]; 1271 } 1272 CTGUNLOCK(); 1273 return (sz); 1274 } 1275 ctgp = ctgp->ctg_next; 1276 } 1277 1278 CTGUNLOCK(); 1279 return (0); 1280 } 1281 1282 /* 1283 * contig_alloc: 1284 * 1285 * allocates contiguous memory to satisfy the 'size' and dma attributes 1286 * specified in 'attr'. 1287 * 1288 * Not all of memory need to be physically contiguous if the 1289 * scatter-gather list length is greater than 1. 1290 */ 1291 1292 /*ARGSUSED*/ 1293 void * 1294 contig_alloc(size_t size, ddi_dma_attr_t *attr, uintptr_t align, int cansleep) 1295 { 1296 pgcnt_t pgcnt = btopr(size); 1297 size_t asize = pgcnt * PAGESIZE; 1298 page_t *ppl; 1299 int pflag; 1300 void *addr; 1301 1302 extern page_t *page_create_io(vnode_t *, u_offset_t, uint_t, 1303 uint_t, struct as *, caddr_t, ddi_dma_attr_t *); 1304 1305 /* segkmem_xalloc */ 1306 1307 if (align <= PAGESIZE) 1308 addr = vmem_alloc(heap_arena, asize, 1309 (cansleep) ? VM_SLEEP : VM_NOSLEEP); 1310 else 1311 addr = vmem_xalloc(heap_arena, asize, align, 0, 0, NULL, NULL, 1312 (cansleep) ? VM_SLEEP : VM_NOSLEEP); 1313 if (addr) { 1314 ASSERT(!((uintptr_t)addr & (align - 1))); 1315 1316 if (page_resv(pgcnt, (cansleep) ? KM_SLEEP : KM_NOSLEEP) == 0) { 1317 vmem_free(heap_arena, addr, asize); 1318 return (NULL); 1319 } 1320 pflag = PG_EXCL; 1321 1322 if (cansleep) 1323 pflag |= PG_WAIT; 1324 1325 /* 4k req gets from freelists rather than pfn search */ 1326 if (pgcnt > 1 || align > PAGESIZE) 1327 pflag |= PG_PHYSCONTIG; 1328 1329 ppl = page_create_io(&kvp, (u_offset_t)(uintptr_t)addr, 1330 asize, pflag, &kas, (caddr_t)addr, attr); 1331 1332 if (!ppl) { 1333 vmem_free(heap_arena, addr, asize); 1334 page_unresv(pgcnt); 1335 return (NULL); 1336 } 1337 1338 while (ppl != NULL) { 1339 page_t *pp = ppl; 1340 page_sub(&ppl, pp); 1341 ASSERT(page_iolock_assert(pp)); 1342 page_io_unlock(pp); 1343 page_downgrade(pp); 1344 hat_memload(kas.a_hat, (caddr_t)(uintptr_t)pp->p_offset, 1345 pp, (PROT_ALL & ~PROT_USER) | 1346 HAT_NOSYNC, HAT_LOAD_LOCK); 1347 } 1348 } 1349 return (addr); 1350 } 1351 1352 static void 1353 contig_free(void *addr, size_t size) 1354 { 1355 pgcnt_t pgcnt = btopr(size); 1356 size_t asize = pgcnt * PAGESIZE; 1357 caddr_t a, ea; 1358 page_t *pp; 1359 1360 hat_unload(kas.a_hat, addr, asize, HAT_UNLOAD_UNLOCK); 1361 1362 for (a = addr, ea = a + asize; a < ea; a += PAGESIZE) { 1363 pp = page_find(&kvp, (u_offset_t)(uintptr_t)a); 1364 if (!pp) 1365 panic("contig_free: contig pp not found"); 1366 1367 if (!page_tryupgrade(pp)) { 1368 page_unlock(pp); 1369 pp = page_lookup(&kvp, 1370 (u_offset_t)(uintptr_t)a, SE_EXCL); 1371 if (pp == NULL) 1372 panic("contig_free: page freed"); 1373 } 1374 page_destroy(pp, 0); 1375 } 1376 1377 page_unresv(pgcnt); 1378 vmem_free(heap_arena, addr, asize); 1379 } 1380 1381 /* 1382 * Allocate from the system, aligned on a specific boundary. 1383 * The alignment, if non-zero, must be a power of 2. 1384 */ 1385 static void * 1386 kalloca(size_t size, size_t align, int cansleep, int physcontig, 1387 ddi_dma_attr_t *attr) 1388 { 1389 size_t *addr, *raddr, rsize; 1390 size_t hdrsize = 4 * sizeof (size_t); /* must be power of 2 */ 1391 int a, i, c; 1392 vmem_t *vmp; 1393 kmem_cache_t *cp = NULL; 1394 1395 if (attr->dma_attr_addr_lo > mmu_ptob((uint64_t)ddiphysmin)) 1396 return (NULL); 1397 1398 align = MAX(align, hdrsize); 1399 ASSERT((align & (align - 1)) == 0); 1400 1401 /* 1402 * All of our allocators guarantee 16-byte alignment, so we don't 1403 * need to reserve additional space for the header. 1404 * To simplify picking the correct kmem_io_cache, we round up to 1405 * a multiple of KA_ALIGN. 1406 */ 1407 rsize = P2ROUNDUP_TYPED(size + align, KA_ALIGN, size_t); 1408 1409 if (physcontig && rsize > PAGESIZE) { 1410 if (addr = contig_alloc(size, attr, align, cansleep)) { 1411 if (!putctgas(addr, size)) 1412 contig_free(addr, size); 1413 else 1414 return (addr); 1415 } 1416 return (NULL); 1417 } 1418 1419 a = kmem_io_index(attr->dma_attr_addr_hi); 1420 1421 if (rsize > PAGESIZE) { 1422 vmp = kmem_io[a].kmem_io_arena; 1423 raddr = vmem_alloc(vmp, rsize, 1424 (cansleep) ? VM_SLEEP : VM_NOSLEEP); 1425 } else { 1426 c = highbit((rsize >> KA_ALIGN_SHIFT) - 1); 1427 cp = kmem_io[a].kmem_io_cache[c]; 1428 raddr = kmem_cache_alloc(cp, (cansleep) ? KM_SLEEP : 1429 KM_NOSLEEP); 1430 } 1431 1432 if (raddr == NULL) { 1433 int na; 1434 1435 ASSERT(cansleep == 0); 1436 if (rsize > PAGESIZE) 1437 return (NULL); 1438 /* 1439 * System does not have memory in the requested range. 1440 * Try smaller kmem io ranges and larger cache sizes 1441 * to see if there might be memory available in 1442 * these other caches. 1443 */ 1444 1445 for (na = kmem_io_index_next(a); na >= 0; 1446 na = kmem_io_index_next(na)) { 1447 ASSERT(kmem_io[na].kmem_io_arena); 1448 cp = kmem_io[na].kmem_io_cache[c]; 1449 raddr = kmem_cache_alloc(cp, KM_NOSLEEP); 1450 if (raddr) 1451 goto kallocdone; 1452 } 1453 /* now try the larger kmem io cache sizes */ 1454 for (na = a; na >= 0; na = kmem_io_index_next(na)) { 1455 for (i = c + 1; i < KA_NCACHE; i++) { 1456 cp = kmem_io[na].kmem_io_cache[i]; 1457 raddr = kmem_cache_alloc(cp, KM_NOSLEEP); 1458 if (raddr) 1459 goto kallocdone; 1460 } 1461 } 1462 return (NULL); 1463 } 1464 1465 kallocdone: 1466 ASSERT(!P2CROSS((uintptr_t)raddr, (uintptr_t)raddr + rsize - 1, 1467 PAGESIZE) || rsize > PAGESIZE); 1468 1469 addr = (size_t *)P2ROUNDUP((uintptr_t)raddr + hdrsize, align); 1470 ASSERT((uintptr_t)addr + size - (uintptr_t)raddr <= rsize); 1471 1472 addr[-4] = (size_t)cp; 1473 addr[-3] = (size_t)vmp; 1474 addr[-2] = (size_t)raddr; 1475 addr[-1] = rsize; 1476 1477 return (addr); 1478 } 1479 1480 static void 1481 kfreea(void *addr) 1482 { 1483 size_t size; 1484 1485 if (!((uintptr_t)addr & PAGEOFFSET) && (size = getctgsz(addr))) { 1486 contig_free(addr, size); 1487 } else { 1488 size_t *saddr = addr; 1489 if (saddr[-4] == 0) 1490 vmem_free((vmem_t *)saddr[-3], (void *)saddr[-2], 1491 saddr[-1]); 1492 else 1493 kmem_cache_free((kmem_cache_t *)saddr[-4], 1494 (void *)saddr[-2]); 1495 } 1496 } 1497 1498 /*ARGSUSED*/ 1499 void 1500 i_ddi_devacc_to_hatacc(ddi_device_acc_attr_t *devaccp, uint_t *hataccp) 1501 { 1502 } 1503 1504 /* 1505 * Check if the specified cache attribute is supported on the platform. 1506 * This function must be called before i_ddi_cacheattr_to_hatacc(). 1507 */ 1508 boolean_t 1509 i_ddi_check_cache_attr(uint_t flags) 1510 { 1511 /* 1512 * The cache attributes are mutually exclusive. Any combination of 1513 * the attributes leads to a failure. 1514 */ 1515 uint_t cache_attr = IOMEM_CACHE_ATTR(flags); 1516 if ((cache_attr != 0) && ((cache_attr & (cache_attr - 1)) != 0)) 1517 return (B_FALSE); 1518 1519 /* All cache attributes are supported on X86/X64 */ 1520 if (cache_attr & (IOMEM_DATA_UNCACHED | IOMEM_DATA_CACHED | 1521 IOMEM_DATA_UC_WR_COMBINE)) 1522 return (B_TRUE); 1523 1524 /* undefined attributes */ 1525 return (B_FALSE); 1526 } 1527 1528 /* set HAT cache attributes from the cache attributes */ 1529 void 1530 i_ddi_cacheattr_to_hatacc(uint_t flags, uint_t *hataccp) 1531 { 1532 uint_t cache_attr = IOMEM_CACHE_ATTR(flags); 1533 static char *fname = "i_ddi_cacheattr_to_hatacc"; 1534 1535 /* 1536 * If write-combining is not supported, then it falls back 1537 * to uncacheable. 1538 */ 1539 if (cache_attr == IOMEM_DATA_UC_WR_COMBINE && !(x86_feature & X86_PAT)) 1540 cache_attr = IOMEM_DATA_UNCACHED; 1541 1542 /* 1543 * set HAT attrs according to the cache attrs. 1544 */ 1545 switch (cache_attr) { 1546 case IOMEM_DATA_UNCACHED: 1547 *hataccp &= ~HAT_ORDER_MASK; 1548 *hataccp |= (HAT_STRICTORDER | HAT_PLAT_NOCACHE); 1549 break; 1550 case IOMEM_DATA_UC_WR_COMBINE: 1551 *hataccp &= ~HAT_ORDER_MASK; 1552 *hataccp |= (HAT_MERGING_OK | HAT_PLAT_NOCACHE); 1553 break; 1554 case IOMEM_DATA_CACHED: 1555 *hataccp &= ~HAT_ORDER_MASK; 1556 *hataccp |= HAT_UNORDERED_OK; 1557 break; 1558 /* 1559 * This case must not occur because the cache attribute is scrutinized 1560 * before this function is called. 1561 */ 1562 default: 1563 /* 1564 * set cacheable to hat attrs. 1565 */ 1566 *hataccp &= ~HAT_ORDER_MASK; 1567 *hataccp |= HAT_UNORDERED_OK; 1568 cmn_err(CE_WARN, "%s: cache_attr=0x%x is ignored.", 1569 fname, cache_attr); 1570 } 1571 } 1572 1573 /* 1574 * This should actually be called i_ddi_dma_mem_alloc. There should 1575 * also be an i_ddi_pio_mem_alloc. i_ddi_dma_mem_alloc should call 1576 * through the device tree with the DDI_CTLOPS_DMA_ALIGN ctl ops to 1577 * get alignment requirements for DMA memory. i_ddi_pio_mem_alloc 1578 * should use DDI_CTLOPS_PIO_ALIGN. Since we only have i_ddi_mem_alloc 1579 * so far which is used for both, DMA and PIO, we have to use the DMA 1580 * ctl ops to make everybody happy. 1581 */ 1582 /*ARGSUSED*/ 1583 int 1584 i_ddi_mem_alloc(dev_info_t *dip, ddi_dma_attr_t *attr, 1585 size_t length, int cansleep, int flags, 1586 ddi_device_acc_attr_t *accattrp, caddr_t *kaddrp, 1587 size_t *real_length, ddi_acc_hdl_t *ap) 1588 { 1589 caddr_t a; 1590 int iomin; 1591 ddi_acc_impl_t *iap; 1592 int physcontig = 0; 1593 pgcnt_t npages; 1594 pgcnt_t minctg; 1595 uint_t order; 1596 int e; 1597 1598 /* 1599 * Check legality of arguments 1600 */ 1601 if (length == 0 || kaddrp == NULL || attr == NULL) { 1602 return (DDI_FAILURE); 1603 } 1604 1605 if (attr->dma_attr_minxfer == 0 || attr->dma_attr_align == 0 || 1606 (attr->dma_attr_align & (attr->dma_attr_align - 1)) || 1607 (attr->dma_attr_minxfer & (attr->dma_attr_minxfer - 1))) { 1608 return (DDI_FAILURE); 1609 } 1610 1611 /* 1612 * figure out most restrictive alignment requirement 1613 */ 1614 iomin = attr->dma_attr_minxfer; 1615 iomin = maxbit(iomin, attr->dma_attr_align); 1616 if (iomin == 0) 1617 return (DDI_FAILURE); 1618 1619 ASSERT((iomin & (iomin - 1)) == 0); 1620 1621 /* 1622 * if we allocate memory with IOMEM_DATA_UNCACHED or 1623 * IOMEM_DATA_UC_WR_COMBINE, make sure we allocate a page aligned 1624 * memory that ends on a page boundry. 1625 * Don't want to have to different cache mappings to the same 1626 * physical page. 1627 */ 1628 if (OVERRIDE_CACHE_ATTR(flags)) { 1629 iomin = (iomin + MMU_PAGEOFFSET) & MMU_PAGEMASK; 1630 length = (length + MMU_PAGEOFFSET) & (size_t)MMU_PAGEMASK; 1631 } 1632 1633 /* 1634 * Determine if we need to satisfy the request for physically 1635 * contiguous memory or alignments larger than pagesize. 1636 */ 1637 npages = btopr(length + attr->dma_attr_align); 1638 minctg = howmany(npages, attr->dma_attr_sgllen); 1639 1640 if (minctg > 1) { 1641 uint64_t pfnseg = attr->dma_attr_seg >> PAGESHIFT; 1642 /* 1643 * verify that the minimum contig requirement for the 1644 * actual length does not cross segment boundary. 1645 */ 1646 length = P2ROUNDUP_TYPED(length, attr->dma_attr_minxfer, 1647 size_t); 1648 npages = btopr(length); 1649 minctg = howmany(npages, attr->dma_attr_sgllen); 1650 if (minctg > pfnseg + 1) 1651 return (DDI_FAILURE); 1652 physcontig = 1; 1653 } else { 1654 length = P2ROUNDUP_TYPED(length, iomin, size_t); 1655 } 1656 1657 /* 1658 * Allocate the requested amount from the system. 1659 */ 1660 a = kalloca(length, iomin, cansleep, physcontig, attr); 1661 1662 if ((*kaddrp = a) == NULL) 1663 return (DDI_FAILURE); 1664 1665 /* 1666 * if we to modify the cache attributes, go back and muck with the 1667 * mappings. 1668 */ 1669 if (OVERRIDE_CACHE_ATTR(flags)) { 1670 order = 0; 1671 i_ddi_cacheattr_to_hatacc(flags, &order); 1672 e = kmem_override_cache_attrs(a, length, order); 1673 if (e != 0) { 1674 kfreea(a); 1675 return (DDI_FAILURE); 1676 } 1677 } 1678 1679 if (real_length) { 1680 *real_length = length; 1681 } 1682 if (ap) { 1683 /* 1684 * initialize access handle 1685 */ 1686 iap = (ddi_acc_impl_t *)ap->ah_platform_private; 1687 iap->ahi_acc_attr |= DDI_ACCATTR_CPU_VADDR; 1688 impl_acc_hdl_init(ap); 1689 } 1690 1691 return (DDI_SUCCESS); 1692 } 1693 1694 /* 1695 * covert old DMA limits structure to DMA attribute structure 1696 * and continue 1697 */ 1698 int 1699 i_ddi_mem_alloc_lim(dev_info_t *dip, ddi_dma_lim_t *limits, 1700 size_t length, int cansleep, int streaming, 1701 ddi_device_acc_attr_t *accattrp, caddr_t *kaddrp, 1702 uint_t *real_length, ddi_acc_hdl_t *ap) 1703 { 1704 ddi_dma_attr_t dma_attr, *attrp; 1705 size_t rlen; 1706 int ret; 1707 1708 if (limits == NULL) { 1709 return (DDI_FAILURE); 1710 } 1711 1712 /* 1713 * set up DMA attribute structure to pass to i_ddi_mem_alloc() 1714 */ 1715 attrp = &dma_attr; 1716 attrp->dma_attr_version = DMA_ATTR_V0; 1717 attrp->dma_attr_addr_lo = (uint64_t)limits->dlim_addr_lo; 1718 attrp->dma_attr_addr_hi = (uint64_t)limits->dlim_addr_hi; 1719 attrp->dma_attr_count_max = (uint64_t)limits->dlim_ctreg_max; 1720 attrp->dma_attr_align = 1; 1721 attrp->dma_attr_burstsizes = (uint_t)limits->dlim_burstsizes; 1722 attrp->dma_attr_minxfer = (uint32_t)limits->dlim_minxfer; 1723 attrp->dma_attr_maxxfer = (uint64_t)limits->dlim_reqsize; 1724 attrp->dma_attr_seg = (uint64_t)limits->dlim_adreg_max; 1725 attrp->dma_attr_sgllen = limits->dlim_sgllen; 1726 attrp->dma_attr_granular = (uint32_t)limits->dlim_granular; 1727 attrp->dma_attr_flags = 0; 1728 1729 ret = i_ddi_mem_alloc(dip, attrp, length, cansleep, streaming, 1730 accattrp, kaddrp, &rlen, ap); 1731 if (ret == DDI_SUCCESS) { 1732 if (real_length) 1733 *real_length = (uint_t)rlen; 1734 } 1735 return (ret); 1736 } 1737 1738 /* ARGSUSED */ 1739 void 1740 i_ddi_mem_free(caddr_t kaddr, ddi_acc_hdl_t *ap) 1741 { 1742 if (ap != NULL) { 1743 /* 1744 * if we modified the cache attributes on alloc, go back and 1745 * fix them since this memory could be returned to the 1746 * general pool. 1747 */ 1748 if (OVERRIDE_CACHE_ATTR(ap->ah_xfermodes)) { 1749 uint_t order = 0; 1750 int e; 1751 i_ddi_cacheattr_to_hatacc(IOMEM_DATA_CACHED, &order); 1752 e = kmem_override_cache_attrs(kaddr, ap->ah_len, order); 1753 if (e != 0) { 1754 cmn_err(CE_WARN, "i_ddi_mem_free() failed to " 1755 "override cache attrs, memory leaked\n"); 1756 return; 1757 } 1758 } 1759 } 1760 kfreea(kaddr); 1761 } 1762 1763 /* 1764 * Access Barriers 1765 * 1766 */ 1767 /*ARGSUSED*/ 1768 int 1769 i_ddi_ontrap(ddi_acc_handle_t hp) 1770 { 1771 return (DDI_FAILURE); 1772 } 1773 1774 /*ARGSUSED*/ 1775 void 1776 i_ddi_notrap(ddi_acc_handle_t hp) 1777 { 1778 } 1779 1780 1781 /* 1782 * Misc Functions 1783 */ 1784 1785 /* 1786 * Implementation instance override functions 1787 * 1788 * No override on i86pc 1789 */ 1790 /*ARGSUSED*/ 1791 uint_t 1792 impl_assign_instance(dev_info_t *dip) 1793 { 1794 return ((uint_t)-1); 1795 } 1796 1797 /*ARGSUSED*/ 1798 int 1799 impl_keep_instance(dev_info_t *dip) 1800 { 1801 1802 #if defined(__xpv) 1803 /* 1804 * Do not persist instance numbers assigned to devices in dom0 1805 */ 1806 dev_info_t *pdip; 1807 if (DOMAIN_IS_INITDOMAIN(xen_info)) { 1808 if (((pdip = ddi_get_parent(dip)) != NULL) && 1809 (strcmp(ddi_get_name(pdip), "xpvd") == 0)) 1810 return (DDI_SUCCESS); 1811 } 1812 #endif 1813 return (DDI_FAILURE); 1814 } 1815 1816 /*ARGSUSED*/ 1817 int 1818 impl_free_instance(dev_info_t *dip) 1819 { 1820 return (DDI_FAILURE); 1821 } 1822 1823 /*ARGSUSED*/ 1824 int 1825 impl_check_cpu(dev_info_t *devi) 1826 { 1827 return (DDI_SUCCESS); 1828 } 1829 1830 /* 1831 * Referenced in common/cpr_driver.c: Power off machine. 1832 * Don't know how to power off i86pc. 1833 */ 1834 void 1835 arch_power_down() 1836 {} 1837 1838 /* 1839 * Copy name to property_name, since name 1840 * is in the low address range below kernelbase. 1841 */ 1842 static void 1843 copy_boot_str(const char *boot_str, char *kern_str, int len) 1844 { 1845 int i = 0; 1846 1847 while (i < len - 1 && boot_str[i] != '\0') { 1848 kern_str[i] = boot_str[i]; 1849 i++; 1850 } 1851 1852 kern_str[i] = 0; /* null terminate */ 1853 if (boot_str[i] != '\0') 1854 cmn_err(CE_WARN, 1855 "boot property string is truncated to %s", kern_str); 1856 } 1857 1858 static void 1859 get_boot_properties(void) 1860 { 1861 extern char hw_provider[]; 1862 dev_info_t *devi; 1863 char *name; 1864 int length; 1865 char property_name[50], property_val[50]; 1866 void *bop_staging_area; 1867 1868 bop_staging_area = kmem_zalloc(MMU_PAGESIZE, KM_NOSLEEP); 1869 1870 /* 1871 * Import "root" properties from the boot. 1872 * 1873 * We do this by invoking BOP_NEXTPROP until the list 1874 * is completely copied in. 1875 */ 1876 1877 devi = ddi_root_node(); 1878 for (name = BOP_NEXTPROP(bootops, ""); /* get first */ 1879 name; /* NULL => DONE */ 1880 name = BOP_NEXTPROP(bootops, name)) { /* get next */ 1881 1882 /* copy string to memory above kernelbase */ 1883 copy_boot_str(name, property_name, 50); 1884 1885 /* 1886 * Skip vga properties. They will be picked up later 1887 * by get_vga_properties. 1888 */ 1889 if (strcmp(property_name, "display-edif-block") == 0 || 1890 strcmp(property_name, "display-edif-id") == 0) { 1891 continue; 1892 } 1893 1894 length = BOP_GETPROPLEN(bootops, property_name); 1895 if (length == 0) 1896 continue; 1897 if (length > MMU_PAGESIZE) { 1898 cmn_err(CE_NOTE, 1899 "boot property %s longer than 0x%x, ignored\n", 1900 property_name, MMU_PAGESIZE); 1901 continue; 1902 } 1903 BOP_GETPROP(bootops, property_name, bop_staging_area); 1904 1905 /* 1906 * special properties: 1907 * si-machine, si-hw-provider 1908 * goes to kernel data structures. 1909 * bios-boot-device and stdout 1910 * goes to hardware property list so it may show up 1911 * in the prtconf -vp output. This is needed by 1912 * Install/Upgrade. Once we fix install upgrade, 1913 * this can be taken out. 1914 */ 1915 if (strcmp(name, "si-machine") == 0) { 1916 (void) strncpy(utsname.machine, bop_staging_area, 1917 SYS_NMLN); 1918 utsname.machine[SYS_NMLN - 1] = (char)NULL; 1919 } else if (strcmp(name, "si-hw-provider") == 0) { 1920 (void) strncpy(hw_provider, bop_staging_area, SYS_NMLN); 1921 hw_provider[SYS_NMLN - 1] = (char)NULL; 1922 } else if (strcmp(name, "bios-boot-device") == 0) { 1923 copy_boot_str(bop_staging_area, property_val, 50); 1924 (void) ndi_prop_update_string(DDI_DEV_T_NONE, devi, 1925 property_name, property_val); 1926 } else if (strcmp(name, "stdout") == 0) { 1927 (void) ndi_prop_update_int(DDI_DEV_T_NONE, devi, 1928 property_name, *((int *)bop_staging_area)); 1929 } else { 1930 /* Property type unknown, use old prop interface */ 1931 (void) e_ddi_prop_create(DDI_DEV_T_NONE, devi, 1932 DDI_PROP_CANSLEEP, property_name, bop_staging_area, 1933 length); 1934 } 1935 } 1936 1937 kmem_free(bop_staging_area, MMU_PAGESIZE); 1938 } 1939 1940 static void 1941 get_vga_properties(void) 1942 { 1943 dev_info_t *devi; 1944 major_t major; 1945 char *name; 1946 int length; 1947 char property_val[50]; 1948 void *bop_staging_area; 1949 1950 /* 1951 * XXXX Hack Allert! 1952 * There really needs to be a better way for identifying various 1953 * console framebuffers and their related issues. Till then, 1954 * check for this one as a replacement to vgatext. 1955 */ 1956 major = ddi_name_to_major("ragexl"); 1957 if (major == (major_t)-1) { 1958 major = ddi_name_to_major("vgatext"); 1959 if (major == (major_t)-1) 1960 return; 1961 } 1962 devi = devnamesp[major].dn_head; 1963 if (devi == NULL) 1964 return; 1965 1966 bop_staging_area = kmem_zalloc(MMU_PAGESIZE, KM_SLEEP); 1967 1968 /* 1969 * Import "vga" properties from the boot. 1970 */ 1971 name = "display-edif-block"; 1972 length = BOP_GETPROPLEN(bootops, name); 1973 if (length > 0 && length < MMU_PAGESIZE) { 1974 BOP_GETPROP(bootops, name, bop_staging_area); 1975 (void) ndi_prop_update_byte_array(DDI_DEV_T_NONE, 1976 devi, name, bop_staging_area, length); 1977 } 1978 1979 /* 1980 * kdmconfig is also looking for display-type and 1981 * video-adapter-type. We default to color and svga. 1982 * 1983 * Could it be "monochrome", "vga"? 1984 * Nah, you've got to come to the 21st century... 1985 * And you can set monitor type manually in kdmconfig 1986 * if you are really an old junky. 1987 */ 1988 (void) ndi_prop_update_string(DDI_DEV_T_NONE, 1989 devi, "display-type", "color"); 1990 (void) ndi_prop_update_string(DDI_DEV_T_NONE, 1991 devi, "video-adapter-type", "svga"); 1992 1993 name = "display-edif-id"; 1994 length = BOP_GETPROPLEN(bootops, name); 1995 if (length > 0 && length < MMU_PAGESIZE) { 1996 BOP_GETPROP(bootops, name, bop_staging_area); 1997 copy_boot_str(bop_staging_area, property_val, length); 1998 (void) ndi_prop_update_string(DDI_DEV_T_NONE, 1999 devi, name, property_val); 2000 } 2001 2002 kmem_free(bop_staging_area, MMU_PAGESIZE); 2003 } 2004 2005 2006 /* 2007 * This is temporary, but absolutely necessary. If we are being 2008 * booted with a device tree created by the DevConf project's bootconf 2009 * program, then we have device information nodes that reflect 2010 * reality. At this point in time in the Solaris release schedule, the 2011 * kernel drivers aren't prepared for reality. They still depend on their 2012 * own ad-hoc interpretations of the properties created when their .conf 2013 * files were interpreted. These drivers use an "ignore-hardware-nodes" 2014 * property to prevent them from using the nodes passed up from the bootconf 2015 * device tree. 2016 * 2017 * Trying to assemble root file system drivers as we are booting from 2018 * devconf will fail if the kernel driver is basing its name_addr's on the 2019 * psuedo-node device info while the bootpath passed up from bootconf is using 2020 * reality-based name_addrs. We help the boot along in this case by 2021 * looking at the pre-bootconf bootpath and determining if we would have 2022 * successfully matched if that had been the bootpath we had chosen. 2023 * 2024 * Note that we only even perform this extra check if we've booted 2025 * using bootconf's 1275 compliant bootpath, this is the boot device, and 2026 * we're trying to match the name_addr specified in the 1275 bootpath. 2027 */ 2028 2029 #define MAXCOMPONENTLEN 32 2030 2031 int 2032 x86_old_bootpath_name_addr_match(dev_info_t *cdip, char *caddr, char *naddr) 2033 { 2034 /* 2035 * There are multiple criteria to be met before we can even 2036 * consider allowing a name_addr match here. 2037 * 2038 * 1) We must have been booted such that the bootconf program 2039 * created device tree nodes and properties. This can be 2040 * determined by examining the 'bootpath' property. This 2041 * property will be a non-null string iff bootconf was 2042 * involved in the boot. 2043 * 2044 * 2) The module that we want to match must be the boot device. 2045 * 2046 * 3) The instance of the module we are thinking of letting be 2047 * our match must be ignoring hardware nodes. 2048 * 2049 * 4) The name_addr we want to match must be the name_addr 2050 * specified in the 1275 bootpath. 2051 */ 2052 static char bootdev_module[MAXCOMPONENTLEN]; 2053 static char bootdev_oldmod[MAXCOMPONENTLEN]; 2054 static char bootdev_newaddr[MAXCOMPONENTLEN]; 2055 static char bootdev_oldaddr[MAXCOMPONENTLEN]; 2056 static int quickexit; 2057 2058 char *daddr; 2059 int dlen; 2060 2061 char *lkupname; 2062 int rv = DDI_FAILURE; 2063 2064 if ((ddi_getlongprop(DDI_DEV_T_ANY, cdip, DDI_PROP_DONTPASS, 2065 "devconf-addr", (caddr_t)&daddr, &dlen) == DDI_PROP_SUCCESS) && 2066 (ddi_getprop(DDI_DEV_T_ANY, cdip, DDI_PROP_DONTPASS, 2067 "ignore-hardware-nodes", -1) != -1)) { 2068 if (strcmp(daddr, caddr) == 0) { 2069 return (DDI_SUCCESS); 2070 } 2071 } 2072 2073 if (quickexit) 2074 return (rv); 2075 2076 if (bootdev_module[0] == '\0') { 2077 char *addrp, *eoaddrp; 2078 char *busp, *modp, *atp; 2079 char *bp1275, *bp; 2080 int bp1275len, bplen; 2081 2082 bp1275 = bp = addrp = eoaddrp = busp = modp = atp = NULL; 2083 2084 if (ddi_getlongprop(DDI_DEV_T_ANY, 2085 ddi_root_node(), 0, "bootpath", 2086 (caddr_t)&bp1275, &bp1275len) != DDI_PROP_SUCCESS || 2087 bp1275len <= 1) { 2088 /* 2089 * We didn't boot from bootconf so we never need to 2090 * do any special matches. 2091 */ 2092 quickexit = 1; 2093 if (bp1275) 2094 kmem_free(bp1275, bp1275len); 2095 return (rv); 2096 } 2097 2098 if (ddi_getlongprop(DDI_DEV_T_ANY, 2099 ddi_root_node(), 0, "boot-path", 2100 (caddr_t)&bp, &bplen) != DDI_PROP_SUCCESS || bplen <= 1) { 2101 /* 2102 * No fallback position for matching. This is 2103 * certainly unexpected, but we'll handle it 2104 * just in case. 2105 */ 2106 quickexit = 1; 2107 kmem_free(bp1275, bp1275len); 2108 if (bp) 2109 kmem_free(bp, bplen); 2110 return (rv); 2111 } 2112 2113 /* 2114 * Determine boot device module and 1275 name_addr 2115 * 2116 * bootpath assumed to be of the form /bus/module@name_addr 2117 */ 2118 if (busp = strchr(bp1275, '/')) { 2119 if (modp = strchr(busp + 1, '/')) { 2120 if (atp = strchr(modp + 1, '@')) { 2121 *atp = '\0'; 2122 addrp = atp + 1; 2123 if (eoaddrp = strchr(addrp, '/')) 2124 *eoaddrp = '\0'; 2125 } 2126 } 2127 } 2128 2129 if (modp && addrp) { 2130 (void) strncpy(bootdev_module, modp + 1, 2131 MAXCOMPONENTLEN); 2132 bootdev_module[MAXCOMPONENTLEN - 1] = '\0'; 2133 2134 (void) strncpy(bootdev_newaddr, addrp, MAXCOMPONENTLEN); 2135 bootdev_newaddr[MAXCOMPONENTLEN - 1] = '\0'; 2136 } else { 2137 quickexit = 1; 2138 kmem_free(bp1275, bp1275len); 2139 kmem_free(bp, bplen); 2140 return (rv); 2141 } 2142 2143 /* 2144 * Determine fallback name_addr 2145 * 2146 * 10/3/96 - Also save fallback module name because it 2147 * might actually be different than the current module 2148 * name. E.G., ISA pnp drivers have new names. 2149 * 2150 * bootpath assumed to be of the form /bus/module@name_addr 2151 */ 2152 addrp = NULL; 2153 if (busp = strchr(bp, '/')) { 2154 if (modp = strchr(busp + 1, '/')) { 2155 if (atp = strchr(modp + 1, '@')) { 2156 *atp = '\0'; 2157 addrp = atp + 1; 2158 if (eoaddrp = strchr(addrp, '/')) 2159 *eoaddrp = '\0'; 2160 } 2161 } 2162 } 2163 2164 if (modp && addrp) { 2165 (void) strncpy(bootdev_oldmod, modp + 1, 2166 MAXCOMPONENTLEN); 2167 bootdev_module[MAXCOMPONENTLEN - 1] = '\0'; 2168 2169 (void) strncpy(bootdev_oldaddr, addrp, MAXCOMPONENTLEN); 2170 bootdev_oldaddr[MAXCOMPONENTLEN - 1] = '\0'; 2171 } 2172 2173 /* Free up the bootpath storage now that we're done with it. */ 2174 kmem_free(bp1275, bp1275len); 2175 kmem_free(bp, bplen); 2176 2177 if (bootdev_oldaddr[0] == '\0') { 2178 quickexit = 1; 2179 return (rv); 2180 } 2181 } 2182 2183 if (((lkupname = ddi_get_name(cdip)) != NULL) && 2184 (strcmp(bootdev_module, lkupname) == 0 || 2185 strcmp(bootdev_oldmod, lkupname) == 0) && 2186 ((ddi_getprop(DDI_DEV_T_ANY, cdip, DDI_PROP_DONTPASS, 2187 "ignore-hardware-nodes", -1) != -1) || 2188 ignore_hardware_nodes) && 2189 strcmp(bootdev_newaddr, caddr) == 0 && 2190 strcmp(bootdev_oldaddr, naddr) == 0) { 2191 rv = DDI_SUCCESS; 2192 } 2193 2194 return (rv); 2195 } 2196 2197 /* 2198 * Perform a copy from a memory mapped device (whose devinfo pointer is devi) 2199 * separately mapped at devaddr in the kernel to a kernel buffer at kaddr. 2200 */ 2201 /*ARGSUSED*/ 2202 int 2203 e_ddi_copyfromdev(dev_info_t *devi, 2204 off_t off, const void *devaddr, void *kaddr, size_t len) 2205 { 2206 bcopy(devaddr, kaddr, len); 2207 return (0); 2208 } 2209 2210 /* 2211 * Perform a copy to a memory mapped device (whose devinfo pointer is devi) 2212 * separately mapped at devaddr in the kernel from a kernel buffer at kaddr. 2213 */ 2214 /*ARGSUSED*/ 2215 int 2216 e_ddi_copytodev(dev_info_t *devi, 2217 off_t off, const void *kaddr, void *devaddr, size_t len) 2218 { 2219 bcopy(kaddr, devaddr, len); 2220 return (0); 2221 } 2222 2223 2224 static int 2225 poke_mem(peekpoke_ctlops_t *in_args) 2226 { 2227 int err = DDI_SUCCESS; 2228 on_trap_data_t otd; 2229 2230 /* Set up protected environment. */ 2231 if (!on_trap(&otd, OT_DATA_ACCESS)) { 2232 switch (in_args->size) { 2233 case sizeof (uint8_t): 2234 *(uint8_t *)(in_args->dev_addr) = 2235 *(uint8_t *)in_args->host_addr; 2236 break; 2237 2238 case sizeof (uint16_t): 2239 *(uint16_t *)(in_args->dev_addr) = 2240 *(uint16_t *)in_args->host_addr; 2241 break; 2242 2243 case sizeof (uint32_t): 2244 *(uint32_t *)(in_args->dev_addr) = 2245 *(uint32_t *)in_args->host_addr; 2246 break; 2247 2248 case sizeof (uint64_t): 2249 *(uint64_t *)(in_args->dev_addr) = 2250 *(uint64_t *)in_args->host_addr; 2251 break; 2252 2253 default: 2254 err = DDI_FAILURE; 2255 break; 2256 } 2257 } else 2258 err = DDI_FAILURE; 2259 2260 /* Take down protected environment. */ 2261 no_trap(); 2262 2263 return (err); 2264 } 2265 2266 2267 static int 2268 peek_mem(peekpoke_ctlops_t *in_args) 2269 { 2270 int err = DDI_SUCCESS; 2271 on_trap_data_t otd; 2272 2273 if (!on_trap(&otd, OT_DATA_ACCESS)) { 2274 switch (in_args->size) { 2275 case sizeof (uint8_t): 2276 *(uint8_t *)in_args->host_addr = 2277 *(uint8_t *)in_args->dev_addr; 2278 break; 2279 2280 case sizeof (uint16_t): 2281 *(uint16_t *)in_args->host_addr = 2282 *(uint16_t *)in_args->dev_addr; 2283 break; 2284 2285 case sizeof (uint32_t): 2286 *(uint32_t *)in_args->host_addr = 2287 *(uint32_t *)in_args->dev_addr; 2288 break; 2289 2290 case sizeof (uint64_t): 2291 *(uint64_t *)in_args->host_addr = 2292 *(uint64_t *)in_args->dev_addr; 2293 break; 2294 2295 default: 2296 err = DDI_FAILURE; 2297 break; 2298 } 2299 } else 2300 err = DDI_FAILURE; 2301 2302 no_trap(); 2303 return (err); 2304 } 2305 2306 2307 /* 2308 * This is called only to process peek/poke when the DIP is NULL. 2309 * Assume that this is for memory, as nexi take care of device safe accesses. 2310 */ 2311 int 2312 peekpoke_mem(ddi_ctl_enum_t cmd, peekpoke_ctlops_t *in_args) 2313 { 2314 return (cmd == DDI_CTLOPS_PEEK ? peek_mem(in_args) : poke_mem(in_args)); 2315 } 2316 2317 /* 2318 * we've just done a cautious put/get. Check if it was successful by 2319 * calling pci_ereport_post() on all puts and for any gets that return -1 2320 */ 2321 static int 2322 pci_peekpoke_check_fma(dev_info_t *dip, void *arg, ddi_ctl_enum_t ctlop) 2323 { 2324 int rval = DDI_SUCCESS; 2325 peekpoke_ctlops_t *in_args = (peekpoke_ctlops_t *)arg; 2326 ddi_fm_error_t de; 2327 ddi_acc_impl_t *hp = (ddi_acc_impl_t *)in_args->handle; 2328 ddi_acc_hdl_t *hdlp = (ddi_acc_hdl_t *)in_args->handle; 2329 int check_err = 0; 2330 int repcount = in_args->repcount; 2331 2332 if (ctlop == DDI_CTLOPS_POKE && 2333 hdlp->ah_acc.devacc_attr_access != DDI_CAUTIOUS_ACC) 2334 return (DDI_SUCCESS); 2335 2336 if (ctlop == DDI_CTLOPS_PEEK && 2337 hdlp->ah_acc.devacc_attr_access != DDI_CAUTIOUS_ACC) { 2338 for (; repcount; repcount--) { 2339 switch (in_args->size) { 2340 case sizeof (uint8_t): 2341 if (*(uint8_t *)in_args->host_addr == 0xff) 2342 check_err = 1; 2343 break; 2344 case sizeof (uint16_t): 2345 if (*(uint16_t *)in_args->host_addr == 0xffff) 2346 check_err = 1; 2347 break; 2348 case sizeof (uint32_t): 2349 if (*(uint32_t *)in_args->host_addr == 2350 0xffffffff) 2351 check_err = 1; 2352 break; 2353 case sizeof (uint64_t): 2354 if (*(uint64_t *)in_args->host_addr == 2355 0xffffffffffffffff) 2356 check_err = 1; 2357 break; 2358 } 2359 } 2360 if (check_err == 0) 2361 return (DDI_SUCCESS); 2362 } 2363 /* 2364 * for a cautious put or get or a non-cautious get that returned -1 call 2365 * io framework to see if there really was an error 2366 */ 2367 bzero(&de, sizeof (ddi_fm_error_t)); 2368 de.fme_version = DDI_FME_VERSION; 2369 de.fme_ena = fm_ena_generate(0, FM_ENA_FMT1); 2370 if (hdlp->ah_acc.devacc_attr_access == DDI_CAUTIOUS_ACC) { 2371 de.fme_flag = DDI_FM_ERR_EXPECTED; 2372 de.fme_acc_handle = in_args->handle; 2373 } else if (hdlp->ah_acc.devacc_attr_access == DDI_DEFAULT_ACC) { 2374 /* 2375 * We only get here with DDI_DEFAULT_ACC for config space gets. 2376 * Non-hardened drivers may be probing the hardware and 2377 * expecting -1 returned. So need to treat errors on 2378 * DDI_DEFAULT_ACC as DDI_FM_ERR_EXPECTED. 2379 */ 2380 de.fme_flag = DDI_FM_ERR_EXPECTED; 2381 de.fme_acc_handle = in_args->handle; 2382 } else { 2383 /* 2384 * Hardened driver doing protected accesses shouldn't 2385 * get errors unless there's a hardware problem. Treat 2386 * as nonfatal if there's an error, but set UNEXPECTED 2387 * so we raise ereports on any errors and potentially 2388 * fault the device 2389 */ 2390 de.fme_flag = DDI_FM_ERR_UNEXPECTED; 2391 } 2392 pci_ereport_post(dip, &de, NULL); 2393 if (hdlp->ah_acc.devacc_attr_access != DDI_DEFAULT_ACC && 2394 de.fme_status != DDI_FM_OK) { 2395 ndi_err_t *errp = (ndi_err_t *)hp->ahi_err; 2396 rval = DDI_FAILURE; 2397 errp->err_ena = de.fme_ena; 2398 errp->err_expected = de.fme_flag; 2399 errp->err_status = DDI_FM_NONFATAL; 2400 } 2401 return (rval); 2402 } 2403 2404 /* 2405 * pci_peekpoke_check_nofma() is for when an error occurs on a register access 2406 * during pci_ereport_post(). We can't call pci_ereport_post() again or we'd 2407 * recurse, so assume all puts are OK and gets have failed if they return -1 2408 */ 2409 static int 2410 pci_peekpoke_check_nofma(void *arg, ddi_ctl_enum_t ctlop) 2411 { 2412 int rval = DDI_SUCCESS; 2413 peekpoke_ctlops_t *in_args = (peekpoke_ctlops_t *)arg; 2414 ddi_acc_impl_t *hp = (ddi_acc_impl_t *)in_args->handle; 2415 ddi_acc_hdl_t *hdlp = (ddi_acc_hdl_t *)in_args->handle; 2416 int repcount = in_args->repcount; 2417 2418 if (ctlop == DDI_CTLOPS_POKE) 2419 return (rval); 2420 2421 for (; repcount; repcount--) { 2422 switch (in_args->size) { 2423 case sizeof (uint8_t): 2424 if (*(uint8_t *)in_args->host_addr == 0xff) 2425 rval = DDI_FAILURE; 2426 break; 2427 case sizeof (uint16_t): 2428 if (*(uint16_t *)in_args->host_addr == 0xffff) 2429 rval = DDI_FAILURE; 2430 break; 2431 case sizeof (uint32_t): 2432 if (*(uint32_t *)in_args->host_addr == 0xffffffff) 2433 rval = DDI_FAILURE; 2434 break; 2435 case sizeof (uint64_t): 2436 if (*(uint64_t *)in_args->host_addr == 2437 0xffffffffffffffff) 2438 rval = DDI_FAILURE; 2439 break; 2440 } 2441 } 2442 if (hdlp->ah_acc.devacc_attr_access != DDI_DEFAULT_ACC && 2443 rval == DDI_FAILURE) { 2444 ndi_err_t *errp = (ndi_err_t *)hp->ahi_err; 2445 errp->err_ena = fm_ena_generate(0, FM_ENA_FMT1); 2446 errp->err_expected = DDI_FM_ERR_UNEXPECTED; 2447 errp->err_status = DDI_FM_NONFATAL; 2448 } 2449 return (rval); 2450 } 2451 2452 int 2453 pci_peekpoke_check(dev_info_t *dip, dev_info_t *rdip, 2454 ddi_ctl_enum_t ctlop, void *arg, void *result, 2455 int (*handler)(dev_info_t *, dev_info_t *, ddi_ctl_enum_t, void *, 2456 void *), kmutex_t *err_mutexp, kmutex_t *peek_poke_mutexp) 2457 { 2458 int rval; 2459 peekpoke_ctlops_t *in_args = (peekpoke_ctlops_t *)arg; 2460 ddi_acc_impl_t *hp = (ddi_acc_impl_t *)in_args->handle; 2461 2462 /* 2463 * this function only supports cautious accesses, not peeks/pokes 2464 * which don't have a handle 2465 */ 2466 if (hp == NULL) 2467 return (DDI_FAILURE); 2468 2469 if (hp->ahi_acc_attr & DDI_ACCATTR_CONFIG_SPACE) { 2470 if (!mutex_tryenter(err_mutexp)) { 2471 /* 2472 * As this may be a recursive call from within 2473 * pci_ereport_post() we can't wait for the mutexes. 2474 * Fortunately we know someone is already calling 2475 * pci_ereport_post() which will handle the error bits 2476 * for us, and as this is a config space access we can 2477 * just do the access and check return value for -1 2478 * using pci_peekpoke_check_nofma(). 2479 */ 2480 rval = handler(dip, rdip, ctlop, arg, result); 2481 if (rval == DDI_SUCCESS) 2482 rval = pci_peekpoke_check_nofma(arg, ctlop); 2483 return (rval); 2484 } 2485 /* 2486 * This can't be a recursive call. Drop the err_mutex and get 2487 * both mutexes in the right order. If an error hasn't already 2488 * been detected by the ontrap code, use pci_peekpoke_check_fma 2489 * which will call pci_ereport_post() to check error status. 2490 */ 2491 mutex_exit(err_mutexp); 2492 } 2493 mutex_enter(peek_poke_mutexp); 2494 rval = handler(dip, rdip, ctlop, arg, result); 2495 if (rval == DDI_SUCCESS) { 2496 mutex_enter(err_mutexp); 2497 rval = pci_peekpoke_check_fma(dip, arg, ctlop); 2498 mutex_exit(err_mutexp); 2499 } 2500 mutex_exit(peek_poke_mutexp); 2501 return (rval); 2502 } 2503 2504 void 2505 impl_setup_ddi(void) 2506 { 2507 dev_info_t *xdip, *isa_dip; 2508 rd_existing_t rd_mem_prop; 2509 int err; 2510 2511 ndi_devi_alloc_sleep(ddi_root_node(), "ramdisk", 2512 (pnode_t)DEVI_SID_NODEID, &xdip); 2513 2514 (void) BOP_GETPROP(bootops, 2515 "ramdisk_start", (void *)&ramdisk_start); 2516 (void) BOP_GETPROP(bootops, 2517 "ramdisk_end", (void *)&ramdisk_end); 2518 2519 #ifdef __xpv 2520 ramdisk_start -= ONE_GIG; 2521 ramdisk_end -= ONE_GIG; 2522 #endif 2523 rd_mem_prop.phys = ramdisk_start; 2524 rd_mem_prop.size = ramdisk_end - ramdisk_start + 1; 2525 2526 (void) ndi_prop_update_byte_array(DDI_DEV_T_NONE, xdip, 2527 RD_EXISTING_PROP_NAME, (uchar_t *)&rd_mem_prop, 2528 sizeof (rd_mem_prop)); 2529 err = ndi_devi_bind_driver(xdip, 0); 2530 ASSERT(err == 0); 2531 2532 /* isa node */ 2533 ndi_devi_alloc_sleep(ddi_root_node(), "isa", 2534 (pnode_t)DEVI_SID_NODEID, &isa_dip); 2535 (void) ndi_prop_update_string(DDI_DEV_T_NONE, isa_dip, 2536 "device_type", "isa"); 2537 (void) ndi_prop_update_string(DDI_DEV_T_NONE, isa_dip, 2538 "bus-type", "isa"); 2539 (void) ndi_devi_bind_driver(isa_dip, 0); 2540 2541 /* 2542 * Read in the properties from the boot. 2543 */ 2544 get_boot_properties(); 2545 2546 /* do bus dependent probes. */ 2547 impl_bus_initialprobe(); 2548 2549 /* not framebuffer should be enumerated, if present */ 2550 get_vga_properties(); 2551 } 2552 2553 dev_t 2554 getrootdev(void) 2555 { 2556 /* 2557 * Precedence given to rootdev if set in /etc/system 2558 */ 2559 if (root_is_svm == B_TRUE) { 2560 return (ddi_pathname_to_dev_t(svm_bootpath)); 2561 } 2562 2563 /* 2564 * Usually rootfs.bo_name is initialized by the 2565 * the bootpath property from bootenv.rc, but 2566 * defaults to "/ramdisk:a" otherwise. 2567 */ 2568 return (ddi_pathname_to_dev_t(rootfs.bo_name)); 2569 } 2570 2571 static struct bus_probe { 2572 struct bus_probe *next; 2573 void (*probe)(int); 2574 } *bus_probes; 2575 2576 void 2577 impl_bus_add_probe(void (*func)(int)) 2578 { 2579 struct bus_probe *probe; 2580 2581 probe = kmem_alloc(sizeof (*probe), KM_SLEEP); 2582 probe->next = bus_probes; 2583 probe->probe = func; 2584 bus_probes = probe; 2585 } 2586 2587 /*ARGSUSED*/ 2588 void 2589 impl_bus_delete_probe(void (*func)(int)) 2590 { 2591 struct bus_probe *prev = NULL; 2592 struct bus_probe *probe = bus_probes; 2593 2594 while (probe) { 2595 if (probe->probe == func) 2596 break; 2597 prev = probe; 2598 probe = probe->next; 2599 } 2600 2601 if (probe == NULL) 2602 return; 2603 2604 if (prev) 2605 prev->next = probe->next; 2606 else 2607 bus_probes = probe->next; 2608 2609 kmem_free(probe, sizeof (struct bus_probe)); 2610 } 2611 2612 /* 2613 * impl_bus_initialprobe 2614 * Modload the prom simulator, then let it probe to verify existence 2615 * and type of PCI support. 2616 */ 2617 static void 2618 impl_bus_initialprobe(void) 2619 { 2620 struct bus_probe *probe; 2621 2622 /* load modules to install bus probes */ 2623 #if defined(__xpv) 2624 if (DOMAIN_IS_INITDOMAIN(xen_info)) { 2625 if (modload("misc", "pci_autoconfig") < 0) { 2626 panic("failed to load misc/pci_autoconfig"); 2627 } 2628 } 2629 (void) modload("misc", "xpv_autoconfig"); 2630 #else 2631 if (modload("misc", "pci_autoconfig") < 0) { 2632 panic("failed to load misc/pci_autoconfig"); 2633 } 2634 #endif 2635 2636 probe = bus_probes; 2637 while (probe) { 2638 /* run the probe functions */ 2639 (*probe->probe)(0); 2640 probe = probe->next; 2641 } 2642 } 2643 2644 /* 2645 * impl_bus_reprobe 2646 * Reprogram devices not set up by firmware. 2647 */ 2648 static void 2649 impl_bus_reprobe(void) 2650 { 2651 struct bus_probe *probe; 2652 2653 probe = bus_probes; 2654 while (probe) { 2655 /* run the probe function */ 2656 (*probe->probe)(1); 2657 probe = probe->next; 2658 } 2659 } 2660 2661 2662 /* 2663 * The following functions ready a cautious request to go up to the nexus 2664 * driver. It is up to the nexus driver to decide how to process the request. 2665 * It may choose to call i_ddi_do_caut_get/put in this file, or do it 2666 * differently. 2667 */ 2668 2669 static void 2670 i_ddi_caut_getput_ctlops(ddi_acc_impl_t *hp, uint64_t host_addr, 2671 uint64_t dev_addr, size_t size, size_t repcount, uint_t flags, 2672 ddi_ctl_enum_t cmd) 2673 { 2674 peekpoke_ctlops_t cautacc_ctlops_arg; 2675 2676 cautacc_ctlops_arg.size = size; 2677 cautacc_ctlops_arg.dev_addr = dev_addr; 2678 cautacc_ctlops_arg.host_addr = host_addr; 2679 cautacc_ctlops_arg.handle = (ddi_acc_handle_t)hp; 2680 cautacc_ctlops_arg.repcount = repcount; 2681 cautacc_ctlops_arg.flags = flags; 2682 2683 (void) ddi_ctlops(hp->ahi_common.ah_dip, hp->ahi_common.ah_dip, cmd, 2684 &cautacc_ctlops_arg, NULL); 2685 } 2686 2687 uint8_t 2688 i_ddi_caut_get8(ddi_acc_impl_t *hp, uint8_t *addr) 2689 { 2690 uint8_t value; 2691 i_ddi_caut_getput_ctlops(hp, (uintptr_t)&value, (uintptr_t)addr, 2692 sizeof (uint8_t), 1, 0, DDI_CTLOPS_PEEK); 2693 2694 return (value); 2695 } 2696 2697 uint16_t 2698 i_ddi_caut_get16(ddi_acc_impl_t *hp, uint16_t *addr) 2699 { 2700 uint16_t value; 2701 i_ddi_caut_getput_ctlops(hp, (uintptr_t)&value, (uintptr_t)addr, 2702 sizeof (uint16_t), 1, 0, DDI_CTLOPS_PEEK); 2703 2704 return (value); 2705 } 2706 2707 uint32_t 2708 i_ddi_caut_get32(ddi_acc_impl_t *hp, uint32_t *addr) 2709 { 2710 uint32_t value; 2711 i_ddi_caut_getput_ctlops(hp, (uintptr_t)&value, (uintptr_t)addr, 2712 sizeof (uint32_t), 1, 0, DDI_CTLOPS_PEEK); 2713 2714 return (value); 2715 } 2716 2717 uint64_t 2718 i_ddi_caut_get64(ddi_acc_impl_t *hp, uint64_t *addr) 2719 { 2720 uint64_t value; 2721 i_ddi_caut_getput_ctlops(hp, (uintptr_t)&value, (uintptr_t)addr, 2722 sizeof (uint64_t), 1, 0, DDI_CTLOPS_PEEK); 2723 2724 return (value); 2725 } 2726 2727 void 2728 i_ddi_caut_put8(ddi_acc_impl_t *hp, uint8_t *addr, uint8_t value) 2729 { 2730 i_ddi_caut_getput_ctlops(hp, (uintptr_t)&value, (uintptr_t)addr, 2731 sizeof (uint8_t), 1, 0, DDI_CTLOPS_POKE); 2732 } 2733 2734 void 2735 i_ddi_caut_put16(ddi_acc_impl_t *hp, uint16_t *addr, uint16_t value) 2736 { 2737 i_ddi_caut_getput_ctlops(hp, (uintptr_t)&value, (uintptr_t)addr, 2738 sizeof (uint16_t), 1, 0, DDI_CTLOPS_POKE); 2739 } 2740 2741 void 2742 i_ddi_caut_put32(ddi_acc_impl_t *hp, uint32_t *addr, uint32_t value) 2743 { 2744 i_ddi_caut_getput_ctlops(hp, (uintptr_t)&value, (uintptr_t)addr, 2745 sizeof (uint32_t), 1, 0, DDI_CTLOPS_POKE); 2746 } 2747 2748 void 2749 i_ddi_caut_put64(ddi_acc_impl_t *hp, uint64_t *addr, uint64_t value) 2750 { 2751 i_ddi_caut_getput_ctlops(hp, (uintptr_t)&value, (uintptr_t)addr, 2752 sizeof (uint64_t), 1, 0, DDI_CTLOPS_POKE); 2753 } 2754 2755 void 2756 i_ddi_caut_rep_get8(ddi_acc_impl_t *hp, uint8_t *host_addr, uint8_t *dev_addr, 2757 size_t repcount, uint_t flags) 2758 { 2759 i_ddi_caut_getput_ctlops(hp, (uintptr_t)host_addr, (uintptr_t)dev_addr, 2760 sizeof (uint8_t), repcount, flags, DDI_CTLOPS_PEEK); 2761 } 2762 2763 void 2764 i_ddi_caut_rep_get16(ddi_acc_impl_t *hp, uint16_t *host_addr, 2765 uint16_t *dev_addr, size_t repcount, uint_t flags) 2766 { 2767 i_ddi_caut_getput_ctlops(hp, (uintptr_t)host_addr, (uintptr_t)dev_addr, 2768 sizeof (uint16_t), repcount, flags, DDI_CTLOPS_PEEK); 2769 } 2770 2771 void 2772 i_ddi_caut_rep_get32(ddi_acc_impl_t *hp, uint32_t *host_addr, 2773 uint32_t *dev_addr, size_t repcount, uint_t flags) 2774 { 2775 i_ddi_caut_getput_ctlops(hp, (uintptr_t)host_addr, (uintptr_t)dev_addr, 2776 sizeof (uint32_t), repcount, flags, DDI_CTLOPS_PEEK); 2777 } 2778 2779 void 2780 i_ddi_caut_rep_get64(ddi_acc_impl_t *hp, uint64_t *host_addr, 2781 uint64_t *dev_addr, size_t repcount, uint_t flags) 2782 { 2783 i_ddi_caut_getput_ctlops(hp, (uintptr_t)host_addr, (uintptr_t)dev_addr, 2784 sizeof (uint64_t), repcount, flags, DDI_CTLOPS_PEEK); 2785 } 2786 2787 void 2788 i_ddi_caut_rep_put8(ddi_acc_impl_t *hp, uint8_t *host_addr, uint8_t *dev_addr, 2789 size_t repcount, uint_t flags) 2790 { 2791 i_ddi_caut_getput_ctlops(hp, (uintptr_t)host_addr, (uintptr_t)dev_addr, 2792 sizeof (uint8_t), repcount, flags, DDI_CTLOPS_POKE); 2793 } 2794 2795 void 2796 i_ddi_caut_rep_put16(ddi_acc_impl_t *hp, uint16_t *host_addr, 2797 uint16_t *dev_addr, size_t repcount, uint_t flags) 2798 { 2799 i_ddi_caut_getput_ctlops(hp, (uintptr_t)host_addr, (uintptr_t)dev_addr, 2800 sizeof (uint16_t), repcount, flags, DDI_CTLOPS_POKE); 2801 } 2802 2803 void 2804 i_ddi_caut_rep_put32(ddi_acc_impl_t *hp, uint32_t *host_addr, 2805 uint32_t *dev_addr, size_t repcount, uint_t flags) 2806 { 2807 i_ddi_caut_getput_ctlops(hp, (uintptr_t)host_addr, (uintptr_t)dev_addr, 2808 sizeof (uint32_t), repcount, flags, DDI_CTLOPS_POKE); 2809 } 2810 2811 void 2812 i_ddi_caut_rep_put64(ddi_acc_impl_t *hp, uint64_t *host_addr, 2813 uint64_t *dev_addr, size_t repcount, uint_t flags) 2814 { 2815 i_ddi_caut_getput_ctlops(hp, (uintptr_t)host_addr, (uintptr_t)dev_addr, 2816 sizeof (uint64_t), repcount, flags, DDI_CTLOPS_POKE); 2817 } 2818 2819 boolean_t 2820 i_ddi_copybuf_required(ddi_dma_attr_t *attrp) 2821 { 2822 uint64_t hi_pa; 2823 2824 hi_pa = ((uint64_t)physmax + 1ull) << PAGESHIFT; 2825 if (attrp->dma_attr_addr_hi < hi_pa) { 2826 return (B_TRUE); 2827 } 2828 2829 return (B_FALSE); 2830 } 2831 2832 size_t 2833 i_ddi_copybuf_size() 2834 { 2835 return (dma_max_copybuf_size); 2836 } 2837 2838 /* 2839 * i_ddi_dma_max() 2840 * returns the maximum DMA size which can be performed in a single DMA 2841 * window taking into account the devices DMA contraints (attrp), the 2842 * maximum copy buffer size (if applicable), and the worse case buffer 2843 * fragmentation. 2844 */ 2845 /*ARGSUSED*/ 2846 uint32_t 2847 i_ddi_dma_max(dev_info_t *dip, ddi_dma_attr_t *attrp) 2848 { 2849 uint64_t maxxfer; 2850 2851 2852 /* 2853 * take the min of maxxfer and the the worse case fragementation 2854 * (e.g. every cookie <= 1 page) 2855 */ 2856 maxxfer = MIN(attrp->dma_attr_maxxfer, 2857 ((uint64_t)(attrp->dma_attr_sgllen - 1) << PAGESHIFT)); 2858 2859 /* 2860 * If the DMA engine can't reach all off memory, we also need to take 2861 * the max size of the copybuf into consideration. 2862 */ 2863 if (i_ddi_copybuf_required(attrp)) { 2864 maxxfer = MIN(i_ddi_copybuf_size(), maxxfer); 2865 } 2866 2867 /* 2868 * we only return a 32-bit value. Make sure it's not -1. Round to a 2869 * page so it won't be mistaken for an error value during debug. 2870 */ 2871 if (maxxfer >= 0xFFFFFFFF) { 2872 maxxfer = 0xFFFFF000; 2873 } 2874 2875 /* 2876 * make sure the value we return is a whole multiple of the 2877 * granlarity. 2878 */ 2879 if (attrp->dma_attr_granular > 1) { 2880 maxxfer = maxxfer - (maxxfer % attrp->dma_attr_granular); 2881 } 2882 2883 return ((uint32_t)maxxfer); 2884 } 2885