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