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