1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 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/ramdisk.h> 60 #include <sys/sunndi.h> 61 #include <sys/vmem.h> 62 #include <sys/pci_impl.h> 63 64 /* 65 * DDI Boot Configuration 66 */ 67 68 /* 69 * No platform drivers on this platform 70 */ 71 char *platform_module_list[] = { 72 (char *)0 73 }; 74 75 /* pci bus resource maps */ 76 struct pci_bus_resource *pci_bus_res; 77 78 extern int root_is_svm; 79 uint64_t ramdisk_start, ramdisk_end; 80 81 /* 82 * Forward declarations 83 */ 84 static int getlongprop_buf(); 85 static void get_boot_properties(void); 86 static void impl_bus_initialprobe(void); 87 static void impl_bus_reprobe(void); 88 89 static int poke_mem(peekpoke_ctlops_t *in_args); 90 static int peek_mem(peekpoke_ctlops_t *in_args); 91 92 #define CTGENTRIES 15 93 94 static struct ctgas { 95 struct ctgas *ctg_next; 96 int ctg_index; 97 void *ctg_addr[CTGENTRIES]; 98 size_t ctg_size[CTGENTRIES]; 99 } ctglist; 100 101 static kmutex_t ctgmutex; 102 #define CTGLOCK() mutex_enter(&ctgmutex) 103 #define CTGUNLOCK() mutex_exit(&ctgmutex) 104 105 /* 106 * Minimum pfn value of page_t's put on the free list. This is to simplify 107 * support of ddi dma memory requests which specify small, non-zero addr_lo 108 * values. 109 * 110 * The default value of 2, which corresponds to the only known non-zero addr_lo 111 * value used, means a single page will be sacrificed (pfn typically starts 112 * at 1). ddiphysmin can be set to 0 to disable. It cannot be set above 0x100 113 * otherwise mp startup panics. 114 */ 115 pfn_t ddiphysmin = 2; 116 117 static void 118 check_driver_disable(void) 119 { 120 int proplen = 128; 121 char *prop_name; 122 char *drv_name, *propval; 123 major_t major; 124 125 prop_name = kmem_alloc(proplen, KM_SLEEP); 126 for (major = 0; major < devcnt; major++) { 127 drv_name = ddi_major_to_name(major); 128 if (drv_name == NULL) 129 continue; 130 (void) snprintf(prop_name, proplen, "disable-%s", drv_name); 131 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_root_node(), 132 DDI_PROP_DONTPASS, prop_name, &propval) == DDI_SUCCESS) { 133 if (strcmp(propval, "true") == 0) { 134 devnamesp[major].dn_flags |= DN_DRIVER_REMOVED; 135 cmn_err(CE_NOTE, "driver %s disabled", 136 drv_name); 137 } 138 ddi_prop_free(propval); 139 } 140 } 141 kmem_free(prop_name, proplen); 142 } 143 144 145 /* 146 * Configure the hardware on the system. 147 * Called before the rootfs is mounted 148 */ 149 void 150 configure(void) 151 { 152 extern void i_ddi_init_root(); 153 154 #if defined(__i386) 155 extern int fpu_pentium_fdivbug; 156 #endif /* __i386 */ 157 extern int fpu_ignored; 158 159 /* 160 * Determine if an FPU is attached 161 */ 162 163 fpu_probe(); 164 165 #if defined(__i386) 166 if (fpu_pentium_fdivbug) { 167 printf("\ 168 FP hardware exhibits Pentium floating point divide problem\n"); 169 } 170 #endif /* __i386 */ 171 172 if (fpu_ignored) { 173 printf("FP hardware will not be used\n"); 174 } else if (!fpu_exists) { 175 printf("No FPU in configuration\n"); 176 } 177 178 /* 179 * Initialize devices on the machine. 180 * Uses configuration tree built by the PROMs to determine what 181 * is present, and builds a tree of prototype dev_info nodes 182 * corresponding to the hardware which identified itself. 183 */ 184 #if !defined(SAS) && !defined(MPSAS) 185 /* 186 * Check for disabled drivers and initialize root node. 187 */ 188 check_driver_disable(); 189 i_ddi_init_root(); 190 191 /* 192 * attach the isa nexus to get ACPI resource usage 193 * isa is "kind of" a pseudo node 194 */ 195 (void) i_ddi_attach_pseudo_node("isa"); 196 197 /* reprogram devices not set up by firmware (BIOS) */ 198 impl_bus_reprobe(); 199 #endif /* !SAS && !MPSAS */ 200 } 201 202 /* 203 * The "status" property indicates the operational status of a device. 204 * If this property is present, the value is a string indicating the 205 * status of the device as follows: 206 * 207 * "okay" operational. 208 * "disabled" not operational, but might become operational. 209 * "fail" not operational because a fault has been detected, 210 * and it is unlikely that the device will become 211 * operational without repair. no additional details 212 * are available. 213 * "fail-xxx" not operational because a fault has been detected, 214 * and it is unlikely that the device will become 215 * operational without repair. "xxx" is additional 216 * human-readable information about the particular 217 * fault condition that was detected. 218 * 219 * The absence of this property means that the operational status is 220 * unknown or okay. 221 * 222 * This routine checks the status property of the specified device node 223 * and returns 0 if the operational status indicates failure, and 1 otherwise. 224 * 225 * The property may exist on plug-in cards the existed before IEEE 1275-1994. 226 * And, in that case, the property may not even be a string. So we carefully 227 * check for the value "fail", in the beginning of the string, noting 228 * the property length. 229 */ 230 int 231 status_okay(int id, char *buf, int buflen) 232 { 233 char status_buf[OBP_MAXPROPNAME]; 234 char *bufp = buf; 235 int len = buflen; 236 int proplen; 237 static const char *status = "status"; 238 static const char *fail = "fail"; 239 int fail_len = (int)strlen(fail); 240 241 /* 242 * Get the proplen ... if it's smaller than "fail", 243 * or doesn't exist ... then we don't care, since 244 * the value can't begin with the char string "fail". 245 * 246 * NB: proplen, if it's a string, includes the NULL in the 247 * the size of the property, and fail_len does not. 248 */ 249 proplen = prom_getproplen((dnode_t)id, (caddr_t)status); 250 if (proplen <= fail_len) /* nonexistant or uninteresting len */ 251 return (1); 252 253 /* 254 * if a buffer was provided, use it 255 */ 256 if ((buf == (char *)NULL) || (buflen <= 0)) { 257 bufp = status_buf; 258 len = sizeof (status_buf); 259 } 260 *bufp = (char)0; 261 262 /* 263 * Get the property into the buffer, to the extent of the buffer, 264 * and in case the buffer is smaller than the property size, 265 * NULL terminate the buffer. (This handles the case where 266 * a buffer was passed in and the caller wants to print the 267 * value, but the buffer was too small). 268 */ 269 (void) prom_bounded_getprop((dnode_t)id, (caddr_t)status, 270 (caddr_t)bufp, len); 271 *(bufp + len - 1) = (char)0; 272 273 /* 274 * If the value begins with the char string "fail", 275 * then it means the node is failed. We don't care 276 * about any other values. We assume the node is ok 277 * although it might be 'disabled'. 278 */ 279 if (strncmp(bufp, fail, fail_len) == 0) 280 return (0); 281 282 return (1); 283 } 284 285 /* 286 * Check the status of the device node passed as an argument. 287 * 288 * if ((status is OKAY) || (status is DISABLED)) 289 * return DDI_SUCCESS 290 * else 291 * print a warning and return DDI_FAILURE 292 */ 293 /*ARGSUSED1*/ 294 int 295 check_status(int id, char *name, dev_info_t *parent) 296 { 297 char status_buf[64]; 298 char devtype_buf[OBP_MAXPROPNAME]; 299 int retval = DDI_FAILURE; 300 301 /* 302 * is the status okay? 303 */ 304 if (status_okay(id, status_buf, sizeof (status_buf))) 305 return (DDI_SUCCESS); 306 307 /* 308 * a status property indicating bad memory will be associated 309 * with a node which has a "device_type" property with a value of 310 * "memory-controller". in this situation, return DDI_SUCCESS 311 */ 312 if (getlongprop_buf(id, OBP_DEVICETYPE, devtype_buf, 313 sizeof (devtype_buf)) > 0) { 314 if (strcmp(devtype_buf, "memory-controller") == 0) 315 retval = DDI_SUCCESS; 316 } 317 318 /* 319 * print the status property information 320 */ 321 cmn_err(CE_WARN, "status '%s' for '%s'", status_buf, name); 322 return (retval); 323 } 324 325 /*ARGSUSED*/ 326 uint_t 327 softlevel1(caddr_t arg1, caddr_t arg2) 328 { 329 softint(); 330 return (1); 331 } 332 333 /* 334 * Allow for implementation specific correction of PROM property values. 335 */ 336 337 /*ARGSUSED*/ 338 void 339 impl_fix_props(dev_info_t *dip, dev_info_t *ch_dip, char *name, int len, 340 caddr_t buffer) 341 { 342 /* 343 * There are no adjustments needed in this implementation. 344 */ 345 } 346 347 static int 348 getlongprop_buf(int id, char *name, char *buf, int maxlen) 349 { 350 int size; 351 352 size = prom_getproplen((dnode_t)id, name); 353 if (size <= 0 || (size > maxlen - 1)) 354 return (-1); 355 356 if (-1 == prom_getprop((dnode_t)id, name, buf)) 357 return (-1); 358 359 if (strcmp("name", name) == 0) { 360 if (buf[size - 1] != '\0') { 361 buf[size] = '\0'; 362 size += 1; 363 } 364 } 365 366 return (size); 367 } 368 369 static int 370 get_prop_int_array(dev_info_t *di, char *pname, int **pval, uint_t *plen) 371 { 372 int ret; 373 374 if ((ret = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, di, 375 DDI_PROP_DONTPASS, pname, pval, plen)) 376 == DDI_PROP_SUCCESS) { 377 *plen = (*plen) * (sizeof (int)); 378 } 379 return (ret); 380 } 381 382 383 /* 384 * Node Configuration 385 */ 386 387 struct prop_ispec { 388 uint_t pri, vec; 389 }; 390 391 /* 392 * For the x86, we're prepared to claim that the interrupt string 393 * is in the form of a list of <ipl,vec> specifications. 394 */ 395 396 #define VEC_MIN 1 397 #define VEC_MAX 255 398 399 static int 400 impl_xlate_intrs(dev_info_t *child, int *in, 401 struct ddi_parent_private_data *pdptr) 402 { 403 size_t size; 404 int n; 405 struct intrspec *new; 406 caddr_t got_prop; 407 int *inpri; 408 int got_len; 409 extern int ignore_hardware_nodes; /* force flag from ddi_impl.c */ 410 411 static char bad_intr_fmt[] = 412 "bad interrupt spec from %s%d - ipl %d, irq %d\n"; 413 414 /* 415 * determine if the driver is expecting the new style "interrupts" 416 * property which just contains the IRQ, or the old style which 417 * contains pairs of <IPL,IRQ>. if it is the new style, we always 418 * assign IPL 5 unless an "interrupt-priorities" property exists. 419 * in that case, the "interrupt-priorities" property contains the 420 * IPL values that match, one for one, the IRQ values in the 421 * "interrupts" property. 422 */ 423 inpri = NULL; 424 if ((ddi_getprop(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS, 425 "ignore-hardware-nodes", -1) != -1) || ignore_hardware_nodes) { 426 /* the old style "interrupts" property... */ 427 428 /* 429 * The list consists of <ipl,vec> elements 430 */ 431 if ((n = (*in++ >> 1)) < 1) 432 return (DDI_FAILURE); 433 434 pdptr->par_nintr = n; 435 size = n * sizeof (struct intrspec); 436 new = pdptr->par_intr = kmem_zalloc(size, KM_SLEEP); 437 438 while (n--) { 439 int level = *in++; 440 int vec = *in++; 441 442 if (level < 1 || level > MAXIPL || 443 vec < VEC_MIN || vec > VEC_MAX) { 444 cmn_err(CE_CONT, bad_intr_fmt, 445 DEVI(child)->devi_name, 446 DEVI(child)->devi_instance, level, vec); 447 goto broken; 448 } 449 new->intrspec_pri = level; 450 if (vec != 2) 451 new->intrspec_vec = vec; 452 else 453 /* 454 * irq 2 on the PC bus is tied to irq 9 455 * on ISA, EISA and MicroChannel 456 */ 457 new->intrspec_vec = 9; 458 new++; 459 } 460 461 return (DDI_SUCCESS); 462 } else { 463 /* the new style "interrupts" property... */ 464 465 /* 466 * The list consists of <vec> elements 467 */ 468 if ((n = (*in++)) < 1) 469 return (DDI_FAILURE); 470 471 pdptr->par_nintr = n; 472 size = n * sizeof (struct intrspec); 473 new = pdptr->par_intr = kmem_zalloc(size, KM_SLEEP); 474 475 /* XXX check for "interrupt-priorities" property... */ 476 if (ddi_getlongprop(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS, 477 "interrupt-priorities", (caddr_t)&got_prop, &got_len) 478 == DDI_PROP_SUCCESS) { 479 if (n != (got_len / sizeof (int))) { 480 cmn_err(CE_CONT, 481 "bad interrupt-priorities length" 482 " from %s%d: expected %d, got %d\n", 483 DEVI(child)->devi_name, 484 DEVI(child)->devi_instance, n, 485 (int)(got_len / sizeof (int))); 486 goto broken; 487 } 488 inpri = (int *)got_prop; 489 } 490 491 while (n--) { 492 int level; 493 int vec = *in++; 494 495 if (inpri == NULL) 496 level = 5; 497 else 498 level = *inpri++; 499 500 if (level < 1 || level > MAXIPL || 501 vec < VEC_MIN || vec > VEC_MAX) { 502 cmn_err(CE_CONT, bad_intr_fmt, 503 DEVI(child)->devi_name, 504 DEVI(child)->devi_instance, level, vec); 505 goto broken; 506 } 507 new->intrspec_pri = level; 508 if (vec != 2) 509 new->intrspec_vec = vec; 510 else 511 /* 512 * irq 2 on the PC bus is tied to irq 9 513 * on ISA, EISA and MicroChannel 514 */ 515 new->intrspec_vec = 9; 516 new++; 517 } 518 519 if (inpri != NULL) 520 kmem_free(got_prop, got_len); 521 return (DDI_SUCCESS); 522 } 523 524 broken: 525 kmem_free(pdptr->par_intr, size); 526 pdptr->par_intr = NULL; 527 pdptr->par_nintr = 0; 528 if (inpri != NULL) 529 kmem_free(got_prop, got_len); 530 531 return (DDI_FAILURE); 532 } 533 534 /* 535 * Create a ddi_parent_private_data structure from the ddi properties of 536 * the dev_info node. 537 * 538 * The "reg" and either an "intr" or "interrupts" properties are required 539 * if the driver wishes to create mappings or field interrupts on behalf 540 * of the device. 541 * 542 * The "reg" property is assumed to be a list of at least one triple 543 * 544 * <bustype, address, size>*1 545 * 546 * The "intr" property is assumed to be a list of at least one duple 547 * 548 * <SPARC ipl, vector#>*1 549 * 550 * The "interrupts" property is assumed to be a list of at least one 551 * n-tuples that describes the interrupt capabilities of the bus the device 552 * is connected to. For SBus, this looks like 553 * 554 * <SBus-level>*1 555 * 556 * (This property obsoletes the 'intr' property). 557 * 558 * The "ranges" property is optional. 559 */ 560 void 561 make_ddi_ppd(dev_info_t *child, struct ddi_parent_private_data **ppd) 562 { 563 struct ddi_parent_private_data *pdptr; 564 int n; 565 int *reg_prop, *rng_prop, *intr_prop, *irupts_prop; 566 uint_t reg_len, rng_len, intr_len, irupts_len; 567 568 *ppd = pdptr = kmem_zalloc(sizeof (*pdptr), KM_SLEEP); 569 570 /* 571 * Handle the 'reg' property. 572 */ 573 if ((get_prop_int_array(child, "reg", ®_prop, ®_len) == 574 DDI_PROP_SUCCESS) && (reg_len != 0)) { 575 pdptr->par_nreg = reg_len / (int)sizeof (struct regspec); 576 pdptr->par_reg = (struct regspec *)reg_prop; 577 } 578 579 /* 580 * See if I have a range (adding one where needed - this 581 * means to add one for sbus node in sun4c, when romvec > 0, 582 * if no range is already defined in the PROM node. 583 * (Currently no sun4c PROMS define range properties, 584 * but they should and may in the future.) For the SBus 585 * node, the range is defined by the SBus reg property. 586 */ 587 if (get_prop_int_array(child, "ranges", &rng_prop, &rng_len) 588 == DDI_PROP_SUCCESS) { 589 pdptr->par_nrng = rng_len / (int)(sizeof (struct rangespec)); 590 pdptr->par_rng = (struct rangespec *)rng_prop; 591 } 592 593 /* 594 * Handle the 'intr' and 'interrupts' properties 595 */ 596 597 /* 598 * For backwards compatibility 599 * we first look for the 'intr' property for the device. 600 */ 601 if (get_prop_int_array(child, "intr", &intr_prop, &intr_len) 602 != DDI_PROP_SUCCESS) { 603 intr_len = 0; 604 } 605 606 /* 607 * If we're to support bus adapters and future platforms cleanly, 608 * we need to support the generalized 'interrupts' property. 609 */ 610 if (get_prop_int_array(child, "interrupts", &irupts_prop, 611 &irupts_len) != DDI_PROP_SUCCESS) { 612 irupts_len = 0; 613 } else if (intr_len != 0) { 614 /* 615 * If both 'intr' and 'interrupts' are defined, 616 * then 'interrupts' wins and we toss the 'intr' away. 617 */ 618 ddi_prop_free((void *)intr_prop); 619 intr_len = 0; 620 } 621 622 if (intr_len != 0) { 623 624 /* 625 * Translate the 'intr' property into an array 626 * an array of struct intrspec's. There's not really 627 * very much to do here except copy what's out there. 628 */ 629 630 struct intrspec *new; 631 struct prop_ispec *l; 632 633 n = pdptr->par_nintr = 634 intr_len / sizeof (struct prop_ispec); 635 l = (struct prop_ispec *)intr_prop; 636 pdptr->par_intr = 637 new = kmem_zalloc(n * sizeof (struct intrspec), KM_SLEEP); 638 while (n--) { 639 new->intrspec_pri = l->pri; 640 new->intrspec_vec = l->vec; 641 new++; 642 l++; 643 } 644 ddi_prop_free((void *)intr_prop); 645 646 } else if ((n = irupts_len) != 0) { 647 size_t size; 648 int *out; 649 650 /* 651 * Translate the 'interrupts' property into an array 652 * of intrspecs for the rest of the DDI framework to 653 * toy with. Only our ancestors really know how to 654 * do this, so ask 'em. We massage the 'interrupts' 655 * property so that it is pre-pended by a count of 656 * the number of integers in the argument. 657 */ 658 size = sizeof (int) + n; 659 out = kmem_alloc(size, KM_SLEEP); 660 *out = n / sizeof (int); 661 bcopy(irupts_prop, out + 1, (size_t)n); 662 ddi_prop_free((void *)irupts_prop); 663 if (impl_xlate_intrs(child, out, pdptr) != DDI_SUCCESS) { 664 cmn_err(CE_CONT, 665 "Unable to translate 'interrupts' for %s%d\n", 666 DEVI(child)->devi_binding_name, 667 DEVI(child)->devi_instance); 668 } 669 kmem_free(out, size); 670 } 671 } 672 673 /* 674 * Name a child 675 */ 676 static int 677 impl_sunbus_name_child(dev_info_t *child, char *name, int namelen) 678 { 679 /* 680 * Fill in parent-private data and this function returns to us 681 * an indication if it used "registers" to fill in the data. 682 */ 683 if (ddi_get_parent_data(child) == NULL) { 684 struct ddi_parent_private_data *pdptr; 685 make_ddi_ppd(child, &pdptr); 686 ddi_set_parent_data(child, pdptr); 687 } 688 689 name[0] = '\0'; 690 if (sparc_pd_getnreg(child) > 0) { 691 (void) snprintf(name, namelen, "%x,%x", 692 (uint_t)sparc_pd_getreg(child, 0)->regspec_bustype, 693 (uint_t)sparc_pd_getreg(child, 0)->regspec_addr); 694 } 695 696 return (DDI_SUCCESS); 697 } 698 699 /* 700 * Called from the bus_ctl op of sunbus (sbus, obio, etc) nexus drivers 701 * to implement the DDI_CTLOPS_INITCHILD operation. That is, it names 702 * the children of sun busses based on the reg spec. 703 * 704 * Handles the following properties (in make_ddi_ppd): 705 * Property value 706 * Name type 707 * reg register spec 708 * intr old-form interrupt spec 709 * interrupts new (bus-oriented) interrupt spec 710 * ranges range spec 711 */ 712 int 713 impl_ddi_sunbus_initchild(dev_info_t *child) 714 { 715 char name[MAXNAMELEN]; 716 void impl_ddi_sunbus_removechild(dev_info_t *); 717 718 /* 719 * Name the child, also makes parent private data 720 */ 721 (void) impl_sunbus_name_child(child, name, MAXNAMELEN); 722 ddi_set_name_addr(child, name); 723 724 /* 725 * Attempt to merge a .conf node; if successful, remove the 726 * .conf node. 727 */ 728 if ((ndi_dev_is_persistent_node(child) == 0) && 729 (ndi_merge_node(child, impl_sunbus_name_child) == DDI_SUCCESS)) { 730 /* 731 * Return failure to remove node 732 */ 733 impl_ddi_sunbus_removechild(child); 734 return (DDI_FAILURE); 735 } 736 return (DDI_SUCCESS); 737 } 738 739 void 740 impl_free_ddi_ppd(dev_info_t *dip) 741 { 742 struct ddi_parent_private_data *pdptr; 743 size_t n; 744 745 if ((pdptr = ddi_get_parent_data(dip)) == NULL) 746 return; 747 748 if ((n = (size_t)pdptr->par_nintr) != 0) 749 /* 750 * Note that kmem_free is used here (instead of 751 * ddi_prop_free) because the contents of the 752 * property were placed into a separate buffer and 753 * mucked with a bit before being stored in par_intr. 754 * The actual return value from the prop lookup 755 * was freed with ddi_prop_free previously. 756 */ 757 kmem_free(pdptr->par_intr, n * sizeof (struct intrspec)); 758 759 if ((n = (size_t)pdptr->par_nrng) != 0) 760 ddi_prop_free((void *)pdptr->par_rng); 761 762 if ((n = pdptr->par_nreg) != 0) 763 ddi_prop_free((void *)pdptr->par_reg); 764 765 kmem_free(pdptr, sizeof (*pdptr)); 766 ddi_set_parent_data(dip, NULL); 767 } 768 769 void 770 impl_ddi_sunbus_removechild(dev_info_t *dip) 771 { 772 impl_free_ddi_ppd(dip); 773 ddi_set_name_addr(dip, NULL); 774 /* 775 * Strip the node to properly convert it back to prototype form 776 */ 777 impl_rem_dev_props(dip); 778 } 779 780 /* 781 * DDI Interrupt 782 */ 783 784 /* 785 * turn this on to force isa, eisa, and mca device to ignore the new 786 * hardware nodes in the device tree (normally turned on only for 787 * drivers that need it by setting the property "ignore-hardware-nodes" 788 * in their driver.conf file). 789 * 790 * 7/31/96 -- Turned off globally. Leaving variable in for the moment 791 * as safety valve. 792 */ 793 int ignore_hardware_nodes = 0; 794 795 /* 796 * Local data 797 */ 798 static struct impl_bus_promops *impl_busp; 799 800 801 /* 802 * New DDI interrupt framework 803 */ 804 805 /* 806 * i_ddi_intr_ops: 807 * 808 * This is the interrupt operator function wrapper for the bus function 809 * bus_intr_op. 810 */ 811 int 812 i_ddi_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t op, 813 ddi_intr_handle_impl_t *hdlp, void * result) 814 { 815 dev_info_t *pdip = (dev_info_t *)DEVI(dip)->devi_parent; 816 int ret = DDI_FAILURE; 817 818 /* request parent to process this interrupt op */ 819 if (NEXUS_HAS_INTR_OP(pdip)) 820 ret = (*(DEVI(pdip)->devi_ops->devo_bus_ops->bus_intr_op))( 821 pdip, rdip, op, hdlp, result); 822 else 823 cmn_err(CE_WARN, "Failed to process interrupt " 824 "for %s%d due to down-rev nexus driver %s%d", 825 ddi_get_name(rdip), ddi_get_instance(rdip), 826 ddi_get_name(pdip), ddi_get_instance(pdip)); 827 return (ret); 828 } 829 830 /* 831 * i_ddi_add_softint - allocate and add a soft interrupt to the system 832 */ 833 int 834 i_ddi_add_softint(ddi_softint_hdl_impl_t *hdlp) 835 { 836 int ret; 837 838 /* add soft interrupt handler */ 839 ret = add_avsoftintr((void *)hdlp, hdlp->ih_pri, hdlp->ih_cb_func, 840 DEVI(hdlp->ih_dip)->devi_name, hdlp->ih_cb_arg1, hdlp->ih_cb_arg2); 841 return (ret ? DDI_SUCCESS : DDI_FAILURE); 842 } 843 844 845 void 846 i_ddi_remove_softint(ddi_softint_hdl_impl_t *hdlp) 847 { 848 (void) rem_avsoftintr((void *)hdlp, hdlp->ih_pri, hdlp->ih_cb_func); 849 } 850 851 852 extern void (*setsoftint)(int); 853 854 int 855 i_ddi_trigger_softint(ddi_softint_hdl_impl_t *hdlp, void *arg2) 856 { 857 int ret = DDI_SUCCESS; 858 859 if (hdlp->ih_pending) { 860 ret = DDI_EPENDING; 861 } else { 862 update_avsoftintr_args((void *)hdlp, 863 hdlp->ih_pri, arg2); 864 hdlp->ih_pending = 1; 865 } 866 867 (*setsoftint)(hdlp->ih_pri); 868 return (ret); 869 } 870 871 /* 872 * i_ddi_set_softint_pri: 873 * 874 * The way this works is that it first tries to add a softint vector 875 * at the new priority in hdlp. If that succeeds; then it removes the 876 * existing softint vector at the old priority. 877 */ 878 int 879 i_ddi_set_softint_pri(ddi_softint_hdl_impl_t *hdlp, uint_t old_pri) 880 { 881 /* 882 * If a softint is pending at the old priority then fail the request. 883 * OR 884 * If we failed to add a softint vector with the new priority; then 885 * fail the request with a DDI_FAILURE 886 */ 887 if (hdlp->ih_pending || i_ddi_add_softint(hdlp) != DDI_SUCCESS) 888 return (DDI_FAILURE); 889 890 /* Now, remove the softint at the old priority */ 891 (void) rem_avsoftintr((void *)hdlp, old_pri, hdlp->ih_cb_func); 892 return (DDI_SUCCESS); 893 } 894 895 /* 896 * DDI Memory/DMA 897 */ 898 899 /* 900 * Support for allocating DMAable memory to implement 901 * ddi_dma_mem_alloc(9F) interface. 902 */ 903 904 #define KA_ALIGN_SHIFT 7 905 #define KA_ALIGN (1 << KA_ALIGN_SHIFT) 906 #define KA_NCACHE (PAGESHIFT + 1 - KA_ALIGN_SHIFT) 907 908 /* 909 * Dummy DMA attribute template for kmem_io[].kmem_io_attr. We only 910 * care about addr_lo, addr_hi, and align. addr_hi will be dynamically set. 911 */ 912 913 static ddi_dma_attr_t kmem_io_attr = { 914 DMA_ATTR_V0, 915 0x0000000000000000ULL, /* dma_attr_addr_lo */ 916 0x0000000000000000ULL, /* dma_attr_addr_hi */ 917 0x00ffffff, 918 0x1000, /* dma_attr_align */ 919 1, 1, 0xffffffffULL, 0xffffffffULL, 0x1, 1, 0 920 }; 921 922 /* kmem io memory ranges and indices */ 923 enum { 924 IO_4P, IO_64G, IO_4G, IO_2G, IO_1G, IO_512M, 925 IO_256M, IO_128M, IO_64M, IO_32M, IO_16M, MAX_MEM_RANGES 926 }; 927 928 static struct { 929 vmem_t *kmem_io_arena; 930 kmem_cache_t *kmem_io_cache[KA_NCACHE]; 931 ddi_dma_attr_t kmem_io_attr; 932 } kmem_io[MAX_MEM_RANGES]; 933 934 static int kmem_io_idx; /* index of first populated kmem_io[] */ 935 936 static page_t * 937 page_create_io_wrapper(void *addr, size_t len, int vmflag, void *arg) 938 { 939 extern page_t *page_create_io(vnode_t *, u_offset_t, uint_t, 940 uint_t, struct as *, caddr_t, ddi_dma_attr_t *); 941 942 return (page_create_io(&kvp, (u_offset_t)(uintptr_t)addr, len, 943 PG_EXCL | ((vmflag & VM_NOSLEEP) ? 0 : PG_WAIT), &kas, addr, arg)); 944 } 945 946 static void * 947 segkmem_alloc_io_4P(vmem_t *vmp, size_t size, int vmflag) 948 { 949 return (segkmem_xalloc(vmp, NULL, size, vmflag, 0, 950 page_create_io_wrapper, &kmem_io[IO_4P].kmem_io_attr)); 951 } 952 953 static void * 954 segkmem_alloc_io_64G(vmem_t *vmp, size_t size, int vmflag) 955 { 956 return (segkmem_xalloc(vmp, NULL, size, vmflag, 0, 957 page_create_io_wrapper, &kmem_io[IO_64G].kmem_io_attr)); 958 } 959 960 static void * 961 segkmem_alloc_io_4G(vmem_t *vmp, size_t size, int vmflag) 962 { 963 return (segkmem_xalloc(vmp, NULL, size, vmflag, 0, 964 page_create_io_wrapper, &kmem_io[IO_4G].kmem_io_attr)); 965 } 966 967 static void * 968 segkmem_alloc_io_2G(vmem_t *vmp, size_t size, int vmflag) 969 { 970 return (segkmem_xalloc(vmp, NULL, size, vmflag, 0, 971 page_create_io_wrapper, &kmem_io[IO_2G].kmem_io_attr)); 972 } 973 974 static void * 975 segkmem_alloc_io_1G(vmem_t *vmp, size_t size, int vmflag) 976 { 977 return (segkmem_xalloc(vmp, NULL, size, vmflag, 0, 978 page_create_io_wrapper, &kmem_io[IO_1G].kmem_io_attr)); 979 } 980 981 static void * 982 segkmem_alloc_io_512M(vmem_t *vmp, size_t size, int vmflag) 983 { 984 return (segkmem_xalloc(vmp, NULL, size, vmflag, 0, 985 page_create_io_wrapper, &kmem_io[IO_512M].kmem_io_attr)); 986 } 987 988 static void * 989 segkmem_alloc_io_256M(vmem_t *vmp, size_t size, int vmflag) 990 { 991 return (segkmem_xalloc(vmp, NULL, size, vmflag, 0, 992 page_create_io_wrapper, &kmem_io[IO_256M].kmem_io_attr)); 993 } 994 995 static void * 996 segkmem_alloc_io_128M(vmem_t *vmp, size_t size, int vmflag) 997 { 998 return (segkmem_xalloc(vmp, NULL, size, vmflag, 0, 999 page_create_io_wrapper, &kmem_io[IO_128M].kmem_io_attr)); 1000 } 1001 1002 static void * 1003 segkmem_alloc_io_64M(vmem_t *vmp, size_t size, int vmflag) 1004 { 1005 return (segkmem_xalloc(vmp, NULL, size, vmflag, 0, 1006 page_create_io_wrapper, &kmem_io[IO_64M].kmem_io_attr)); 1007 } 1008 1009 static void * 1010 segkmem_alloc_io_32M(vmem_t *vmp, size_t size, int vmflag) 1011 { 1012 return (segkmem_xalloc(vmp, NULL, size, vmflag, 0, 1013 page_create_io_wrapper, &kmem_io[IO_32M].kmem_io_attr)); 1014 } 1015 1016 static void * 1017 segkmem_alloc_io_16M(vmem_t *vmp, size_t size, int vmflag) 1018 { 1019 return (segkmem_xalloc(vmp, NULL, size, vmflag, 0, 1020 page_create_io_wrapper, &kmem_io[IO_16M].kmem_io_attr)); 1021 } 1022 1023 struct { 1024 uint64_t io_limit; 1025 char *io_name; 1026 void *(*io_alloc)(vmem_t *, size_t, int); 1027 int io_initial; /* kmem_io_init during startup */ 1028 } io_arena_params[MAX_MEM_RANGES] = { 1029 {0x000fffffffffffffULL, "kmem_io_4P", segkmem_alloc_io_4P, 1}, 1030 {0x0000000fffffffffULL, "kmem_io_64G", segkmem_alloc_io_64G, 0}, 1031 {0x00000000ffffffffULL, "kmem_io_4G", segkmem_alloc_io_4G, 1}, 1032 {0x000000007fffffffULL, "kmem_io_2G", segkmem_alloc_io_2G, 1}, 1033 {0x000000003fffffffULL, "kmem_io_1G", segkmem_alloc_io_1G, 0}, 1034 {0x000000001fffffffULL, "kmem_io_512M", segkmem_alloc_io_512M, 0}, 1035 {0x000000000fffffffULL, "kmem_io_256M", segkmem_alloc_io_256M, 0}, 1036 {0x0000000007ffffffULL, "kmem_io_128M", segkmem_alloc_io_128M, 0}, 1037 {0x0000000003ffffffULL, "kmem_io_64M", segkmem_alloc_io_64M, 0}, 1038 {0x0000000001ffffffULL, "kmem_io_32M", segkmem_alloc_io_32M, 0}, 1039 {0x0000000000ffffffULL, "kmem_io_16M", segkmem_alloc_io_16M, 1} 1040 }; 1041 1042 void 1043 kmem_io_init(int a) 1044 { 1045 int c; 1046 char name[40]; 1047 1048 kmem_io[a].kmem_io_arena = vmem_create(io_arena_params[a].io_name, 1049 NULL, 0, PAGESIZE, io_arena_params[a].io_alloc, 1050 segkmem_free, heap_arena, 0, VM_SLEEP); 1051 for (c = 0; c < KA_NCACHE; c++) { 1052 size_t size = KA_ALIGN << c; 1053 (void) sprintf(name, "%s_%lu", 1054 io_arena_params[a].io_name, size); 1055 kmem_io[a].kmem_io_cache[c] = kmem_cache_create(name, 1056 size, size, NULL, NULL, NULL, NULL, 1057 kmem_io[a].kmem_io_arena, 0); 1058 } 1059 } 1060 1061 /* 1062 * Return the index of the highest memory range for addr. 1063 */ 1064 static int 1065 kmem_io_index(uint64_t addr) 1066 { 1067 int n; 1068 1069 for (n = kmem_io_idx; n < MAX_MEM_RANGES; n++) { 1070 if (kmem_io[n].kmem_io_attr.dma_attr_addr_hi <= addr) { 1071 if (kmem_io[n].kmem_io_arena == NULL) 1072 kmem_io_init(n); 1073 return (n); 1074 } 1075 } 1076 panic("kmem_io_index: invalid addr - must be at least 16m"); 1077 1078 /*NOTREACHED*/ 1079 } 1080 1081 /* 1082 * Return the index of the next kmem_io populated memory range 1083 * after curindex. 1084 */ 1085 static int 1086 kmem_io_index_next(int curindex) 1087 { 1088 int n; 1089 1090 for (n = curindex + 1; n < MAX_MEM_RANGES; n++) { 1091 if (kmem_io[n].kmem_io_arena) 1092 return (n); 1093 } 1094 return (-1); 1095 } 1096 1097 void 1098 ka_init(void) 1099 { 1100 int a; 1101 extern pfn_t physmax; 1102 uint64_t maxphysaddr = mmu_ptob((uint64_t)physmax + 1) - 1; 1103 1104 ASSERT(maxphysaddr <= io_arena_params[0].io_limit); 1105 1106 for (a = 0; a < MAX_MEM_RANGES; a++) { 1107 if (maxphysaddr >= io_arena_params[a + 1].io_limit) { 1108 if (maxphysaddr > io_arena_params[a + 1].io_limit) 1109 io_arena_params[a].io_limit = maxphysaddr; 1110 else 1111 a++; 1112 break; 1113 } 1114 } 1115 kmem_io_idx = a; 1116 1117 for (; a < MAX_MEM_RANGES; a++) { 1118 kmem_io[a].kmem_io_attr = kmem_io_attr; 1119 kmem_io[a].kmem_io_attr.dma_attr_addr_hi = 1120 io_arena_params[a].io_limit; 1121 /* 1122 * initialize kmem_io[] arena/cache corresponding to 1123 * maxphysaddr and to the "common" io memory ranges that 1124 * have io_initial set to a non-zero value. 1125 */ 1126 if (io_arena_params[a].io_initial || a == kmem_io_idx) 1127 kmem_io_init(a); 1128 } 1129 } 1130 1131 /* 1132 * put contig address/size 1133 */ 1134 static void * 1135 putctgas(void *addr, size_t size) 1136 { 1137 struct ctgas *ctgp = &ctglist; 1138 int i; 1139 1140 CTGLOCK(); 1141 do { 1142 if ((i = ctgp->ctg_index) < CTGENTRIES) { 1143 ctgp->ctg_addr[i] = addr; 1144 ctgp->ctg_size[i] = size; 1145 ctgp->ctg_index++; 1146 break; 1147 } 1148 if (!ctgp->ctg_next) 1149 ctgp->ctg_next = kmem_zalloc(sizeof (struct ctgas), 1150 KM_NOSLEEP); 1151 ctgp = ctgp->ctg_next; 1152 } while (ctgp); 1153 1154 CTGUNLOCK(); 1155 return (ctgp); 1156 } 1157 1158 /* 1159 * get contig size by addr 1160 */ 1161 static size_t 1162 getctgsz(void *addr) 1163 { 1164 struct ctgas *ctgp = &ctglist; 1165 int i, j; 1166 size_t sz; 1167 1168 ASSERT(addr); 1169 CTGLOCK(); 1170 1171 while (ctgp) { 1172 for (i = 0; i < ctgp->ctg_index; i++) { 1173 if (addr != ctgp->ctg_addr[i]) 1174 continue; 1175 1176 sz = ctgp->ctg_size[i]; 1177 j = --ctgp->ctg_index; 1178 if (i != j) { 1179 ctgp->ctg_size[i] = ctgp->ctg_size[j]; 1180 ctgp->ctg_addr[i] = ctgp->ctg_addr[j]; 1181 } 1182 CTGUNLOCK(); 1183 return (sz); 1184 } 1185 ctgp = ctgp->ctg_next; 1186 } 1187 1188 CTGUNLOCK(); 1189 return (0); 1190 } 1191 1192 /* 1193 * contig_alloc: 1194 * 1195 * allocates contiguous memory to satisfy the 'size' and dma attributes 1196 * specified in 'attr'. 1197 * 1198 * Not all of memory need to be physically contiguous if the 1199 * scatter-gather list length is greater than 1. 1200 */ 1201 1202 /*ARGSUSED*/ 1203 void * 1204 contig_alloc(size_t size, ddi_dma_attr_t *attr, uintptr_t align, int cansleep) 1205 { 1206 pgcnt_t pgcnt = btopr(size); 1207 size_t asize = pgcnt * PAGESIZE; 1208 page_t *ppl; 1209 int pflag; 1210 void *addr; 1211 1212 extern page_t *page_create_io(vnode_t *, u_offset_t, uint_t, 1213 uint_t, struct as *, caddr_t, ddi_dma_attr_t *); 1214 1215 /* segkmem_xalloc */ 1216 1217 if (align <= PAGESIZE) 1218 addr = vmem_alloc(heap_arena, asize, 1219 (cansleep) ? VM_SLEEP : VM_NOSLEEP); 1220 else 1221 addr = vmem_xalloc(heap_arena, asize, align, 0, 0, NULL, NULL, 1222 (cansleep) ? VM_SLEEP : VM_NOSLEEP); 1223 if (addr) { 1224 ASSERT(!((uintptr_t)addr & (align - 1))); 1225 1226 if (page_resv(pgcnt, 1227 (cansleep) ? KM_SLEEP : KM_NOSLEEP) == 0) { 1228 1229 vmem_free(heap_arena, addr, asize); 1230 return (NULL); 1231 } 1232 pflag = PG_EXCL; 1233 1234 if (cansleep) 1235 pflag |= PG_WAIT; 1236 1237 /* 4k req gets from freelists rather than pfn search */ 1238 if (pgcnt > 1 || align > PAGESIZE) 1239 pflag |= PG_PHYSCONTIG; 1240 1241 ppl = page_create_io(&kvp, (u_offset_t)(uintptr_t)addr, 1242 asize, pflag, &kas, (caddr_t)addr, attr); 1243 1244 if (!ppl) { 1245 vmem_free(heap_arena, addr, asize); 1246 page_unresv(pgcnt); 1247 return (NULL); 1248 } 1249 1250 while (ppl != NULL) { 1251 page_t *pp = ppl; 1252 page_sub(&ppl, pp); 1253 ASSERT(page_iolock_assert(pp)); 1254 page_io_unlock(pp); 1255 page_downgrade(pp); 1256 hat_memload(kas.a_hat, (caddr_t)(uintptr_t)pp->p_offset, 1257 pp, (PROT_ALL & ~PROT_USER) | 1258 HAT_NOSYNC, HAT_LOAD_LOCK); 1259 } 1260 } 1261 return (addr); 1262 } 1263 1264 static void 1265 contig_free(void *addr, size_t size) 1266 { 1267 pgcnt_t pgcnt = btopr(size); 1268 size_t asize = pgcnt * PAGESIZE; 1269 caddr_t a, ea; 1270 page_t *pp; 1271 1272 hat_unload(kas.a_hat, addr, asize, HAT_UNLOAD_UNLOCK); 1273 1274 for (a = addr, ea = a + asize; a < ea; a += PAGESIZE) { 1275 pp = page_find(&kvp, 1276 (u_offset_t)(uintptr_t)a); 1277 if (!pp) 1278 panic("contig_free: contig pp not found"); 1279 1280 if (!page_tryupgrade(pp)) { 1281 page_unlock(pp); 1282 pp = page_lookup(&kvp, 1283 (u_offset_t)(uintptr_t)a, SE_EXCL); 1284 if (pp == NULL) 1285 panic("contig_free: page freed"); 1286 } 1287 page_destroy(pp, 0); 1288 } 1289 1290 page_unresv(pgcnt); 1291 vmem_free(heap_arena, addr, asize); 1292 } 1293 1294 /* 1295 * Allocate from the system, aligned on a specific boundary. 1296 * The alignment, if non-zero, must be a power of 2. 1297 */ 1298 static void * 1299 kalloca(size_t size, size_t align, int cansleep, int physcontig, 1300 ddi_dma_attr_t *attr) 1301 { 1302 size_t *addr, *raddr, rsize; 1303 size_t hdrsize = 4 * sizeof (size_t); /* must be power of 2 */ 1304 int a, i, c; 1305 vmem_t *vmp; 1306 kmem_cache_t *cp = NULL; 1307 1308 align = MAX(align, hdrsize); 1309 ASSERT((align & (align - 1)) == 0); 1310 1311 /* 1312 * All of our allocators guarantee 16-byte alignment, so we don't 1313 * need to reserve additional space for the header. 1314 * To simplify picking the correct kmem_io_cache, we round up to 1315 * a multiple of KA_ALIGN. 1316 */ 1317 rsize = P2ROUNDUP_TYPED(size + align, KA_ALIGN, size_t); 1318 1319 if (physcontig && rsize > PAGESIZE) { 1320 if (addr = contig_alloc(size, attr, align, cansleep)) { 1321 if (!putctgas(addr, size)) 1322 contig_free(addr, size); 1323 else 1324 return (addr); 1325 } 1326 return (NULL); 1327 } 1328 1329 ASSERT(attr->dma_attr_addr_lo <= mmu_ptob((uint64_t)ddiphysmin)); 1330 1331 a = kmem_io_index(attr->dma_attr_addr_hi); 1332 1333 if (rsize > PAGESIZE) { 1334 vmp = kmem_io[a].kmem_io_arena; 1335 raddr = vmem_alloc(vmp, rsize, 1336 (cansleep) ? VM_SLEEP : VM_NOSLEEP); 1337 } else { 1338 c = highbit((rsize >> KA_ALIGN_SHIFT) - 1); 1339 cp = kmem_io[a].kmem_io_cache[c]; 1340 raddr = kmem_cache_alloc(cp, (cansleep) ? KM_SLEEP : 1341 KM_NOSLEEP); 1342 } 1343 1344 if (raddr == NULL) { 1345 int na; 1346 1347 ASSERT(cansleep == 0); 1348 if (rsize > PAGESIZE) 1349 return (NULL); 1350 /* 1351 * System does not have memory in the requested range. 1352 * Try smaller kmem io ranges and larger cache sizes 1353 * to see if there might be memory available in 1354 * these other caches. 1355 */ 1356 1357 for (na = kmem_io_index_next(a); na >= 0; 1358 na = kmem_io_index_next(na)) { 1359 ASSERT(kmem_io[na].kmem_io_arena); 1360 cp = kmem_io[na].kmem_io_cache[c]; 1361 raddr = kmem_cache_alloc(cp, KM_NOSLEEP); 1362 if (raddr) 1363 goto kallocdone; 1364 } 1365 /* now try the larger kmem io cache sizes */ 1366 for (na = a; na >= 0; na = kmem_io_index_next(na)) { 1367 for (i = c + 1; i < KA_NCACHE; i++) { 1368 cp = kmem_io[na].kmem_io_cache[i]; 1369 raddr = kmem_cache_alloc(cp, KM_NOSLEEP); 1370 if (raddr) 1371 goto kallocdone; 1372 } 1373 } 1374 return (NULL); 1375 } 1376 1377 kallocdone: 1378 ASSERT(!P2CROSS((uintptr_t)raddr, (uintptr_t)raddr + rsize - 1, 1379 PAGESIZE) || rsize > PAGESIZE); 1380 1381 addr = (size_t *)P2ROUNDUP((uintptr_t)raddr + hdrsize, align); 1382 ASSERT((uintptr_t)addr + size - (uintptr_t)raddr <= rsize); 1383 1384 addr[-4] = (size_t)cp; 1385 addr[-3] = (size_t)vmp; 1386 addr[-2] = (size_t)raddr; 1387 addr[-1] = rsize; 1388 1389 return (addr); 1390 } 1391 1392 static void 1393 kfreea(void *addr) 1394 { 1395 size_t size; 1396 1397 if (!((uintptr_t)addr & PAGEOFFSET) && (size = getctgsz(addr))) { 1398 contig_free(addr, size); 1399 } else { 1400 size_t *saddr = addr; 1401 if (saddr[-4] == 0) 1402 vmem_free((vmem_t *)saddr[-3], (void *)saddr[-2], 1403 saddr[-1]); 1404 else 1405 kmem_cache_free((kmem_cache_t *)saddr[-4], 1406 (void *)saddr[-2]); 1407 } 1408 } 1409 1410 /* 1411 * This should actually be called i_ddi_dma_mem_alloc. There should 1412 * also be an i_ddi_pio_mem_alloc. i_ddi_dma_mem_alloc should call 1413 * through the device tree with the DDI_CTLOPS_DMA_ALIGN ctl ops to 1414 * get alignment requirements for DMA memory. i_ddi_pio_mem_alloc 1415 * should use DDI_CTLOPS_PIO_ALIGN. Since we only have i_ddi_mem_alloc 1416 * so far which is used for both, DMA and PIO, we have to use the DMA 1417 * ctl ops to make everybody happy. 1418 */ 1419 /*ARGSUSED*/ 1420 int 1421 i_ddi_mem_alloc(dev_info_t *dip, ddi_dma_attr_t *attr, 1422 size_t length, int cansleep, int streaming, 1423 ddi_device_acc_attr_t *accattrp, caddr_t *kaddrp, 1424 size_t *real_length, ddi_acc_hdl_t *ap) 1425 { 1426 caddr_t a; 1427 int iomin; 1428 ddi_acc_impl_t *iap; 1429 int physcontig = 0; 1430 pgcnt_t npages; 1431 pgcnt_t minctg; 1432 1433 /* 1434 * Check legality of arguments 1435 */ 1436 if (length == 0 || kaddrp == NULL || attr == NULL) { 1437 return (DDI_FAILURE); 1438 } 1439 if (attr->dma_attr_minxfer == 0 || attr->dma_attr_align == 0 || 1440 (attr->dma_attr_align & (attr->dma_attr_align - 1)) || 1441 (attr->dma_attr_minxfer & (attr->dma_attr_minxfer - 1))) { 1442 return (DDI_FAILURE); 1443 } 1444 1445 /* 1446 * figure out most restrictive alignment requirement 1447 */ 1448 iomin = attr->dma_attr_minxfer; 1449 iomin = maxbit(iomin, attr->dma_attr_align); 1450 if (iomin == 0) 1451 return (DDI_FAILURE); 1452 1453 ASSERT((iomin & (iomin - 1)) == 0); 1454 1455 1456 /* 1457 * Determine if we need to satisfy the request for physically 1458 * contiguous memory or alignments larger than pagesize. 1459 */ 1460 npages = btopr(length + attr->dma_attr_align); 1461 minctg = howmany(npages, attr->dma_attr_sgllen); 1462 1463 if (minctg > 1) { 1464 uint64_t pfnseg = attr->dma_attr_seg >> PAGESHIFT; 1465 /* 1466 * verify that the minimum contig requirement for the 1467 * actual length does not cross segment boundary. 1468 */ 1469 length = P2ROUNDUP_TYPED(length, attr->dma_attr_minxfer, 1470 size_t); 1471 npages = btopr(length); 1472 minctg = howmany(npages, attr->dma_attr_sgllen); 1473 if (minctg > pfnseg + 1) 1474 return (DDI_FAILURE); 1475 physcontig = 1; 1476 } else { 1477 length = P2ROUNDUP_TYPED(length, iomin, size_t); 1478 } 1479 1480 /* 1481 * Allocate the requested amount from the system. 1482 */ 1483 a = kalloca(length, iomin, cansleep, physcontig, attr); 1484 1485 if ((*kaddrp = a) == NULL) 1486 return (DDI_FAILURE); 1487 1488 if (real_length) { 1489 *real_length = length; 1490 } 1491 if (ap) { 1492 /* 1493 * initialize access handle 1494 */ 1495 iap = (ddi_acc_impl_t *)ap->ah_platform_private; 1496 iap->ahi_acc_attr |= DDI_ACCATTR_CPU_VADDR; 1497 impl_acc_hdl_init(ap); 1498 } 1499 return (DDI_SUCCESS); 1500 } 1501 1502 /* 1503 * covert old DMA limits structure to DMA attribute structure 1504 * and continue 1505 */ 1506 int 1507 i_ddi_mem_alloc_lim(dev_info_t *dip, ddi_dma_lim_t *limits, 1508 size_t length, int cansleep, int streaming, 1509 ddi_device_acc_attr_t *accattrp, caddr_t *kaddrp, 1510 uint_t *real_length, ddi_acc_hdl_t *ap) 1511 { 1512 ddi_dma_attr_t dma_attr, *attrp; 1513 size_t rlen; 1514 int ret; 1515 1516 if (limits == NULL) { 1517 return (DDI_FAILURE); 1518 } 1519 1520 /* 1521 * set up DMA attribute structure to pass to i_ddi_mem_alloc() 1522 */ 1523 attrp = &dma_attr; 1524 attrp->dma_attr_version = DMA_ATTR_V0; 1525 attrp->dma_attr_addr_lo = (uint64_t)limits->dlim_addr_lo; 1526 attrp->dma_attr_addr_hi = (uint64_t)limits->dlim_addr_hi; 1527 attrp->dma_attr_count_max = (uint64_t)limits->dlim_ctreg_max; 1528 attrp->dma_attr_align = 1; 1529 attrp->dma_attr_burstsizes = (uint_t)limits->dlim_burstsizes; 1530 attrp->dma_attr_minxfer = (uint32_t)limits->dlim_minxfer; 1531 attrp->dma_attr_maxxfer = (uint64_t)limits->dlim_reqsize; 1532 attrp->dma_attr_seg = (uint64_t)limits->dlim_adreg_max; 1533 attrp->dma_attr_sgllen = limits->dlim_sgllen; 1534 attrp->dma_attr_granular = (uint32_t)limits->dlim_granular; 1535 attrp->dma_attr_flags = 0; 1536 1537 ret = i_ddi_mem_alloc(dip, attrp, length, cansleep, streaming, 1538 accattrp, kaddrp, &rlen, ap); 1539 if (ret == DDI_SUCCESS) { 1540 if (real_length) 1541 *real_length = (uint_t)rlen; 1542 } 1543 return (ret); 1544 } 1545 1546 /* ARGSUSED */ 1547 void 1548 i_ddi_mem_free(caddr_t kaddr, int stream) 1549 { 1550 kfreea(kaddr); 1551 } 1552 1553 /* 1554 * Access Barriers 1555 * 1556 */ 1557 /*ARGSUSED*/ 1558 int 1559 i_ddi_ontrap(ddi_acc_handle_t hp) 1560 { 1561 return (DDI_FAILURE); 1562 } 1563 1564 /*ARGSUSED*/ 1565 void 1566 i_ddi_notrap(ddi_acc_handle_t hp) 1567 { 1568 } 1569 1570 1571 /* 1572 * Misc Functions 1573 */ 1574 1575 /* 1576 * Implementation instance override functions 1577 * 1578 * No override on i86pc 1579 */ 1580 /*ARGSUSED*/ 1581 uint_t 1582 impl_assign_instance(dev_info_t *dip) 1583 { 1584 return ((uint_t)-1); 1585 } 1586 1587 /*ARGSUSED*/ 1588 int 1589 impl_keep_instance(dev_info_t *dip) 1590 { 1591 return (DDI_FAILURE); 1592 } 1593 1594 /*ARGSUSED*/ 1595 int 1596 impl_free_instance(dev_info_t *dip) 1597 { 1598 return (DDI_FAILURE); 1599 } 1600 1601 /*ARGSUSED*/ 1602 int 1603 impl_check_cpu(dev_info_t *devi) 1604 { 1605 return (DDI_SUCCESS); 1606 } 1607 1608 /* 1609 * Referenced in common/cpr_driver.c: Power off machine. 1610 * Don't know how to power off i86pc. 1611 */ 1612 void 1613 arch_power_down() 1614 {} 1615 1616 /* 1617 * Copy name to property_name, since name 1618 * is in the low address range below kernelbase. 1619 */ 1620 static void 1621 copy_boot_str(const char *boot_str, char *kern_str, int len) 1622 { 1623 int i = 0; 1624 1625 while (i < len - 1 && boot_str[i] != '\0') { 1626 kern_str[i] = boot_str[i]; 1627 i++; 1628 } 1629 1630 kern_str[i] = 0; /* null terminate */ 1631 if (boot_str[i] != '\0') 1632 cmn_err(CE_WARN, 1633 "boot property string is truncated to %s", kern_str); 1634 } 1635 1636 static void 1637 get_boot_properties(void) 1638 { 1639 extern char hw_provider[]; 1640 dev_info_t *devi; 1641 char *name; 1642 int length; 1643 char property_name[50], property_val[50]; 1644 void *bop_staging_area; 1645 1646 bop_staging_area = kmem_zalloc(MMU_PAGESIZE, KM_NOSLEEP); 1647 1648 /* 1649 * Import "root" properties from the boot. 1650 * 1651 * We do this by invoking BOP_NEXTPROP until the list 1652 * is completely copied in. 1653 */ 1654 1655 devi = ddi_root_node(); 1656 for (name = BOP_NEXTPROP(bootops, ""); /* get first */ 1657 name; /* NULL => DONE */ 1658 name = BOP_NEXTPROP(bootops, name)) { /* get next */ 1659 1660 /* copy string to memory above kernelbase */ 1661 copy_boot_str(name, property_name, 50); 1662 1663 /* 1664 * Skip vga properties. They will be picked up later 1665 * by get_vga_properties. 1666 */ 1667 if (strcmp(property_name, "display-edif-block") == 0 || 1668 strcmp(property_name, "display-edif-id") == 0) { 1669 continue; 1670 } 1671 1672 length = BOP_GETPROPLEN(bootops, property_name); 1673 if (length == 0) 1674 continue; 1675 if (length > MMU_PAGESIZE) { 1676 cmn_err(CE_NOTE, 1677 "boot property %s longer than 0x%x, ignored\n", 1678 property_name, MMU_PAGESIZE); 1679 continue; 1680 } 1681 BOP_GETPROP(bootops, property_name, bop_staging_area); 1682 1683 /* 1684 * special properties: 1685 * si-machine, si-hw-provider 1686 * goes to kernel data structures. 1687 * bios-boot-device and stdout 1688 * goes to hardware property list so it may show up 1689 * in the prtconf -vp output. This is needed by 1690 * Install/Upgrade. Once we fix install upgrade, 1691 * this can be taken out. 1692 */ 1693 if (strcmp(name, "si-machine") == 0) { 1694 (void) strncpy(utsname.machine, bop_staging_area, 1695 SYS_NMLN); 1696 utsname.machine[SYS_NMLN - 1] = (char)NULL; 1697 } else if (strcmp(name, "si-hw-provider") == 0) { 1698 (void) strncpy(hw_provider, bop_staging_area, SYS_NMLN); 1699 hw_provider[SYS_NMLN - 1] = (char)NULL; 1700 } else if (strcmp(name, "bios-boot-device") == 0) { 1701 copy_boot_str(bop_staging_area, property_val, 50); 1702 (void) ndi_prop_update_string(DDI_DEV_T_NONE, devi, 1703 property_name, property_val); 1704 } else if (strcmp(name, "stdout") == 0) { 1705 (void) ndi_prop_update_int(DDI_DEV_T_NONE, devi, 1706 property_name, *((int *)bop_staging_area)); 1707 } else { 1708 /* Property type unknown, use old prop interface */ 1709 (void) e_ddi_prop_create(DDI_DEV_T_NONE, devi, 1710 DDI_PROP_CANSLEEP, property_name, bop_staging_area, 1711 length); 1712 } 1713 } 1714 1715 kmem_free(bop_staging_area, MMU_PAGESIZE); 1716 } 1717 1718 static void 1719 get_vga_properties(void) 1720 { 1721 dev_info_t *devi; 1722 major_t major; 1723 char *name; 1724 int length; 1725 char property_val[50]; 1726 void *bop_staging_area; 1727 1728 major = ddi_name_to_major("vgatext"); 1729 if (major == (major_t)-1) 1730 return; 1731 devi = devnamesp[major].dn_head; 1732 if (devi == NULL) 1733 return; 1734 1735 bop_staging_area = kmem_zalloc(MMU_PAGESIZE, KM_SLEEP); 1736 1737 /* 1738 * Import "vga" properties from the boot. 1739 */ 1740 name = "display-edif-block"; 1741 length = BOP_GETPROPLEN(bootops, name); 1742 if (length > 0 && length < MMU_PAGESIZE) { 1743 BOP_GETPROP(bootops, name, bop_staging_area); 1744 (void) ndi_prop_update_byte_array(DDI_DEV_T_NONE, 1745 devi, name, bop_staging_area, length); 1746 } 1747 1748 /* 1749 * kdmconfig is also looking for display-type and 1750 * video-adapter-type. We default to color and svga. 1751 * 1752 * Could it be "monochrome", "vga"? 1753 * Nah, you've got to come to the 21st century... 1754 * And you can set monitor type manually in kdmconfig 1755 * if you are really an old junky. 1756 */ 1757 (void) ndi_prop_update_string(DDI_DEV_T_NONE, 1758 devi, "display-type", "color"); 1759 (void) ndi_prop_update_string(DDI_DEV_T_NONE, 1760 devi, "video-adapter-type", "svga"); 1761 1762 name = "display-edif-id"; 1763 length = BOP_GETPROPLEN(bootops, name); 1764 if (length > 0 && length < MMU_PAGESIZE) { 1765 BOP_GETPROP(bootops, name, bop_staging_area); 1766 copy_boot_str(bop_staging_area, property_val, length); 1767 (void) ndi_prop_update_string(DDI_DEV_T_NONE, 1768 devi, name, property_val); 1769 } 1770 1771 kmem_free(bop_staging_area, MMU_PAGESIZE); 1772 } 1773 1774 1775 /* 1776 * This is temporary, but absolutely necessary. If we are being 1777 * booted with a device tree created by the DevConf project's bootconf 1778 * program, then we have device information nodes that reflect 1779 * reality. At this point in time in the Solaris release schedule, the 1780 * kernel drivers aren't prepared for reality. They still depend on their 1781 * own ad-hoc interpretations of the properties created when their .conf 1782 * files were interpreted. These drivers use an "ignore-hardware-nodes" 1783 * property to prevent them from using the nodes passed up from the bootconf 1784 * device tree. 1785 * 1786 * Trying to assemble root file system drivers as we are booting from 1787 * devconf will fail if the kernel driver is basing its name_addr's on the 1788 * psuedo-node device info while the bootpath passed up from bootconf is using 1789 * reality-based name_addrs. We help the boot along in this case by 1790 * looking at the pre-bootconf bootpath and determining if we would have 1791 * successfully matched if that had been the bootpath we had chosen. 1792 * 1793 * Note that we only even perform this extra check if we've booted 1794 * using bootconf's 1275 compliant bootpath, this is the boot device, and 1795 * we're trying to match the name_addr specified in the 1275 bootpath. 1796 */ 1797 1798 #define MAXCOMPONENTLEN 32 1799 1800 int 1801 x86_old_bootpath_name_addr_match(dev_info_t *cdip, char *caddr, char *naddr) 1802 { 1803 /* 1804 * There are multiple criteria to be met before we can even 1805 * consider allowing a name_addr match here. 1806 * 1807 * 1) We must have been booted such that the bootconf program 1808 * created device tree nodes and properties. This can be 1809 * determined by examining the 'bootpath' property. This 1810 * property will be a non-null string iff bootconf was 1811 * involved in the boot. 1812 * 1813 * 2) The module that we want to match must be the boot device. 1814 * 1815 * 3) The instance of the module we are thinking of letting be 1816 * our match must be ignoring hardware nodes. 1817 * 1818 * 4) The name_addr we want to match must be the name_addr 1819 * specified in the 1275 bootpath. 1820 */ 1821 static char bootdev_module[MAXCOMPONENTLEN]; 1822 static char bootdev_oldmod[MAXCOMPONENTLEN]; 1823 static char bootdev_newaddr[MAXCOMPONENTLEN]; 1824 static char bootdev_oldaddr[MAXCOMPONENTLEN]; 1825 static int quickexit; 1826 1827 char *daddr; 1828 int dlen; 1829 1830 char *lkupname; 1831 int rv = DDI_FAILURE; 1832 1833 if ((ddi_getlongprop(DDI_DEV_T_ANY, cdip, DDI_PROP_DONTPASS, 1834 "devconf-addr", (caddr_t)&daddr, &dlen) == DDI_PROP_SUCCESS) && 1835 (ddi_getprop(DDI_DEV_T_ANY, cdip, DDI_PROP_DONTPASS, 1836 "ignore-hardware-nodes", -1) != -1)) { 1837 if (strcmp(daddr, caddr) == 0) { 1838 return (DDI_SUCCESS); 1839 } 1840 } 1841 1842 if (quickexit) 1843 return (rv); 1844 1845 if (bootdev_module[0] == '\0') { 1846 char *addrp, *eoaddrp; 1847 char *busp, *modp, *atp; 1848 char *bp1275, *bp; 1849 int bp1275len, bplen; 1850 1851 bp1275 = bp = addrp = eoaddrp = busp = modp = atp = NULL; 1852 1853 if (ddi_getlongprop(DDI_DEV_T_ANY, 1854 ddi_root_node(), 0, "bootpath", 1855 (caddr_t)&bp1275, &bp1275len) != DDI_PROP_SUCCESS || 1856 bp1275len <= 1) { 1857 /* 1858 * We didn't boot from bootconf so we never need to 1859 * do any special matches. 1860 */ 1861 quickexit = 1; 1862 if (bp1275) 1863 kmem_free(bp1275, bp1275len); 1864 return (rv); 1865 } 1866 1867 if (ddi_getlongprop(DDI_DEV_T_ANY, 1868 ddi_root_node(), 0, "boot-path", 1869 (caddr_t)&bp, &bplen) != DDI_PROP_SUCCESS || bplen <= 1) { 1870 /* 1871 * No fallback position for matching. This is 1872 * certainly unexpected, but we'll handle it 1873 * just in case. 1874 */ 1875 quickexit = 1; 1876 kmem_free(bp1275, bp1275len); 1877 if (bp) 1878 kmem_free(bp, bplen); 1879 return (rv); 1880 } 1881 1882 /* 1883 * Determine boot device module and 1275 name_addr 1884 * 1885 * bootpath assumed to be of the form /bus/module@name_addr 1886 */ 1887 if (busp = strchr(bp1275, '/')) { 1888 if (modp = strchr(busp + 1, '/')) { 1889 if (atp = strchr(modp + 1, '@')) { 1890 *atp = '\0'; 1891 addrp = atp + 1; 1892 if (eoaddrp = strchr(addrp, '/')) 1893 *eoaddrp = '\0'; 1894 } 1895 } 1896 } 1897 1898 if (modp && addrp) { 1899 (void) strncpy(bootdev_module, modp + 1, 1900 MAXCOMPONENTLEN); 1901 bootdev_module[MAXCOMPONENTLEN - 1] = '\0'; 1902 1903 (void) strncpy(bootdev_newaddr, addrp, MAXCOMPONENTLEN); 1904 bootdev_newaddr[MAXCOMPONENTLEN - 1] = '\0'; 1905 } else { 1906 quickexit = 1; 1907 kmem_free(bp1275, bp1275len); 1908 kmem_free(bp, bplen); 1909 return (rv); 1910 } 1911 1912 /* 1913 * Determine fallback name_addr 1914 * 1915 * 10/3/96 - Also save fallback module name because it 1916 * might actually be different than the current module 1917 * name. E.G., ISA pnp drivers have new names. 1918 * 1919 * bootpath assumed to be of the form /bus/module@name_addr 1920 */ 1921 addrp = NULL; 1922 if (busp = strchr(bp, '/')) { 1923 if (modp = strchr(busp + 1, '/')) { 1924 if (atp = strchr(modp + 1, '@')) { 1925 *atp = '\0'; 1926 addrp = atp + 1; 1927 if (eoaddrp = strchr(addrp, '/')) 1928 *eoaddrp = '\0'; 1929 } 1930 } 1931 } 1932 1933 if (modp && addrp) { 1934 (void) strncpy(bootdev_oldmod, modp + 1, 1935 MAXCOMPONENTLEN); 1936 bootdev_module[MAXCOMPONENTLEN - 1] = '\0'; 1937 1938 (void) strncpy(bootdev_oldaddr, addrp, MAXCOMPONENTLEN); 1939 bootdev_oldaddr[MAXCOMPONENTLEN - 1] = '\0'; 1940 } 1941 1942 /* Free up the bootpath storage now that we're done with it. */ 1943 kmem_free(bp1275, bp1275len); 1944 kmem_free(bp, bplen); 1945 1946 if (bootdev_oldaddr[0] == '\0') { 1947 quickexit = 1; 1948 return (rv); 1949 } 1950 } 1951 1952 if (((lkupname = ddi_get_name(cdip)) != NULL) && 1953 (strcmp(bootdev_module, lkupname) == 0 || 1954 strcmp(bootdev_oldmod, lkupname) == 0) && 1955 ((ddi_getprop(DDI_DEV_T_ANY, cdip, DDI_PROP_DONTPASS, 1956 "ignore-hardware-nodes", -1) != -1) || 1957 ignore_hardware_nodes) && 1958 strcmp(bootdev_newaddr, caddr) == 0 && 1959 strcmp(bootdev_oldaddr, naddr) == 0) { 1960 rv = DDI_SUCCESS; 1961 } 1962 1963 return (rv); 1964 } 1965 1966 /* 1967 * Perform a copy from a memory mapped device (whose devinfo pointer is devi) 1968 * separately mapped at devaddr in the kernel to a kernel buffer at kaddr. 1969 */ 1970 /*ARGSUSED*/ 1971 int 1972 e_ddi_copyfromdev(dev_info_t *devi, 1973 off_t off, const void *devaddr, void *kaddr, size_t len) 1974 { 1975 bcopy(devaddr, kaddr, len); 1976 return (0); 1977 } 1978 1979 /* 1980 * Perform a copy to a memory mapped device (whose devinfo pointer is devi) 1981 * separately mapped at devaddr in the kernel from a kernel buffer at kaddr. 1982 */ 1983 /*ARGSUSED*/ 1984 int 1985 e_ddi_copytodev(dev_info_t *devi, 1986 off_t off, const void *kaddr, void *devaddr, size_t len) 1987 { 1988 bcopy(kaddr, devaddr, len); 1989 return (0); 1990 } 1991 1992 1993 static int 1994 poke_mem(peekpoke_ctlops_t *in_args) 1995 { 1996 int err = DDI_SUCCESS; 1997 on_trap_data_t otd; 1998 1999 /* Set up protected environment. */ 2000 if (!on_trap(&otd, OT_DATA_ACCESS)) { 2001 switch (in_args->size) { 2002 case sizeof (uint8_t): 2003 *(uint8_t *)(in_args->dev_addr) = 2004 *(uint8_t *)in_args->host_addr; 2005 break; 2006 2007 case sizeof (uint16_t): 2008 *(uint16_t *)(in_args->dev_addr) = 2009 *(uint16_t *)in_args->host_addr; 2010 break; 2011 2012 case sizeof (uint32_t): 2013 *(uint32_t *)(in_args->dev_addr) = 2014 *(uint32_t *)in_args->host_addr; 2015 break; 2016 2017 case sizeof (uint64_t): 2018 *(uint64_t *)(in_args->dev_addr) = 2019 *(uint64_t *)in_args->host_addr; 2020 break; 2021 2022 default: 2023 err = DDI_FAILURE; 2024 break; 2025 } 2026 } else 2027 err = DDI_FAILURE; 2028 2029 /* Take down protected environment. */ 2030 no_trap(); 2031 2032 return (err); 2033 } 2034 2035 2036 static int 2037 peek_mem(peekpoke_ctlops_t *in_args) 2038 { 2039 int err = DDI_SUCCESS; 2040 on_trap_data_t otd; 2041 2042 if (!on_trap(&otd, OT_DATA_ACCESS)) { 2043 switch (in_args->size) { 2044 case sizeof (uint8_t): 2045 *(uint8_t *)in_args->host_addr = 2046 *(uint8_t *)in_args->dev_addr; 2047 break; 2048 2049 case sizeof (uint16_t): 2050 *(uint16_t *)in_args->host_addr = 2051 *(uint16_t *)in_args->dev_addr; 2052 break; 2053 2054 case sizeof (uint32_t): 2055 *(uint32_t *)in_args->host_addr = 2056 *(uint32_t *)in_args->dev_addr; 2057 break; 2058 2059 case sizeof (uint64_t): 2060 *(uint64_t *)in_args->host_addr = 2061 *(uint64_t *)in_args->dev_addr; 2062 break; 2063 2064 default: 2065 err = DDI_FAILURE; 2066 break; 2067 } 2068 } else 2069 err = DDI_FAILURE; 2070 2071 no_trap(); 2072 return (err); 2073 } 2074 2075 2076 /* 2077 * This is called only to process peek/poke when the DIP is NULL. 2078 * Assume that this is for memory, as nexi take care of device safe accesses. 2079 */ 2080 int 2081 peekpoke_mem(ddi_ctl_enum_t cmd, peekpoke_ctlops_t *in_args) 2082 { 2083 return (cmd == DDI_CTLOPS_PEEK ? peek_mem(in_args) : poke_mem(in_args)); 2084 } 2085 2086 void 2087 impl_setup_ddi(void) 2088 { 2089 dev_info_t *xdip, *isa_dip; 2090 rd_existing_t rd_mem_prop; 2091 int err; 2092 2093 ndi_devi_alloc_sleep(ddi_root_node(), "ramdisk", 2094 (dnode_t)DEVI_SID_NODEID, &xdip); 2095 2096 (void) BOP_GETPROP(bootops, 2097 "ramdisk_start", (void *)&ramdisk_start); 2098 (void) BOP_GETPROP(bootops, 2099 "ramdisk_end", (void *)&ramdisk_end); 2100 2101 rd_mem_prop.phys = ramdisk_start; 2102 rd_mem_prop.size = ramdisk_end - ramdisk_start + 1; 2103 2104 (void) ndi_prop_update_byte_array(DDI_DEV_T_NONE, xdip, 2105 RD_EXISTING_PROP_NAME, (uchar_t *)&rd_mem_prop, 2106 sizeof (rd_mem_prop)); 2107 err = ndi_devi_bind_driver(xdip, 0); 2108 ASSERT(err == 0); 2109 2110 /* isa node */ 2111 ndi_devi_alloc_sleep(ddi_root_node(), "isa", 2112 (dnode_t)DEVI_SID_NODEID, &isa_dip); 2113 (void) ndi_prop_update_string(DDI_DEV_T_NONE, isa_dip, 2114 "device_type", "isa"); 2115 (void) ndi_prop_update_string(DDI_DEV_T_NONE, isa_dip, 2116 "bus-type", "isa"); 2117 (void) ndi_devi_bind_driver(isa_dip, 0); 2118 2119 /* 2120 * Read in the properties from the boot. 2121 */ 2122 get_boot_properties(); 2123 2124 /* do bus dependent probes. */ 2125 impl_bus_initialprobe(); 2126 2127 /* not framebuffer should be enumerated, if present */ 2128 get_vga_properties(); 2129 } 2130 2131 dev_t 2132 getrootdev(void) 2133 { 2134 /* 2135 * Precedence given to rootdev if set in /etc/system 2136 */ 2137 if (root_is_svm) { 2138 return (ddi_pathname_to_dev_t(svm_bootpath)); 2139 } 2140 2141 /* 2142 * Usually rootfs.bo_name is initialized by the 2143 * the bootpath property from bootenv.rc, but 2144 * defaults to "/ramdisk:a" otherwise. 2145 */ 2146 return (ddi_pathname_to_dev_t(rootfs.bo_name)); 2147 } 2148 2149 static struct bus_probe { 2150 struct bus_probe *next; 2151 void (*probe)(int); 2152 } *bus_probes; 2153 2154 void 2155 impl_bus_add_probe(void (*func)(int)) 2156 { 2157 struct bus_probe *probe; 2158 2159 probe = kmem_alloc(sizeof (*probe), KM_SLEEP); 2160 probe->next = bus_probes; 2161 probe->probe = func; 2162 bus_probes = probe; 2163 } 2164 2165 /*ARGSUSED*/ 2166 void 2167 impl_bus_delete_probe(void (*func)(int)) 2168 { 2169 struct bus_probe *prev = NULL; 2170 struct bus_probe *probe = bus_probes; 2171 2172 while (probe) { 2173 if (probe->probe == func) 2174 break; 2175 prev = probe; 2176 probe = probe->next; 2177 } 2178 2179 if (probe == NULL) 2180 return; 2181 2182 if (prev) 2183 prev->next = probe->next; 2184 else 2185 bus_probes = probe->next; 2186 2187 kmem_free(probe, sizeof (struct bus_probe)); 2188 } 2189 2190 /* 2191 * impl_bus_initialprobe 2192 * Modload the prom simulator, then let it probe to verify existence 2193 * and type of PCI support. 2194 */ 2195 static void 2196 impl_bus_initialprobe(void) 2197 { 2198 struct bus_probe *probe; 2199 2200 /* load modules to install bus probes */ 2201 if (modload("misc", "pci_autoconfig") < 0) { 2202 cmn_err(CE_PANIC, "failed to load misc/pci_autoconfig"); 2203 } 2204 2205 probe = bus_probes; 2206 while (probe) { 2207 /* run the probe function */ 2208 (*probe->probe)(0); 2209 probe = probe->next; 2210 } 2211 } 2212 2213 /* 2214 * impl_bus_reprobe 2215 * Reprogram devices not set up by firmware. 2216 */ 2217 static void 2218 impl_bus_reprobe(void) 2219 { 2220 struct bus_probe *probe; 2221 2222 probe = bus_probes; 2223 while (probe) { 2224 /* run the probe function */ 2225 (*probe->probe)(1); 2226 probe = probe->next; 2227 } 2228 } 2229