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 * Create a ddi_parent_private_data structure from the ddi properties of 393 * the dev_info node. 394 * 395 * The "reg" and either an "intr" or "interrupts" properties are required 396 * if the driver wishes to create mappings or field interrupts on behalf 397 * of the device. 398 * 399 * The "reg" property is assumed to be a list of at least one triple 400 * 401 * <bustype, address, size>*1 402 * 403 * The "intr" property is assumed to be a list of at least one duple 404 * 405 * <SPARC ipl, vector#>*1 406 * 407 * The "interrupts" property is assumed to be a list of at least one 408 * n-tuples that describes the interrupt capabilities of the bus the device 409 * is connected to. For SBus, this looks like 410 * 411 * <SBus-level>*1 412 * 413 * (This property obsoletes the 'intr' property). 414 * 415 * The "ranges" property is optional. 416 */ 417 void 418 make_ddi_ppd(dev_info_t *child, struct ddi_parent_private_data **ppd) 419 { 420 struct ddi_parent_private_data *pdptr; 421 int n; 422 int *reg_prop, *rng_prop, *intr_prop, *irupts_prop; 423 uint_t reg_len, rng_len, intr_len, irupts_len; 424 425 *ppd = pdptr = kmem_zalloc(sizeof (*pdptr), KM_SLEEP); 426 427 /* 428 * Handle the 'reg' property. 429 */ 430 if ((get_prop_int_array(child, "reg", ®_prop, ®_len) == 431 DDI_PROP_SUCCESS) && (reg_len != 0)) { 432 pdptr->par_nreg = reg_len / (int)sizeof (struct regspec); 433 pdptr->par_reg = (struct regspec *)reg_prop; 434 } 435 436 /* 437 * See if I have a range (adding one where needed - this 438 * means to add one for sbus node in sun4c, when romvec > 0, 439 * if no range is already defined in the PROM node. 440 * (Currently no sun4c PROMS define range properties, 441 * but they should and may in the future.) For the SBus 442 * node, the range is defined by the SBus reg property. 443 */ 444 if (get_prop_int_array(child, "ranges", &rng_prop, &rng_len) 445 == DDI_PROP_SUCCESS) { 446 pdptr->par_nrng = rng_len / (int)(sizeof (struct rangespec)); 447 pdptr->par_rng = (struct rangespec *)rng_prop; 448 } 449 450 /* 451 * Handle the 'intr' and 'interrupts' properties 452 */ 453 454 /* 455 * For backwards compatibility 456 * we first look for the 'intr' property for the device. 457 */ 458 if (get_prop_int_array(child, "intr", &intr_prop, &intr_len) 459 != DDI_PROP_SUCCESS) { 460 intr_len = 0; 461 } 462 463 /* 464 * If we're to support bus adapters and future platforms cleanly, 465 * we need to support the generalized 'interrupts' property. 466 */ 467 if (get_prop_int_array(child, "interrupts", &irupts_prop, 468 &irupts_len) != DDI_PROP_SUCCESS) { 469 irupts_len = 0; 470 } else if (intr_len != 0) { 471 /* 472 * If both 'intr' and 'interrupts' are defined, 473 * then 'interrupts' wins and we toss the 'intr' away. 474 */ 475 ddi_prop_free((void *)intr_prop); 476 intr_len = 0; 477 } 478 479 if (intr_len != 0) { 480 481 /* 482 * Translate the 'intr' property into an array 483 * an array of struct intrspec's. There's not really 484 * very much to do here except copy what's out there. 485 */ 486 487 struct intrspec *new; 488 struct prop_ispec *l; 489 490 n = pdptr->par_nintr = 491 intr_len / sizeof (struct prop_ispec); 492 l = (struct prop_ispec *)intr_prop; 493 pdptr->par_intr = 494 new = kmem_zalloc(n * sizeof (struct intrspec), KM_SLEEP); 495 while (n--) { 496 new->intrspec_pri = l->pri; 497 new->intrspec_vec = l->vec; 498 new++; 499 l++; 500 } 501 ddi_prop_free((void *)intr_prop); 502 503 } else if ((n = irupts_len) != 0) { 504 size_t size; 505 int *out; 506 507 /* 508 * Translate the 'interrupts' property into an array 509 * of intrspecs for the rest of the DDI framework to 510 * toy with. Only our ancestors really know how to 511 * do this, so ask 'em. We massage the 'interrupts' 512 * property so that it is pre-pended by a count of 513 * the number of integers in the argument. 514 */ 515 size = sizeof (int) + n; 516 out = kmem_alloc(size, KM_SLEEP); 517 *out = n / sizeof (int); 518 bcopy(irupts_prop, out + 1, (size_t)n); 519 ddi_prop_free((void *)irupts_prop); 520 if (ddi_ctlops(child, child, DDI_CTLOPS_XLATE_INTRS, 521 out, pdptr) != DDI_SUCCESS) { 522 cmn_err(CE_CONT, 523 "Unable to translate 'interrupts' for %s%d\n", 524 DEVI(child)->devi_binding_name, 525 DEVI(child)->devi_instance); 526 } 527 kmem_free(out, size); 528 } 529 } 530 531 /* 532 * Name a child 533 */ 534 static int 535 impl_sunbus_name_child(dev_info_t *child, char *name, int namelen) 536 { 537 /* 538 * Fill in parent-private data and this function returns to us 539 * an indication if it used "registers" to fill in the data. 540 */ 541 if (ddi_get_parent_data(child) == NULL) { 542 struct ddi_parent_private_data *pdptr; 543 make_ddi_ppd(child, &pdptr); 544 ddi_set_parent_data(child, pdptr); 545 } 546 547 name[0] = '\0'; 548 if (sparc_pd_getnreg(child) > 0) { 549 (void) snprintf(name, namelen, "%x,%x", 550 (uint_t)sparc_pd_getreg(child, 0)->regspec_bustype, 551 (uint_t)sparc_pd_getreg(child, 0)->regspec_addr); 552 } 553 554 return (DDI_SUCCESS); 555 } 556 557 /* 558 * Called from the bus_ctl op of sunbus (sbus, obio, etc) nexus drivers 559 * to implement the DDI_CTLOPS_INITCHILD operation. That is, it names 560 * the children of sun busses based on the reg spec. 561 * 562 * Handles the following properties (in make_ddi_ppd): 563 * Property value 564 * Name type 565 * reg register spec 566 * intr old-form interrupt spec 567 * interrupts new (bus-oriented) interrupt spec 568 * ranges range spec 569 */ 570 int 571 impl_ddi_sunbus_initchild(dev_info_t *child) 572 { 573 char name[MAXNAMELEN]; 574 void impl_ddi_sunbus_removechild(dev_info_t *); 575 576 /* 577 * Name the child, also makes parent private data 578 */ 579 (void) impl_sunbus_name_child(child, name, MAXNAMELEN); 580 ddi_set_name_addr(child, name); 581 582 /* 583 * Attempt to merge a .conf node; if successful, remove the 584 * .conf node. 585 */ 586 if ((ndi_dev_is_persistent_node(child) == 0) && 587 (ndi_merge_node(child, impl_sunbus_name_child) == DDI_SUCCESS)) { 588 /* 589 * Return failure to remove node 590 */ 591 impl_ddi_sunbus_removechild(child); 592 return (DDI_FAILURE); 593 } 594 return (DDI_SUCCESS); 595 } 596 597 void 598 impl_free_ddi_ppd(dev_info_t *dip) 599 { 600 struct ddi_parent_private_data *pdptr; 601 size_t n; 602 603 if ((pdptr = ddi_get_parent_data(dip)) == NULL) 604 return; 605 606 if ((n = (size_t)pdptr->par_nintr) != 0) 607 /* 608 * Note that kmem_free is used here (instead of 609 * ddi_prop_free) because the contents of the 610 * property were placed into a separate buffer and 611 * mucked with a bit before being stored in par_intr. 612 * The actual return value from the prop lookup 613 * was freed with ddi_prop_free previously. 614 */ 615 kmem_free(pdptr->par_intr, n * sizeof (struct intrspec)); 616 617 if ((n = (size_t)pdptr->par_nrng) != 0) 618 ddi_prop_free((void *)pdptr->par_rng); 619 620 if ((n = pdptr->par_nreg) != 0) 621 ddi_prop_free((void *)pdptr->par_reg); 622 623 kmem_free(pdptr, sizeof (*pdptr)); 624 ddi_set_parent_data(dip, NULL); 625 } 626 627 void 628 impl_ddi_sunbus_removechild(dev_info_t *dip) 629 { 630 impl_free_ddi_ppd(dip); 631 ddi_set_name_addr(dip, NULL); 632 /* 633 * Strip the node to properly convert it back to prototype form 634 */ 635 impl_rem_dev_props(dip); 636 } 637 638 /* 639 * DDI Interrupt 640 */ 641 642 /* 643 * turn this on to force isa, eisa, and mca device to ignore the new 644 * hardware nodes in the device tree (normally turned on only for 645 * drivers that need it by setting the property "ignore-hardware-nodes" 646 * in their driver.conf file). 647 * 648 * 7/31/96 -- Turned off globally. Leaving variable in for the moment 649 * as safety valve. 650 */ 651 int ignore_hardware_nodes = 0; 652 653 /* 654 * Local data 655 */ 656 static struct impl_bus_promops *impl_busp; 657 658 659 /* 660 * New DDI interrupt framework 661 */ 662 663 /* 664 * i_ddi_handle_intr_ops: 665 */ 666 int 667 i_ddi_handle_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t op, 668 ddi_intr_handle_impl_t *hdlp, void * result) 669 { 670 return (i_ddi_intr_ops(dip, rdip, op, hdlp, result)); 671 } 672 673 /* 674 * i_ddi_intr_ops: 675 * 676 * This is the interrupt operator function wrapper for the bus function 677 * bus_intr_op. 678 */ 679 int 680 i_ddi_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t op, 681 ddi_intr_handle_impl_t *hdlp, void * result) 682 { 683 dev_info_t *pdip = (dev_info_t *)DEVI(dip)->devi_parent; 684 int ret = DDI_FAILURE; 685 686 /* request parent to process this interrupt op */ 687 if (NEXUS_HAS_INTR_OP(pdip)) 688 ret = (*(DEVI(pdip)->devi_ops->devo_bus_ops->bus_intr_op))( 689 pdip, rdip, op, hdlp, result); 690 else 691 cmn_err(CE_WARN, "Failed to process interrupt " 692 "for %s%d due to down-rev nexus driver %s%d", 693 ddi_get_name(rdip), ddi_get_instance(rdip), 694 ddi_get_name(pdip), ddi_get_instance(pdip)); 695 return (ret); 696 } 697 698 /* 699 * i_ddi_add_softint - allocate and add a soft interrupt to the system 700 */ 701 int 702 i_ddi_add_softint(ddi_softint_hdl_impl_t *hdlp) 703 { 704 int ret; 705 706 /* add soft interrupt handler */ 707 ret = add_avsoftintr((void *)hdlp, hdlp->ih_pri, hdlp->ih_cb_func, 708 DEVI(hdlp->ih_dip)->devi_name, hdlp->ih_cb_arg1, hdlp->ih_cb_arg2); 709 return (ret ? DDI_SUCCESS : DDI_FAILURE); 710 } 711 712 713 void 714 i_ddi_remove_softint(ddi_softint_hdl_impl_t *hdlp) 715 { 716 (void) rem_avsoftintr((void *)hdlp, hdlp->ih_pri, hdlp->ih_cb_func); 717 } 718 719 720 extern void (*setsoftint)(int); 721 722 int 723 i_ddi_trigger_softint(ddi_softint_hdl_impl_t *hdlp, void *arg2) 724 { 725 int ret = DDI_SUCCESS; 726 727 if (hdlp->ih_pending) { 728 ret = DDI_EPENDING; 729 } else { 730 update_avsoftintr_args((void *)hdlp, 731 hdlp->ih_pri, arg2); 732 hdlp->ih_pending = 1; 733 } 734 735 (*setsoftint)(hdlp->ih_pri); 736 return (ret); 737 } 738 739 /* 740 * i_ddi_set_softint_pri: 741 * 742 * The way this works is that it first tries to add a softint vector 743 * at the new priority in hdlp. If that succeeds; then it removes the 744 * existing softint vector at the old priority. 745 */ 746 int 747 i_ddi_set_softint_pri(ddi_softint_hdl_impl_t *hdlp, uint_t old_pri) 748 { 749 /* 750 * If a softint is pending at the old priority then fail the request. 751 * OR 752 * If we failed to add a softint vector with the new priority; then 753 * fail the request with a DDI_FAILURE 754 */ 755 if (hdlp->ih_pending || i_ddi_add_softint(hdlp) != DDI_SUCCESS) 756 return (DDI_FAILURE); 757 758 /* Now, remove the softint at the old priority */ 759 (void) rem_avsoftintr((void *)hdlp, old_pri, hdlp->ih_cb_func); 760 return (DDI_SUCCESS); 761 } 762 763 /* 764 * DDI Memory/DMA 765 */ 766 767 /* 768 * Support for allocating DMAable memory to implement 769 * ddi_dma_mem_alloc(9F) interface. 770 */ 771 772 #define KA_ALIGN_SHIFT 7 773 #define KA_ALIGN (1 << KA_ALIGN_SHIFT) 774 #define KA_NCACHE (PAGESHIFT + 1 - KA_ALIGN_SHIFT) 775 776 /* 777 * Dummy DMA attribute template for kmem_io[].kmem_io_attr. We only 778 * care about addr_lo, addr_hi, and align. addr_hi will be dynamically set. 779 */ 780 781 static ddi_dma_attr_t kmem_io_attr = { 782 DMA_ATTR_V0, 783 0x0000000000000000ULL, /* dma_attr_addr_lo */ 784 0x0000000000000000ULL, /* dma_attr_addr_hi */ 785 0x00ffffff, 786 0x1000, /* dma_attr_align */ 787 1, 1, 0xffffffffULL, 0xffffffffULL, 0x1, 1, 0 788 }; 789 790 /* kmem io memory ranges and indices */ 791 enum { 792 IO_4P, IO_64G, IO_4G, IO_2G, IO_1G, IO_512M, 793 IO_256M, IO_128M, IO_64M, IO_32M, IO_16M, MAX_MEM_RANGES 794 }; 795 796 static struct { 797 vmem_t *kmem_io_arena; 798 kmem_cache_t *kmem_io_cache[KA_NCACHE]; 799 ddi_dma_attr_t kmem_io_attr; 800 } kmem_io[MAX_MEM_RANGES]; 801 802 static int kmem_io_idx; /* index of first populated kmem_io[] */ 803 804 static page_t * 805 page_create_io_wrapper(void *addr, size_t len, int vmflag, void *arg) 806 { 807 extern page_t *page_create_io(vnode_t *, u_offset_t, uint_t, 808 uint_t, struct as *, caddr_t, ddi_dma_attr_t *); 809 810 return (page_create_io(&kvp, (u_offset_t)(uintptr_t)addr, len, 811 PG_EXCL | ((vmflag & VM_NOSLEEP) ? 0 : PG_WAIT), &kas, addr, arg)); 812 } 813 814 static void * 815 segkmem_alloc_io_4P(vmem_t *vmp, size_t size, int vmflag) 816 { 817 return (segkmem_xalloc(vmp, NULL, size, vmflag, 0, 818 page_create_io_wrapper, &kmem_io[IO_4P].kmem_io_attr)); 819 } 820 821 static void * 822 segkmem_alloc_io_64G(vmem_t *vmp, size_t size, int vmflag) 823 { 824 return (segkmem_xalloc(vmp, NULL, size, vmflag, 0, 825 page_create_io_wrapper, &kmem_io[IO_64G].kmem_io_attr)); 826 } 827 828 static void * 829 segkmem_alloc_io_4G(vmem_t *vmp, size_t size, int vmflag) 830 { 831 return (segkmem_xalloc(vmp, NULL, size, vmflag, 0, 832 page_create_io_wrapper, &kmem_io[IO_4G].kmem_io_attr)); 833 } 834 835 static void * 836 segkmem_alloc_io_2G(vmem_t *vmp, size_t size, int vmflag) 837 { 838 return (segkmem_xalloc(vmp, NULL, size, vmflag, 0, 839 page_create_io_wrapper, &kmem_io[IO_2G].kmem_io_attr)); 840 } 841 842 static void * 843 segkmem_alloc_io_1G(vmem_t *vmp, size_t size, int vmflag) 844 { 845 return (segkmem_xalloc(vmp, NULL, size, vmflag, 0, 846 page_create_io_wrapper, &kmem_io[IO_1G].kmem_io_attr)); 847 } 848 849 static void * 850 segkmem_alloc_io_512M(vmem_t *vmp, size_t size, int vmflag) 851 { 852 return (segkmem_xalloc(vmp, NULL, size, vmflag, 0, 853 page_create_io_wrapper, &kmem_io[IO_512M].kmem_io_attr)); 854 } 855 856 static void * 857 segkmem_alloc_io_256M(vmem_t *vmp, size_t size, int vmflag) 858 { 859 return (segkmem_xalloc(vmp, NULL, size, vmflag, 0, 860 page_create_io_wrapper, &kmem_io[IO_256M].kmem_io_attr)); 861 } 862 863 static void * 864 segkmem_alloc_io_128M(vmem_t *vmp, size_t size, int vmflag) 865 { 866 return (segkmem_xalloc(vmp, NULL, size, vmflag, 0, 867 page_create_io_wrapper, &kmem_io[IO_128M].kmem_io_attr)); 868 } 869 870 static void * 871 segkmem_alloc_io_64M(vmem_t *vmp, size_t size, int vmflag) 872 { 873 return (segkmem_xalloc(vmp, NULL, size, vmflag, 0, 874 page_create_io_wrapper, &kmem_io[IO_64M].kmem_io_attr)); 875 } 876 877 static void * 878 segkmem_alloc_io_32M(vmem_t *vmp, size_t size, int vmflag) 879 { 880 return (segkmem_xalloc(vmp, NULL, size, vmflag, 0, 881 page_create_io_wrapper, &kmem_io[IO_32M].kmem_io_attr)); 882 } 883 884 static void * 885 segkmem_alloc_io_16M(vmem_t *vmp, size_t size, int vmflag) 886 { 887 return (segkmem_xalloc(vmp, NULL, size, vmflag, 0, 888 page_create_io_wrapper, &kmem_io[IO_16M].kmem_io_attr)); 889 } 890 891 struct { 892 uint64_t io_limit; 893 char *io_name; 894 void *(*io_alloc)(vmem_t *, size_t, int); 895 int io_initial; /* kmem_io_init during startup */ 896 } io_arena_params[MAX_MEM_RANGES] = { 897 {0x000fffffffffffffULL, "kmem_io_4P", segkmem_alloc_io_4P, 1}, 898 {0x0000000fffffffffULL, "kmem_io_64G", segkmem_alloc_io_64G, 0}, 899 {0x00000000ffffffffULL, "kmem_io_4G", segkmem_alloc_io_4G, 1}, 900 {0x000000007fffffffULL, "kmem_io_2G", segkmem_alloc_io_2G, 1}, 901 {0x000000003fffffffULL, "kmem_io_1G", segkmem_alloc_io_1G, 0}, 902 {0x000000001fffffffULL, "kmem_io_512M", segkmem_alloc_io_512M, 0}, 903 {0x000000000fffffffULL, "kmem_io_256M", segkmem_alloc_io_256M, 0}, 904 {0x0000000007ffffffULL, "kmem_io_128M", segkmem_alloc_io_128M, 0}, 905 {0x0000000003ffffffULL, "kmem_io_64M", segkmem_alloc_io_64M, 0}, 906 {0x0000000001ffffffULL, "kmem_io_32M", segkmem_alloc_io_32M, 0}, 907 {0x0000000000ffffffULL, "kmem_io_16M", segkmem_alloc_io_16M, 1} 908 }; 909 910 void 911 kmem_io_init(int a) 912 { 913 int c; 914 char name[40]; 915 916 kmem_io[a].kmem_io_arena = vmem_create(io_arena_params[a].io_name, 917 NULL, 0, PAGESIZE, io_arena_params[a].io_alloc, 918 segkmem_free, heap_arena, 0, VM_SLEEP); 919 for (c = 0; c < KA_NCACHE; c++) { 920 size_t size = KA_ALIGN << c; 921 (void) sprintf(name, "%s_%lu", 922 io_arena_params[a].io_name, size); 923 kmem_io[a].kmem_io_cache[c] = kmem_cache_create(name, 924 size, size, NULL, NULL, NULL, NULL, 925 kmem_io[a].kmem_io_arena, 0); 926 } 927 } 928 929 /* 930 * Return the index of the highest memory range for addr. 931 */ 932 static int 933 kmem_io_index(uint64_t addr) 934 { 935 int n; 936 937 for (n = kmem_io_idx; n < MAX_MEM_RANGES; n++) { 938 if (kmem_io[n].kmem_io_attr.dma_attr_addr_hi <= addr) { 939 if (kmem_io[n].kmem_io_arena == NULL) 940 kmem_io_init(n); 941 return (n); 942 } 943 } 944 panic("kmem_io_index: invalid addr - must be at least 16m"); 945 946 /*NOTREACHED*/ 947 } 948 949 /* 950 * Return the index of the next kmem_io populated memory range 951 * after curindex. 952 */ 953 static int 954 kmem_io_index_next(int curindex) 955 { 956 int n; 957 958 for (n = curindex + 1; n < MAX_MEM_RANGES; n++) { 959 if (kmem_io[n].kmem_io_arena) 960 return (n); 961 } 962 return (-1); 963 } 964 965 void 966 ka_init(void) 967 { 968 int a; 969 extern pfn_t physmax; 970 uint64_t maxphysaddr = mmu_ptob((uint64_t)physmax + 1) - 1; 971 972 ASSERT(maxphysaddr <= io_arena_params[0].io_limit); 973 974 for (a = 0; a < MAX_MEM_RANGES; a++) { 975 if (maxphysaddr >= io_arena_params[a + 1].io_limit) { 976 if (maxphysaddr > io_arena_params[a + 1].io_limit) 977 io_arena_params[a].io_limit = maxphysaddr; 978 else 979 a++; 980 break; 981 } 982 } 983 kmem_io_idx = a; 984 985 for (; a < MAX_MEM_RANGES; a++) { 986 kmem_io[a].kmem_io_attr = kmem_io_attr; 987 kmem_io[a].kmem_io_attr.dma_attr_addr_hi = 988 io_arena_params[a].io_limit; 989 /* 990 * initialize kmem_io[] arena/cache corresponding to 991 * maxphysaddr and to the "common" io memory ranges that 992 * have io_initial set to a non-zero value. 993 */ 994 if (io_arena_params[a].io_initial || a == kmem_io_idx) 995 kmem_io_init(a); 996 } 997 } 998 999 /* 1000 * put contig address/size 1001 */ 1002 static void * 1003 putctgas(void *addr, size_t size) 1004 { 1005 struct ctgas *ctgp = &ctglist; 1006 int i; 1007 1008 CTGLOCK(); 1009 do { 1010 if ((i = ctgp->ctg_index) < CTGENTRIES) { 1011 ctgp->ctg_addr[i] = addr; 1012 ctgp->ctg_size[i] = size; 1013 ctgp->ctg_index++; 1014 break; 1015 } 1016 if (!ctgp->ctg_next) 1017 ctgp->ctg_next = kmem_zalloc(sizeof (struct ctgas), 1018 KM_NOSLEEP); 1019 ctgp = ctgp->ctg_next; 1020 } while (ctgp); 1021 1022 CTGUNLOCK(); 1023 return (ctgp); 1024 } 1025 1026 /* 1027 * get contig size by addr 1028 */ 1029 static size_t 1030 getctgsz(void *addr) 1031 { 1032 struct ctgas *ctgp = &ctglist; 1033 int i, j; 1034 size_t sz; 1035 1036 ASSERT(addr); 1037 CTGLOCK(); 1038 1039 while (ctgp) { 1040 for (i = 0; i < ctgp->ctg_index; i++) { 1041 if (addr != ctgp->ctg_addr[i]) 1042 continue; 1043 1044 sz = ctgp->ctg_size[i]; 1045 j = --ctgp->ctg_index; 1046 if (i != j) { 1047 ctgp->ctg_size[i] = ctgp->ctg_size[j]; 1048 ctgp->ctg_addr[i] = ctgp->ctg_addr[j]; 1049 } 1050 CTGUNLOCK(); 1051 return (sz); 1052 } 1053 ctgp = ctgp->ctg_next; 1054 } 1055 1056 CTGUNLOCK(); 1057 return (0); 1058 } 1059 1060 /* 1061 * contig_alloc: 1062 * 1063 * allocates contiguous memory to satisfy the 'size' and dma attributes 1064 * specified in 'attr'. 1065 * 1066 * Not all of memory need to be physically contiguous if the 1067 * scatter-gather list length is greater than 1. 1068 */ 1069 1070 /*ARGSUSED*/ 1071 void * 1072 contig_alloc(size_t size, ddi_dma_attr_t *attr, uintptr_t align, int cansleep) 1073 { 1074 pgcnt_t pgcnt = btopr(size); 1075 size_t asize = pgcnt * PAGESIZE; 1076 page_t *ppl; 1077 int pflag; 1078 void *addr; 1079 1080 extern page_t *page_create_io(vnode_t *, u_offset_t, uint_t, 1081 uint_t, struct as *, caddr_t, ddi_dma_attr_t *); 1082 1083 /* segkmem_xalloc */ 1084 1085 if (align <= PAGESIZE) 1086 addr = vmem_alloc(heap_arena, asize, 1087 (cansleep) ? VM_SLEEP : VM_NOSLEEP); 1088 else 1089 addr = vmem_xalloc(heap_arena, asize, align, 0, 0, NULL, NULL, 1090 (cansleep) ? VM_SLEEP : VM_NOSLEEP); 1091 if (addr) { 1092 ASSERT(!((uintptr_t)addr & (align - 1))); 1093 1094 if (page_resv(pgcnt, 1095 (cansleep) ? KM_SLEEP : KM_NOSLEEP) == 0) { 1096 1097 vmem_free(heap_arena, addr, asize); 1098 return (NULL); 1099 } 1100 pflag = PG_EXCL; 1101 1102 if (cansleep) 1103 pflag |= PG_WAIT; 1104 1105 /* 4k req gets from freelists rather than pfn search */ 1106 if (pgcnt > 1 || align > PAGESIZE) 1107 pflag |= PG_PHYSCONTIG; 1108 1109 ppl = page_create_io(&kvp, (u_offset_t)(uintptr_t)addr, 1110 asize, pflag, &kas, (caddr_t)addr, attr); 1111 1112 if (!ppl) { 1113 vmem_free(heap_arena, addr, asize); 1114 page_unresv(pgcnt); 1115 return (NULL); 1116 } 1117 1118 while (ppl != NULL) { 1119 page_t *pp = ppl; 1120 page_sub(&ppl, pp); 1121 ASSERT(page_iolock_assert(pp)); 1122 page_io_unlock(pp); 1123 page_downgrade(pp); 1124 hat_memload(kas.a_hat, (caddr_t)(uintptr_t)pp->p_offset, 1125 pp, (PROT_ALL & ~PROT_USER) | 1126 HAT_NOSYNC, HAT_LOAD_LOCK); 1127 } 1128 } 1129 return (addr); 1130 } 1131 1132 static void 1133 contig_free(void *addr, size_t size) 1134 { 1135 pgcnt_t pgcnt = btopr(size); 1136 size_t asize = pgcnt * PAGESIZE; 1137 caddr_t a, ea; 1138 page_t *pp; 1139 1140 hat_unload(kas.a_hat, addr, asize, HAT_UNLOAD_UNLOCK); 1141 1142 for (a = addr, ea = a + asize; a < ea; a += PAGESIZE) { 1143 pp = page_find(&kvp, 1144 (u_offset_t)(uintptr_t)a); 1145 if (!pp) 1146 panic("contig_free: contig pp not found"); 1147 1148 if (!page_tryupgrade(pp)) { 1149 page_unlock(pp); 1150 pp = page_lookup(&kvp, 1151 (u_offset_t)(uintptr_t)a, SE_EXCL); 1152 if (pp == NULL) 1153 panic("contig_free: page freed"); 1154 } 1155 page_destroy(pp, 0); 1156 } 1157 1158 page_unresv(pgcnt); 1159 vmem_free(heap_arena, addr, asize); 1160 } 1161 1162 /* 1163 * Allocate from the system, aligned on a specific boundary. 1164 * The alignment, if non-zero, must be a power of 2. 1165 */ 1166 static void * 1167 kalloca(size_t size, size_t align, int cansleep, int physcontig, 1168 ddi_dma_attr_t *attr) 1169 { 1170 size_t *addr, *raddr, rsize; 1171 size_t hdrsize = 4 * sizeof (size_t); /* must be power of 2 */ 1172 int a, i, c; 1173 vmem_t *vmp; 1174 kmem_cache_t *cp = NULL; 1175 1176 align = MAX(align, hdrsize); 1177 ASSERT((align & (align - 1)) == 0); 1178 1179 /* 1180 * All of our allocators guarantee 16-byte alignment, so we don't 1181 * need to reserve additional space for the header. 1182 * To simplify picking the correct kmem_io_cache, we round up to 1183 * a multiple of KA_ALIGN. 1184 */ 1185 rsize = P2ROUNDUP_TYPED(size + align, KA_ALIGN, size_t); 1186 1187 if (physcontig && rsize > PAGESIZE) { 1188 if (addr = contig_alloc(size, attr, align, cansleep)) { 1189 if (!putctgas(addr, size)) 1190 contig_free(addr, size); 1191 else 1192 return (addr); 1193 } 1194 return (NULL); 1195 } 1196 1197 ASSERT(attr->dma_attr_addr_lo <= mmu_ptob((uint64_t)ddiphysmin)); 1198 1199 a = kmem_io_index(attr->dma_attr_addr_hi); 1200 1201 if (rsize > PAGESIZE) { 1202 vmp = kmem_io[a].kmem_io_arena; 1203 raddr = vmem_alloc(vmp, rsize, 1204 (cansleep) ? VM_SLEEP : VM_NOSLEEP); 1205 } else { 1206 c = highbit((rsize >> KA_ALIGN_SHIFT) - 1); 1207 cp = kmem_io[a].kmem_io_cache[c]; 1208 raddr = kmem_cache_alloc(cp, (cansleep) ? KM_SLEEP : 1209 KM_NOSLEEP); 1210 } 1211 1212 if (raddr == NULL) { 1213 int na; 1214 1215 ASSERT(cansleep == 0); 1216 if (rsize > PAGESIZE) 1217 return (NULL); 1218 /* 1219 * System does not have memory in the requested range. 1220 * Try smaller kmem io ranges and larger cache sizes 1221 * to see if there might be memory available in 1222 * these other caches. 1223 */ 1224 1225 for (na = kmem_io_index_next(a); na >= 0; 1226 na = kmem_io_index_next(na)) { 1227 ASSERT(kmem_io[na].kmem_io_arena); 1228 cp = kmem_io[na].kmem_io_cache[c]; 1229 raddr = kmem_cache_alloc(cp, KM_NOSLEEP); 1230 if (raddr) 1231 goto kallocdone; 1232 } 1233 /* now try the larger kmem io cache sizes */ 1234 for (na = a; na >= 0; na = kmem_io_index_next(na)) { 1235 for (i = c + 1; i < KA_NCACHE; i++) { 1236 cp = kmem_io[na].kmem_io_cache[i]; 1237 raddr = kmem_cache_alloc(cp, KM_NOSLEEP); 1238 if (raddr) 1239 goto kallocdone; 1240 } 1241 } 1242 return (NULL); 1243 } 1244 1245 kallocdone: 1246 ASSERT(!P2CROSS((uintptr_t)raddr, (uintptr_t)raddr + rsize - 1, 1247 PAGESIZE) || rsize > PAGESIZE); 1248 1249 addr = (size_t *)P2ROUNDUP((uintptr_t)raddr + hdrsize, align); 1250 ASSERT((uintptr_t)addr + size - (uintptr_t)raddr <= rsize); 1251 1252 addr[-4] = (size_t)cp; 1253 addr[-3] = (size_t)vmp; 1254 addr[-2] = (size_t)raddr; 1255 addr[-1] = rsize; 1256 1257 return (addr); 1258 } 1259 1260 static void 1261 kfreea(void *addr) 1262 { 1263 size_t size; 1264 1265 if (!((uintptr_t)addr & PAGEOFFSET) && (size = getctgsz(addr))) { 1266 contig_free(addr, size); 1267 } else { 1268 size_t *saddr = addr; 1269 if (saddr[-4] == 0) 1270 vmem_free((vmem_t *)saddr[-3], (void *)saddr[-2], 1271 saddr[-1]); 1272 else 1273 kmem_cache_free((kmem_cache_t *)saddr[-4], 1274 (void *)saddr[-2]); 1275 } 1276 } 1277 1278 /* 1279 * This should actually be called i_ddi_dma_mem_alloc. There should 1280 * also be an i_ddi_pio_mem_alloc. i_ddi_dma_mem_alloc should call 1281 * through the device tree with the DDI_CTLOPS_DMA_ALIGN ctl ops to 1282 * get alignment requirements for DMA memory. i_ddi_pio_mem_alloc 1283 * should use DDI_CTLOPS_PIO_ALIGN. Since we only have i_ddi_mem_alloc 1284 * so far which is used for both, DMA and PIO, we have to use the DMA 1285 * ctl ops to make everybody happy. 1286 */ 1287 /*ARGSUSED*/ 1288 int 1289 i_ddi_mem_alloc(dev_info_t *dip, ddi_dma_attr_t *attr, 1290 size_t length, int cansleep, int streaming, 1291 ddi_device_acc_attr_t *accattrp, caddr_t *kaddrp, 1292 size_t *real_length, ddi_acc_hdl_t *ap) 1293 { 1294 caddr_t a; 1295 int iomin; 1296 ddi_acc_impl_t *iap; 1297 int physcontig = 0; 1298 pgcnt_t npages; 1299 pgcnt_t minctg; 1300 1301 /* 1302 * Check legality of arguments 1303 */ 1304 if (length == 0 || kaddrp == NULL || attr == NULL) { 1305 return (DDI_FAILURE); 1306 } 1307 if (attr->dma_attr_minxfer == 0 || attr->dma_attr_align == 0 || 1308 (attr->dma_attr_align & (attr->dma_attr_align - 1)) || 1309 (attr->dma_attr_minxfer & (attr->dma_attr_minxfer - 1))) { 1310 return (DDI_FAILURE); 1311 } 1312 1313 /* 1314 * figure out most restrictive alignment requirement 1315 */ 1316 iomin = attr->dma_attr_minxfer; 1317 iomin = maxbit(iomin, attr->dma_attr_align); 1318 if (iomin == 0) 1319 return (DDI_FAILURE); 1320 1321 ASSERT((iomin & (iomin - 1)) == 0); 1322 1323 1324 /* 1325 * Determine if we need to satisfy the request for physically 1326 * contiguous memory or alignments larger than pagesize. 1327 */ 1328 npages = btopr(length + attr->dma_attr_align); 1329 minctg = howmany(npages, attr->dma_attr_sgllen); 1330 1331 if (minctg > 1) { 1332 uint64_t pfnseg = attr->dma_attr_seg >> PAGESHIFT; 1333 /* 1334 * verify that the minimum contig requirement for the 1335 * actual length does not cross segment boundary. 1336 */ 1337 length = P2ROUNDUP_TYPED(length, attr->dma_attr_minxfer, 1338 size_t); 1339 npages = btopr(length); 1340 minctg = howmany(npages, attr->dma_attr_sgllen); 1341 if (minctg > pfnseg + 1) 1342 return (DDI_FAILURE); 1343 physcontig = 1; 1344 } else { 1345 length = P2ROUNDUP_TYPED(length, iomin, size_t); 1346 } 1347 1348 /* 1349 * Allocate the requested amount from the system. 1350 */ 1351 a = kalloca(length, iomin, cansleep, physcontig, attr); 1352 1353 if ((*kaddrp = a) == NULL) 1354 return (DDI_FAILURE); 1355 1356 if (real_length) { 1357 *real_length = length; 1358 } 1359 if (ap) { 1360 /* 1361 * initialize access handle 1362 */ 1363 iap = (ddi_acc_impl_t *)ap->ah_platform_private; 1364 iap->ahi_acc_attr |= DDI_ACCATTR_CPU_VADDR; 1365 impl_acc_hdl_init(ap); 1366 } 1367 return (DDI_SUCCESS); 1368 } 1369 1370 /* 1371 * covert old DMA limits structure to DMA attribute structure 1372 * and continue 1373 */ 1374 int 1375 i_ddi_mem_alloc_lim(dev_info_t *dip, ddi_dma_lim_t *limits, 1376 size_t length, int cansleep, int streaming, 1377 ddi_device_acc_attr_t *accattrp, caddr_t *kaddrp, 1378 uint_t *real_length, ddi_acc_hdl_t *ap) 1379 { 1380 ddi_dma_attr_t dma_attr, *attrp; 1381 size_t rlen; 1382 int ret; 1383 1384 if (limits == NULL) { 1385 return (DDI_FAILURE); 1386 } 1387 1388 /* 1389 * set up DMA attribute structure to pass to i_ddi_mem_alloc() 1390 */ 1391 attrp = &dma_attr; 1392 attrp->dma_attr_version = DMA_ATTR_V0; 1393 attrp->dma_attr_addr_lo = (uint64_t)limits->dlim_addr_lo; 1394 attrp->dma_attr_addr_hi = (uint64_t)limits->dlim_addr_hi; 1395 attrp->dma_attr_count_max = (uint64_t)limits->dlim_ctreg_max; 1396 attrp->dma_attr_align = 1; 1397 attrp->dma_attr_burstsizes = (uint_t)limits->dlim_burstsizes; 1398 attrp->dma_attr_minxfer = (uint32_t)limits->dlim_minxfer; 1399 attrp->dma_attr_maxxfer = (uint64_t)limits->dlim_reqsize; 1400 attrp->dma_attr_seg = (uint64_t)limits->dlim_adreg_max; 1401 attrp->dma_attr_sgllen = limits->dlim_sgllen; 1402 attrp->dma_attr_granular = (uint32_t)limits->dlim_granular; 1403 attrp->dma_attr_flags = 0; 1404 1405 ret = i_ddi_mem_alloc(dip, attrp, length, cansleep, streaming, 1406 accattrp, kaddrp, &rlen, ap); 1407 if (ret == DDI_SUCCESS) { 1408 if (real_length) 1409 *real_length = (uint_t)rlen; 1410 } 1411 return (ret); 1412 } 1413 1414 /* ARGSUSED */ 1415 void 1416 i_ddi_mem_free(caddr_t kaddr, int stream) 1417 { 1418 kfreea(kaddr); 1419 } 1420 1421 /* 1422 * Access Barriers 1423 * 1424 */ 1425 /*ARGSUSED*/ 1426 int 1427 i_ddi_ontrap(ddi_acc_handle_t hp) 1428 { 1429 return (DDI_FAILURE); 1430 } 1431 1432 /*ARGSUSED*/ 1433 void 1434 i_ddi_notrap(ddi_acc_handle_t hp) 1435 { 1436 } 1437 1438 1439 /* 1440 * Misc Functions 1441 */ 1442 1443 /* 1444 * Implementation instance override functions 1445 * 1446 * No override on i86pc 1447 */ 1448 /*ARGSUSED*/ 1449 uint_t 1450 impl_assign_instance(dev_info_t *dip) 1451 { 1452 return ((uint_t)-1); 1453 } 1454 1455 /*ARGSUSED*/ 1456 int 1457 impl_keep_instance(dev_info_t *dip) 1458 { 1459 return (DDI_FAILURE); 1460 } 1461 1462 /*ARGSUSED*/ 1463 int 1464 impl_free_instance(dev_info_t *dip) 1465 { 1466 return (DDI_FAILURE); 1467 } 1468 1469 /*ARGSUSED*/ 1470 int 1471 impl_check_cpu(dev_info_t *devi) 1472 { 1473 return (DDI_SUCCESS); 1474 } 1475 1476 /* 1477 * Referenced in common/cpr_driver.c: Power off machine. 1478 * Don't know how to power off i86pc. 1479 */ 1480 void 1481 arch_power_down() 1482 {} 1483 1484 /* 1485 * Copy name to property_name, since name 1486 * is in the low address range below kernelbase. 1487 */ 1488 static void 1489 copy_boot_str(const char *boot_str, char *kern_str, int len) 1490 { 1491 int i = 0; 1492 1493 while (i < len - 1 && boot_str[i] != '\0') { 1494 kern_str[i] = boot_str[i]; 1495 i++; 1496 } 1497 1498 kern_str[i] = 0; /* null terminate */ 1499 if (boot_str[i] != '\0') 1500 cmn_err(CE_WARN, 1501 "boot property string is truncated to %s", kern_str); 1502 } 1503 1504 static void 1505 get_boot_properties(void) 1506 { 1507 extern char hw_provider[]; 1508 dev_info_t *devi; 1509 char *name; 1510 int length; 1511 char property_name[50], property_val[50]; 1512 void *bop_staging_area; 1513 1514 bop_staging_area = kmem_zalloc(MMU_PAGESIZE, KM_NOSLEEP); 1515 1516 /* 1517 * Import "root" properties from the boot. 1518 * 1519 * We do this by invoking BOP_NEXTPROP until the list 1520 * is completely copied in. 1521 */ 1522 1523 devi = ddi_root_node(); 1524 for (name = BOP_NEXTPROP(bootops, ""); /* get first */ 1525 name; /* NULL => DONE */ 1526 name = BOP_NEXTPROP(bootops, name)) { /* get next */ 1527 1528 /* copy string to memory above kernelbase */ 1529 copy_boot_str(name, property_name, 50); 1530 1531 /* 1532 * Skip vga properties. They will be picked up later 1533 * by get_vga_properties. 1534 */ 1535 if (strcmp(property_name, "display-edif-block") == 0 || 1536 strcmp(property_name, "display-edif-id") == 0) { 1537 continue; 1538 } 1539 1540 length = BOP_GETPROPLEN(bootops, property_name); 1541 if (length == 0) 1542 continue; 1543 if (length > MMU_PAGESIZE) { 1544 cmn_err(CE_NOTE, 1545 "boot property %s longer than 0x%x, ignored\n", 1546 property_name, MMU_PAGESIZE); 1547 continue; 1548 } 1549 BOP_GETPROP(bootops, property_name, bop_staging_area); 1550 1551 /* 1552 * special properties: 1553 * si-machine, si-hw-provider 1554 * goes to kernel data structures. 1555 * bios-boot-device and stdout 1556 * goes to hardware property list so it may show up 1557 * in the prtconf -vp output. This is needed by 1558 * Install/Upgrade. Once we fix install upgrade, 1559 * this can be taken out. 1560 */ 1561 if (strcmp(name, "si-machine") == 0) { 1562 (void) strncpy(utsname.machine, bop_staging_area, 1563 SYS_NMLN); 1564 utsname.machine[SYS_NMLN - 1] = (char)NULL; 1565 } else if (strcmp(name, "si-hw-provider") == 0) { 1566 (void) strncpy(hw_provider, bop_staging_area, SYS_NMLN); 1567 hw_provider[SYS_NMLN - 1] = (char)NULL; 1568 } else if (strcmp(name, "bios-boot-device") == 0) { 1569 copy_boot_str(bop_staging_area, property_val, 50); 1570 (void) ndi_prop_update_string(DDI_DEV_T_NONE, devi, 1571 property_name, property_val); 1572 } else if (strcmp(name, "stdout") == 0) { 1573 (void) ndi_prop_update_int(DDI_DEV_T_NONE, devi, 1574 property_name, *((int *)bop_staging_area)); 1575 } else { 1576 /* Property type unknown, use old prop interface */ 1577 (void) e_ddi_prop_create(DDI_DEV_T_NONE, devi, 1578 DDI_PROP_CANSLEEP, property_name, bop_staging_area, 1579 length); 1580 } 1581 } 1582 1583 kmem_free(bop_staging_area, MMU_PAGESIZE); 1584 } 1585 1586 static void 1587 get_vga_properties(void) 1588 { 1589 dev_info_t *devi; 1590 major_t major; 1591 char *name; 1592 int length; 1593 char property_val[50]; 1594 void *bop_staging_area; 1595 1596 major = ddi_name_to_major("vgatext"); 1597 if (major == (major_t)-1) 1598 return; 1599 devi = devnamesp[major].dn_head; 1600 if (devi == NULL) 1601 return; 1602 1603 bop_staging_area = kmem_zalloc(MMU_PAGESIZE, KM_SLEEP); 1604 1605 /* 1606 * Import "vga" properties from the boot. 1607 */ 1608 name = "display-edif-block"; 1609 length = BOP_GETPROPLEN(bootops, name); 1610 if (length > 0 && length < MMU_PAGESIZE) { 1611 BOP_GETPROP(bootops, name, bop_staging_area); 1612 (void) ndi_prop_update_byte_array(DDI_DEV_T_NONE, 1613 devi, name, bop_staging_area, length); 1614 } 1615 1616 /* 1617 * kdmconfig is also looking for display-type and 1618 * video-adapter-type. We default to color and svga. 1619 * 1620 * Could it be "monochrome", "vga"? 1621 * Nah, you've got to come to the 21st century... 1622 * And you can set monitor type manually in kdmconfig 1623 * if you are really an old junky. 1624 */ 1625 (void) ndi_prop_update_string(DDI_DEV_T_NONE, 1626 devi, "display-type", "color"); 1627 (void) ndi_prop_update_string(DDI_DEV_T_NONE, 1628 devi, "video-adapter-type", "svga"); 1629 1630 name = "display-edif-id"; 1631 length = BOP_GETPROPLEN(bootops, name); 1632 if (length > 0 && length < MMU_PAGESIZE) { 1633 BOP_GETPROP(bootops, name, bop_staging_area); 1634 copy_boot_str(bop_staging_area, property_val, length); 1635 (void) ndi_prop_update_string(DDI_DEV_T_NONE, 1636 devi, name, property_val); 1637 } 1638 1639 kmem_free(bop_staging_area, MMU_PAGESIZE); 1640 } 1641 1642 1643 /* 1644 * This is temporary, but absolutely necessary. If we are being 1645 * booted with a device tree created by the DevConf project's bootconf 1646 * program, then we have device information nodes that reflect 1647 * reality. At this point in time in the Solaris release schedule, the 1648 * kernel drivers aren't prepared for reality. They still depend on their 1649 * own ad-hoc interpretations of the properties created when their .conf 1650 * files were interpreted. These drivers use an "ignore-hardware-nodes" 1651 * property to prevent them from using the nodes passed up from the bootconf 1652 * device tree. 1653 * 1654 * Trying to assemble root file system drivers as we are booting from 1655 * devconf will fail if the kernel driver is basing its name_addr's on the 1656 * psuedo-node device info while the bootpath passed up from bootconf is using 1657 * reality-based name_addrs. We help the boot along in this case by 1658 * looking at the pre-bootconf bootpath and determining if we would have 1659 * successfully matched if that had been the bootpath we had chosen. 1660 * 1661 * Note that we only even perform this extra check if we've booted 1662 * using bootconf's 1275 compliant bootpath, this is the boot device, and 1663 * we're trying to match the name_addr specified in the 1275 bootpath. 1664 */ 1665 1666 #define MAXCOMPONENTLEN 32 1667 1668 int 1669 x86_old_bootpath_name_addr_match(dev_info_t *cdip, char *caddr, char *naddr) 1670 { 1671 /* 1672 * There are multiple criteria to be met before we can even 1673 * consider allowing a name_addr match here. 1674 * 1675 * 1) We must have been booted such that the bootconf program 1676 * created device tree nodes and properties. This can be 1677 * determined by examining the 'bootpath' property. This 1678 * property will be a non-null string iff bootconf was 1679 * involved in the boot. 1680 * 1681 * 2) The module that we want to match must be the boot device. 1682 * 1683 * 3) The instance of the module we are thinking of letting be 1684 * our match must be ignoring hardware nodes. 1685 * 1686 * 4) The name_addr we want to match must be the name_addr 1687 * specified in the 1275 bootpath. 1688 */ 1689 static char bootdev_module[MAXCOMPONENTLEN]; 1690 static char bootdev_oldmod[MAXCOMPONENTLEN]; 1691 static char bootdev_newaddr[MAXCOMPONENTLEN]; 1692 static char bootdev_oldaddr[MAXCOMPONENTLEN]; 1693 static int quickexit; 1694 1695 char *daddr; 1696 int dlen; 1697 1698 char *lkupname; 1699 int rv = DDI_FAILURE; 1700 1701 if ((ddi_getlongprop(DDI_DEV_T_ANY, cdip, DDI_PROP_DONTPASS, 1702 "devconf-addr", (caddr_t)&daddr, &dlen) == DDI_PROP_SUCCESS) && 1703 (ddi_getprop(DDI_DEV_T_ANY, cdip, DDI_PROP_DONTPASS, 1704 "ignore-hardware-nodes", -1) != -1)) { 1705 if (strcmp(daddr, caddr) == 0) { 1706 return (DDI_SUCCESS); 1707 } 1708 } 1709 1710 if (quickexit) 1711 return (rv); 1712 1713 if (bootdev_module[0] == '\0') { 1714 char *addrp, *eoaddrp; 1715 char *busp, *modp, *atp; 1716 char *bp1275, *bp; 1717 int bp1275len, bplen; 1718 1719 bp1275 = bp = addrp = eoaddrp = busp = modp = atp = NULL; 1720 1721 if (ddi_getlongprop(DDI_DEV_T_ANY, 1722 ddi_root_node(), 0, "bootpath", 1723 (caddr_t)&bp1275, &bp1275len) != DDI_PROP_SUCCESS || 1724 bp1275len <= 1) { 1725 /* 1726 * We didn't boot from bootconf so we never need to 1727 * do any special matches. 1728 */ 1729 quickexit = 1; 1730 if (bp1275) 1731 kmem_free(bp1275, bp1275len); 1732 return (rv); 1733 } 1734 1735 if (ddi_getlongprop(DDI_DEV_T_ANY, 1736 ddi_root_node(), 0, "boot-path", 1737 (caddr_t)&bp, &bplen) != DDI_PROP_SUCCESS || bplen <= 1) { 1738 /* 1739 * No fallback position for matching. This is 1740 * certainly unexpected, but we'll handle it 1741 * just in case. 1742 */ 1743 quickexit = 1; 1744 kmem_free(bp1275, bp1275len); 1745 if (bp) 1746 kmem_free(bp, bplen); 1747 return (rv); 1748 } 1749 1750 /* 1751 * Determine boot device module and 1275 name_addr 1752 * 1753 * bootpath assumed to be of the form /bus/module@name_addr 1754 */ 1755 if (busp = strchr(bp1275, '/')) { 1756 if (modp = strchr(busp + 1, '/')) { 1757 if (atp = strchr(modp + 1, '@')) { 1758 *atp = '\0'; 1759 addrp = atp + 1; 1760 if (eoaddrp = strchr(addrp, '/')) 1761 *eoaddrp = '\0'; 1762 } 1763 } 1764 } 1765 1766 if (modp && addrp) { 1767 (void) strncpy(bootdev_module, modp + 1, 1768 MAXCOMPONENTLEN); 1769 bootdev_module[MAXCOMPONENTLEN - 1] = '\0'; 1770 1771 (void) strncpy(bootdev_newaddr, addrp, MAXCOMPONENTLEN); 1772 bootdev_newaddr[MAXCOMPONENTLEN - 1] = '\0'; 1773 } else { 1774 quickexit = 1; 1775 kmem_free(bp1275, bp1275len); 1776 kmem_free(bp, bplen); 1777 return (rv); 1778 } 1779 1780 /* 1781 * Determine fallback name_addr 1782 * 1783 * 10/3/96 - Also save fallback module name because it 1784 * might actually be different than the current module 1785 * name. E.G., ISA pnp drivers have new names. 1786 * 1787 * bootpath assumed to be of the form /bus/module@name_addr 1788 */ 1789 addrp = NULL; 1790 if (busp = strchr(bp, '/')) { 1791 if (modp = strchr(busp + 1, '/')) { 1792 if (atp = strchr(modp + 1, '@')) { 1793 *atp = '\0'; 1794 addrp = atp + 1; 1795 if (eoaddrp = strchr(addrp, '/')) 1796 *eoaddrp = '\0'; 1797 } 1798 } 1799 } 1800 1801 if (modp && addrp) { 1802 (void) strncpy(bootdev_oldmod, modp + 1, 1803 MAXCOMPONENTLEN); 1804 bootdev_module[MAXCOMPONENTLEN - 1] = '\0'; 1805 1806 (void) strncpy(bootdev_oldaddr, addrp, MAXCOMPONENTLEN); 1807 bootdev_oldaddr[MAXCOMPONENTLEN - 1] = '\0'; 1808 } 1809 1810 /* Free up the bootpath storage now that we're done with it. */ 1811 kmem_free(bp1275, bp1275len); 1812 kmem_free(bp, bplen); 1813 1814 if (bootdev_oldaddr[0] == '\0') { 1815 quickexit = 1; 1816 return (rv); 1817 } 1818 } 1819 1820 if (((lkupname = ddi_get_name(cdip)) != NULL) && 1821 (strcmp(bootdev_module, lkupname) == 0 || 1822 strcmp(bootdev_oldmod, lkupname) == 0) && 1823 ((ddi_getprop(DDI_DEV_T_ANY, cdip, DDI_PROP_DONTPASS, 1824 "ignore-hardware-nodes", -1) != -1) || 1825 ignore_hardware_nodes) && 1826 strcmp(bootdev_newaddr, caddr) == 0 && 1827 strcmp(bootdev_oldaddr, naddr) == 0) { 1828 rv = DDI_SUCCESS; 1829 } 1830 1831 return (rv); 1832 } 1833 1834 /* 1835 * Perform a copy from a memory mapped device (whose devinfo pointer is devi) 1836 * separately mapped at devaddr in the kernel to a kernel buffer at kaddr. 1837 */ 1838 /*ARGSUSED*/ 1839 int 1840 e_ddi_copyfromdev(dev_info_t *devi, 1841 off_t off, const void *devaddr, void *kaddr, size_t len) 1842 { 1843 bcopy(devaddr, kaddr, len); 1844 return (0); 1845 } 1846 1847 /* 1848 * Perform a copy to a memory mapped device (whose devinfo pointer is devi) 1849 * separately mapped at devaddr in the kernel from a kernel buffer at kaddr. 1850 */ 1851 /*ARGSUSED*/ 1852 int 1853 e_ddi_copytodev(dev_info_t *devi, 1854 off_t off, const void *kaddr, void *devaddr, size_t len) 1855 { 1856 bcopy(kaddr, devaddr, len); 1857 return (0); 1858 } 1859 1860 1861 static int 1862 poke_mem(peekpoke_ctlops_t *in_args) 1863 { 1864 int err = DDI_SUCCESS; 1865 on_trap_data_t otd; 1866 1867 /* Set up protected environment. */ 1868 if (!on_trap(&otd, OT_DATA_ACCESS)) { 1869 switch (in_args->size) { 1870 case sizeof (uint8_t): 1871 *(uint8_t *)(in_args->dev_addr) = 1872 *(uint8_t *)in_args->host_addr; 1873 break; 1874 1875 case sizeof (uint16_t): 1876 *(uint16_t *)(in_args->dev_addr) = 1877 *(uint16_t *)in_args->host_addr; 1878 break; 1879 1880 case sizeof (uint32_t): 1881 *(uint32_t *)(in_args->dev_addr) = 1882 *(uint32_t *)in_args->host_addr; 1883 break; 1884 1885 case sizeof (uint64_t): 1886 *(uint64_t *)(in_args->dev_addr) = 1887 *(uint64_t *)in_args->host_addr; 1888 break; 1889 1890 default: 1891 err = DDI_FAILURE; 1892 break; 1893 } 1894 } else 1895 err = DDI_FAILURE; 1896 1897 /* Take down protected environment. */ 1898 no_trap(); 1899 1900 return (err); 1901 } 1902 1903 1904 static int 1905 peek_mem(peekpoke_ctlops_t *in_args) 1906 { 1907 int err = DDI_SUCCESS; 1908 on_trap_data_t otd; 1909 1910 if (!on_trap(&otd, OT_DATA_ACCESS)) { 1911 switch (in_args->size) { 1912 case sizeof (uint8_t): 1913 *(uint8_t *)in_args->host_addr = 1914 *(uint8_t *)in_args->dev_addr; 1915 break; 1916 1917 case sizeof (uint16_t): 1918 *(uint16_t *)in_args->host_addr = 1919 *(uint16_t *)in_args->dev_addr; 1920 break; 1921 1922 case sizeof (uint32_t): 1923 *(uint32_t *)in_args->host_addr = 1924 *(uint32_t *)in_args->dev_addr; 1925 break; 1926 1927 case sizeof (uint64_t): 1928 *(uint64_t *)in_args->host_addr = 1929 *(uint64_t *)in_args->dev_addr; 1930 break; 1931 1932 default: 1933 err = DDI_FAILURE; 1934 break; 1935 } 1936 } else 1937 err = DDI_FAILURE; 1938 1939 no_trap(); 1940 return (err); 1941 } 1942 1943 1944 /* 1945 * This is called only to process peek/poke when the DIP is NULL. 1946 * Assume that this is for memory, as nexi take care of device safe accesses. 1947 */ 1948 int 1949 peekpoke_mem(ddi_ctl_enum_t cmd, peekpoke_ctlops_t *in_args) 1950 { 1951 return (cmd == DDI_CTLOPS_PEEK ? peek_mem(in_args) : poke_mem(in_args)); 1952 } 1953 1954 void 1955 impl_setup_ddi(void) 1956 { 1957 dev_info_t *xdip, *isa_dip; 1958 rd_existing_t rd_mem_prop; 1959 int err; 1960 1961 ndi_devi_alloc_sleep(ddi_root_node(), "ramdisk", 1962 (dnode_t)DEVI_SID_NODEID, &xdip); 1963 1964 (void) BOP_GETPROP(bootops, 1965 "ramdisk_start", (void *)&ramdisk_start); 1966 (void) BOP_GETPROP(bootops, 1967 "ramdisk_end", (void *)&ramdisk_end); 1968 1969 rd_mem_prop.phys = ramdisk_start; 1970 rd_mem_prop.size = ramdisk_end - ramdisk_start + 1; 1971 1972 (void) ndi_prop_update_byte_array(DDI_DEV_T_NONE, xdip, 1973 RD_EXISTING_PROP_NAME, (uchar_t *)&rd_mem_prop, 1974 sizeof (rd_mem_prop)); 1975 err = ndi_devi_bind_driver(xdip, 0); 1976 ASSERT(err == 0); 1977 1978 /* isa node */ 1979 ndi_devi_alloc_sleep(ddi_root_node(), "isa", 1980 (dnode_t)DEVI_SID_NODEID, &isa_dip); 1981 (void) ndi_prop_update_string(DDI_DEV_T_NONE, isa_dip, 1982 "device_type", "isa"); 1983 (void) ndi_prop_update_string(DDI_DEV_T_NONE, isa_dip, 1984 "bus-type", "isa"); 1985 (void) ndi_devi_bind_driver(isa_dip, 0); 1986 1987 /* 1988 * Read in the properties from the boot. 1989 */ 1990 get_boot_properties(); 1991 1992 /* do bus dependent probes. */ 1993 impl_bus_initialprobe(); 1994 1995 /* not framebuffer should be enumerated, if present */ 1996 get_vga_properties(); 1997 } 1998 1999 dev_t 2000 getrootdev(void) 2001 { 2002 /* 2003 * Precedence given to rootdev if set in /etc/system 2004 */ 2005 if (root_is_svm) { 2006 return (ddi_pathname_to_dev_t(svm_bootpath)); 2007 } 2008 2009 /* 2010 * Usually rootfs.bo_name is initialized by the 2011 * the bootpath property from bootenv.rc, but 2012 * defaults to "/ramdisk:a" otherwise. 2013 */ 2014 return (ddi_pathname_to_dev_t(rootfs.bo_name)); 2015 } 2016 2017 static struct bus_probe { 2018 struct bus_probe *next; 2019 void (*probe)(int); 2020 } *bus_probes; 2021 2022 void 2023 impl_bus_add_probe(void (*func)(int)) 2024 { 2025 struct bus_probe *probe; 2026 2027 probe = kmem_alloc(sizeof (*probe), KM_SLEEP); 2028 probe->next = bus_probes; 2029 probe->probe = func; 2030 bus_probes = probe; 2031 } 2032 2033 /*ARGSUSED*/ 2034 void 2035 impl_bus_delete_probe(void (*func)(int)) 2036 { 2037 struct bus_probe *prev = NULL; 2038 struct bus_probe *probe = bus_probes; 2039 2040 while (probe) { 2041 if (probe->probe == func) 2042 break; 2043 prev = probe; 2044 probe = probe->next; 2045 } 2046 2047 if (probe == NULL) 2048 return; 2049 2050 if (prev) 2051 prev->next = probe->next; 2052 else 2053 bus_probes = probe->next; 2054 2055 kmem_free(probe, sizeof (struct bus_probe)); 2056 } 2057 2058 /* 2059 * impl_bus_initialprobe 2060 * Modload the prom simulator, then let it probe to verify existence 2061 * and type of PCI support. 2062 */ 2063 static void 2064 impl_bus_initialprobe(void) 2065 { 2066 struct bus_probe *probe; 2067 2068 /* load modules to install bus probes */ 2069 if (modload("misc", "pci_autoconfig") < 0) { 2070 cmn_err(CE_PANIC, "failed to load misc/pci_autoconfig"); 2071 } 2072 2073 probe = bus_probes; 2074 while (probe) { 2075 /* run the probe function */ 2076 (*probe->probe)(0); 2077 probe = probe->next; 2078 } 2079 } 2080 2081 /* 2082 * impl_bus_reprobe 2083 * Reprogram devices not set up by firmware. 2084 */ 2085 static void 2086 impl_bus_reprobe(void) 2087 { 2088 struct bus_probe *probe; 2089 2090 probe = bus_probes; 2091 while (probe) { 2092 /* run the probe function */ 2093 (*probe->probe)(1); 2094 probe = probe->next; 2095 } 2096 } 2097