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 /* 23 * Copyright 2006 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_intr_handle_impl_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 * get_intr_parent() is a generic routine that process a 1275 interrupt 398 * map (imap) property. This function returns a dev_info_t structure 399 * which claims ownership of the interrupt domain. 400 * It also returns the new interrupt translation within this new domain. 401 * If an interrupt-parent or interrupt-map property are not found, 402 * then we fallback to using the device tree's parent. 403 * 404 * imap entry format: 405 * <reg>,<interrupt>,<phandle>,<translated interrupt> 406 * reg - The register specification in the interrupts domain 407 * interrupt - The interrupt specification 408 * phandle - PROM handle of the device that owns the xlated interrupt domain 409 * translated interrupt - interrupt specifier in the parents domain 410 * note: <reg>,<interrupt> - The reg and interrupt can be combined to create 411 * a unique entry called a unit interrupt specifier. 412 * 413 * Here's the processing steps: 414 * step1 - If the interrupt-parent property exists, create the ispec and 415 * return the dip of the interrupt parent. 416 * step2 - Extract the interrupt-map property and the interrupt-map-mask 417 * If these don't exist, just return the device tree parent. 418 * step3 - build up the unit interrupt specifier to match against the 419 * interrupt map property 420 * step4 - Scan the interrupt-map property until a match is found 421 * step4a - Extract the interrupt parent 422 * step4b - Compare the unit interrupt specifier 423 */ 424 dev_info_t * 425 get_intr_parent(dev_info_t *pdip, dev_info_t *dip, ddi_intr_handle_impl_t *hdlp) 426 { 427 prop_1275_cell_t *imap, *imap_mask, *scan, *reg_p, *match_req; 428 int32_t imap_sz, imap_cells, imap_scan_cells, imap_mask_sz, 429 addr_cells, intr_cells, reg_len, i, j; 430 int32_t match_found = 0; 431 dev_info_t *intr_parent_dip = NULL; 432 uint32_t *intr = &hdlp->ih_vector; 433 uint32_t nodeid; 434 #ifdef DEBUG 435 static int debug = 0; 436 #endif 437 438 /* 439 * step1 440 * If we have an interrupt-parent property, this property represents 441 * the nodeid of our interrupt parent. 442 */ 443 if ((nodeid = ddi_getprop(DDI_DEV_T_ANY, dip, 0, 444 "interrupt-parent", -1)) != -1) { 445 intr_parent_dip = e_ddi_nodeid_to_dip(nodeid); 446 ASSERT(intr_parent_dip); 447 448 /* 449 * Attach the interrupt parent. 450 * 451 * N.B. e_ddi_nodeid_to_dip() isn't safe under DR. 452 * Also, interrupt parent isn't held. This needs 453 * to be revisited if DR-capable platforms implement 454 * interrupt redirection. 455 */ 456 if (i_ddi_attach_node_hierarchy(intr_parent_dip) 457 != DDI_SUCCESS) { 458 ndi_rele_devi(intr_parent_dip); 459 return (NULL); 460 } 461 462 return (intr_parent_dip); 463 } 464 465 /* 466 * step2 467 * Get interrupt map structure from PROM property 468 */ 469 if (ddi_getlongprop(DDI_DEV_T_ANY, pdip, DDI_PROP_DONTPASS, 470 "interrupt-map", (caddr_t)&imap, &imap_sz) 471 != DDI_PROP_SUCCESS) { 472 /* 473 * If we don't have an imap property, default to using the 474 * device tree. 475 */ 476 477 ndi_hold_devi(pdip); 478 return (pdip); 479 } 480 481 /* Get the interrupt mask property */ 482 if (ddi_getlongprop(DDI_DEV_T_ANY, pdip, DDI_PROP_DONTPASS, 483 "interrupt-map-mask", (caddr_t)&imap_mask, &imap_mask_sz) 484 != DDI_PROP_SUCCESS) { 485 /* 486 * If we don't find this property, we have to fail the request 487 * because the 1275 imap property wasn't defined correctly. 488 */ 489 ASSERT(intr_parent_dip == NULL); 490 goto exit2; 491 } 492 493 /* Get the address cell size */ 494 addr_cells = ddi_getprop(DDI_DEV_T_ANY, pdip, 0, 495 "#address-cells", 2); 496 497 /* Get the interrupts cell size */ 498 intr_cells = ddi_getprop(DDI_DEV_T_ANY, pdip, 0, 499 "#interrupt-cells", 1); 500 501 /* 502 * step3 503 * Now lets build up the unit interrupt specifier e.g. reg,intr 504 * and apply the imap mask. match_req will hold this when we're 505 * through. 506 */ 507 if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "reg", 508 (caddr_t)®_p, ®_len) != DDI_SUCCESS) { 509 ASSERT(intr_parent_dip == NULL); 510 goto exit3; 511 } 512 513 match_req = kmem_alloc(CELLS_1275_TO_BYTES(addr_cells) + 514 CELLS_1275_TO_BYTES(intr_cells), KM_SLEEP); 515 516 for (i = 0; i < addr_cells; i++) 517 match_req[i] = (reg_p[i] & imap_mask[i]); 518 519 for (j = 0; j < intr_cells; i++, j++) 520 match_req[i] = (intr[j] & imap_mask[i]); 521 522 /* Calculate the imap size in cells */ 523 imap_cells = BYTES_TO_1275_CELLS(imap_sz); 524 525 #ifdef DEBUG 526 if (debug) 527 prom_printf("reg cell size 0x%x, intr cell size 0x%x, " 528 "match_request 0x%p, imap 0x%p\n", addr_cells, intr_cells, 529 match_req, imap); 530 #endif 531 532 /* 533 * Scan the imap property looking for a match of the interrupt unit 534 * specifier. This loop is rather complex since the data within the 535 * imap property may vary in size. 536 */ 537 for (scan = imap, imap_scan_cells = i = 0; 538 imap_scan_cells < imap_cells; scan += i, imap_scan_cells += i) { 539 int new_intr_cells; 540 541 /* Set the index to the nodeid field */ 542 i = addr_cells + intr_cells; 543 544 /* 545 * step4a 546 * Translate the nodeid field to a dip 547 */ 548 ASSERT(intr_parent_dip == NULL); 549 intr_parent_dip = e_ddi_nodeid_to_dip((uint_t)scan[i++]); 550 551 ASSERT(intr_parent_dip != 0); 552 #ifdef DEBUG 553 if (debug) 554 prom_printf("scan 0x%p\n", scan); 555 #endif 556 /* 557 * The tmp_dip describes the new domain, get it's interrupt 558 * cell size 559 */ 560 new_intr_cells = ddi_getprop(DDI_DEV_T_ANY, intr_parent_dip, 0, 561 "#interrupts-cells", 1); 562 563 /* 564 * step4b 565 * See if we have a match on the interrupt unit specifier 566 */ 567 if (cells_1275_cmp(match_req, scan, addr_cells + intr_cells) 568 == 0) { 569 uint32_t *intr; 570 571 match_found = 1; 572 573 /* 574 * If we have an imap parent whose not in our device 575 * tree path, we need to hold and install that driver. 576 */ 577 if (i_ddi_attach_node_hierarchy(intr_parent_dip) 578 != DDI_SUCCESS) { 579 ndi_rele_devi(intr_parent_dip); 580 intr_parent_dip = (dev_info_t *)NULL; 581 goto exit4; 582 } 583 584 /* 585 * We need to handcraft an ispec along with a bus 586 * interrupt value, so we can dup it into our 587 * standard ispec structure. 588 */ 589 /* Extract the translated interrupt information */ 590 intr = kmem_alloc( 591 CELLS_1275_TO_BYTES(new_intr_cells), KM_SLEEP); 592 593 for (j = 0; j < new_intr_cells; j++, i++) 594 intr[j] = scan[i]; 595 596 cells_1275_copy(intr, &hdlp->ih_vector, new_intr_cells); 597 598 kmem_free(intr, CELLS_1275_TO_BYTES(new_intr_cells)); 599 600 #ifdef DEBUG 601 if (debug) 602 prom_printf("dip 0x%p\n", intr_parent_dip); 603 #endif 604 break; 605 } else { 606 #ifdef DEBUG 607 if (debug) 608 prom_printf("dip 0x%p\n", intr_parent_dip); 609 #endif 610 ndi_rele_devi(intr_parent_dip); 611 intr_parent_dip = NULL; 612 i += new_intr_cells; 613 } 614 } 615 616 /* 617 * If we haven't found our interrupt parent at this point, fallback 618 * to using the device tree. 619 */ 620 if (!match_found) { 621 ndi_hold_devi(pdip); 622 ASSERT(intr_parent_dip == NULL); 623 intr_parent_dip = pdip; 624 } 625 626 ASSERT(intr_parent_dip != NULL); 627 628 exit4: 629 kmem_free(reg_p, reg_len); 630 kmem_free(match_req, CELLS_1275_TO_BYTES(addr_cells) + 631 CELLS_1275_TO_BYTES(intr_cells)); 632 633 exit3: 634 kmem_free(imap_mask, imap_mask_sz); 635 636 exit2: 637 kmem_free(imap, imap_sz); 638 639 return (intr_parent_dip); 640 } 641 642 /* 643 * process_intr_ops: 644 * 645 * Process the interrupt op via the interrupt parent. 646 */ 647 int 648 process_intr_ops(dev_info_t *pdip, dev_info_t *rdip, ddi_intr_op_t op, 649 ddi_intr_handle_impl_t *hdlp, void *result) 650 { 651 int ret = DDI_FAILURE; 652 653 if (NEXUS_HAS_INTR_OP(pdip)) { 654 ret = (*(DEVI(pdip)->devi_ops->devo_bus_ops-> 655 bus_intr_op)) (pdip, rdip, op, hdlp, result); 656 } else { 657 cmn_err(CE_WARN, "Failed to process interrupt " 658 "for %s%d due to down-rev nexus driver %s%d", 659 ddi_get_name(rdip), ddi_get_instance(rdip), 660 ddi_get_name(pdip), ddi_get_instance(pdip)); 661 } 662 663 return (ret); 664 } 665 666 /*ARGSUSED*/ 667 uint_t 668 softlevel1(caddr_t arg) 669 { 670 softint(); 671 return (1); 672 } 673 674 /* 675 * indirection table, to save us some large switch statements 676 * NOTE: This must agree with "INTLEVEL_foo" constants in 677 * <sys/avintr.h> 678 */ 679 struct autovec *const vectorlist[] = { 0 }; 680 681 /* 682 * This value is exported here for the functions in avintr.c 683 */ 684 const uint_t maxautovec = (sizeof (vectorlist) / sizeof (vectorlist[0])); 685 686 /* 687 * Check for machine specific interrupt levels which cannot be reassigned by 688 * settrap(), sun4u version. 689 * 690 * sun4u does not support V8 SPARC "fast trap" handlers. 691 */ 692 /*ARGSUSED*/ 693 int 694 exclude_settrap(int lvl) 695 { 696 return (1); 697 } 698 699 /* 700 * Check for machine specific interrupt levels which cannot have interrupt 701 * handlers added. We allow levels 1 through 15; level 0 is nonsense. 702 */ 703 /*ARGSUSED*/ 704 int 705 exclude_level(int lvl) 706 { 707 return ((lvl < 1) || (lvl > 15)); 708 } 709 710 /* 711 * Wrapper functions used by New DDI interrupt framework. 712 */ 713 714 /* 715 * i_ddi_intr_ops: 716 */ 717 int 718 i_ddi_intr_ops(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t op, 719 ddi_intr_handle_impl_t *hdlp, void *result) 720 { 721 dev_info_t *pdip = ddi_get_parent(dip); 722 int ret = DDI_FAILURE; 723 724 /* 725 * The following check is required to address 726 * one of the test case of ADDI test suite. 727 */ 728 if (pdip == NULL) 729 return (DDI_FAILURE); 730 731 if (hdlp->ih_type != DDI_INTR_TYPE_FIXED) 732 return (process_intr_ops(pdip, rdip, op, hdlp, result)); 733 734 if (hdlp->ih_vector == 0) 735 hdlp->ih_vector = i_ddi_get_inum(rdip, hdlp->ih_inum); 736 737 if (hdlp->ih_pri == 0) 738 hdlp->ih_pri = i_ddi_get_intr_pri(rdip, hdlp->ih_inum); 739 740 switch (op) { 741 case DDI_INTROP_ADDISR: 742 case DDI_INTROP_REMISR: 743 case DDI_INTROP_ENABLE: 744 case DDI_INTROP_DISABLE: 745 case DDI_INTROP_BLOCKENABLE: 746 case DDI_INTROP_BLOCKDISABLE: 747 /* 748 * Try and determine our parent and possibly an interrupt 749 * translation. intr parent dip returned held 750 */ 751 if ((pdip = get_intr_parent(pdip, dip, hdlp)) == NULL) 752 goto done; 753 } 754 755 ret = process_intr_ops(pdip, rdip, op, hdlp, result); 756 757 done: 758 switch (op) { 759 case DDI_INTROP_ADDISR: 760 case DDI_INTROP_REMISR: 761 case DDI_INTROP_ENABLE: 762 case DDI_INTROP_DISABLE: 763 case DDI_INTROP_BLOCKENABLE: 764 case DDI_INTROP_BLOCKDISABLE: 765 /* Release hold acquired in get_intr_parent() */ 766 if (pdip) 767 ndi_rele_devi(pdip); 768 } 769 770 hdlp->ih_vector = 0; 771 772 return (ret); 773 } 774 775 /* 776 * i_ddi_add_ivintr: 777 */ 778 /*ARGSUSED*/ 779 int 780 i_ddi_add_ivintr(ddi_intr_handle_impl_t *hdlp) 781 { 782 /* Sanity check the entry we're about to add */ 783 if (GET_IVINTR(hdlp->ih_vector)) { 784 cmn_err(CE_WARN, "mondo 0x%x in use", hdlp->ih_vector); 785 return (DDI_FAILURE); 786 } 787 788 /* 789 * If the PIL was set and is valid use it, otherwise 790 * default it to 1 791 */ 792 if ((hdlp->ih_pri < 1) || (hdlp->ih_pri > PIL_MAX)) 793 hdlp->ih_pri = 1; 794 795 VERIFY(add_ivintr(hdlp->ih_vector, hdlp->ih_pri, 796 (intrfunc)hdlp->ih_cb_func, hdlp->ih_cb_arg1, NULL) == 0); 797 798 return (DDI_SUCCESS); 799 } 800 801 /* 802 * i_ddi_rem_ivintr: 803 */ 804 /*ARGSUSED*/ 805 void 806 i_ddi_rem_ivintr(ddi_intr_handle_impl_t *hdlp) 807 { 808 rem_ivintr(hdlp->ih_vector, NULL); 809 } 810 811 /* 812 * i_ddi_get_inum - Get the interrupt number property from the 813 * specified device. Note that this function is called only for 814 * the FIXED interrupt type. 815 */ 816 uint32_t 817 i_ddi_get_inum(dev_info_t *dip, uint_t inumber) 818 { 819 int32_t intrlen, intr_cells, max_intrs; 820 prop_1275_cell_t *ip, intr_sz; 821 uint32_t intr = 0; 822 823 if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS | 824 DDI_PROP_CANSLEEP, 825 "interrupts", (caddr_t)&ip, &intrlen) == DDI_SUCCESS) { 826 827 intr_cells = ddi_getprop(DDI_DEV_T_ANY, dip, 0, 828 "#interrupt-cells", 1); 829 830 /* adjust for number of bytes */ 831 intr_sz = CELLS_1275_TO_BYTES(intr_cells); 832 833 /* Calculate the number of interrupts */ 834 max_intrs = intrlen / intr_sz; 835 836 if (inumber < max_intrs) { 837 prop_1275_cell_t *intrp = ip; 838 839 /* Index into interrupt property */ 840 intrp += (inumber * intr_cells); 841 842 cells_1275_copy(intrp, &intr, intr_cells); 843 } 844 845 kmem_free(ip, intrlen); 846 } 847 848 return (intr); 849 } 850 851 /* 852 * i_ddi_get_intr_pri - Get the interrupt-priorities property from 853 * the specified device. Note that this function is called only for 854 * the FIXED interrupt type. 855 */ 856 uint32_t 857 i_ddi_get_intr_pri(dev_info_t *dip, uint_t inumber) 858 { 859 uint32_t *intr_prio_p; 860 uint32_t pri = 0; 861 int32_t i; 862 863 /* 864 * Use the "interrupt-priorities" property to determine the 865 * the pil/ipl for the interrupt handler. 866 */ 867 if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 868 "interrupt-priorities", (caddr_t)&intr_prio_p, 869 &i) == DDI_SUCCESS) { 870 if (inumber < (i / sizeof (int32_t))) 871 pri = intr_prio_p[inumber]; 872 kmem_free(intr_prio_p, i); 873 } 874 875 return (pri); 876 } 877 878 int 879 i_ddi_get_nintrs(dev_info_t *dip) 880 { 881 int32_t intrlen; 882 prop_1275_cell_t intr_sz; 883 prop_1275_cell_t *ip; 884 int32_t ret = 0; 885 886 if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS | 887 DDI_PROP_CANSLEEP, 888 "interrupts", (caddr_t)&ip, &intrlen) == DDI_SUCCESS) { 889 890 intr_sz = ddi_getprop(DDI_DEV_T_ANY, dip, 0, 891 "#interrupt-cells", 1); 892 /* adjust for number of bytes */ 893 intr_sz = CELLS_1275_TO_BYTES(intr_sz); 894 895 ret = intrlen / intr_sz; 896 897 kmem_free(ip, intrlen); 898 } 899 900 return (ret); 901 } 902 903 /* 904 * i_ddi_add_softint - allocate and add a soft interrupt to the system 905 */ 906 int 907 i_ddi_add_softint(ddi_softint_hdl_impl_t *hdlp) 908 { 909 uint_t rval; 910 911 if ((rval = add_softintr(hdlp->ih_pri, hdlp->ih_cb_func, 912 hdlp->ih_cb_arg1)) == 0) { 913 914 return (DDI_FAILURE); 915 } 916 917 /* use uintptr_t to suppress the gcc warning */ 918 hdlp->ih_private = (void *)(uintptr_t)rval; 919 920 return (DDI_SUCCESS); 921 } 922 923 void 924 i_ddi_remove_softint(ddi_softint_hdl_impl_t *hdlp) 925 { 926 uint_t intr_id; 927 928 /* disable */ 929 ASSERT(hdlp->ih_private != NULL); 930 931 /* use uintptr_t to suppress the gcc warning */ 932 intr_id = (uint_t)(uintptr_t)hdlp->ih_private; 933 934 rem_softintr(intr_id); 935 hdlp->ih_private = NULL; 936 } 937 938 int 939 i_ddi_trigger_softint(ddi_softint_hdl_impl_t *hdlp, void *arg2) 940 { 941 uint_t intr_id; 942 int ret; 943 944 ASSERT(hdlp != NULL); 945 ASSERT(hdlp->ih_private != NULL); 946 947 /* use uintptr_t to suppress the gcc warning */ 948 intr_id = (uint_t)(uintptr_t)hdlp->ih_private; 949 950 /* update the vector table for the 2nd arg */ 951 ret = update_softint_arg2(intr_id, arg2); 952 if (ret == DDI_SUCCESS) 953 setsoftint(intr_id); 954 955 return (ret); 956 } 957 958 /* ARGSUSED */ 959 int 960 i_ddi_set_softint_pri(ddi_softint_hdl_impl_t *hdlp, uint_t old_pri) 961 { 962 uint_t intr_id; 963 int ret; 964 965 ASSERT(hdlp != NULL); 966 ASSERT(hdlp->ih_private != NULL); 967 968 /* use uintptr_t to suppress the gcc warning */ 969 intr_id = (uint_t)(uintptr_t)hdlp->ih_private; 970 971 /* update the vector table for the new priority */ 972 ret = update_softint_pri(intr_id, hdlp->ih_pri); 973 974 return (ret); 975 } 976 977 /*ARGSUSED*/ 978 void 979 i_ddi_alloc_intr_phdl(ddi_intr_handle_impl_t *hdlp) 980 { 981 } 982 983 /*ARGSUSED*/ 984 void 985 i_ddi_free_intr_phdl(ddi_intr_handle_impl_t *hdlp) 986 { 987 } 988 989 /* 990 * SECTION: DDI Memory/DMA 991 */ 992 993 /* 994 * Check if the endianess attribute is supported on the platform. 995 * This function must be called before i_ddi_devacc_to_hatacc(). 996 */ 997 boolean_t 998 i_ddi_check_endian_attr(ddi_device_acc_attr_t *devaccp) 999 { 1000 #if defined(lint) 1001 *devaccp = *devaccp; 1002 #endif 1003 /* 1004 * All kinds of endianess is supported on SPARC. 1005 */ 1006 return (B_TRUE); 1007 } 1008 1009 /* set HAT endianess attributes from ddi_device_acc_attr */ 1010 void 1011 i_ddi_devacc_to_hatacc(ddi_device_acc_attr_t *devaccp, uint_t *hataccp) 1012 { 1013 if (devaccp != NULL) { 1014 if (devaccp->devacc_attr_endian_flags == DDI_STRUCTURE_LE_ACC) { 1015 *hataccp &= ~HAT_ENDIAN_MASK; 1016 *hataccp |= HAT_STRUCTURE_LE; 1017 } 1018 } 1019 } 1020 1021 /* 1022 * Check if the specified cache attribute is supported on the platform. 1023 * This function must be called before i_ddi_cacheattr_to_hatacc(). 1024 */ 1025 boolean_t 1026 i_ddi_check_cache_attr(uint_t flags) 1027 { 1028 /* 1029 * The cache attributes are mutually exclusive. Any combination of 1030 * the attributes leads to a failure. 1031 */ 1032 uint_t cache_attr = IOMEM_CACHE_ATTR(flags); 1033 if ((cache_attr != 0) && ((cache_attr & (cache_attr - 1)) != 0)) 1034 return (B_FALSE); 1035 1036 /* 1037 * On the sparc architecture, only IOMEM_DATA_CACHED is meaningful, 1038 * but others lead to a failure. 1039 */ 1040 if (cache_attr & IOMEM_DATA_CACHED) 1041 return (B_TRUE); 1042 else 1043 return (B_FALSE); 1044 } 1045 1046 /* set HAT cache attributes from the cache attributes */ 1047 void 1048 i_ddi_cacheattr_to_hatacc(uint_t flags, uint_t *hataccp) 1049 { 1050 uint_t cache_attr = IOMEM_CACHE_ATTR(flags); 1051 static char *fname = "i_ddi_cacheattr_to_hatacc"; 1052 #if defined(lint) 1053 *hataccp = *hataccp; 1054 #endif 1055 /* 1056 * set HAT attrs according to the cache attrs. 1057 */ 1058 switch (cache_attr) { 1059 /* 1060 * The cache coherency is always maintained on SPARC, and 1061 * nothing is required. 1062 */ 1063 case IOMEM_DATA_CACHED: 1064 break; 1065 /* 1066 * Both IOMEM_DATA_UC_WRITE_COMBINED and IOMEM_DATA_UNCACHED are 1067 * not supported on SPARC -- this case must not occur because the 1068 * cache attribute is scrutinized before this function is called. 1069 */ 1070 case IOMEM_DATA_UNCACHED: 1071 case IOMEM_DATA_UC_WR_COMBINE: 1072 default: 1073 cmn_err(CE_WARN, "%s: cache_attr=0x%x is ignored.", 1074 fname, cache_attr); 1075 } 1076 } 1077 1078 static vmem_t *little_endian_arena; 1079 static vmem_t *big_endian_arena; 1080 1081 static void * 1082 segkmem_alloc_le(vmem_t *vmp, size_t size, int flag) 1083 { 1084 return (segkmem_xalloc(vmp, NULL, size, flag, HAT_STRUCTURE_LE, 1085 segkmem_page_create, NULL)); 1086 } 1087 1088 static void * 1089 segkmem_alloc_be(vmem_t *vmp, size_t size, int flag) 1090 { 1091 return (segkmem_xalloc(vmp, NULL, size, flag, HAT_STRUCTURE_BE, 1092 segkmem_page_create, NULL)); 1093 } 1094 1095 void 1096 ka_init(void) 1097 { 1098 little_endian_arena = vmem_create("little_endian", NULL, 0, 1, 1099 segkmem_alloc_le, segkmem_free, heap_arena, 0, VM_SLEEP); 1100 big_endian_arena = vmem_create("big_endian", NULL, 0, 1, 1101 segkmem_alloc_be, segkmem_free, heap_arena, 0, VM_SLEEP); 1102 } 1103 1104 /* 1105 * Allocate from the system, aligned on a specific boundary. 1106 * The alignment, if non-zero, must be a power of 2. 1107 */ 1108 static void * 1109 kalloca(size_t size, size_t align, int cansleep, uint_t endian_flags) 1110 { 1111 size_t *addr, *raddr, rsize; 1112 size_t hdrsize = 4 * sizeof (size_t); /* must be power of 2 */ 1113 1114 align = MAX(align, hdrsize); 1115 ASSERT((align & (align - 1)) == 0); 1116 1117 /* 1118 * We need to allocate 1119 * rsize = size + hdrsize + align - MIN(hdrsize, buffer_alignment) 1120 * bytes to be sure we have enough freedom to satisfy the request. 1121 * Since the buffer alignment depends on the request size, this is 1122 * not straightforward to use directly. 1123 * 1124 * kmem guarantees that any allocation of a 64-byte multiple will be 1125 * 64-byte aligned. Since rounding up the request could add more 1126 * than we save, we compute the size with and without alignment, and 1127 * use the smaller of the two. 1128 */ 1129 rsize = size + hdrsize + align; 1130 1131 if (endian_flags == DDI_STRUCTURE_LE_ACC) { 1132 raddr = vmem_alloc(little_endian_arena, rsize, 1133 cansleep ? VM_SLEEP : VM_NOSLEEP); 1134 } else { 1135 raddr = vmem_alloc(big_endian_arena, rsize, 1136 cansleep ? VM_SLEEP : VM_NOSLEEP); 1137 } 1138 1139 if (raddr == NULL) 1140 return (NULL); 1141 1142 addr = (size_t *)P2ROUNDUP((uintptr_t)raddr + hdrsize, align); 1143 ASSERT((uintptr_t)addr + size - (uintptr_t)raddr <= rsize); 1144 1145 addr[-3] = (size_t)endian_flags; 1146 addr[-2] = (size_t)raddr; 1147 addr[-1] = rsize; 1148 1149 return (addr); 1150 } 1151 1152 static void 1153 kfreea(void *addr) 1154 { 1155 size_t *saddr = addr; 1156 1157 if (saddr[-3] == DDI_STRUCTURE_LE_ACC) 1158 vmem_free(little_endian_arena, (void *)saddr[-2], saddr[-1]); 1159 else 1160 vmem_free(big_endian_arena, (void *)saddr[-2], saddr[-1]); 1161 } 1162 1163 int 1164 i_ddi_mem_alloc(dev_info_t *dip, ddi_dma_attr_t *attr, 1165 size_t length, int cansleep, int flags, 1166 ddi_device_acc_attr_t *accattrp, 1167 caddr_t *kaddrp, size_t *real_length, ddi_acc_hdl_t *handlep) 1168 { 1169 caddr_t a; 1170 int iomin, align, streaming; 1171 uint_t endian_flags = DDI_NEVERSWAP_ACC; 1172 1173 #if defined(lint) 1174 *handlep = *handlep; 1175 #endif 1176 1177 /* 1178 * Check legality of arguments 1179 */ 1180 if (length == 0 || kaddrp == NULL || attr == NULL) { 1181 return (DDI_FAILURE); 1182 } 1183 1184 if (attr->dma_attr_minxfer == 0 || attr->dma_attr_align == 0 || 1185 (attr->dma_attr_align & (attr->dma_attr_align - 1)) || 1186 (attr->dma_attr_minxfer & (attr->dma_attr_minxfer - 1))) { 1187 return (DDI_FAILURE); 1188 } 1189 1190 /* 1191 * check if a streaming sequential xfer is requested. 1192 */ 1193 streaming = (flags & DDI_DMA_STREAMING) ? 1 : 0; 1194 1195 /* 1196 * Drivers for 64-bit capable SBus devices will encode 1197 * the burtsizes for 64-bit xfers in the upper 16-bits. 1198 * For DMA alignment, we use the most restrictive 1199 * alignment of 32-bit and 64-bit xfers. 1200 */ 1201 iomin = (attr->dma_attr_burstsizes & 0xffff) | 1202 ((attr->dma_attr_burstsizes >> 16) & 0xffff); 1203 /* 1204 * If a driver set burtsizes to 0, we give him byte alignment. 1205 * Otherwise align at the burtsizes boundary. 1206 */ 1207 if (iomin == 0) 1208 iomin = 1; 1209 else 1210 iomin = 1 << (ddi_fls(iomin) - 1); 1211 iomin = maxbit(iomin, attr->dma_attr_minxfer); 1212 iomin = maxbit(iomin, attr->dma_attr_align); 1213 iomin = ddi_iomin(dip, iomin, streaming); 1214 if (iomin == 0) 1215 return (DDI_FAILURE); 1216 1217 ASSERT((iomin & (iomin - 1)) == 0); 1218 ASSERT(iomin >= attr->dma_attr_minxfer); 1219 ASSERT(iomin >= attr->dma_attr_align); 1220 1221 length = P2ROUNDUP(length, iomin); 1222 align = iomin; 1223 1224 if (accattrp != NULL) 1225 endian_flags = accattrp->devacc_attr_endian_flags; 1226 1227 a = kalloca(length, align, cansleep, endian_flags); 1228 if ((*kaddrp = a) == 0) { 1229 return (DDI_FAILURE); 1230 } else { 1231 if (real_length) { 1232 *real_length = length; 1233 } 1234 if (handlep) { 1235 /* 1236 * assign handle information 1237 */ 1238 impl_acc_hdl_init(handlep); 1239 } 1240 return (DDI_SUCCESS); 1241 } 1242 } 1243 1244 /* 1245 * covert old DMA limits structure to DMA attribute structure 1246 * and continue 1247 */ 1248 int 1249 i_ddi_mem_alloc_lim(dev_info_t *dip, ddi_dma_lim_t *limits, 1250 size_t length, int cansleep, int streaming, 1251 ddi_device_acc_attr_t *accattrp, caddr_t *kaddrp, 1252 uint_t *real_length, ddi_acc_hdl_t *ap) 1253 { 1254 ddi_dma_attr_t dma_attr, *attrp; 1255 size_t rlen; 1256 int ret; 1257 1258 ASSERT(limits); 1259 attrp = &dma_attr; 1260 attrp->dma_attr_version = DMA_ATTR_V0; 1261 attrp->dma_attr_addr_lo = (uint64_t)limits->dlim_addr_lo; 1262 attrp->dma_attr_addr_hi = (uint64_t)limits->dlim_addr_hi; 1263 attrp->dma_attr_count_max = (uint64_t)-1; 1264 attrp->dma_attr_align = 1; 1265 attrp->dma_attr_burstsizes = (uint_t)limits->dlim_burstsizes; 1266 attrp->dma_attr_minxfer = (uint32_t)limits->dlim_minxfer; 1267 attrp->dma_attr_maxxfer = (uint64_t)-1; 1268 attrp->dma_attr_seg = (uint64_t)limits->dlim_cntr_max; 1269 attrp->dma_attr_sgllen = 1; 1270 attrp->dma_attr_granular = 1; 1271 attrp->dma_attr_flags = 0; 1272 1273 ret = i_ddi_mem_alloc(dip, attrp, length, cansleep, streaming, 1274 accattrp, kaddrp, &rlen, ap); 1275 if (ret == DDI_SUCCESS) { 1276 if (real_length) 1277 *real_length = (uint_t)rlen; 1278 } 1279 return (ret); 1280 } 1281 1282 /* ARGSUSED */ 1283 void 1284 i_ddi_mem_free(caddr_t kaddr, ddi_acc_hdl_t *ap) 1285 { 1286 kfreea(kaddr); 1287 } 1288 1289 /* 1290 * SECTION: DDI Data Access 1291 */ 1292 1293 static uintptr_t impl_acc_hdl_id = 0; 1294 1295 /* 1296 * access handle allocator 1297 */ 1298 ddi_acc_hdl_t * 1299 impl_acc_hdl_get(ddi_acc_handle_t hdl) 1300 { 1301 /* 1302 * Extract the access handle address from the DDI implemented 1303 * access handle 1304 */ 1305 return (&((ddi_acc_impl_t *)hdl)->ahi_common); 1306 } 1307 1308 ddi_acc_handle_t 1309 impl_acc_hdl_alloc(int (*waitfp)(caddr_t), caddr_t arg) 1310 { 1311 ddi_acc_impl_t *hp; 1312 on_trap_data_t *otp; 1313 int sleepflag; 1314 1315 sleepflag = ((waitfp == (int (*)())KM_SLEEP) ? KM_SLEEP : KM_NOSLEEP); 1316 1317 /* 1318 * Allocate and initialize the data access handle and error status. 1319 */ 1320 if ((hp = kmem_zalloc(sizeof (ddi_acc_impl_t), sleepflag)) == NULL) 1321 goto fail; 1322 if ((hp->ahi_err = (ndi_err_t *)kmem_zalloc( 1323 sizeof (ndi_err_t), sleepflag)) == NULL) { 1324 kmem_free(hp, sizeof (ddi_acc_impl_t)); 1325 goto fail; 1326 } 1327 if ((otp = (on_trap_data_t *)kmem_zalloc( 1328 sizeof (on_trap_data_t), sleepflag)) == NULL) { 1329 kmem_free(hp->ahi_err, sizeof (ndi_err_t)); 1330 kmem_free(hp, sizeof (ddi_acc_impl_t)); 1331 goto fail; 1332 } 1333 hp->ahi_err->err_ontrap = otp; 1334 hp->ahi_common.ah_platform_private = (void *)hp; 1335 1336 return ((ddi_acc_handle_t)hp); 1337 fail: 1338 if ((waitfp != (int (*)())KM_SLEEP) && 1339 (waitfp != (int (*)())KM_NOSLEEP)) 1340 ddi_set_callback(waitfp, arg, &impl_acc_hdl_id); 1341 return (NULL); 1342 } 1343 1344 void 1345 impl_acc_hdl_free(ddi_acc_handle_t handle) 1346 { 1347 ddi_acc_impl_t *hp; 1348 1349 /* 1350 * The supplied (ddi_acc_handle_t) is actually a (ddi_acc_impl_t *), 1351 * because that's what we allocated in impl_acc_hdl_alloc() above. 1352 */ 1353 hp = (ddi_acc_impl_t *)handle; 1354 if (hp) { 1355 kmem_free(hp->ahi_err->err_ontrap, sizeof (on_trap_data_t)); 1356 kmem_free(hp->ahi_err, sizeof (ndi_err_t)); 1357 kmem_free(hp, sizeof (ddi_acc_impl_t)); 1358 if (impl_acc_hdl_id) 1359 ddi_run_callback(&impl_acc_hdl_id); 1360 } 1361 } 1362 1363 #define PCI_GET_MP_PFN(mp, page_no) ((mp)->dmai_ndvmapages == 1 ? \ 1364 (pfn_t)(mp)->dmai_iopte:(((pfn_t *)(mp)->dmai_iopte)[page_no])) 1365 1366 /* 1367 * Function called after a dma fault occurred to find out whether the 1368 * fault address is associated with a driver that is able to handle faults 1369 * and recover from faults. 1370 */ 1371 /* ARGSUSED */ 1372 int 1373 impl_dma_check(dev_info_t *dip, const void *handle, const void *addr, 1374 const void *not_used) 1375 { 1376 ddi_dma_impl_t *mp = (ddi_dma_impl_t *)handle; 1377 pfn_t fault_pfn = mmu_btop(*(uint64_t *)addr); 1378 pfn_t comp_pfn; 1379 1380 /* 1381 * The driver has to set DDI_DMA_FLAGERR to recover from dma faults. 1382 */ 1383 int page; 1384 1385 ASSERT(mp); 1386 for (page = 0; page < mp->dmai_ndvmapages; page++) { 1387 comp_pfn = PCI_GET_MP_PFN(mp, page); 1388 if (fault_pfn == comp_pfn) 1389 return (DDI_FM_NONFATAL); 1390 } 1391 return (DDI_FM_UNKNOWN); 1392 } 1393 1394 /* 1395 * Function used to check if a given access handle owns the failing address. 1396 * Called by ndi_fmc_error, when we detect a PIO error. 1397 */ 1398 /* ARGSUSED */ 1399 static int 1400 impl_acc_check(dev_info_t *dip, const void *handle, const void *addr, 1401 const void *not_used) 1402 { 1403 pfn_t pfn, fault_pfn; 1404 ddi_acc_hdl_t *hp; 1405 1406 hp = impl_acc_hdl_get((ddi_acc_handle_t)handle); 1407 1408 ASSERT(hp); 1409 1410 if (addr != NULL) { 1411 pfn = hp->ah_pfn; 1412 fault_pfn = mmu_btop(*(uint64_t *)addr); 1413 if (fault_pfn >= pfn && fault_pfn < (pfn + hp->ah_pnum)) 1414 return (DDI_FM_NONFATAL); 1415 } 1416 return (DDI_FM_UNKNOWN); 1417 } 1418 1419 void 1420 impl_acc_err_init(ddi_acc_hdl_t *handlep) 1421 { 1422 int fmcap; 1423 ndi_err_t *errp; 1424 on_trap_data_t *otp; 1425 ddi_acc_impl_t *hp = (ddi_acc_impl_t *)handlep; 1426 1427 fmcap = ddi_fm_capable(handlep->ah_dip); 1428 1429 if (handlep->ah_acc.devacc_attr_version < DDI_DEVICE_ATTR_V1 || 1430 !DDI_FM_ACC_ERR_CAP(fmcap)) { 1431 handlep->ah_acc.devacc_attr_access = DDI_DEFAULT_ACC; 1432 } else if (DDI_FM_ACC_ERR_CAP(fmcap)) { 1433 if (handlep->ah_acc.devacc_attr_access == DDI_DEFAULT_ACC) { 1434 i_ddi_drv_ereport_post(handlep->ah_dip, DVR_EFMCAP, 1435 NULL, DDI_NOSLEEP); 1436 } else { 1437 errp = hp->ahi_err; 1438 otp = (on_trap_data_t *)errp->err_ontrap; 1439 otp->ot_handle = (void *)(hp); 1440 otp->ot_prot = OT_DATA_ACCESS; 1441 if (handlep->ah_acc.devacc_attr_access == 1442 DDI_CAUTIOUS_ACC) 1443 otp->ot_trampoline = 1444 (uintptr_t)&i_ddi_caut_trampoline; 1445 else 1446 otp->ot_trampoline = 1447 (uintptr_t)&i_ddi_prot_trampoline; 1448 errp->err_status = DDI_FM_OK; 1449 errp->err_expected = DDI_FM_ERR_UNEXPECTED; 1450 errp->err_cf = impl_acc_check; 1451 } 1452 } 1453 } 1454 1455 void 1456 impl_acc_hdl_init(ddi_acc_hdl_t *handlep) 1457 { 1458 ddi_acc_impl_t *hp; 1459 1460 ASSERT(handlep); 1461 1462 hp = (ddi_acc_impl_t *)handlep; 1463 1464 /* 1465 * check for SW byte-swapping 1466 */ 1467 hp->ahi_get8 = i_ddi_get8; 1468 hp->ahi_put8 = i_ddi_put8; 1469 hp->ahi_rep_get8 = i_ddi_rep_get8; 1470 hp->ahi_rep_put8 = i_ddi_rep_put8; 1471 if (handlep->ah_acc.devacc_attr_endian_flags & DDI_STRUCTURE_LE_ACC) { 1472 hp->ahi_get16 = i_ddi_swap_get16; 1473 hp->ahi_get32 = i_ddi_swap_get32; 1474 hp->ahi_get64 = i_ddi_swap_get64; 1475 hp->ahi_put16 = i_ddi_swap_put16; 1476 hp->ahi_put32 = i_ddi_swap_put32; 1477 hp->ahi_put64 = i_ddi_swap_put64; 1478 hp->ahi_rep_get16 = i_ddi_swap_rep_get16; 1479 hp->ahi_rep_get32 = i_ddi_swap_rep_get32; 1480 hp->ahi_rep_get64 = i_ddi_swap_rep_get64; 1481 hp->ahi_rep_put16 = i_ddi_swap_rep_put16; 1482 hp->ahi_rep_put32 = i_ddi_swap_rep_put32; 1483 hp->ahi_rep_put64 = i_ddi_swap_rep_put64; 1484 } else { 1485 hp->ahi_get16 = i_ddi_get16; 1486 hp->ahi_get32 = i_ddi_get32; 1487 hp->ahi_get64 = i_ddi_get64; 1488 hp->ahi_put16 = i_ddi_put16; 1489 hp->ahi_put32 = i_ddi_put32; 1490 hp->ahi_put64 = i_ddi_put64; 1491 hp->ahi_rep_get16 = i_ddi_rep_get16; 1492 hp->ahi_rep_get32 = i_ddi_rep_get32; 1493 hp->ahi_rep_get64 = i_ddi_rep_get64; 1494 hp->ahi_rep_put16 = i_ddi_rep_put16; 1495 hp->ahi_rep_put32 = i_ddi_rep_put32; 1496 hp->ahi_rep_put64 = i_ddi_rep_put64; 1497 } 1498 1499 /* Legacy fault flags and support */ 1500 hp->ahi_fault_check = i_ddi_acc_fault_check; 1501 hp->ahi_fault_notify = i_ddi_acc_fault_notify; 1502 hp->ahi_fault = 0; 1503 impl_acc_err_init(handlep); 1504 } 1505 1506 void 1507 i_ddi_acc_set_fault(ddi_acc_handle_t handle) 1508 { 1509 ddi_acc_impl_t *hp = (ddi_acc_impl_t *)handle; 1510 1511 if (!hp->ahi_fault) { 1512 hp->ahi_fault = 1; 1513 (*hp->ahi_fault_notify)(hp); 1514 } 1515 } 1516 1517 void 1518 i_ddi_acc_clr_fault(ddi_acc_handle_t handle) 1519 { 1520 ddi_acc_impl_t *hp = (ddi_acc_impl_t *)handle; 1521 1522 if (hp->ahi_fault) { 1523 hp->ahi_fault = 0; 1524 (*hp->ahi_fault_notify)(hp); 1525 } 1526 } 1527 1528 /* ARGSUSED */ 1529 void 1530 i_ddi_acc_fault_notify(ddi_acc_impl_t *hp) 1531 { 1532 /* Default version, does nothing */ 1533 } 1534 1535 /* 1536 * SECTION: Misc functions 1537 */ 1538 1539 /* 1540 * instance wrappers 1541 */ 1542 /*ARGSUSED*/ 1543 uint_t 1544 impl_assign_instance(dev_info_t *dip) 1545 { 1546 return ((uint_t)-1); 1547 } 1548 1549 /*ARGSUSED*/ 1550 int 1551 impl_keep_instance(dev_info_t *dip) 1552 { 1553 return (DDI_FAILURE); 1554 } 1555 1556 /*ARGSUSED*/ 1557 int 1558 impl_free_instance(dev_info_t *dip) 1559 { 1560 return (DDI_FAILURE); 1561 } 1562 1563 /*ARGSUSED*/ 1564 int 1565 impl_check_cpu(dev_info_t *devi) 1566 { 1567 return (DDI_SUCCESS); 1568 } 1569 1570 1571 static const char *nocopydevs[] = { 1572 "SUNW,ffb", 1573 "SUNW,afb", 1574 NULL 1575 }; 1576 1577 /* 1578 * Perform a copy from a memory mapped device (whose devinfo pointer is devi) 1579 * separately mapped at devaddr in the kernel to a kernel buffer at kaddr. 1580 */ 1581 /*ARGSUSED*/ 1582 int 1583 e_ddi_copyfromdev(dev_info_t *devi, 1584 off_t off, const void *devaddr, void *kaddr, size_t len) 1585 { 1586 const char **argv; 1587 1588 for (argv = nocopydevs; *argv; argv++) 1589 if (strcmp(ddi_binding_name(devi), *argv) == 0) { 1590 bzero(kaddr, len); 1591 return (0); 1592 } 1593 1594 bcopy(devaddr, kaddr, len); 1595 return (0); 1596 } 1597 1598 /* 1599 * Perform a copy to a memory mapped device (whose devinfo pointer is devi) 1600 * separately mapped at devaddr in the kernel from a kernel buffer at kaddr. 1601 */ 1602 /*ARGSUSED*/ 1603 int 1604 e_ddi_copytodev(dev_info_t *devi, 1605 off_t off, const void *kaddr, void *devaddr, size_t len) 1606 { 1607 const char **argv; 1608 1609 for (argv = nocopydevs; *argv; argv++) 1610 if (strcmp(ddi_binding_name(devi), *argv) == 0) 1611 return (1); 1612 1613 bcopy(kaddr, devaddr, len); 1614 return (0); 1615 } 1616 1617 /* 1618 * Boot Configuration 1619 */ 1620 idprom_t idprom; 1621 1622 /* 1623 * Configure the hardware on the system. 1624 * Called before the rootfs is mounted 1625 */ 1626 void 1627 configure(void) 1628 { 1629 extern void i_ddi_init_root(); 1630 1631 /* We better have released boot by this time! */ 1632 ASSERT(!bootops); 1633 1634 /* 1635 * Determine whether or not to use the fpu, V9 SPARC cpus 1636 * always have one. Could check for existence of a fp queue, 1637 * Ultra I, II and IIa do not have a fp queue. 1638 */ 1639 if (fpu_exists) 1640 fpu_probe(); 1641 else 1642 cmn_err(CE_CONT, "FPU not in use\n"); 1643 1644 #if 0 /* XXXQ - not necessary for sun4u */ 1645 /* 1646 * This following line fixes bugid 1041296; we need to do a 1647 * prom_nextnode(0) because this call ALSO patches the DMA+ 1648 * bug in Campus-B and Phoenix. The prom uncaches the traptable 1649 * page as a side-effect of devr_next(0) (which prom_nextnode calls), 1650 * so this *must* be executed early on. (XXX This is untrue for sun4u) 1651 */ 1652 (void) prom_nextnode((pnode_t)0); 1653 #endif 1654 1655 /* 1656 * Initialize devices on the machine. 1657 * Uses configuration tree built by the PROMs to determine what 1658 * is present, and builds a tree of prototype dev_info nodes 1659 * corresponding to the hardware which identified itself. 1660 */ 1661 i_ddi_init_root(); 1662 1663 #ifdef DDI_PROP_DEBUG 1664 (void) ddi_prop_debug(1); /* Enable property debugging */ 1665 #endif /* DDI_PROP_DEBUG */ 1666 } 1667 1668 /* 1669 * The "status" property indicates the operational status of a device. 1670 * If this property is present, the value is a string indicating the 1671 * status of the device as follows: 1672 * 1673 * "okay" operational. 1674 * "disabled" not operational, but might become operational. 1675 * "fail" not operational because a fault has been detected, 1676 * and it is unlikely that the device will become 1677 * operational without repair. no additional details 1678 * are available. 1679 * "fail-xxx" not operational because a fault has been detected, 1680 * and it is unlikely that the device will become 1681 * operational without repair. "xxx" is additional 1682 * human-readable information about the particular 1683 * fault condition that was detected. 1684 * 1685 * The absence of this property means that the operational status is 1686 * unknown or okay. 1687 * 1688 * This routine checks the status property of the specified device node 1689 * and returns 0 if the operational status indicates failure, and 1 otherwise. 1690 * 1691 * The property may exist on plug-in cards the existed before IEEE 1275-1994. 1692 * And, in that case, the property may not even be a string. So we carefully 1693 * check for the value "fail", in the beginning of the string, noting 1694 * the property length. 1695 */ 1696 int 1697 status_okay(int id, char *buf, int buflen) 1698 { 1699 char status_buf[OBP_MAXPROPNAME]; 1700 char *bufp = buf; 1701 int len = buflen; 1702 int proplen; 1703 static const char *status = "status"; 1704 static const char *fail = "fail"; 1705 size_t fail_len = strlen(fail); 1706 1707 /* 1708 * Get the proplen ... if it's smaller than "fail", 1709 * or doesn't exist ... then we don't care, since 1710 * the value can't begin with the char string "fail". 1711 * 1712 * NB: proplen, if it's a string, includes the NULL in the 1713 * the size of the property, and fail_len does not. 1714 */ 1715 proplen = prom_getproplen((pnode_t)id, (caddr_t)status); 1716 if (proplen <= fail_len) /* nonexistent or uninteresting len */ 1717 return (1); 1718 1719 /* 1720 * if a buffer was provided, use it 1721 */ 1722 if ((buf == (char *)NULL) || (buflen <= 0)) { 1723 bufp = status_buf; 1724 len = sizeof (status_buf); 1725 } 1726 *bufp = (char)0; 1727 1728 /* 1729 * Get the property into the buffer, to the extent of the buffer, 1730 * and in case the buffer is smaller than the property size, 1731 * NULL terminate the buffer. (This handles the case where 1732 * a buffer was passed in and the caller wants to print the 1733 * value, but the buffer was too small). 1734 */ 1735 (void) prom_bounded_getprop((pnode_t)id, (caddr_t)status, 1736 (caddr_t)bufp, len); 1737 *(bufp + len - 1) = (char)0; 1738 1739 /* 1740 * If the value begins with the char string "fail", 1741 * then it means the node is failed. We don't care 1742 * about any other values. We assume the node is ok 1743 * although it might be 'disabled'. 1744 */ 1745 if (strncmp(bufp, fail, fail_len) == 0) 1746 return (0); 1747 1748 return (1); 1749 } 1750 1751 1752 /* 1753 * We set the cpu type from the idprom, if we can. 1754 * Note that we just read out the contents of it, for the most part. 1755 */ 1756 void 1757 setcputype(void) 1758 { 1759 /* 1760 * We cache the idprom info early on so that we don't 1761 * rummage through the NVRAM unnecessarily later. 1762 */ 1763 (void) prom_getidprom((caddr_t)&idprom, sizeof (idprom)); 1764 } 1765 1766 /* 1767 * Here is where we actually infer meanings to the members of idprom_t 1768 */ 1769 void 1770 parse_idprom(void) 1771 { 1772 if (idprom.id_format == IDFORM_1) { 1773 uint_t i; 1774 1775 (void) localetheraddr((struct ether_addr *)idprom.id_ether, 1776 (struct ether_addr *)NULL); 1777 1778 i = idprom.id_machine << 24; 1779 i = i + idprom.id_serial; 1780 numtos((ulong_t)i, hw_serial); 1781 } else 1782 prom_printf("Invalid format code in IDprom.\n"); 1783 } 1784 1785 /* 1786 * Allow for implementation specific correction of PROM property values. 1787 */ 1788 /*ARGSUSED*/ 1789 void 1790 impl_fix_props(dev_info_t *dip, dev_info_t *ch_dip, char *name, int len, 1791 caddr_t buffer) 1792 { 1793 /* 1794 * There are no adjustments needed in this implementation. 1795 */ 1796 } 1797 1798 /* 1799 * The following functions ready a cautious request to go up to the nexus 1800 * driver. It is up to the nexus driver to decide how to process the request. 1801 * It may choose to call i_ddi_do_caut_get/put in this file, or do it 1802 * differently. 1803 */ 1804 1805 static void 1806 i_ddi_caut_getput_ctlops( 1807 ddi_acc_impl_t *hp, uint64_t host_addr, uint64_t dev_addr, size_t size, 1808 size_t repcount, uint_t flags, ddi_ctl_enum_t cmd) 1809 { 1810 peekpoke_ctlops_t cautacc_ctlops_arg; 1811 1812 cautacc_ctlops_arg.size = size; 1813 cautacc_ctlops_arg.dev_addr = dev_addr; 1814 cautacc_ctlops_arg.host_addr = host_addr; 1815 cautacc_ctlops_arg.handle = (ddi_acc_handle_t)hp; 1816 cautacc_ctlops_arg.repcount = repcount; 1817 cautacc_ctlops_arg.flags = flags; 1818 1819 (void) ddi_ctlops(hp->ahi_common.ah_dip, hp->ahi_common.ah_dip, cmd, 1820 &cautacc_ctlops_arg, NULL); 1821 } 1822 1823 uint8_t 1824 i_ddi_caut_get8(ddi_acc_impl_t *hp, uint8_t *addr) 1825 { 1826 uint8_t value; 1827 i_ddi_caut_getput_ctlops(hp, (uint64_t)&value, (uint64_t)addr, 1828 sizeof (uint8_t), 1, 0, DDI_CTLOPS_PEEK); 1829 1830 return (value); 1831 } 1832 1833 uint16_t 1834 i_ddi_caut_get16(ddi_acc_impl_t *hp, uint16_t *addr) 1835 { 1836 uint16_t value; 1837 i_ddi_caut_getput_ctlops(hp, (uint64_t)&value, (uint64_t)addr, 1838 sizeof (uint16_t), 1, 0, DDI_CTLOPS_PEEK); 1839 1840 return (value); 1841 } 1842 1843 uint32_t 1844 i_ddi_caut_get32(ddi_acc_impl_t *hp, uint32_t *addr) 1845 { 1846 uint32_t value; 1847 i_ddi_caut_getput_ctlops(hp, (uint64_t)&value, (uint64_t)addr, 1848 sizeof (uint32_t), 1, 0, DDI_CTLOPS_PEEK); 1849 1850 return (value); 1851 } 1852 1853 uint64_t 1854 i_ddi_caut_get64(ddi_acc_impl_t *hp, uint64_t *addr) 1855 { 1856 uint64_t value; 1857 i_ddi_caut_getput_ctlops(hp, (uint64_t)&value, (uint64_t)addr, 1858 sizeof (uint64_t), 1, 0, DDI_CTLOPS_PEEK); 1859 1860 return (value); 1861 } 1862 1863 void 1864 i_ddi_caut_put8(ddi_acc_impl_t *hp, uint8_t *addr, uint8_t value) 1865 { 1866 i_ddi_caut_getput_ctlops(hp, (uint64_t)&value, (uint64_t)addr, 1867 sizeof (uint8_t), 1, 0, DDI_CTLOPS_POKE); 1868 } 1869 1870 void 1871 i_ddi_caut_put16(ddi_acc_impl_t *hp, uint16_t *addr, uint16_t value) 1872 { 1873 i_ddi_caut_getput_ctlops(hp, (uint64_t)&value, (uint64_t)addr, 1874 sizeof (uint16_t), 1, 0, DDI_CTLOPS_POKE); 1875 } 1876 1877 void 1878 i_ddi_caut_put32(ddi_acc_impl_t *hp, uint32_t *addr, uint32_t value) 1879 { 1880 i_ddi_caut_getput_ctlops(hp, (uint64_t)&value, (uint64_t)addr, 1881 sizeof (uint32_t), 1, 0, DDI_CTLOPS_POKE); 1882 } 1883 1884 void 1885 i_ddi_caut_put64(ddi_acc_impl_t *hp, uint64_t *addr, uint64_t value) 1886 { 1887 i_ddi_caut_getput_ctlops(hp, (uint64_t)&value, (uint64_t)addr, 1888 sizeof (uint64_t), 1, 0, DDI_CTLOPS_POKE); 1889 } 1890 1891 void 1892 i_ddi_caut_rep_get8(ddi_acc_impl_t *hp, uint8_t *host_addr, uint8_t *dev_addr, 1893 size_t repcount, uint_t flags) 1894 { 1895 i_ddi_caut_getput_ctlops(hp, (uint64_t)host_addr, (uint64_t)dev_addr, 1896 sizeof (uint8_t), repcount, flags, DDI_CTLOPS_PEEK); 1897 } 1898 1899 void 1900 i_ddi_caut_rep_get16(ddi_acc_impl_t *hp, uint16_t *host_addr, 1901 uint16_t *dev_addr, size_t repcount, uint_t flags) 1902 { 1903 i_ddi_caut_getput_ctlops(hp, (uint64_t)host_addr, (uint64_t)dev_addr, 1904 sizeof (uint16_t), repcount, flags, DDI_CTLOPS_PEEK); 1905 } 1906 1907 void 1908 i_ddi_caut_rep_get32(ddi_acc_impl_t *hp, uint32_t *host_addr, 1909 uint32_t *dev_addr, size_t repcount, uint_t flags) 1910 { 1911 i_ddi_caut_getput_ctlops(hp, (uint64_t)host_addr, (uint64_t)dev_addr, 1912 sizeof (uint32_t), repcount, flags, DDI_CTLOPS_PEEK); 1913 } 1914 1915 void 1916 i_ddi_caut_rep_get64(ddi_acc_impl_t *hp, uint64_t *host_addr, 1917 uint64_t *dev_addr, size_t repcount, uint_t flags) 1918 { 1919 i_ddi_caut_getput_ctlops(hp, (uint64_t)host_addr, (uint64_t)dev_addr, 1920 sizeof (uint64_t), repcount, flags, DDI_CTLOPS_PEEK); 1921 } 1922 1923 void 1924 i_ddi_caut_rep_put8(ddi_acc_impl_t *hp, uint8_t *host_addr, uint8_t *dev_addr, 1925 size_t repcount, uint_t flags) 1926 { 1927 i_ddi_caut_getput_ctlops(hp, (uint64_t)host_addr, (uint64_t)dev_addr, 1928 sizeof (uint8_t), repcount, flags, DDI_CTLOPS_POKE); 1929 } 1930 1931 void 1932 i_ddi_caut_rep_put16(ddi_acc_impl_t *hp, uint16_t *host_addr, 1933 uint16_t *dev_addr, size_t repcount, uint_t flags) 1934 { 1935 i_ddi_caut_getput_ctlops(hp, (uint64_t)host_addr, (uint64_t)dev_addr, 1936 sizeof (uint16_t), repcount, flags, DDI_CTLOPS_POKE); 1937 } 1938 1939 void 1940 i_ddi_caut_rep_put32(ddi_acc_impl_t *hp, uint32_t *host_addr, 1941 uint32_t *dev_addr, size_t repcount, uint_t flags) 1942 { 1943 i_ddi_caut_getput_ctlops(hp, (uint64_t)host_addr, (uint64_t)dev_addr, 1944 sizeof (uint32_t), repcount, flags, DDI_CTLOPS_POKE); 1945 } 1946 1947 void 1948 i_ddi_caut_rep_put64(ddi_acc_impl_t *hp, uint64_t *host_addr, 1949 uint64_t *dev_addr, size_t repcount, uint_t flags) 1950 { 1951 i_ddi_caut_getput_ctlops(hp, (uint64_t)host_addr, (uint64_t)dev_addr, 1952 sizeof (uint64_t), repcount, flags, DDI_CTLOPS_POKE); 1953 } 1954 1955 /* 1956 * This is called only to process peek/poke when the DIP is NULL. 1957 * Assume that this is for memory, as nexi take care of device safe accesses. 1958 */ 1959 int 1960 peekpoke_mem(ddi_ctl_enum_t cmd, peekpoke_ctlops_t *in_args) 1961 { 1962 int err = DDI_SUCCESS; 1963 on_trap_data_t otd; 1964 1965 /* Set up protected environment. */ 1966 if (!on_trap(&otd, OT_DATA_ACCESS)) { 1967 uintptr_t tramp = otd.ot_trampoline; 1968 1969 if (cmd == DDI_CTLOPS_POKE) { 1970 otd.ot_trampoline = (uintptr_t)&poke_fault; 1971 err = do_poke(in_args->size, (void *)in_args->dev_addr, 1972 (void *)in_args->host_addr); 1973 } else { 1974 otd.ot_trampoline = (uintptr_t)&peek_fault; 1975 err = do_peek(in_args->size, (void *)in_args->dev_addr, 1976 (void *)in_args->host_addr); 1977 } 1978 otd.ot_trampoline = tramp; 1979 } else 1980 err = DDI_FAILURE; 1981 1982 /* Take down protected environment. */ 1983 no_trap(); 1984 1985 return (err); 1986 } 1987