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 * sun4 specific DDI implementation 31 */ 32 #include <sys/cpuvar.h> 33 #include <sys/ddi_subrdefs.h> 34 #include <sys/machsystm.h> 35 #include <sys/sunndi.h> 36 #include <sys/sysmacros.h> 37 #include <sys/ontrap.h> 38 #include <vm/seg_kmem.h> 39 #include <sys/membar.h> 40 #include <sys/dditypes.h> 41 #include <sys/ndifm.h> 42 #include <sys/fm/io/ddi.h> 43 #include <sys/ivintr.h> 44 #include <sys/bootconf.h> 45 #include <sys/conf.h> 46 #include <sys/ethernet.h> 47 #include <sys/idprom.h> 48 #include <sys/promif.h> 49 #include <sys/prom_plat.h> 50 #include <sys/systeminfo.h> 51 #include <sys/fpu/fpusystm.h> 52 #include <sys/vm.h> 53 #include <sys/fs/dv_node.h> 54 #include <sys/fs/snode.h> 55 #include <sys/ddi_isa.h> 56 57 dev_info_t *get_intr_parent(dev_info_t *, dev_info_t *, 58 ddi_ispec_t *, ddi_ispec_t **); 59 #pragma weak get_intr_parent 60 61 int process_intr_ops(dev_info_t *, dev_info_t *, ddi_intr_op_t, 62 ddi_intr_handle_impl_t *, void *); 63 #pragma weak process_intr_ops 64 65 void cells_1275_copy(prop_1275_cell_t *, prop_1275_cell_t *, int32_t); 66 prop_1275_cell_t *cells_1275_cmp(prop_1275_cell_t *, prop_1275_cell_t *, 67 int32_t len); 68 #pragma weak cells_1275_copy 69 70 /* 71 * Wrapper for ddi_prop_lookup_int_array(). 72 * This is handy because it returns the prop length in 73 * bytes which is what most of the callers require. 74 */ 75 76 static int 77 get_prop_int_array(dev_info_t *di, char *pname, int **pval, uint_t *plen) 78 { 79 int ret; 80 81 if ((ret = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, di, 82 DDI_PROP_DONTPASS, pname, pval, plen)) == DDI_PROP_SUCCESS) { 83 *plen = (*plen) * (uint_t)sizeof (int); 84 } 85 return (ret); 86 } 87 88 /* 89 * SECTION: DDI Node Configuration 90 */ 91 92 /* 93 * init_regspec_64: 94 * 95 * If the parent #size-cells is 2, convert the upa-style or 96 * safari-style reg property from 2-size cells to 1 size cell 97 * format, ignoring the size_hi, which must be zero for devices. 98 * (It won't be zero in the memory list properties in the memory 99 * nodes, but that doesn't matter here.) 100 */ 101 struct ddi_parent_private_data * 102 init_regspec_64(dev_info_t *dip) 103 { 104 struct ddi_parent_private_data *pd; 105 dev_info_t *parent; 106 int size_cells; 107 108 /* 109 * If there are no "reg"s in the child node, return. 110 */ 111 pd = ddi_get_parent_data(dip); 112 if ((pd == NULL) || (pd->par_nreg == 0)) { 113 return (pd); 114 } 115 parent = ddi_get_parent(dip); 116 117 size_cells = ddi_prop_get_int(DDI_DEV_T_ANY, parent, 118 DDI_PROP_DONTPASS, "#size-cells", 1); 119 120 if (size_cells != 1) { 121 122 int n, j; 123 struct regspec *irp; 124 struct reg_64 { 125 uint_t addr_hi, addr_lo, size_hi, size_lo; 126 }; 127 struct reg_64 *r64_rp; 128 struct regspec *rp; 129 uint_t len = 0; 130 int *reg_prop; 131 132 ASSERT(size_cells == 2); 133 134 /* 135 * We already looked the property up once before if 136 * pd is non-NULL. 137 */ 138 (void) ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 139 DDI_PROP_DONTPASS, OBP_REG, ®_prop, &len); 140 ASSERT(len != 0); 141 142 n = sizeof (struct reg_64) / sizeof (int); 143 n = len / n; 144 145 /* 146 * We're allocating a buffer the size of the PROM's property, 147 * but we're only using a smaller portion when we assign it 148 * to a regspec. We do this so that in the 149 * impl_ddi_sunbus_removechild function, we will 150 * always free the right amount of memory. 151 */ 152 irp = rp = (struct regspec *)reg_prop; 153 r64_rp = (struct reg_64 *)pd->par_reg; 154 155 for (j = 0; j < n; ++j, ++rp, ++r64_rp) { 156 ASSERT(r64_rp->size_hi == 0); 157 rp->regspec_bustype = r64_rp->addr_hi; 158 rp->regspec_addr = r64_rp->addr_lo; 159 rp->regspec_size = r64_rp->size_lo; 160 } 161 162 ddi_prop_free((void *)pd->par_reg); 163 pd->par_nreg = n; 164 pd->par_reg = irp; 165 } 166 return (pd); 167 } 168 169 /* 170 * Create a ddi_parent_private_data structure from the ddi properties of 171 * the dev_info node. 172 * 173 * The "reg" is required if the driver wishes to create mappings on behalf 174 * of the device. The "reg" property is assumed to be a list of at least 175 * one triplet 176 * 177 * <bustype, address, size>*1 178 * 179 * The "interrupt" property is no longer part of parent private data on 180 * sun4u. The interrupt parent is may not be the device tree parent. 181 * 182 * The "ranges" property describes the mapping of child addresses to parent 183 * addresses. 184 * 185 * N.B. struct rangespec is defined for the following default values: 186 * parent child 187 * #address-cells 2 2 188 * #size-cells 1 1 189 * This function doesn't deal with non-default cells and will not create 190 * ranges in such cases. 191 */ 192 void 193 make_ddi_ppd(dev_info_t *child, struct ddi_parent_private_data **ppd) 194 { 195 struct ddi_parent_private_data *pdptr; 196 int *reg_prop, *rng_prop; 197 uint_t reg_len = 0, rng_len = 0; 198 dev_info_t *parent; 199 int parent_addr_cells, parent_size_cells; 200 int child_addr_cells, child_size_cells; 201 202 *ppd = pdptr = kmem_zalloc(sizeof (*pdptr), KM_SLEEP); 203 204 /* 205 * root node has no parent private data, so *ppd should 206 * be initialized for naming to work properly. 207 */ 208 if ((parent = ddi_get_parent(child)) == NULL) 209 return; 210 211 /* 212 * Set reg field of parent data from "reg" property 213 */ 214 if ((get_prop_int_array(child, OBP_REG, ®_prop, ®_len) 215 == DDI_PROP_SUCCESS) && (reg_len != 0)) { 216 pdptr->par_nreg = (int)(reg_len / sizeof (struct regspec)); 217 pdptr->par_reg = (struct regspec *)reg_prop; 218 } 219 220 /* 221 * "ranges" property ... 222 * 223 * This function does not handle cases where #address-cells != 2 224 * and * min(parent, child) #size-cells != 1 (see bugid 4211124). 225 * 226 * Nexus drivers with such exceptions (e.g. pci ranges) 227 * should either create a separate function for handling 228 * ranges or not use parent private data to store ranges. 229 */ 230 231 /* root node has no ranges */ 232 if ((parent = ddi_get_parent(child)) == NULL) 233 return; 234 235 child_addr_cells = ddi_prop_get_int(DDI_DEV_T_ANY, child, 236 DDI_PROP_DONTPASS, "#address-cells", 2); 237 child_size_cells = ddi_prop_get_int(DDI_DEV_T_ANY, child, 238 DDI_PROP_DONTPASS, "#size-cells", 1); 239 parent_addr_cells = ddi_prop_get_int(DDI_DEV_T_ANY, parent, 240 DDI_PROP_DONTPASS, "#address-cells", 2); 241 parent_size_cells = ddi_prop_get_int(DDI_DEV_T_ANY, parent, 242 DDI_PROP_DONTPASS, "#size-cells", 1); 243 if (child_addr_cells != 2 || parent_addr_cells != 2 || 244 (child_size_cells != 1 && parent_size_cells != 1)) { 245 NDI_CONFIG_DEBUG((CE_NOTE, "!ranges not made in parent data; " 246 "#address-cells or #size-cells have non-default value")); 247 return; 248 } 249 250 if (get_prop_int_array(child, OBP_RANGES, &rng_prop, &rng_len) 251 == DDI_PROP_SUCCESS) { 252 pdptr->par_nrng = rng_len / (int)(sizeof (struct rangespec)); 253 pdptr->par_rng = (struct rangespec *)rng_prop; 254 } 255 } 256 257 /* 258 * Free ddi_parent_private_data structure 259 */ 260 void 261 impl_free_ddi_ppd(dev_info_t *dip) 262 { 263 struct ddi_parent_private_data *pdptr = ddi_get_parent_data(dip); 264 265 if (pdptr == NULL) 266 return; 267 268 if (pdptr->par_nrng != 0) 269 ddi_prop_free((void *)pdptr->par_rng); 270 271 if (pdptr->par_nreg != 0) 272 ddi_prop_free((void *)pdptr->par_reg); 273 274 kmem_free(pdptr, sizeof (*pdptr)); 275 ddi_set_parent_data(dip, NULL); 276 } 277 278 /* 279 * Name a child of sun busses based on the reg spec. 280 * Handles the following properties: 281 * 282 * Property value 283 * Name type 284 * 285 * reg register spec 286 * interrupts new (bus-oriented) interrupt spec 287 * ranges range spec 288 * 289 * This may be called multiple times, independent of 290 * initchild calls. 291 */ 292 static int 293 impl_sunbus_name_child(dev_info_t *child, char *name, int namelen) 294 { 295 struct ddi_parent_private_data *pdptr; 296 struct regspec *rp; 297 298 /* 299 * Fill in parent-private data and this function returns to us 300 * an indication if it used "registers" to fill in the data. 301 */ 302 if (ddi_get_parent_data(child) == NULL) { 303 make_ddi_ppd(child, &pdptr); 304 ddi_set_parent_data(child, pdptr); 305 } 306 307 /* 308 * No reg property, return null string as address 309 * (e.g. root node) 310 */ 311 name[0] = '\0'; 312 if (sparc_pd_getnreg(child) == 0) { 313 return (DDI_SUCCESS); 314 } 315 316 rp = sparc_pd_getreg(child, 0); 317 (void) snprintf(name, namelen, "%x,%x", 318 rp->regspec_bustype, rp->regspec_addr); 319 return (DDI_SUCCESS); 320 } 321 322 323 /* 324 * Called from the bus_ctl op of some drivers. 325 * to implement the DDI_CTLOPS_INITCHILD operation. 326 * 327 * NEW drivers should NOT use this function, but should declare 328 * there own initchild/uninitchild handlers. (This function assumes 329 * the layout of the parent private data and the format of "reg", 330 * "ranges", "interrupts" properties and that #address-cells and 331 * #size-cells of the parent bus are defined to be default values.) 332 */ 333 int 334 impl_ddi_sunbus_initchild(dev_info_t *child) 335 { 336 char name[MAXNAMELEN]; 337 338 (void) impl_sunbus_name_child(child, name, MAXNAMELEN); 339 ddi_set_name_addr(child, name); 340 341 /* 342 * Try to merge .conf node. If successful, return failure to 343 * remove this child. 344 */ 345 if ((ndi_dev_is_persistent_node(child) == 0) && 346 (ndi_merge_node(child, impl_sunbus_name_child) == DDI_SUCCESS)) { 347 impl_ddi_sunbus_removechild(child); 348 return (DDI_FAILURE); 349 } 350 return (DDI_SUCCESS); 351 } 352 353 /* 354 * A better name for this function would be impl_ddi_sunbus_uninitchild() 355 * It does not remove the child, it uninitializes it, reclaiming the 356 * resources taken by impl_ddi_sunbus_initchild. 357 */ 358 void 359 impl_ddi_sunbus_removechild(dev_info_t *dip) 360 { 361 impl_free_ddi_ppd(dip); 362 ddi_set_name_addr(dip, NULL); 363 /* 364 * Strip the node to properly convert it back to prototype form 365 */ 366 impl_rem_dev_props(dip); 367 } 368 369 /* 370 * SECTION: DDI Interrupt 371 */ 372 373 void 374 cells_1275_copy(prop_1275_cell_t *from, prop_1275_cell_t *to, int32_t len) 375 { 376 int i; 377 for (i = 0; i < len; i++) 378 *to = *from; 379 } 380 381 prop_1275_cell_t * 382 cells_1275_cmp(prop_1275_cell_t *cell1, prop_1275_cell_t *cell2, int32_t len) 383 { 384 prop_1275_cell_t *match_cell = 0; 385 int32_t i; 386 387 for (i = 0; i < len; i++) 388 if (cell1[i] != cell2[i]) { 389 match_cell = &cell1[i]; 390 break; 391 } 392 393 return (match_cell); 394 } 395 396 /* 397 * Wrapper functions used by New DDI interrupt framework. 398 */ 399 400 /* 401 * i_ddi_handle_intr_ops: 402 */ 403 int 404 i_ddi_handle_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t op, 405 ddi_intr_handle_impl_t *hdlp, void *result) 406 { 407 ddi_intrspec_t ispec; 408 int ret; 409 410 if (hdlp->ih_type != DDI_INTR_TYPE_FIXED) 411 return (i_ddi_intr_ops(dip, rdip, op, hdlp, result)); 412 413 i_ddi_alloc_ispec(dip, hdlp->ih_inum, &ispec); 414 if ((ddi_ispec_t *)ispec == NULL) 415 return (DDI_FAILURE); 416 417 hdlp->ih_private = (void *)ispec; 418 ret = i_ddi_intr_ops(dip, rdip, op, hdlp, result); 419 hdlp->ih_private = NULL; 420 421 i_ddi_free_ispec(ispec); 422 return (ret); 423 } 424 425 /* 426 * i_ddi_intr_ops: 427 */ 428 int 429 i_ddi_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t op, 430 ddi_intr_handle_impl_t *hdlp, void *result) 431 { 432 ddi_ispec_t *sav_ip, *ip = NULL; 433 dev_info_t *pdip = ddi_get_parent(dip); 434 int ret = DDI_FAILURE; 435 436 if (hdlp->ih_type != DDI_INTR_TYPE_FIXED) 437 return (process_intr_ops(pdip, rdip, op, hdlp, result)); 438 439 switch (op) { 440 case DDI_INTROP_ADDISR: 441 case DDI_INTROP_REMISR: 442 case DDI_INTROP_ENABLE: 443 case DDI_INTROP_DISABLE: 444 case DDI_INTROP_BLOCKENABLE: 445 case DDI_INTROP_BLOCKDISABLE: 446 /* Save the ispec */ 447 sav_ip = (ddi_ispec_t *)hdlp->ih_private; 448 449 /* 450 * If we have an ispec struct, try and determine our 451 * parent and possibly an interrupt translation. 452 * intr parent dip returned held 453 */ 454 if ((pdip = get_intr_parent(pdip, dip, sav_ip, &ip)) != NULL) { 455 /* Insert the interrupt info structure */ 456 hdlp->ih_private = (void *)ip; 457 } else 458 goto done; 459 } 460 461 ret = process_intr_ops(pdip, rdip, op, hdlp, result); 462 463 done: 464 switch (op) { 465 case DDI_INTROP_ADDISR: 466 case DDI_INTROP_REMISR: 467 case DDI_INTROP_ENABLE: 468 case DDI_INTROP_DISABLE: 469 case DDI_INTROP_BLOCKENABLE: 470 case DDI_INTROP_BLOCKDISABLE: 471 /* Release hold acquired in get_intr_parent() */ 472 if (pdip) 473 ndi_rele_devi(pdip); 474 475 if (ip) { 476 /* Set the PIL according to what the parent did */ 477 sav_ip->is_pil = ip->is_pil; 478 479 /* Free the stacked ispec structure */ 480 i_ddi_free_ispec((ddi_intrspec_t)ip); 481 } 482 483 /* Restore the interrupt info */ 484 hdlp->ih_private = (void *)sav_ip; 485 } 486 487 return (ret); 488 } 489 490 /* 491 * process_intr_ops: 492 * 493 * Process the interrupt op via the interrupt parent. 494 */ 495 int 496 process_intr_ops(dev_info_t *pdip, dev_info_t *rdip, ddi_intr_op_t op, 497 ddi_intr_handle_impl_t *hdlp, void *result) 498 { 499 int ret = DDI_FAILURE; 500 501 if (NEXUS_HAS_INTR_OP(pdip)) { 502 ret = (*(DEVI(pdip)->devi_ops->devo_bus_ops-> 503 bus_intr_op)) (pdip, rdip, op, hdlp, result); 504 } else { 505 cmn_err(CE_WARN, "Failed to process interrupt " 506 "for %s%d due to down-rev nexus driver %s%d", 507 ddi_get_name(rdip), ddi_get_instance(rdip), 508 ddi_get_name(pdip), ddi_get_instance(pdip)); 509 } 510 511 return (ret); 512 } 513 514 /* 515 * i_ddi_add_ivintr: 516 */ 517 /*ARGSUSED*/ 518 int 519 i_ddi_add_ivintr(ddi_intr_handle_impl_t *hdlp) 520 { 521 /* Sanity check the entry we're about to add */ 522 if (GET_IVINTR(hdlp->ih_vector)) { 523 cmn_err(CE_WARN, "mondo 0x%x in use", hdlp->ih_vector); 524 return (DDI_FAILURE); 525 } 526 527 /* 528 * If the PIL was set and is valid use it, otherwise 529 * default it to 1 530 */ 531 if ((hdlp->ih_pri < 1) || (hdlp->ih_pri > PIL_MAX)) 532 hdlp->ih_pri = 1; 533 534 VERIFY(add_ivintr(hdlp->ih_vector, hdlp->ih_pri, 535 (intrfunc)hdlp->ih_cb_func, hdlp->ih_cb_arg1, NULL) == 0); 536 537 return (DDI_SUCCESS); 538 } 539 540 /* 541 * i_ddi_rem_ivintr: 542 */ 543 /*ARGSUSED*/ 544 void 545 i_ddi_rem_ivintr(ddi_intr_handle_impl_t *hdlp) 546 { 547 rem_ivintr(hdlp->ih_vector, NULL); 548 } 549 550 /* 551 * i_ddi_add_softint - allocate and add a soft interrupt to the system 552 */ 553 int 554 i_ddi_add_softint(ddi_softint_hdl_impl_t *hdlp) 555 { 556 uint_t rval; 557 558 if ((rval = (uint_t)add_softintr(hdlp->ih_pri, 559 hdlp->ih_cb_func, hdlp->ih_cb_arg1)) == 0) { 560 561 return (DDI_FAILURE); 562 } 563 564 hdlp->ih_private = (void *)rval; 565 566 return (DDI_SUCCESS); 567 } 568 569 void 570 i_ddi_remove_softint(ddi_softint_hdl_impl_t *hdlp) 571 { 572 uint_t intr_id; 573 574 /* disable */ 575 ASSERT(hdlp->ih_private != NULL); 576 intr_id = (uint_t)hdlp->ih_private; 577 rem_softintr(intr_id); 578 hdlp->ih_private = NULL; 579 } 580 581 int 582 i_ddi_trigger_softint(ddi_softint_hdl_impl_t *hdlp, void *arg2) 583 { 584 uint_t intr_id; 585 int ret; 586 587 ASSERT(hdlp != NULL); 588 ASSERT(hdlp->ih_private != NULL); 589 590 intr_id = (uint_t)hdlp->ih_private; 591 592 /* update the vector table for the 2nd arg */ 593 ret = update_softint_arg2(intr_id, arg2); 594 if (ret == DDI_SUCCESS) 595 setsoftint(intr_id); 596 597 return (ret); 598 } 599 600 /* ARGSUSED */ 601 int 602 i_ddi_set_softint_pri(ddi_softint_hdl_impl_t *hdlp, uint_t old_pri) 603 { 604 uint_t intr_id; 605 int ret; 606 607 ASSERT(hdlp != NULL); 608 ASSERT(hdlp->ih_private != NULL); 609 610 intr_id = (uint_t)hdlp->ih_private; 611 612 /* update the vector table for the new priority */ 613 ret = update_softint_pri(intr_id, hdlp->ih_pri); 614 615 return (ret); 616 } 617 618 /* 619 * Support routine for allocating and initializing an interrupt specification. 620 * The bus interrupt value will be allocated at the end of this structure, so 621 * the corresponding routine i_ddi_free_ispec() should be used to free the 622 * interrupt specification. 623 */ 624 void 625 i_ddi_alloc_ispec(dev_info_t *dip, uint_t inumber, ddi_intrspec_t *intrspecp) 626 { 627 int32_t intrlen, intr_cells, max_intrs; 628 prop_1275_cell_t *ip; 629 prop_1275_cell_t intr_sz; 630 ddi_ispec_t **ispecp = (ddi_ispec_t **)intrspecp; 631 632 *ispecp = NULL; 633 if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS | 634 DDI_PROP_CANSLEEP, 635 "interrupts", (caddr_t)&ip, &intrlen) == DDI_SUCCESS) { 636 637 intr_cells = ddi_getprop(DDI_DEV_T_ANY, dip, 0, 638 "#interrupt-cells", 1); 639 640 /* adjust for number of bytes */ 641 intr_sz = CELLS_1275_TO_BYTES(intr_cells); 642 643 /* Calculate the number of interrupts */ 644 max_intrs = intrlen / intr_sz; 645 646 if (inumber < max_intrs) { 647 prop_1275_cell_t *intrp = ip; 648 649 *ispecp = kmem_zalloc( 650 (sizeof (ddi_ispec_t) + intr_sz), KM_SLEEP); 651 652 (*ispecp)->is_intr = 653 (uint32_t *)(*ispecp + 1); 654 655 /* Index into interrupt property */ 656 intrp += (inumber * intr_cells); 657 658 cells_1275_copy(intrp, 659 (*ispecp)->is_intr, intr_cells); 660 661 (*ispecp)->is_intr_sz = intr_sz; 662 663 (*ispecp)->is_pil = i_ddi_get_intr_pri(dip, inumber); 664 } 665 666 kmem_free(ip, intrlen); 667 } 668 } 669 670 /* 671 * Analog routine to i_ddi_alloc_ispec() used to free the interrupt 672 * specification and the associated bus interrupt value. 673 */ 674 void 675 i_ddi_free_ispec(ddi_intrspec_t intrspecp) 676 { 677 ddi_ispec_t *ispecp = (ddi_ispec_t *)intrspecp; 678 679 kmem_free(ispecp, sizeof (ddi_ispec_t) + (ispecp->is_intr_sz)); 680 } 681 682 /* 683 * i_ddi_get_intr_pri - Get the interrupt-priorities property from 684 * the specified device. 685 */ 686 uint32_t 687 i_ddi_get_intr_pri(dev_info_t *dip, uint_t inumber) 688 { 689 uint32_t *intr_prio_p; 690 uint32_t pri = 0; 691 int32_t i; 692 693 /* 694 * Use the "interrupt-priorities" property to determine the 695 * the pil/ipl for the interrupt handler. 696 */ 697 if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 698 "interrupt-priorities", (caddr_t)&intr_prio_p, 699 &i) == DDI_SUCCESS) { 700 if (inumber < (i / sizeof (int32_t))) 701 pri = intr_prio_p[inumber]; 702 kmem_free(intr_prio_p, i); 703 } 704 705 return (pri); 706 } 707 708 /* 709 * SECTION: DDI Memory/DMA 710 */ 711 712 static vmem_t *little_endian_arena; 713 static vmem_t *big_endian_arena; 714 715 static void * 716 segkmem_alloc_le(vmem_t *vmp, size_t size, int flag) 717 { 718 return (segkmem_xalloc(vmp, NULL, size, flag, HAT_STRUCTURE_LE, 719 segkmem_page_create, NULL)); 720 } 721 722 static void * 723 segkmem_alloc_be(vmem_t *vmp, size_t size, int flag) 724 { 725 return (segkmem_xalloc(vmp, NULL, size, flag, HAT_STRUCTURE_BE, 726 segkmem_page_create, NULL)); 727 } 728 729 void 730 ka_init(void) 731 { 732 little_endian_arena = vmem_create("little_endian", NULL, 0, 1, 733 segkmem_alloc_le, segkmem_free, heap_arena, 0, VM_SLEEP); 734 big_endian_arena = vmem_create("big_endian", NULL, 0, 1, 735 segkmem_alloc_be, segkmem_free, heap_arena, 0, VM_SLEEP); 736 } 737 738 /* 739 * Allocate from the system, aligned on a specific boundary. 740 * The alignment, if non-zero, must be a power of 2. 741 */ 742 static void * 743 kalloca(size_t size, size_t align, int cansleep, uint_t endian_flags) 744 { 745 size_t *addr, *raddr, rsize; 746 size_t hdrsize = 4 * sizeof (size_t); /* must be power of 2 */ 747 748 align = MAX(align, hdrsize); 749 ASSERT((align & (align - 1)) == 0); 750 751 /* 752 * We need to allocate 753 * rsize = size + hdrsize + align - MIN(hdrsize, buffer_alignment) 754 * bytes to be sure we have enough freedom to satisfy the request. 755 * Since the buffer alignment depends on the request size, this is 756 * not straightforward to use directly. 757 * 758 * kmem guarantees that any allocation of a 64-byte multiple will be 759 * 64-byte aligned. Since rounding up the request could add more 760 * than we save, we compute the size with and without alignment, and 761 * use the smaller of the two. 762 */ 763 rsize = size + hdrsize + align; 764 765 if (endian_flags == DDI_STRUCTURE_LE_ACC) { 766 raddr = vmem_alloc(little_endian_arena, rsize, 767 cansleep ? VM_SLEEP : VM_NOSLEEP); 768 } else { 769 raddr = vmem_alloc(big_endian_arena, rsize, 770 cansleep ? VM_SLEEP : VM_NOSLEEP); 771 } 772 773 if (raddr == NULL) 774 return (NULL); 775 776 addr = (size_t *)P2ROUNDUP((uintptr_t)raddr + hdrsize, align); 777 ASSERT((uintptr_t)addr + size - (uintptr_t)raddr <= rsize); 778 779 addr[-3] = (size_t)endian_flags; 780 addr[-2] = (size_t)raddr; 781 addr[-1] = rsize; 782 783 return (addr); 784 } 785 786 static void 787 kfreea(void *addr) 788 { 789 size_t *saddr = addr; 790 791 if (saddr[-3] == DDI_STRUCTURE_LE_ACC) 792 vmem_free(little_endian_arena, (void *)saddr[-2], saddr[-1]); 793 else 794 vmem_free(big_endian_arena, (void *)saddr[-2], saddr[-1]); 795 } 796 797 int 798 i_ddi_mem_alloc(dev_info_t *dip, ddi_dma_attr_t *attr, 799 size_t length, int cansleep, int streaming, 800 ddi_device_acc_attr_t *accattrp, 801 caddr_t *kaddrp, size_t *real_length, ddi_acc_hdl_t *handlep) 802 { 803 caddr_t a; 804 int iomin, align; 805 uint_t endian_flags = DDI_NEVERSWAP_ACC; 806 807 #if defined(lint) 808 *handlep = *handlep; 809 #endif 810 811 /* 812 * Check legality of arguments 813 */ 814 if (length == 0 || kaddrp == NULL || attr == NULL) { 815 return (DDI_FAILURE); 816 } 817 if (attr->dma_attr_minxfer == 0 || attr->dma_attr_align == 0 || 818 (attr->dma_attr_align & (attr->dma_attr_align - 1)) || 819 (attr->dma_attr_minxfer & (attr->dma_attr_minxfer - 1))) { 820 return (DDI_FAILURE); 821 } 822 823 /* 824 * Drivers for 64-bit capable SBus devices will encode 825 * the burtsizes for 64-bit xfers in the upper 16-bits. 826 * For DMA alignment, we use the most restrictive 827 * alignment of 32-bit and 64-bit xfers. 828 */ 829 iomin = (attr->dma_attr_burstsizes & 0xffff) | 830 ((attr->dma_attr_burstsizes >> 16) & 0xffff); 831 /* 832 * If a driver set burtsizes to 0, we give him byte alignment. 833 * Otherwise align at the burtsizes boundary. 834 */ 835 if (iomin == 0) 836 iomin = 1; 837 else 838 iomin = 1 << (ddi_fls(iomin) - 1); 839 iomin = maxbit(iomin, attr->dma_attr_minxfer); 840 iomin = maxbit(iomin, attr->dma_attr_align); 841 iomin = ddi_iomin(dip, iomin, streaming); 842 if (iomin == 0) 843 return (DDI_FAILURE); 844 845 ASSERT((iomin & (iomin - 1)) == 0); 846 ASSERT(iomin >= attr->dma_attr_minxfer); 847 ASSERT(iomin >= attr->dma_attr_align); 848 849 length = P2ROUNDUP(length, iomin); 850 align = iomin; 851 852 if (accattrp != NULL) 853 endian_flags = accattrp->devacc_attr_endian_flags; 854 855 a = kalloca(length, align, cansleep, endian_flags); 856 if ((*kaddrp = a) == 0) { 857 return (DDI_FAILURE); 858 } else { 859 if (real_length) { 860 *real_length = length; 861 } 862 if (handlep) { 863 /* 864 * assign handle information 865 */ 866 impl_acc_hdl_init(handlep); 867 } 868 return (DDI_SUCCESS); 869 } 870 } 871 872 /* 873 * covert old DMA limits structure to DMA attribute structure 874 * and continue 875 */ 876 int 877 i_ddi_mem_alloc_lim(dev_info_t *dip, ddi_dma_lim_t *limits, 878 size_t length, int cansleep, int streaming, 879 ddi_device_acc_attr_t *accattrp, caddr_t *kaddrp, 880 uint_t *real_length, ddi_acc_hdl_t *ap) 881 { 882 ddi_dma_attr_t dma_attr, *attrp; 883 size_t rlen; 884 int ret; 885 886 ASSERT(limits); 887 attrp = &dma_attr; 888 attrp->dma_attr_version = DMA_ATTR_V0; 889 attrp->dma_attr_addr_lo = (uint64_t)limits->dlim_addr_lo; 890 attrp->dma_attr_addr_hi = (uint64_t)limits->dlim_addr_hi; 891 attrp->dma_attr_count_max = (uint64_t)-1; 892 attrp->dma_attr_align = 1; 893 attrp->dma_attr_burstsizes = (uint_t)limits->dlim_burstsizes; 894 attrp->dma_attr_minxfer = (uint32_t)limits->dlim_minxfer; 895 attrp->dma_attr_maxxfer = (uint64_t)-1; 896 attrp->dma_attr_seg = (uint64_t)limits->dlim_cntr_max; 897 attrp->dma_attr_sgllen = 1; 898 attrp->dma_attr_granular = 1; 899 attrp->dma_attr_flags = 0; 900 901 ret = i_ddi_mem_alloc(dip, attrp, length, cansleep, streaming, 902 accattrp, kaddrp, &rlen, ap); 903 if (ret == DDI_SUCCESS) { 904 if (real_length) 905 *real_length = (uint_t)rlen; 906 } 907 return (ret); 908 } 909 910 /* ARGSUSED */ 911 void 912 i_ddi_mem_free(caddr_t kaddr, int stream) 913 { 914 kfreea(kaddr); 915 } 916 917 /* 918 * SECTION: DDI Data Access 919 */ 920 921 static uintptr_t impl_acc_hdl_id = 0; 922 923 /* 924 * access handle allocator 925 */ 926 ddi_acc_hdl_t * 927 impl_acc_hdl_get(ddi_acc_handle_t hdl) 928 { 929 /* 930 * Extract the access handle address from the DDI implemented 931 * access handle 932 */ 933 return (&((ddi_acc_impl_t *)hdl)->ahi_common); 934 } 935 936 ddi_acc_handle_t 937 impl_acc_hdl_alloc(int (*waitfp)(caddr_t), caddr_t arg) 938 { 939 ddi_acc_impl_t *hp; 940 on_trap_data_t *otp; 941 int sleepflag; 942 943 sleepflag = ((waitfp == (int (*)())KM_SLEEP) ? KM_SLEEP : KM_NOSLEEP); 944 945 /* 946 * Allocate and initialize the data access handle and error status. 947 */ 948 if ((hp = kmem_zalloc(sizeof (ddi_acc_impl_t), sleepflag)) == NULL) 949 goto fail; 950 if ((hp->ahi_err = (ndi_err_t *)kmem_zalloc( 951 sizeof (ndi_err_t), sleepflag)) == NULL) { 952 kmem_free(hp, sizeof (ddi_acc_impl_t)); 953 goto fail; 954 } 955 if ((otp = (on_trap_data_t *)kmem_zalloc( 956 sizeof (on_trap_data_t), sleepflag)) == NULL) { 957 kmem_free(hp->ahi_err, sizeof (ndi_err_t)); 958 kmem_free(hp, sizeof (ddi_acc_impl_t)); 959 goto fail; 960 } 961 hp->ahi_err->err_ontrap = otp; 962 hp->ahi_common.ah_platform_private = (void *)hp; 963 964 return ((ddi_acc_handle_t)hp); 965 fail: 966 if ((waitfp != (int (*)())KM_SLEEP) && 967 (waitfp != (int (*)())KM_NOSLEEP)) 968 ddi_set_callback(waitfp, arg, &impl_acc_hdl_id); 969 return (NULL); 970 } 971 972 void 973 impl_acc_hdl_free(ddi_acc_handle_t handle) 974 { 975 ddi_acc_impl_t *hp; 976 977 /* 978 * The supplied (ddi_acc_handle_t) is actually a (ddi_acc_impl_t *), 979 * because that's what we allocated in impl_acc_hdl_alloc() above. 980 */ 981 hp = (ddi_acc_impl_t *)handle; 982 if (hp) { 983 kmem_free(hp->ahi_err->err_ontrap, sizeof (on_trap_data_t)); 984 kmem_free(hp->ahi_err, sizeof (ndi_err_t)); 985 kmem_free(hp, sizeof (ddi_acc_impl_t)); 986 if (impl_acc_hdl_id) 987 ddi_run_callback(&impl_acc_hdl_id); 988 } 989 } 990 991 void 992 impl_acc_err_init(ddi_acc_hdl_t *handlep) 993 { 994 int fmcap; 995 ndi_err_t *errp; 996 on_trap_data_t *otp; 997 ddi_acc_impl_t *hp = (ddi_acc_impl_t *)handlep; 998 999 fmcap = ddi_fm_capable(handlep->ah_dip); 1000 1001 if (handlep->ah_acc.devacc_attr_version < DDI_DEVICE_ATTR_V1 || 1002 !DDI_FM_ACC_ERR_CAP(fmcap)) { 1003 handlep->ah_acc.devacc_attr_access = DDI_DEFAULT_ACC; 1004 } else if (DDI_FM_ACC_ERR_CAP(fmcap)) { 1005 if (handlep->ah_acc.devacc_attr_access == DDI_DEFAULT_ACC) { 1006 i_ddi_drv_ereport_post(handlep->ah_dip, DVR_EFMCAP, 1007 NULL, DDI_NOSLEEP); 1008 } else { 1009 errp = hp->ahi_err; 1010 otp = (on_trap_data_t *)errp->err_ontrap; 1011 otp->ot_handle = (void *)(hp); 1012 otp->ot_prot = OT_DATA_ACCESS; 1013 if (handlep->ah_acc.devacc_attr_access == 1014 DDI_CAUTIOUS_ACC) 1015 otp->ot_trampoline = 1016 (uintptr_t)&i_ddi_caut_trampoline; 1017 else 1018 otp->ot_trampoline = 1019 (uintptr_t)&i_ddi_prot_trampoline; 1020 errp->err_status = DDI_FM_OK; 1021 errp->err_expected = DDI_FM_ERR_UNEXPECTED; 1022 } 1023 } 1024 } 1025 1026 void 1027 impl_acc_hdl_init(ddi_acc_hdl_t *handlep) 1028 { 1029 ddi_acc_impl_t *hp; 1030 1031 ASSERT(handlep); 1032 1033 hp = (ddi_acc_impl_t *)handlep; 1034 1035 /* 1036 * check for SW byte-swapping 1037 */ 1038 hp->ahi_get8 = i_ddi_get8; 1039 hp->ahi_put8 = i_ddi_put8; 1040 hp->ahi_rep_get8 = i_ddi_rep_get8; 1041 hp->ahi_rep_put8 = i_ddi_rep_put8; 1042 if (handlep->ah_acc.devacc_attr_endian_flags & DDI_STRUCTURE_LE_ACC) { 1043 hp->ahi_get16 = i_ddi_swap_get16; 1044 hp->ahi_get32 = i_ddi_swap_get32; 1045 hp->ahi_get64 = i_ddi_swap_get64; 1046 hp->ahi_put16 = i_ddi_swap_put16; 1047 hp->ahi_put32 = i_ddi_swap_put32; 1048 hp->ahi_put64 = i_ddi_swap_put64; 1049 hp->ahi_rep_get16 = i_ddi_swap_rep_get16; 1050 hp->ahi_rep_get32 = i_ddi_swap_rep_get32; 1051 hp->ahi_rep_get64 = i_ddi_swap_rep_get64; 1052 hp->ahi_rep_put16 = i_ddi_swap_rep_put16; 1053 hp->ahi_rep_put32 = i_ddi_swap_rep_put32; 1054 hp->ahi_rep_put64 = i_ddi_swap_rep_put64; 1055 } else { 1056 hp->ahi_get16 = i_ddi_get16; 1057 hp->ahi_get32 = i_ddi_get32; 1058 hp->ahi_get64 = i_ddi_get64; 1059 hp->ahi_put16 = i_ddi_put16; 1060 hp->ahi_put32 = i_ddi_put32; 1061 hp->ahi_put64 = i_ddi_put64; 1062 hp->ahi_rep_get16 = i_ddi_rep_get16; 1063 hp->ahi_rep_get32 = i_ddi_rep_get32; 1064 hp->ahi_rep_get64 = i_ddi_rep_get64; 1065 hp->ahi_rep_put16 = i_ddi_rep_put16; 1066 hp->ahi_rep_put32 = i_ddi_rep_put32; 1067 hp->ahi_rep_put64 = i_ddi_rep_put64; 1068 } 1069 1070 /* Legacy fault flags and support */ 1071 hp->ahi_fault_check = i_ddi_acc_fault_check; 1072 hp->ahi_fault_notify = i_ddi_acc_fault_notify; 1073 hp->ahi_fault = 0; 1074 impl_acc_err_init(handlep); 1075 } 1076 1077 void 1078 i_ddi_acc_set_fault(ddi_acc_handle_t handle) 1079 { 1080 ddi_acc_impl_t *hp = (ddi_acc_impl_t *)handle; 1081 1082 if (!hp->ahi_fault) { 1083 hp->ahi_fault = 1; 1084 (*hp->ahi_fault_notify)(hp); 1085 } 1086 } 1087 1088 void 1089 i_ddi_acc_clr_fault(ddi_acc_handle_t handle) 1090 { 1091 ddi_acc_impl_t *hp = (ddi_acc_impl_t *)handle; 1092 1093 if (hp->ahi_fault) { 1094 hp->ahi_fault = 0; 1095 (*hp->ahi_fault_notify)(hp); 1096 } 1097 } 1098 1099 /* ARGSUSED */ 1100 void 1101 i_ddi_acc_fault_notify(ddi_acc_impl_t *hp) 1102 { 1103 /* Default version, does nothing */ 1104 } 1105 1106 /* 1107 * SECTION: Misc functions 1108 */ 1109 1110 /* 1111 * instance wrappers 1112 */ 1113 /*ARGSUSED*/ 1114 uint_t 1115 impl_assign_instance(dev_info_t *dip) 1116 { 1117 return ((uint_t)-1); 1118 } 1119 1120 /*ARGSUSED*/ 1121 int 1122 impl_keep_instance(dev_info_t *dip) 1123 { 1124 return (DDI_FAILURE); 1125 } 1126 1127 /*ARGSUSED*/ 1128 int 1129 impl_free_instance(dev_info_t *dip) 1130 { 1131 return (DDI_FAILURE); 1132 } 1133 1134 /*ARGSUSED*/ 1135 int 1136 impl_check_cpu(dev_info_t *devi) 1137 { 1138 return (DDI_SUCCESS); 1139 } 1140 1141 1142 static const char *nocopydevs[] = { 1143 "SUNW,ffb", 1144 "SUNW,afb", 1145 NULL 1146 }; 1147 1148 /* 1149 * Perform a copy from a memory mapped device (whose devinfo pointer is devi) 1150 * separately mapped at devaddr in the kernel to a kernel buffer at kaddr. 1151 */ 1152 /*ARGSUSED*/ 1153 int 1154 e_ddi_copyfromdev(dev_info_t *devi, 1155 off_t off, const void *devaddr, void *kaddr, size_t len) 1156 { 1157 const char **argv; 1158 1159 for (argv = nocopydevs; *argv; argv++) 1160 if (strcmp(ddi_binding_name(devi), *argv) == 0) { 1161 bzero(kaddr, len); 1162 return (0); 1163 } 1164 1165 bcopy(devaddr, kaddr, len); 1166 return (0); 1167 } 1168 1169 /* 1170 * Perform a copy to a memory mapped device (whose devinfo pointer is devi) 1171 * separately mapped at devaddr in the kernel from a kernel buffer at kaddr. 1172 */ 1173 /*ARGSUSED*/ 1174 int 1175 e_ddi_copytodev(dev_info_t *devi, 1176 off_t off, const void *kaddr, void *devaddr, size_t len) 1177 { 1178 const char **argv; 1179 1180 for (argv = nocopydevs; *argv; argv++) 1181 if (strcmp(ddi_binding_name(devi), *argv) == 0) 1182 return (1); 1183 1184 bcopy(kaddr, devaddr, len); 1185 return (0); 1186 } 1187 1188 /* 1189 * Boot Configuration 1190 */ 1191 idprom_t idprom; 1192 1193 /* 1194 * Configure the hardware on the system. 1195 * Called before the rootfs is mounted 1196 */ 1197 void 1198 configure(void) 1199 { 1200 extern void i_ddi_init_root(); 1201 1202 /* We better have released boot by this time! */ 1203 ASSERT(!bootops); 1204 1205 /* 1206 * Determine whether or not to use the fpu, V9 SPARC cpus 1207 * always have one. Could check for existence of a fp queue, 1208 * Ultra I, II and IIa do not have a fp queue. 1209 */ 1210 if (fpu_exists) 1211 fpu_probe(); 1212 else 1213 cmn_err(CE_CONT, "FPU not in use\n"); 1214 1215 #if 0 /* XXXQ - not necessary for sun4u */ 1216 /* 1217 * This following line fixes bugid 1041296; we need to do a 1218 * prom_nextnode(0) because this call ALSO patches the DMA+ 1219 * bug in Campus-B and Phoenix. The prom uncaches the traptable 1220 * page as a side-effect of devr_next(0) (which prom_nextnode calls), 1221 * so this *must* be executed early on. (XXX This is untrue for sun4u) 1222 */ 1223 (void) prom_nextnode((dnode_t)0); 1224 #endif 1225 1226 /* 1227 * Initialize devices on the machine. 1228 * Uses configuration tree built by the PROMs to determine what 1229 * is present, and builds a tree of prototype dev_info nodes 1230 * corresponding to the hardware which identified itself. 1231 */ 1232 i_ddi_init_root(); 1233 1234 #ifdef DDI_PROP_DEBUG 1235 (void) ddi_prop_debug(1); /* Enable property debugging */ 1236 #endif /* DDI_PROP_DEBUG */ 1237 } 1238 1239 /* 1240 * The "status" property indicates the operational status of a device. 1241 * If this property is present, the value is a string indicating the 1242 * status of the device as follows: 1243 * 1244 * "okay" operational. 1245 * "disabled" not operational, but might become operational. 1246 * "fail" not operational because a fault has been detected, 1247 * and it is unlikely that the device will become 1248 * operational without repair. no additional details 1249 * are available. 1250 * "fail-xxx" not operational because a fault has been detected, 1251 * and it is unlikely that the device will become 1252 * operational without repair. "xxx" is additional 1253 * human-readable information about the particular 1254 * fault condition that was detected. 1255 * 1256 * The absence of this property means that the operational status is 1257 * unknown or okay. 1258 * 1259 * This routine checks the status property of the specified device node 1260 * and returns 0 if the operational status indicates failure, and 1 otherwise. 1261 * 1262 * The property may exist on plug-in cards the existed before IEEE 1275-1994. 1263 * And, in that case, the property may not even be a string. So we carefully 1264 * check for the value "fail", in the beginning of the string, noting 1265 * the property length. 1266 */ 1267 int 1268 status_okay(int id, char *buf, int buflen) 1269 { 1270 char status_buf[OBP_MAXPROPNAME]; 1271 char *bufp = buf; 1272 int len = buflen; 1273 int proplen; 1274 static const char *status = "status"; 1275 static const char *fail = "fail"; 1276 size_t fail_len = strlen(fail); 1277 1278 /* 1279 * Get the proplen ... if it's smaller than "fail", 1280 * or doesn't exist ... then we don't care, since 1281 * the value can't begin with the char string "fail". 1282 * 1283 * NB: proplen, if it's a string, includes the NULL in the 1284 * the size of the property, and fail_len does not. 1285 */ 1286 proplen = prom_getproplen((dnode_t)id, (caddr_t)status); 1287 if (proplen <= fail_len) /* nonexistent or uninteresting len */ 1288 return (1); 1289 1290 /* 1291 * if a buffer was provided, use it 1292 */ 1293 if ((buf == (char *)NULL) || (buflen <= 0)) { 1294 bufp = status_buf; 1295 len = sizeof (status_buf); 1296 } 1297 *bufp = (char)0; 1298 1299 /* 1300 * Get the property into the buffer, to the extent of the buffer, 1301 * and in case the buffer is smaller than the property size, 1302 * NULL terminate the buffer. (This handles the case where 1303 * a buffer was passed in and the caller wants to print the 1304 * value, but the buffer was too small). 1305 */ 1306 (void) prom_bounded_getprop((dnode_t)id, (caddr_t)status, 1307 (caddr_t)bufp, len); 1308 *(bufp + len - 1) = (char)0; 1309 1310 /* 1311 * If the value begins with the char string "fail", 1312 * then it means the node is failed. We don't care 1313 * about any other values. We assume the node is ok 1314 * although it might be 'disabled'. 1315 */ 1316 if (strncmp(bufp, fail, fail_len) == 0) 1317 return (0); 1318 1319 return (1); 1320 } 1321 1322 1323 /* 1324 * We set the cpu type from the idprom, if we can. 1325 * Note that we just read out the contents of it, for the most part. 1326 */ 1327 void 1328 setcputype(void) 1329 { 1330 /* 1331 * We cache the idprom info early on so that we don't 1332 * rummage through the NVRAM unnecessarily later. 1333 */ 1334 (void) prom_getidprom((caddr_t)&idprom, sizeof (idprom)); 1335 } 1336 1337 /* 1338 * Here is where we actually infer meanings to the members of idprom_t 1339 */ 1340 void 1341 parse_idprom(void) 1342 { 1343 if (idprom.id_format == IDFORM_1) { 1344 uint_t i; 1345 1346 (void) localetheraddr((struct ether_addr *)idprom.id_ether, 1347 (struct ether_addr *)NULL); 1348 1349 i = idprom.id_machine << 24; 1350 i = i + idprom.id_serial; 1351 numtos((ulong_t)i, hw_serial); 1352 } else 1353 prom_printf("Invalid format code in IDprom.\n"); 1354 } 1355 1356 /* 1357 * Allow for implementation specific correction of PROM property values. 1358 */ 1359 /*ARGSUSED*/ 1360 void 1361 impl_fix_props(dev_info_t *dip, dev_info_t *ch_dip, char *name, int len, 1362 caddr_t buffer) 1363 { 1364 /* 1365 * There are no adjustments needed in this implementation. 1366 */ 1367 } 1368 1369 /* 1370 * SECTION: DDI Interrupt 1371 */ 1372 1373 /* 1374 * get_intr_parent() is a generic routine that process a 1275 interrupt 1375 * map (imap) property. This function returns a dev_info_t structure 1376 * which claims ownership of the interrupt domain. 1377 * It also returns the new interrupt translation within this new domain. 1378 * If an interrupt-parent or interrupt-map property are not found, 1379 * then we fallback to using the device tree's parent. 1380 * 1381 * imap entry format: 1382 * <reg>,<interrupt>,<phandle>,<translated interrupt> 1383 * reg - The register specification in the interrupts domain 1384 * interrupt - The interrupt specification 1385 * phandle - PROM handle of the device that owns the xlated interrupt domain 1386 * translated interrupt - interrupt specifier in the parents domain 1387 * note: <reg>,<interrupt> - The reg and interrupt can be combined to create 1388 * a unique entry called a unit interrupt specifier. 1389 * 1390 * Here's the processing steps: 1391 * step1 - If the interrupt-parent property exists, create the ispec and 1392 * return the dip of the interrupt parent. 1393 * step2 - Extract the interrupt-map property and the interrupt-map-mask 1394 * If these don't exist, just return the device tree parent. 1395 * step3 - build up the unit interrupt specifier to match against the 1396 * interrupt map property 1397 * step4 - Scan the interrupt-map property until a match is found 1398 * step4a - Extract the interrupt parent 1399 * step4b - Compare the unit interrupt specifier 1400 */ 1401 dev_info_t * 1402 get_intr_parent(dev_info_t *pdip, dev_info_t *dip, 1403 ddi_ispec_t *child_ispecp, ddi_ispec_t **new_ispecp) 1404 { 1405 prop_1275_cell_t *imap, *imap_mask, *scan, *reg_p, *match_req; 1406 int32_t imap_sz, imap_cells, imap_scan_cells, imap_mask_sz, 1407 addr_cells, intr_cells, reg_len, i, j; 1408 int32_t match_found = 0; 1409 dev_info_t *intr_parent_dip = NULL; 1410 ddi_ispec_t *ispecp; 1411 uint32_t *intr = child_ispecp->is_intr; 1412 uint32_t nodeid; 1413 static ddi_ispec_t *dup_ispec(ddi_ispec_t *ispecp); 1414 #ifdef DEBUG 1415 static int debug = 0; 1416 #endif 1417 1418 *new_ispecp = (ddi_ispec_t *)NULL; 1419 1420 /* 1421 * step1 1422 * If we have an interrupt-parent property, this property represents 1423 * the nodeid of our interrupt parent. 1424 */ 1425 if ((nodeid = ddi_getprop(DDI_DEV_T_ANY, dip, 0, 1426 "interrupt-parent", -1)) != -1) { 1427 intr_parent_dip = e_ddi_nodeid_to_dip(nodeid); 1428 ASSERT(intr_parent_dip); 1429 /* 1430 * Attach the interrupt parent. 1431 * 1432 * N.B. e_ddi_nodeid_to_dip() isn't safe under DR. 1433 * Also, interrupt parent isn't held. This needs 1434 * to be revisited if DR-capable platforms implement 1435 * interrupt redirection. 1436 */ 1437 if (i_ddi_attach_node_hierarchy(intr_parent_dip) 1438 != DDI_SUCCESS) { 1439 ndi_rele_devi(intr_parent_dip); 1440 return (NULL); 1441 } 1442 1443 /* Create a new interrupt info struct and initialize it. */ 1444 ispecp = dup_ispec(child_ispecp); 1445 1446 *new_ispecp = ispecp; 1447 return (intr_parent_dip); 1448 } 1449 1450 /* 1451 * step2 1452 * Get interrupt map structure from PROM property 1453 */ 1454 if (ddi_getlongprop(DDI_DEV_T_ANY, pdip, DDI_PROP_DONTPASS, 1455 "interrupt-map", (caddr_t)&imap, &imap_sz) 1456 != DDI_PROP_SUCCESS) { 1457 /* 1458 * If we don't have an imap property, default to using the 1459 * device tree. 1460 */ 1461 /* Create a new interrupt info struct and initialize it. */ 1462 ispecp = dup_ispec(child_ispecp); 1463 1464 *new_ispecp = ispecp; 1465 ndi_hold_devi(pdip); 1466 return (pdip); 1467 } 1468 1469 /* Get the interrupt mask property */ 1470 if (ddi_getlongprop(DDI_DEV_T_ANY, pdip, DDI_PROP_DONTPASS, 1471 "interrupt-map-mask", (caddr_t)&imap_mask, &imap_mask_sz) 1472 != DDI_PROP_SUCCESS) { 1473 /* 1474 * If we don't find this property, we have to fail the request 1475 * because the 1275 imap property wasn't defined correctly. 1476 */ 1477 ASSERT(intr_parent_dip == NULL); 1478 goto exit2; 1479 } 1480 1481 /* Get the address cell size */ 1482 addr_cells = ddi_getprop(DDI_DEV_T_ANY, pdip, 0, 1483 "#address-cells", 2); 1484 1485 /* Get the interrupts cell size */ 1486 intr_cells = ddi_getprop(DDI_DEV_T_ANY, pdip, 0, 1487 "#interrupt-cells", 1); 1488 1489 /* 1490 * step3 1491 * Now lets build up the unit interrupt specifier e.g. reg,intr 1492 * and apply the imap mask. match_req will hold this when we're 1493 * through. 1494 */ 1495 if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "reg", 1496 (caddr_t)®_p, ®_len) != DDI_SUCCESS) { 1497 ASSERT(intr_parent_dip == NULL); 1498 goto exit3; 1499 } 1500 1501 match_req = kmem_alloc(CELLS_1275_TO_BYTES(addr_cells) + 1502 CELLS_1275_TO_BYTES(intr_cells), KM_SLEEP); 1503 1504 for (i = 0; i < addr_cells; i++) 1505 match_req[i] = (reg_p[i] & imap_mask[i]); 1506 1507 for (j = 0; j < intr_cells; i++, j++) 1508 match_req[i] = (intr[j] & imap_mask[i]); 1509 1510 /* Calculate the imap size in cells */ 1511 imap_cells = BYTES_TO_1275_CELLS(imap_sz); 1512 1513 #ifdef DEBUG 1514 if (debug) 1515 prom_printf("reg cell size 0x%x, intr cell size 0x%x, " 1516 "match_request 0x%x, imap 0x%x\n", addr_cells, intr_cells, 1517 match_req, imap); 1518 #endif 1519 1520 /* 1521 * Scan the imap property looking for a match of the interrupt unit 1522 * specifier. This loop is rather complex since the data within the 1523 * imap property may vary in size. 1524 */ 1525 for (scan = imap, imap_scan_cells = i = 0; 1526 imap_scan_cells < imap_cells; scan += i, imap_scan_cells += i) { 1527 int new_intr_cells; 1528 1529 /* Set the index to the nodeid field */ 1530 i = addr_cells + intr_cells; 1531 1532 /* 1533 * step4a 1534 * Translate the nodeid field to a dip 1535 */ 1536 ASSERT(intr_parent_dip == NULL); 1537 intr_parent_dip = e_ddi_nodeid_to_dip((uint_t)scan[i++]); 1538 1539 ASSERT(intr_parent_dip != 0); 1540 #ifdef DEBUG 1541 if (debug) 1542 prom_printf("scan 0x%x\n", scan); 1543 #endif 1544 /* 1545 * The tmp_dip describes the new domain, get it's interrupt 1546 * cell size 1547 */ 1548 new_intr_cells = ddi_getprop(DDI_DEV_T_ANY, intr_parent_dip, 0, 1549 "#interrupts-cells", 1); 1550 1551 /* 1552 * step4b 1553 * See if we have a match on the interrupt unit specifier 1554 */ 1555 if (cells_1275_cmp(match_req, scan, addr_cells + intr_cells) 1556 == 0) { 1557 ddi_ispec_t ispec; 1558 uint32_t *intr; 1559 1560 /* 1561 * Copy The childs ispec info excluding the interrupt 1562 */ 1563 ispec = *child_ispecp; 1564 1565 match_found = 1; 1566 1567 /* 1568 * If we have an imap parent whose not in our device 1569 * tree path, we need to hold and install that driver. 1570 */ 1571 if (i_ddi_attach_node_hierarchy(intr_parent_dip) 1572 != DDI_SUCCESS) { 1573 ndi_rele_devi(intr_parent_dip); 1574 intr_parent_dip = (dev_info_t *)NULL; 1575 goto exit4; 1576 } 1577 1578 /* 1579 * We need to handcraft an ispec along with a bus 1580 * interrupt value, so we can dup it into our 1581 * standard ispec structure. 1582 */ 1583 /* Extract the translated interrupt information */ 1584 intr = kmem_alloc( 1585 CELLS_1275_TO_BYTES(new_intr_cells), KM_SLEEP); 1586 1587 for (j = 0; j < new_intr_cells; j++, i++) 1588 intr[j] = scan[i]; 1589 1590 ispec.is_intr_sz = 1591 CELLS_1275_TO_BYTES(new_intr_cells); 1592 ispec.is_intr = intr; 1593 1594 ispecp = dup_ispec(&ispec); 1595 1596 kmem_free(intr, CELLS_1275_TO_BYTES(new_intr_cells)); 1597 1598 #ifdef DEBUG 1599 if (debug) 1600 prom_printf("dip 0x%x, intr info 0x%x\n", 1601 intr_parent_dip, ispecp); 1602 #endif 1603 1604 break; 1605 } else { 1606 #ifdef DEBUG 1607 if (debug) 1608 prom_printf("dip 0x%x\n", intr_parent_dip); 1609 #endif 1610 ndi_rele_devi(intr_parent_dip); 1611 intr_parent_dip = NULL; 1612 i += new_intr_cells; 1613 } 1614 } 1615 1616 /* 1617 * If we haven't found our interrupt parent at this point, fallback 1618 * to using the device tree. 1619 */ 1620 if (!match_found) { 1621 /* Create a new interrupt info struct and initialize it. */ 1622 ispecp = dup_ispec(child_ispecp); 1623 1624 ndi_hold_devi(pdip); 1625 ASSERT(intr_parent_dip == NULL); 1626 intr_parent_dip = pdip; 1627 } 1628 1629 ASSERT(ispecp != NULL); 1630 ASSERT(intr_parent_dip != NULL); 1631 *new_ispecp = ispecp; 1632 1633 exit4: 1634 kmem_free(reg_p, reg_len); 1635 kmem_free(match_req, CELLS_1275_TO_BYTES(addr_cells) + 1636 CELLS_1275_TO_BYTES(intr_cells)); 1637 1638 exit3: 1639 kmem_free(imap_mask, imap_mask_sz); 1640 1641 exit2: 1642 kmem_free(imap, imap_sz); 1643 1644 return (intr_parent_dip); 1645 } 1646 1647 /* 1648 * Support routine for duplicating and initializing an interrupt specification. 1649 * The bus interrupt value will be allocated at the end of this structure, so 1650 * the corresponding routine i_ddi_free_ispec() should be used to free the 1651 * interrupt specification. 1652 */ 1653 static ddi_ispec_t * 1654 dup_ispec(ddi_ispec_t *ispecp) 1655 { 1656 ddi_ispec_t *new_ispecp; 1657 1658 new_ispecp = kmem_alloc(sizeof (ddi_ispec_t) + ispecp->is_intr_sz, 1659 KM_SLEEP); 1660 1661 /* Copy the contents of the ispec */ 1662 *new_ispecp = *ispecp; 1663 1664 /* Reset the intr pointer to the one just created */ 1665 new_ispecp->is_intr = (uint32_t *)(new_ispecp + 1); 1666 1667 cells_1275_copy(ispecp->is_intr, new_ispecp->is_intr, 1668 BYTES_TO_1275_CELLS(ispecp->is_intr_sz)); 1669 1670 return (new_ispecp); 1671 } 1672 1673 int 1674 i_ddi_get_nintrs(dev_info_t *dip) 1675 { 1676 int32_t intrlen; 1677 prop_1275_cell_t intr_sz; 1678 prop_1275_cell_t *ip; 1679 int32_t ret = 0; 1680 1681 if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS | 1682 DDI_PROP_CANSLEEP, 1683 "interrupts", (caddr_t)&ip, &intrlen) == DDI_SUCCESS) { 1684 1685 intr_sz = ddi_getprop(DDI_DEV_T_ANY, dip, 0, 1686 "#interrupt-cells", 1); 1687 /* adjust for number of bytes */ 1688 intr_sz = CELLS_1275_TO_BYTES(intr_sz); 1689 1690 ret = intrlen / intr_sz; 1691 1692 kmem_free(ip, intrlen); 1693 } 1694 1695 return (ret); 1696 } 1697 1698 /*ARGSUSED*/ 1699 uint_t 1700 softlevel1(caddr_t arg) 1701 { 1702 extern int siron_pending; 1703 1704 siron_pending = 0; 1705 softint(); 1706 return (1); 1707 } 1708 1709 /* 1710 * indirection table, to save us some large switch statements 1711 * NOTE: This must agree with "INTLEVEL_foo" constants in 1712 * <sys/avintr.h> 1713 */ 1714 struct autovec *const vectorlist[] = { 0 }; 1715 1716 /* 1717 * This value is exported here for the functions in avintr.c 1718 */ 1719 const uint_t maxautovec = (sizeof (vectorlist) / sizeof (vectorlist[0])); 1720 1721 /* 1722 * Check for machine specific interrupt levels which cannot be reassigned by 1723 * settrap(), sun4u version. 1724 * 1725 * sun4u does not support V8 SPARC "fast trap" handlers. 1726 */ 1727 /*ARGSUSED*/ 1728 int 1729 exclude_settrap(int lvl) 1730 { 1731 return (1); 1732 } 1733 1734 /* 1735 * Check for machine specific interrupt levels which cannot have interrupt 1736 * handlers added. We allow levels 1 through 15; level 0 is nonsense. 1737 */ 1738 /*ARGSUSED*/ 1739 int 1740 exclude_level(int lvl) 1741 { 1742 return ((lvl < 1) || (lvl > 15)); 1743 } 1744 1745 /* 1746 * The following functions ready a cautious request to go up to the nexus 1747 * driver. It is up to the nexus driver to decide how to process the request. 1748 * It may choose to call i_ddi_do_caut_get/put in this file, or do it 1749 * differently. 1750 */ 1751 1752 static void 1753 i_ddi_caut_getput_ctlops( 1754 ddi_acc_impl_t *hp, uint64_t host_addr, uint64_t dev_addr, size_t size, 1755 size_t repcount, uint_t flags, ddi_ctl_enum_t cmd) 1756 { 1757 peekpoke_ctlops_t cautacc_ctlops_arg; 1758 1759 cautacc_ctlops_arg.size = size; 1760 cautacc_ctlops_arg.dev_addr = dev_addr; 1761 cautacc_ctlops_arg.host_addr = host_addr; 1762 cautacc_ctlops_arg.handle = (ddi_acc_handle_t)hp; 1763 cautacc_ctlops_arg.repcount = repcount; 1764 cautacc_ctlops_arg.flags = flags; 1765 1766 (void) ddi_ctlops(hp->ahi_common.ah_dip, hp->ahi_common.ah_dip, cmd, 1767 &cautacc_ctlops_arg, NULL); 1768 } 1769 1770 uint8_t 1771 i_ddi_caut_get8(ddi_acc_impl_t *hp, uint8_t *addr) 1772 { 1773 uint8_t value; 1774 i_ddi_caut_getput_ctlops(hp, (uint64_t)&value, (uint64_t)addr, 1775 sizeof (uint8_t), 1, 0, DDI_CTLOPS_PEEK); 1776 1777 return (value); 1778 } 1779 1780 uint16_t 1781 i_ddi_caut_get16(ddi_acc_impl_t *hp, uint16_t *addr) 1782 { 1783 uint16_t value; 1784 i_ddi_caut_getput_ctlops(hp, (uint64_t)&value, (uint64_t)addr, 1785 sizeof (uint16_t), 1, 0, DDI_CTLOPS_PEEK); 1786 1787 return (value); 1788 } 1789 1790 uint32_t 1791 i_ddi_caut_get32(ddi_acc_impl_t *hp, uint32_t *addr) 1792 { 1793 uint32_t value; 1794 i_ddi_caut_getput_ctlops(hp, (uint64_t)&value, (uint64_t)addr, 1795 sizeof (uint32_t), 1, 0, DDI_CTLOPS_PEEK); 1796 1797 return (value); 1798 } 1799 1800 uint64_t 1801 i_ddi_caut_get64(ddi_acc_impl_t *hp, uint64_t *addr) 1802 { 1803 uint64_t value; 1804 i_ddi_caut_getput_ctlops(hp, (uint64_t)&value, (uint64_t)addr, 1805 sizeof (uint64_t), 1, 0, DDI_CTLOPS_PEEK); 1806 1807 return (value); 1808 } 1809 1810 void 1811 i_ddi_caut_put8(ddi_acc_impl_t *hp, uint8_t *addr, uint8_t value) 1812 { 1813 i_ddi_caut_getput_ctlops(hp, (uint64_t)&value, (uint64_t)addr, 1814 sizeof (uint8_t), 1, 0, DDI_CTLOPS_POKE); 1815 } 1816 1817 void 1818 i_ddi_caut_put16(ddi_acc_impl_t *hp, uint16_t *addr, uint16_t value) 1819 { 1820 i_ddi_caut_getput_ctlops(hp, (uint64_t)&value, (uint64_t)addr, 1821 sizeof (uint16_t), 1, 0, DDI_CTLOPS_POKE); 1822 } 1823 1824 void 1825 i_ddi_caut_put32(ddi_acc_impl_t *hp, uint32_t *addr, uint32_t value) 1826 { 1827 i_ddi_caut_getput_ctlops(hp, (uint64_t)&value, (uint64_t)addr, 1828 sizeof (uint32_t), 1, 0, DDI_CTLOPS_POKE); 1829 } 1830 1831 void 1832 i_ddi_caut_put64(ddi_acc_impl_t *hp, uint64_t *addr, uint64_t value) 1833 { 1834 i_ddi_caut_getput_ctlops(hp, (uint64_t)&value, (uint64_t)addr, 1835 sizeof (uint64_t), 1, 0, DDI_CTLOPS_POKE); 1836 } 1837 1838 void 1839 i_ddi_caut_rep_get8(ddi_acc_impl_t *hp, uint8_t *host_addr, uint8_t *dev_addr, 1840 size_t repcount, uint_t flags) 1841 { 1842 i_ddi_caut_getput_ctlops(hp, (uint64_t)host_addr, (uint64_t)dev_addr, 1843 sizeof (uint8_t), repcount, flags, DDI_CTLOPS_PEEK); 1844 } 1845 1846 void 1847 i_ddi_caut_rep_get16(ddi_acc_impl_t *hp, uint16_t *host_addr, 1848 uint16_t *dev_addr, size_t repcount, uint_t flags) 1849 { 1850 i_ddi_caut_getput_ctlops(hp, (uint64_t)host_addr, (uint64_t)dev_addr, 1851 sizeof (uint16_t), repcount, flags, DDI_CTLOPS_PEEK); 1852 } 1853 1854 void 1855 i_ddi_caut_rep_get32(ddi_acc_impl_t *hp, uint32_t *host_addr, 1856 uint32_t *dev_addr, size_t repcount, uint_t flags) 1857 { 1858 i_ddi_caut_getput_ctlops(hp, (uint64_t)host_addr, (uint64_t)dev_addr, 1859 sizeof (uint32_t), repcount, flags, DDI_CTLOPS_PEEK); 1860 } 1861 1862 void 1863 i_ddi_caut_rep_get64(ddi_acc_impl_t *hp, uint64_t *host_addr, 1864 uint64_t *dev_addr, size_t repcount, uint_t flags) 1865 { 1866 i_ddi_caut_getput_ctlops(hp, (uint64_t)host_addr, (uint64_t)dev_addr, 1867 sizeof (uint64_t), repcount, flags, DDI_CTLOPS_PEEK); 1868 } 1869 1870 void 1871 i_ddi_caut_rep_put8(ddi_acc_impl_t *hp, uint8_t *host_addr, uint8_t *dev_addr, 1872 size_t repcount, uint_t flags) 1873 { 1874 i_ddi_caut_getput_ctlops(hp, (uint64_t)host_addr, (uint64_t)dev_addr, 1875 sizeof (uint8_t), repcount, flags, DDI_CTLOPS_POKE); 1876 } 1877 1878 void 1879 i_ddi_caut_rep_put16(ddi_acc_impl_t *hp, uint16_t *host_addr, 1880 uint16_t *dev_addr, size_t repcount, uint_t flags) 1881 { 1882 i_ddi_caut_getput_ctlops(hp, (uint64_t)host_addr, (uint64_t)dev_addr, 1883 sizeof (uint16_t), repcount, flags, DDI_CTLOPS_POKE); 1884 } 1885 1886 void 1887 i_ddi_caut_rep_put32(ddi_acc_impl_t *hp, uint32_t *host_addr, 1888 uint32_t *dev_addr, size_t repcount, uint_t flags) 1889 { 1890 i_ddi_caut_getput_ctlops(hp, (uint64_t)host_addr, (uint64_t)dev_addr, 1891 sizeof (uint32_t), repcount, flags, DDI_CTLOPS_POKE); 1892 } 1893 1894 void 1895 i_ddi_caut_rep_put64(ddi_acc_impl_t *hp, uint64_t *host_addr, 1896 uint64_t *dev_addr, size_t repcount, uint_t flags) 1897 { 1898 i_ddi_caut_getput_ctlops(hp, (uint64_t)host_addr, (uint64_t)dev_addr, 1899 sizeof (uint64_t), repcount, flags, DDI_CTLOPS_POKE); 1900 } 1901 1902 /* 1903 * This is called only to process peek/poke when the DIP is NULL. 1904 * Assume that this is for memory, as nexi take care of device safe accesses. 1905 */ 1906 int 1907 peekpoke_mem(ddi_ctl_enum_t cmd, peekpoke_ctlops_t *in_args) 1908 { 1909 int err = DDI_SUCCESS; 1910 on_trap_data_t otd; 1911 1912 /* Set up protected environment. */ 1913 if (!on_trap(&otd, OT_DATA_ACCESS)) { 1914 uintptr_t tramp = otd.ot_trampoline; 1915 1916 if (cmd == DDI_CTLOPS_POKE) { 1917 otd.ot_trampoline = (uintptr_t)&poke_fault; 1918 err = do_poke(in_args->size, (void *)in_args->dev_addr, 1919 (void *)in_args->host_addr); 1920 } else { 1921 otd.ot_trampoline = (uintptr_t)&peek_fault; 1922 err = do_peek(in_args->size, (void *)in_args->dev_addr, 1923 (void *)in_args->host_addr); 1924 } 1925 otd.ot_trampoline = tramp; 1926 } else 1927 err = DDI_FAILURE; 1928 1929 /* Take down protected environment. */ 1930 no_trap(); 1931 1932 return (err); 1933 } 1934