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 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * fcpci.c: Framework PCI fcode ops 31 */ 32 #include <sys/types.h> 33 #include <sys/kmem.h> 34 #include <sys/systm.h> 35 #include <sys/pci.h> 36 #include <sys/ddi.h> 37 #include <sys/sunddi.h> 38 #include <sys/sunndi.h> 39 #include <sys/ddidmareq.h> 40 #include <sys/pci.h> 41 #include <sys/modctl.h> 42 #include <sys/ndi_impldefs.h> 43 #include <sys/fcode.h> 44 #include <sys/promif.h> 45 #include <sys/promimpl.h> 46 #include <sys/ddi_implfuncs.h> 47 48 #define PCI_NPT_bits (PCI_RELOCAT_B | PCI_PREFETCH_B | PCI_ALIAS_B) 49 #define PCICFG_CONF_INDIRECT_MAP 1 50 51 static int pfc_map_in(dev_info_t *, fco_handle_t, fc_ci_t *); 52 static int pfc_map_out(dev_info_t *, fco_handle_t, fc_ci_t *); 53 static int pfc_dma_map_in(dev_info_t *, fco_handle_t, fc_ci_t *); 54 static int pfc_dma_map_out(dev_info_t *, fco_handle_t, fc_ci_t *); 55 static int pfc_dma_sync(dev_info_t *, fco_handle_t, fc_ci_t *); 56 static int pfc_dma_cleanup(dev_info_t *, fco_handle_t, fc_ci_t *); 57 58 static int pfc_register_fetch(dev_info_t *, fco_handle_t, fc_ci_t *); 59 static int pfc_register_store(dev_info_t *, fco_handle_t, fc_ci_t *); 60 static int pfc_config_fetch(dev_info_t *, fco_handle_t, fc_ci_t *); 61 static int pfc_config_store(dev_info_t *, fco_handle_t, fc_ci_t *); 62 63 static int pfc_probe_address(dev_info_t *, fco_handle_t, fc_ci_t *); 64 static int pfc_probe_space(dev_info_t *, fco_handle_t, fc_ci_t *); 65 66 static int pfc_config_child(dev_info_t *, fco_handle_t, fc_ci_t *); 67 static int pfc_get_fcode_size(dev_info_t *, fco_handle_t, fc_ci_t *); 68 static int pfc_get_fcode(dev_info_t *, fco_handle_t, fc_ci_t *); 69 int prom_get_fcode_size(char *); 70 int prom_get_fcode(char *, char *); 71 int pfc_update_assigned_prop(dev_info_t *, pci_regspec_t *); 72 int pfc_remove_assigned_prop(dev_info_t *, pci_regspec_t *); 73 int pci_alloc_resource(dev_info_t *, pci_regspec_t); 74 int pci_free_resource(dev_info_t *, pci_regspec_t); 75 int pci_alloc_mem_chunk(dev_info_t *, uint64_t, uint64_t *, uint64_t *); 76 int pci_alloc_io_chunk(dev_info_t *, uint64_t, uint64_t *, uint64_t *); 77 static int fcpci_indirect_map(dev_info_t *); 78 79 int fcpci_unloadable; 80 81 #ifndef lint 82 static char _depends_on[] = "misc/fcodem misc/busra"; 83 #endif 84 85 #define HIADDR(n) ((uint32_t)(((uint64_t)(n) & 0xFFFFFFFF00000000)>> 32)) 86 #define LOADDR(n)((uint32_t)((uint64_t)(n) & 0x00000000FFFFFFFF)) 87 #define LADDR(lo, hi) (((uint64_t)(hi) << 32) | (uint32_t)(lo)) 88 #define PCI_4GIG_LIMIT 0xFFFFFFFFUL 89 #define PCI_MEMGRAN 0x100000 90 #define PCI_IOGRAN 0x1000 91 92 93 /* 94 * Module linkage information for the kernel. 95 */ 96 static struct modlmisc modlmisc = { 97 &mod_miscops, "FCode pci bus functions %I%" 98 }; 99 100 static struct modlinkage modlinkage = { 101 MODREV_1, (void *)&modlmisc, NULL 102 }; 103 104 int 105 _init(void) 106 { 107 return (mod_install(&modlinkage)); 108 } 109 110 int 111 _fini(void) 112 { 113 if (fcpci_unloadable) 114 return (mod_remove(&modlinkage)); 115 return (EBUSY); 116 } 117 118 int 119 _info(struct modinfo *modinfop) 120 { 121 return (mod_info(&modlinkage, modinfop)); 122 } 123 124 125 struct pfc_ops_v { 126 char *svc_name; 127 fc_ops_t *f; 128 }; 129 130 static struct pfc_ops_v pov[] = { 131 { "map-in", pfc_map_in}, 132 { "map-out", pfc_map_out}, 133 { "dma-map-in", pfc_dma_map_in}, 134 { "dma-map-out", pfc_dma_map_out}, 135 { "dma-sync", pfc_dma_sync}, 136 { "rx@", pfc_register_fetch}, 137 { "rl@", pfc_register_fetch}, 138 { "rw@", pfc_register_fetch}, 139 { "rb@", pfc_register_fetch}, 140 { "rx!", pfc_register_store}, 141 { "rl!", pfc_register_store}, 142 { "rw!", pfc_register_store}, 143 { "rb!", pfc_register_store}, 144 { "config-l@", pfc_config_fetch}, 145 { "config-w@", pfc_config_fetch}, 146 { "config-b@", pfc_config_fetch}, 147 { "config-l!", pfc_config_store}, 148 { "config-w!", pfc_config_store}, 149 { "config-b!", pfc_config_store}, 150 { FC_PROBE_ADDRESS, pfc_probe_address}, 151 { FC_PROBE_SPACE, pfc_probe_space}, 152 { FC_SVC_EXIT, pfc_dma_cleanup}, 153 { FC_CONFIG_CHILD, pfc_config_child}, 154 { FC_GET_FCODE_SIZE, pfc_get_fcode_size}, 155 { FC_GET_FCODE, pfc_get_fcode}, 156 { NULL, NULL} 157 }; 158 159 static struct pfc_ops_v shared_pov[] = { 160 { FC_SVC_EXIT, pfc_dma_cleanup}, 161 { NULL, NULL} 162 }; 163 164 int pci_map_phys(dev_info_t *, pci_regspec_t *, 165 caddr_t *, ddi_device_acc_attr_t *, ddi_acc_handle_t *); 166 167 void pci_unmap_phys(ddi_acc_handle_t *, pci_regspec_t *); 168 169 fco_handle_t 170 pci_fc_ops_alloc_handle(dev_info_t *ap, dev_info_t *child, 171 void *fcode, size_t fcode_size, char *unit_address, 172 struct pci_ops_bus_args *up) 173 { 174 fco_handle_t rp; 175 struct pci_ops_bus_args *bp = NULL; 176 phandle_t h; 177 178 rp = kmem_zalloc(sizeof (struct fc_resource_list), KM_SLEEP); 179 rp->next_handle = fc_ops_alloc_handle(ap, child, fcode, fcode_size, 180 unit_address, NULL); 181 rp->ap = ap; 182 rp->child = child; 183 rp->fcode = fcode; 184 rp->fcode_size = fcode_size; 185 if (unit_address) { 186 char *buf; 187 188 buf = kmem_zalloc(strlen(unit_address) + 1, KM_SLEEP); 189 (void) strcpy(buf, unit_address); 190 rp->unit_address = buf; 191 } 192 193 bp = kmem_zalloc(sizeof (struct pci_ops_bus_args), KM_SLEEP); 194 *bp = *up; 195 rp->bus_args = bp; 196 197 /* 198 * Add the child's nodeid to our table... 199 */ 200 h = ddi_get_nodeid(rp->child); 201 fc_add_dip_to_phandle(fc_handle_to_phandle_head(rp), rp->child, h); 202 203 return (rp); 204 } 205 206 void 207 pci_fc_ops_free_handle(fco_handle_t rp) 208 { 209 struct pci_ops_bus_args *bp; 210 struct fc_resource *ip, *np; 211 212 ASSERT(rp); 213 214 if (rp->next_handle) 215 fc_ops_free_handle(rp->next_handle); 216 if (rp->unit_address) 217 kmem_free(rp->unit_address, strlen(rp->unit_address) + 1); 218 if ((bp = rp->bus_args) != NULL) 219 kmem_free(bp, sizeof (struct pci_ops_bus_args)); 220 221 /* 222 * Release all the resources from the resource list 223 * XXX: We don't handle 'unknown' types, but we don't create them. 224 */ 225 for (ip = rp->head; ip != NULL; ip = np) { 226 np = ip->next; 227 switch (ip->type) { 228 case RT_MAP: 229 FC_DEBUG1(1, CE_CONT, "pci_fc_ops_free: " 230 "pci_unmap_phys(%p)\n", ip->fc_map_handle); 231 pci_unmap_phys(&ip->fc_map_handle, ip->fc_regspec); 232 kmem_free(ip->fc_regspec, sizeof (pci_regspec_t)); 233 break; 234 case RT_DMA: 235 /* DMA has to be freed up at exit time */ 236 cmn_err(CE_CONT, "pfc_fc_ops_free: DMA seen!\n"); 237 break; 238 default: 239 cmn_err(CE_CONT, "pci_fc_ops_free: " 240 "unknown resource type %d\n", ip->type); 241 break; 242 } 243 fc_rem_resource(rp, ip); 244 kmem_free(ip, sizeof (struct fc_resource)); 245 } 246 kmem_free(rp, sizeof (struct fc_resource_list)); 247 } 248 249 int 250 pci_fc_ops(dev_info_t *ap, fco_handle_t rp, fc_ci_t *cp) 251 { 252 struct pfc_ops_v *pv; 253 char *name = fc_cell2ptr(cp->svc_name); 254 255 ASSERT(rp); 256 257 /* 258 * First try the generic fc_ops. If the ops is a shared op, 259 * also call our local function. 260 */ 261 if (fc_ops(ap, rp->next_handle, cp) == 0) { 262 for (pv = shared_pov; pv->svc_name != NULL; ++pv) 263 if (strcmp(pv->svc_name, name) == 0) 264 return (pv->f(ap, rp, cp)); 265 return (0); 266 } 267 268 for (pv = pov; pv->svc_name != NULL; ++pv) 269 if (strcmp(pv->svc_name, name) == 0) 270 return (pv->f(ap, rp, cp)); 271 272 FC_DEBUG1(9, CE_CONT, "pci_fc_ops: <%s> not serviced\n", name); 273 274 return (-1); 275 } 276 277 /* 278 * Create a dma mapping for a given user address. 279 */ 280 static int 281 pfc_dma_map_in(dev_info_t *ap, fco_handle_t rp, fc_ci_t *cp) 282 { 283 ddi_dma_handle_t h; 284 int error; 285 caddr_t virt; 286 size_t len; 287 uint_t flags = DDI_DMA_RDWR | DDI_DMA_CONSISTENT; 288 struct fc_resource *ip; 289 ddi_dma_cookie_t c; 290 struct buf *bp; 291 ddi_dma_attr_t attr; 292 uint_t ccnt; 293 294 if (fc_cell2int(cp->nargs) != 3) 295 return (fc_syntax_error(cp, "nargs must be 3")); 296 297 if (fc_cell2int(cp->nresults) < 1) 298 return (fc_syntax_error(cp, "nresults must be >= 1")); 299 300 /* 301 * XXX: It's not clear what we should do with a non-cacheable request 302 */ 303 virt = fc_cell2ptr(fc_arg(cp, 2)); 304 len = fc_cell2size(fc_arg(cp, 1)); 305 #ifdef notdef 306 cacheable = fc_cell2int(fc_arg(cp, 0)); /* XXX: do what? */ 307 #endif 308 309 FC_DEBUG2(6, CE_CONT, "pcf_dma_map_in: virt %p, len %d\n", virt, len); 310 311 /* 312 * Set up the address space for physio from userland 313 */ 314 error = fc_physio_setup(&bp, virt, len); 315 316 if (error) { 317 FC_DEBUG3(1, CE_CONT, "pfc_dma_map_in: fc_physio_setup failed " 318 "error: %d virt: %p len %d\n", error, virt, len); 319 return (fc_priv_error(cp, "fc_physio_setup failed")); 320 } 321 322 FC_DEBUG1(9, CE_CONT, "pfc_dma_map_in: dma_map_in; bp = %p\n", bp); 323 error = fc_ddi_dma_alloc_handle(ap, &attr, DDI_DMA_SLEEP, NULL, &h); 324 if (error != DDI_SUCCESS) { 325 FC_DEBUG3(1, CE_CONT, "pfc_dma_map_in: real dma-map-in failed " 326 "error: %d virt: %p len %d\n", error, virt, len); 327 return (fc_priv_error(cp, "real dma-map-in failed")); 328 } 329 330 error = fc_ddi_dma_buf_bind_handle(h, bp, flags, DDI_DMA_SLEEP, NULL, 331 &c, &ccnt); 332 if ((error != DDI_DMA_MAPPED) || (ccnt != 1)) { 333 fc_ddi_dma_free_handle(&h); 334 FC_DEBUG3(1, CE_CONT, "pfc_dma_map_in: real dma-map-in failed " 335 "error: %d virt: %p len %d\n", error, virt, len); 336 return (fc_priv_error(cp, "real dma-map-in failed")); 337 } 338 339 if (c.dmac_size < len) { 340 error = fc_ddi_dma_unbind_handle(h); 341 if (error != DDI_SUCCESS) { 342 return (fc_priv_error(cp, "ddi_dma_unbind error")); 343 } 344 fc_ddi_dma_free_handle(&h); 345 return (fc_priv_error(cp, "ddi_dma_buf_bind size < len")); 346 } 347 348 FC_DEBUG1(9, CE_CONT, "pfc_dma_map_in: returning devaddr %x\n", 349 c.dmac_address); 350 351 cp->nresults = fc_int2cell(1); 352 fc_result(cp, 0) = fc_uint32_t2cell(c.dmac_address); /* XXX size */ 353 354 /* 355 * Now we have to log this resource saving the handle and buf header 356 */ 357 ip = kmem_zalloc(sizeof (struct fc_resource), KM_SLEEP); 358 ip->type = RT_DMA; 359 ip->fc_dma_virt = virt; 360 ip->fc_dma_len = len; 361 ip->fc_dma_handle = h; 362 ip->fc_dma_devaddr = c.dmac_address; 363 ip->fc_dma_bp = bp; 364 fc_add_resource(rp, ip); 365 366 return (fc_success_op(ap, rp, cp)); 367 } 368 369 static int 370 pfc_dma_sync(dev_info_t *ap, fco_handle_t rp, fc_ci_t *cp) 371 { 372 void *virt; 373 size_t len; 374 uint32_t devaddr; 375 int error; 376 struct fc_resource *ip; 377 378 if (fc_cell2int(cp->nargs) != 3) 379 return (fc_syntax_error(cp, "nargs must be 3")); 380 381 virt = fc_cell2ptr(fc_arg(cp, 2)); 382 devaddr = fc_cell2uint32_t(fc_arg(cp, 1)); 383 len = fc_cell2size(fc_arg(cp, 0)); 384 385 /* 386 * Find if this virt is 'within' a request we know about 387 */ 388 fc_lock_resource_list(rp); 389 for (ip = rp->head; ip != NULL; ip = ip->next) { 390 if (ip->type != RT_DMA) 391 continue; 392 if (ip->fc_dma_devaddr != devaddr) 393 continue; 394 if (((char *)virt >= (char *)ip->fc_dma_virt) && 395 (((char *)virt + len) <= 396 ((char *)ip->fc_dma_virt + ip->fc_dma_len))) 397 break; 398 } 399 fc_unlock_resource_list(rp); 400 401 if (ip == NULL) 402 return (fc_priv_error(cp, "request not within a " 403 "known dma mapping")); 404 405 /* 406 * We know about this request, so we trust it enough to sync it. 407 * Unfortunately, we don't know which direction, so we'll do 408 * both directions. 409 */ 410 411 error = fc_ddi_dma_sync(ip->fc_dma_handle, 412 (char *)virt - (char *)ip->fc_dma_virt, len, DDI_DMA_SYNC_FORCPU); 413 error |= fc_ddi_dma_sync(ip->fc_dma_handle, 414 (char *)virt - (char *)ip->fc_dma_virt, len, DDI_DMA_SYNC_FORDEV); 415 416 if (error) 417 return (fc_priv_error(cp, "Call to ddi_dma_sync failed")); 418 419 cp->nresults = fc_int2cell(0); 420 return (fc_success_op(ap, rp, cp)); 421 } 422 423 static int 424 pfc_dma_map_out(dev_info_t *ap, fco_handle_t rp, fc_ci_t *cp) 425 { 426 void *virt; 427 size_t len; 428 uint32_t devaddr; 429 struct fc_resource *ip; 430 int e; 431 432 if (fc_cell2int(cp->nargs) != 3) 433 return (fc_syntax_error(cp, "nargs must be 3")); 434 435 virt = fc_cell2ptr(fc_arg(cp, 2)); 436 devaddr = fc_cell2uint32_t(fc_arg(cp, 1)); 437 len = fc_cell2size(fc_arg(cp, 0)); 438 439 /* 440 * Find if this virt matches a request we know about 441 */ 442 fc_lock_resource_list(rp); 443 for (ip = rp->head; ip != NULL; ip = ip->next) { 444 if (ip->type != RT_DMA) 445 continue; 446 if (ip->fc_dma_devaddr != devaddr) 447 continue; 448 if (ip->fc_dma_virt != virt) 449 continue; 450 if (len == ip->fc_dma_len) 451 break; 452 } 453 fc_unlock_resource_list(rp); 454 455 if (ip == NULL) 456 return (fc_priv_error(cp, "request doesn't match a " 457 "known dma mapping")); 458 459 /* 460 * ddi_dma_unbind_handle does an implied sync ... 461 */ 462 e = fc_ddi_dma_unbind_handle(ip->fc_dma_handle); 463 if (e != DDI_SUCCESS) { 464 cmn_err(CE_CONT, "pfc_dma_map_out: ddi_dma_unbind failed!\n"); 465 } 466 fc_ddi_dma_free_handle(&ip->fc_dma_handle); 467 468 /* 469 * Tear down the physio mappings 470 */ 471 fc_physio_free(&ip->fc_dma_bp, ip->fc_dma_virt, ip->fc_dma_len); 472 473 /* 474 * remove the resource from the list and release it. 475 */ 476 fc_rem_resource(rp, ip); 477 kmem_free(ip, sizeof (struct fc_resource)); 478 479 cp->nresults = fc_int2cell(0); 480 return (fc_success_op(ap, rp, cp)); 481 } 482 483 static struct fc_resource * 484 next_dma_resource(fco_handle_t rp) 485 { 486 struct fc_resource *ip; 487 488 fc_lock_resource_list(rp); 489 for (ip = rp->head; ip != NULL; ip = ip->next) 490 if (ip->type == RT_DMA) 491 break; 492 fc_unlock_resource_list(rp); 493 494 return (ip); 495 } 496 497 static int 498 pfc_dma_cleanup(dev_info_t *ap, fco_handle_t rp, fc_ci_t *cp) 499 { 500 struct fc_resource *ip; 501 int e; 502 503 while ((ip = next_dma_resource(rp)) != NULL) { 504 505 FC_DEBUG2(9, CE_CONT, "pfc_dma_cleanup: virt %x len %x\n", 506 ip->fc_dma_virt, ip->fc_dma_len); 507 508 /* 509 * Free the dma handle 510 */ 511 e = fc_ddi_dma_unbind_handle(ip->fc_dma_handle); 512 if (e != DDI_SUCCESS) { 513 cmn_err(CE_CONT, "pfc_dma_cleanup: " 514 "ddi_dma_unbind failed!\n"); 515 } 516 fc_ddi_dma_free_handle(&ip->fc_dma_handle); 517 518 /* 519 * Tear down the userland mapping and free the buf header 520 */ 521 fc_physio_free(&ip->fc_dma_bp, ip->fc_dma_virt, ip->fc_dma_len); 522 523 fc_rem_resource(rp, ip); 524 kmem_free(ip, sizeof (struct fc_resource)); 525 } 526 527 cp->nresults = fc_int2cell(0); 528 return (fc_success_op(ap, rp, cp)); 529 } 530 531 static int 532 pfc_map_in(dev_info_t *ap, fco_handle_t rp, fc_ci_t *cp) 533 { 534 size_t len; 535 int error; 536 caddr_t virt; 537 pci_regspec_t p, *ph; 538 struct fc_resource *ip; 539 ddi_device_acc_attr_t acc; 540 ddi_acc_handle_t h; 541 542 if (fc_cell2int(cp->nargs) != 4) 543 return (fc_syntax_error(cp, "nargs must be 4")); 544 545 if (fc_cell2int(cp->nresults) < 1) 546 return (fc_syntax_error(cp, "nresults must be >= 1")); 547 548 p.pci_size_hi = 0; 549 p.pci_size_low = len = fc_cell2size(fc_arg(cp, 0)); 550 551 p.pci_phys_hi = fc_cell2uint(fc_arg(cp, 1)); 552 p.pci_phys_mid = fc_cell2uint(fc_arg(cp, 2)); 553 p.pci_phys_low = fc_cell2uint(fc_arg(cp, 3)); 554 555 acc.devacc_attr_version = DDI_DEVICE_ATTR_V0; 556 557 /* 558 * Fcode is expecting the bytes are not swapped. 559 */ 560 acc.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC; 561 acc.devacc_attr_dataorder = DDI_STRICTORDER_ACC; 562 563 /* 564 * First We need to allocate the PCI Resource. 565 */ 566 error = pci_alloc_resource(rp->child, p); 567 568 if (error) { 569 return (fc_priv_error(cp, "pci map-in failed")); 570 } 571 572 error = pci_map_phys(rp->child, &p, &virt, &acc, &h); 573 574 if (error) { 575 return (fc_priv_error(cp, "pci map-in failed")); 576 } 577 578 cp->nresults = fc_int2cell(1); 579 fc_result(cp, 0) = fc_ptr2cell(virt); 580 581 /* 582 * Log this resource ... 583 */ 584 ip = kmem_zalloc(sizeof (struct fc_resource), KM_SLEEP); 585 ip->type = RT_MAP; 586 ip->fc_map_virt = virt; 587 ip->fc_map_len = len; 588 ip->fc_map_handle = h; 589 ph = kmem_zalloc(sizeof (pci_regspec_t), KM_SLEEP); 590 *ph = p; 591 ip->fc_regspec = ph; /* cache a copy of the reg spec */ 592 fc_add_resource(rp, ip); 593 594 return (fc_success_op(ap, rp, cp)); 595 } 596 597 static int 598 pfc_map_out(dev_info_t *ap, fco_handle_t rp, fc_ci_t *cp) 599 { 600 caddr_t virt; 601 size_t len; 602 struct fc_resource *ip; 603 604 if (fc_cell2int(cp->nargs) != 2) 605 return (fc_syntax_error(cp, "nargs must be 2")); 606 607 virt = fc_cell2ptr(fc_arg(cp, 1)); 608 609 len = fc_cell2size(fc_arg(cp, 0)); 610 611 /* 612 * Find if this request matches a mapping resource we set up. 613 */ 614 fc_lock_resource_list(rp); 615 for (ip = rp->head; ip != NULL; ip = ip->next) { 616 if (ip->type != RT_MAP) 617 continue; 618 if (ip->fc_map_virt != virt) 619 continue; 620 if (ip->fc_map_len == len) 621 break; 622 } 623 fc_unlock_resource_list(rp); 624 625 if (ip == NULL) 626 return (fc_priv_error(cp, "request doesn't match a " 627 "known mapping")); 628 629 pci_unmap_phys(&ip->fc_map_handle, ip->fc_regspec); 630 631 kmem_free(ip->fc_regspec, sizeof (pci_regspec_t)); 632 633 /* 634 * remove the resource from the list and release it. 635 */ 636 fc_rem_resource(rp, ip); 637 kmem_free(ip, sizeof (struct fc_resource)); 638 639 cp->nresults = fc_int2cell(0); 640 return (fc_success_op(ap, rp, cp)); 641 } 642 643 static int 644 pfc_register_fetch(dev_info_t *ap, fco_handle_t rp, fc_ci_t *cp) 645 { 646 size_t len; 647 caddr_t virt; 648 int error; 649 uint64_t x; 650 uint32_t l; 651 uint16_t w; 652 uint8_t b; 653 char *name = fc_cell2ptr(cp->svc_name); 654 struct fc_resource *ip; 655 656 if (fc_cell2int(cp->nargs) != 1) 657 return (fc_syntax_error(cp, "nargs must be 1")); 658 659 if (fc_cell2int(cp->nresults) < 1) 660 return (fc_syntax_error(cp, "nresults must be >= 1")); 661 662 virt = fc_cell2ptr(fc_arg(cp, 0)); 663 664 /* 665 * Determine the access width .. we can switch on the 2nd 666 * character of the name which is "rx@", "rl@", "rb@" or "rw@" 667 */ 668 switch (*(name + 1)) { 669 case 'x': len = sizeof (x); break; 670 case 'l': len = sizeof (l); break; 671 case 'w': len = sizeof (w); break; 672 case 'b': len = sizeof (b); break; 673 } 674 675 /* 676 * Check the alignment ... 677 */ 678 if (((intptr_t)virt & (len - 1)) != 0) 679 return (fc_priv_error(cp, "unaligned access")); 680 681 /* 682 * Find if this virt is 'within' a request we know about 683 */ 684 fc_lock_resource_list(rp); 685 for (ip = rp->head; ip != NULL; ip = ip->next) { 686 if (ip->type != RT_MAP) 687 continue; 688 if ((virt >= (caddr_t)ip->fc_map_virt) && ((virt + len) <= 689 ((caddr_t)ip->fc_map_virt + ip->fc_map_len))) 690 break; 691 } 692 fc_unlock_resource_list(rp); 693 694 if (ip == NULL) 695 return (fc_priv_error(cp, "request not within a " 696 "known mapping")); 697 698 /* 699 * XXX: We need access handle versions of peek/poke to move 700 * beyond the prototype ... we assume that we have hardware 701 * byte swapping enabled for pci register access here which 702 * is a huge dependency on the current implementation. 703 */ 704 switch (len) { 705 case sizeof (x): 706 error = ddi_peek64(rp->child, (int64_t *)virt, (int64_t *)&x); 707 break; 708 case sizeof (l): 709 error = ddi_peek32(rp->child, (int32_t *)virt, (int32_t *)&l); 710 break; 711 case sizeof (w): 712 error = ddi_peek16(rp->child, (int16_t *)virt, (int16_t *)&w); 713 break; 714 case sizeof (b): 715 error = ddi_peek8(rp->child, (int8_t *)virt, (int8_t *)&b); 716 break; 717 } 718 719 if (error) { 720 return (fc_priv_error(cp, "access error")); 721 } 722 723 cp->nresults = fc_int2cell(1); 724 switch (len) { 725 case sizeof (x): fc_result(cp, 0) = x; break; 726 case sizeof (l): fc_result(cp, 0) = fc_uint32_t2cell(l); break; 727 case sizeof (w): fc_result(cp, 0) = fc_uint16_t2cell(w); break; 728 case sizeof (b): fc_result(cp, 0) = fc_uint8_t2cell(b); break; 729 } 730 return (fc_success_op(ap, rp, cp)); 731 } 732 733 static int 734 pfc_register_store(dev_info_t *ap, fco_handle_t rp, fc_ci_t *cp) 735 { 736 size_t len; 737 caddr_t virt; 738 int error; 739 uint64_t x; 740 uint32_t l; 741 uint16_t w; 742 uint8_t b; 743 char *name = fc_cell2ptr(cp->svc_name); 744 struct fc_resource *ip; 745 746 if (fc_cell2int(cp->nargs) != 2) 747 return (fc_syntax_error(cp, "nargs must be 2")); 748 749 virt = fc_cell2ptr(fc_arg(cp, 0)); 750 751 /* 752 * Determine the access width .. we can switch on the 2nd 753 * character of the name which is "rl!", "rb!" or "rw!" 754 */ 755 switch (*(name + 1)) { 756 case 'x': len = sizeof (x); x = fc_arg(cp, 1); break; 757 case 'l': len = sizeof (l); l = fc_cell2uint32_t(fc_arg(cp, 1)); break; 758 case 'w': len = sizeof (w); w = fc_cell2uint16_t(fc_arg(cp, 1)); break; 759 case 'b': len = sizeof (b); b = fc_cell2uint8_t(fc_arg(cp, 1)); break; 760 } 761 762 /* 763 * Check the alignment ... 764 */ 765 if (((intptr_t)virt & (len - 1)) != 0) 766 return (fc_priv_error(cp, "unaligned access")); 767 768 /* 769 * Find if this virt is 'within' a request we know about 770 */ 771 fc_lock_resource_list(rp); 772 for (ip = rp->head; ip != NULL; ip = ip->next) { 773 if (ip->type != RT_MAP) 774 continue; 775 if ((virt >= (caddr_t)ip->fc_map_virt) && ((virt + len) <= 776 ((caddr_t)ip->fc_map_virt + ip->fc_map_len))) 777 break; 778 } 779 fc_unlock_resource_list(rp); 780 781 if (ip == NULL) 782 return (fc_priv_error(cp, "request not within a " 783 "known mapping")); 784 785 /* 786 * XXX: We need access handle versions of peek/poke to move 787 * beyond the prototype ... we assume that we have hardware 788 * byte swapping enabled for pci register access here which 789 * is a huge dependency on the current implementation. 790 */ 791 switch (len) { 792 case sizeof (x): 793 error = ddi_poke64(rp->child, (int64_t *)virt, x); 794 break; 795 case sizeof (l): 796 error = ddi_poke32(rp->child, (int32_t *)virt, l); 797 break; 798 case sizeof (w): 799 error = ddi_poke16(rp->child, (int16_t *)virt, w); 800 break; 801 case sizeof (b): 802 error = ddi_poke8(rp->child, (int8_t *)virt, b); 803 break; 804 } 805 806 if (error) { 807 return (fc_priv_error(cp, "access error")); 808 } 809 810 cp->nresults = fc_int2cell(0); 811 return (fc_success_op(ap, rp, cp)); 812 } 813 814 static int 815 pfc_config_fetch(dev_info_t *ap, fco_handle_t rp, fc_ci_t *cp) 816 { 817 caddr_t virt, v; 818 int error, reg, flags = 0; 819 size_t len; 820 uint32_t l, tmp; 821 uint16_t w; 822 uint8_t b; 823 char *name = fc_cell2ptr(cp->svc_name); 824 pci_regspec_t p; 825 ddi_device_acc_attr_t acc; 826 ddi_acc_handle_t h; 827 828 if (fc_cell2int(cp->nargs) != 1) 829 return (fc_syntax_error(cp, "nargs must be 1")); 830 831 if (fc_cell2int(cp->nresults) < 1) 832 return (fc_syntax_error(cp, "nresults must be >= 1")); 833 834 /* 835 * Construct a config address pci reg property from the args. 836 * arg[0] is the configuration address. 837 */ 838 p.pci_phys_hi = fc_cell2uint(fc_arg(cp, 0)); 839 p.pci_phys_mid = p.pci_phys_low = 0; 840 p.pci_size_hi = p.pci_size_low = 0; 841 842 /* 843 * Verify that the address is a configuration space address 844 * ss must be zero, n,p,t must be zero. 845 */ 846 if (((p.pci_phys_hi & PCI_ADDR_MASK) != PCI_ADDR_CONFIG) || 847 ((p.pci_phys_hi & PCI_NPT_bits) != 0)) { 848 cmn_err(CE_CONT, "pfc_config_fetch: " 849 "invalid config addr: %x\n", p.pci_phys_hi); 850 return (fc_priv_error(cp, "non-config addr")); 851 } 852 853 /* 854 * Extract the register number from the config address and 855 * remove the register number from the physical address. 856 */ 857 reg = p.pci_phys_hi & PCI_REG_REG_M; 858 p.pci_phys_hi &= ~PCI_REG_REG_M; 859 860 /* 861 * Determine the access width .. we can switch on the 9th 862 * character of the name which is "config-{l,w,b}@" 863 */ 864 switch (*(name + 7)) { 865 case 'l': len = sizeof (l); break; 866 case 'w': len = sizeof (w); break; 867 case 'b': len = sizeof (b); break; 868 } 869 870 /* 871 * Verify that the access is properly aligned 872 */ 873 if ((reg & (len - 1)) != 0) 874 return (fc_priv_error(cp, "unaligned access")); 875 876 /* 877 * Map in configuration space (temporarily) 878 */ 879 acc.devacc_attr_version = DDI_DEVICE_ATTR_V0; 880 acc.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC; 881 acc.devacc_attr_dataorder = DDI_STRICTORDER_ACC; 882 883 error = pci_map_phys(rp->child, &p, &virt, &acc, &h); 884 885 if (error) { 886 return (fc_priv_error(cp, "pci config map-in failed")); 887 } 888 889 if (fcpci_indirect_map(rp->child) == DDI_SUCCESS) 890 flags |= PCICFG_CONF_INDIRECT_MAP; 891 892 if (flags & PCICFG_CONF_INDIRECT_MAP) { 893 tmp = (int32_t)ddi_get32(h, (uint32_t *)virt); 894 error = DDI_SUCCESS; 895 } else 896 error = ddi_peek32(rp->child, (int32_t *)virt, (int32_t *)&tmp); 897 898 if (error == DDI_SUCCESS) 899 if ((tmp == (int32_t)0xffffffff) || (tmp == -1)) { 900 error = DDI_FAILURE; 901 cmn_err(CE_CONT, "fcpcii: conf probe failed.l=%x", tmp); 902 } 903 904 if (error != DDI_SUCCESS) { 905 return (fc_priv_error(cp, "pci config fetch failed")); 906 } 907 908 909 /* 910 * XXX: We need access handle versions of peek/poke to move 911 * beyond the prototype ... we assume that we have hardware 912 * byte swapping enabled for pci register access here which 913 * is a huge dependency on the current implementation. 914 */ 915 v = virt + reg; 916 switch (len) { 917 case sizeof (l): 918 l = (int32_t)ddi_get32(h, (uint32_t *)v); 919 break; 920 case sizeof (w): 921 w = (int16_t)ddi_get16(h, (uint16_t *)v); 922 break; 923 case sizeof (b): 924 b = (int8_t)ddi_get8(h, (uint8_t *)v); 925 break; 926 } 927 928 /* 929 * Remove the temporary config space mapping 930 */ 931 pci_unmap_phys(&h, &p); 932 933 if (error) { 934 return (fc_priv_error(cp, "access error")); 935 } 936 937 cp->nresults = fc_int2cell(1); 938 switch (len) { 939 case sizeof (l): fc_result(cp, 0) = fc_uint32_t2cell(l); break; 940 case sizeof (w): fc_result(cp, 0) = fc_uint16_t2cell(w); break; 941 case sizeof (b): fc_result(cp, 0) = fc_uint8_t2cell(b); break; 942 } 943 944 return (fc_success_op(ap, rp, cp)); 945 } 946 947 static int 948 pfc_config_store(dev_info_t *ap, fco_handle_t rp, fc_ci_t *cp) 949 { 950 caddr_t virt, v; 951 int error, reg, flags = 0; 952 size_t len; 953 uint32_t l, tmp; 954 uint16_t w; 955 uint8_t b; 956 char *name = fc_cell2ptr(cp->svc_name); 957 pci_regspec_t p; 958 ddi_device_acc_attr_t acc; 959 ddi_acc_handle_t h; 960 961 if (fc_cell2int(cp->nargs) != 2) 962 return (fc_syntax_error(cp, "nargs must be 2")); 963 964 /* 965 * Construct a config address pci reg property from the args. 966 * arg[0] is the configuration address. arg[1] is the data. 967 */ 968 p.pci_phys_hi = fc_cell2uint(fc_arg(cp, 0)); 969 p.pci_phys_mid = p.pci_phys_low = 0; 970 p.pci_size_hi = p.pci_size_low = 0; 971 972 /* 973 * Verify that the address is a configuration space address 974 * ss must be zero, n,p,t must be zero. 975 */ 976 if (((p.pci_phys_hi & PCI_ADDR_MASK) != PCI_ADDR_CONFIG) || 977 ((p.pci_phys_hi & PCI_NPT_bits) != 0)) { 978 cmn_err(CE_CONT, "pfc_config_store: " 979 "invalid config addr: %x\n", p.pci_phys_hi); 980 return (fc_priv_error(cp, "non-config addr")); 981 } 982 983 /* 984 * Extract the register number from the config address and 985 * remove the register number from the physical address. 986 */ 987 reg = p.pci_phys_hi & PCI_REG_REG_M; 988 p.pci_phys_hi &= ~PCI_REG_REG_M; 989 990 /* 991 * Determine the access width .. we can switch on the 8th 992 * character of the name which is "config-{l,w,b}@" 993 */ 994 switch (*(name + 7)) { 995 case 'l': len = sizeof (l); l = fc_cell2uint32_t(fc_arg(cp, 1)); break; 996 case 'w': len = sizeof (w); w = fc_cell2uint16_t(fc_arg(cp, 1)); break; 997 case 'b': len = sizeof (b); b = fc_cell2uint8_t(fc_arg(cp, 1)); break; 998 } 999 1000 /* 1001 * Verify that the access is properly aligned 1002 */ 1003 if ((reg & (len - 1)) != 0) 1004 return (fc_priv_error(cp, "unaligned access")); 1005 1006 /* 1007 * Map in configuration space (temporarily) 1008 */ 1009 acc.devacc_attr_version = DDI_DEVICE_ATTR_V0; 1010 acc.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC; 1011 acc.devacc_attr_dataorder = DDI_STRICTORDER_ACC; 1012 1013 error = pci_map_phys(rp->child, &p, &virt, &acc, &h); 1014 1015 if (error) { 1016 return (fc_priv_error(cp, "pci config map-in failed")); 1017 } 1018 1019 if (fcpci_indirect_map(rp->child) == DDI_SUCCESS) 1020 flags |= PCICFG_CONF_INDIRECT_MAP; 1021 1022 if (flags & PCICFG_CONF_INDIRECT_MAP) { 1023 tmp = (int32_t)ddi_get32(h, (uint32_t *)virt); 1024 error = DDI_SUCCESS; 1025 } else 1026 error = ddi_peek32(rp->child, (int32_t *)virt, (int32_t *)&tmp); 1027 1028 if (error == DDI_SUCCESS) 1029 if ((tmp == (int32_t)0xffffffff) || (tmp == -1)) { 1030 error = DDI_FAILURE; 1031 cmn_err(CE_CONT, "fcpci: conf probe failed.l=%x", tmp); 1032 } 1033 1034 if (error != DDI_SUCCESS) { 1035 return (fc_priv_error(cp, "pci config store failed")); 1036 } 1037 1038 1039 /* 1040 * XXX: We need access handle versions of peek/poke to move 1041 * beyond the prototype ... we assume that we have hardware 1042 * byte swapping enabled for pci register access here which 1043 * is a huge dependency on the current implementation. 1044 */ 1045 v = virt + reg; 1046 switch (len) { 1047 case sizeof (l): 1048 ddi_put32(h, (uint32_t *)v, (uint32_t)l); 1049 break; 1050 case sizeof (w): 1051 ddi_put16(h, (uint16_t *)v, (uint16_t)w); 1052 break; 1053 case sizeof (b): 1054 ddi_put8(h, (uint8_t *)v, (uint8_t)b); 1055 break; 1056 } 1057 1058 /* 1059 * Remove the temporary config space mapping 1060 */ 1061 pci_unmap_phys(&h, &p); 1062 1063 if (error) { 1064 return (fc_priv_error(cp, "access error")); 1065 } 1066 1067 cp->nresults = fc_int2cell(0); 1068 return (fc_success_op(ap, rp, cp)); 1069 } 1070 1071 1072 static int 1073 pfc_get_fcode(dev_info_t *ap, fco_handle_t rp, fc_ci_t *cp) 1074 { 1075 caddr_t name_virt, fcode_virt; 1076 char *name, *fcode; 1077 int fcode_len, status; 1078 1079 if (fc_cell2int(cp->nargs) != 3) 1080 return (fc_syntax_error(cp, "nargs must be 3")); 1081 1082 if (fc_cell2int(cp->nresults) < 1) 1083 return (fc_syntax_error(cp, "nresults must be >= 1")); 1084 1085 name_virt = fc_cell2ptr(fc_arg(cp, 0)); 1086 1087 fcode_virt = fc_cell2ptr(fc_arg(cp, 1)); 1088 1089 fcode_len = fc_cell2int(fc_arg(cp, 2)); 1090 1091 name = kmem_zalloc(FC_SVC_NAME_LEN, KM_SLEEP); 1092 1093 if (copyinstr(fc_cell2ptr(name_virt), name, 1094 FC_SVC_NAME_LEN - 1, NULL)) { 1095 status = 0; 1096 } else { 1097 1098 fcode = kmem_zalloc(fcode_len, KM_SLEEP); 1099 1100 if ((status = prom_get_fcode(name, fcode)) != 0) { 1101 1102 if (copyout((void *)fcode, (void *)fcode_virt, 1103 fcode_len)) { 1104 cmn_err(CE_WARN, " pfc_get_fcode: Unable " 1105 "to copy out fcode image\n"); 1106 status = 0; 1107 } 1108 } 1109 1110 kmem_free(fcode, fcode_len); 1111 } 1112 1113 kmem_free(name, FC_SVC_NAME_LEN); 1114 1115 cp->nresults = fc_int2cell(1); 1116 fc_result(cp, 0) = status; 1117 1118 return (fc_success_op(ap, rp, cp)); 1119 } 1120 1121 static int 1122 pfc_get_fcode_size(dev_info_t *ap, fco_handle_t rp, fc_ci_t *cp) 1123 { 1124 caddr_t virt; 1125 char *name; 1126 int len; 1127 1128 if (fc_cell2int(cp->nargs) != 1) 1129 return (fc_syntax_error(cp, "nargs must be 1")); 1130 1131 if (fc_cell2int(cp->nresults) < 1) 1132 return (fc_syntax_error(cp, "nresults must be >= 1")); 1133 1134 virt = fc_cell2ptr(fc_arg(cp, 0)); 1135 1136 name = kmem_zalloc(FC_SVC_NAME_LEN, KM_SLEEP); 1137 1138 if (copyinstr(fc_cell2ptr(virt), name, 1139 FC_SVC_NAME_LEN - 1, NULL)) { 1140 len = 0; 1141 } else { 1142 len = prom_get_fcode_size(name); 1143 } 1144 1145 kmem_free(name, FC_SVC_NAME_LEN); 1146 1147 cp->nresults = fc_int2cell(1); 1148 fc_result(cp, 0) = len; 1149 1150 return (fc_success_op(ap, rp, cp)); 1151 } 1152 1153 /* 1154 * Return the physical probe address: lo=0, mid=0, hi-config-addr 1155 */ 1156 static int 1157 pfc_probe_address(dev_info_t *ap, fco_handle_t rp, fc_ci_t *cp) 1158 { 1159 if (fc_cell2int(cp->nargs) != 0) 1160 return (fc_syntax_error(cp, "nargs must be 0")); 1161 1162 if (fc_cell2int(cp->nresults) < 2) 1163 return (fc_syntax_error(cp, "nresults must be >= 3")); 1164 1165 cp->nresults = fc_int2cell(2); 1166 fc_result(cp, 1) = fc_int2cell(0); /* phys.lo */ 1167 fc_result(cp, 0) = fc_int2cell(0); /* phys.mid */ 1168 1169 return (fc_success_op(ap, rp, cp)); 1170 } 1171 1172 /* 1173 * Return the phys.hi component of the probe address. 1174 */ 1175 static int 1176 pfc_probe_space(dev_info_t *ap, fco_handle_t rp, fc_ci_t *cp) 1177 { 1178 struct pci_ops_bus_args *ba = rp->bus_args; 1179 1180 ASSERT(ba); 1181 1182 if (fc_cell2int(cp->nargs) != 0) 1183 return (fc_syntax_error(cp, "nargs must be 0")); 1184 1185 if (fc_cell2int(cp->nresults) < 1) 1186 return (fc_syntax_error(cp, "nresults must be >= 1")); 1187 1188 cp->nresults = fc_int2cell(1); 1189 fc_result(cp, 0) = fc_uint32_t2cell(ba->config_address); /* phys.hi */ 1190 1191 return (fc_success_op(ap, rp, cp)); 1192 } 1193 1194 static int 1195 pfc_config_child(dev_info_t *ap, fco_handle_t rp, fc_ci_t *cp) 1196 { 1197 fc_phandle_t h; 1198 1199 if (fc_cell2int(cp->nargs) != 0) 1200 return (fc_syntax_error(cp, "nargs must be 0")); 1201 1202 if (fc_cell2int(cp->nresults) < 1) 1203 return (fc_syntax_error(cp, "nresults must be >= 1")); 1204 1205 h = fc_dip_to_phandle(fc_handle_to_phandle_head(rp), rp->child); 1206 1207 cp->nresults = fc_int2cell(1); 1208 fc_result(cp, 0) = fc_phandle2cell(h); 1209 1210 return (fc_success_op(ap, rp, cp)); 1211 } 1212 1213 int 1214 pci_alloc_mem_chunk(dev_info_t *dip, uint64_t mem_align, uint64_t *mem_size, 1215 uint64_t *mem_answer) 1216 { 1217 ndi_ra_request_t req; 1218 int rval; 1219 1220 bzero((caddr_t)&req, sizeof (ndi_ra_request_t)); 1221 req.ra_flags = NDI_RA_ALLOC_BOUNDED; 1222 req.ra_boundbase = 0; 1223 req.ra_boundlen = PCI_4GIG_LIMIT; 1224 req.ra_len = *mem_size; 1225 req.ra_align_mask = mem_align - 1; 1226 1227 rval = ndi_ra_alloc(dip, &req, mem_answer, mem_size, 1228 NDI_RA_TYPE_MEM, NDI_RA_PASS); 1229 1230 return (rval); 1231 } 1232 int 1233 pci_alloc_io_chunk(dev_info_t *dip, uint64_t io_align, uint64_t *io_size, 1234 uint64_t *io_answer) 1235 { 1236 ndi_ra_request_t req; 1237 int rval; 1238 1239 bzero((caddr_t)&req, sizeof (ndi_ra_request_t)); 1240 req.ra_flags = (NDI_RA_ALLOC_BOUNDED | NDI_RA_ALLOC_PARTIAL_OK); 1241 req.ra_boundbase = 0; 1242 req.ra_boundlen = PCI_4GIG_LIMIT; 1243 req.ra_len = *io_size; 1244 req.ra_align_mask = io_align - 1; 1245 1246 rval = ndi_ra_alloc(dip, &req, io_answer, io_size, 1247 NDI_RA_TYPE_IO, NDI_RA_PASS); 1248 1249 return (rval); 1250 } 1251 1252 int 1253 pci_alloc_resource(dev_info_t *dip, pci_regspec_t phys_spec) 1254 { 1255 uint64_t answer; 1256 uint64_t alen; 1257 int offset, tmp; 1258 pci_regspec_t config; 1259 caddr_t virt, v; 1260 ddi_device_acc_attr_t acc; 1261 ddi_acc_handle_t h; 1262 ndi_ra_request_t request; 1263 pci_regspec_t *assigned; 1264 int assigned_len, entries, i, l, flags = 0, error; 1265 1266 l = phys_spec.pci_size_low; 1267 1268 if (ddi_getlongprop(DDI_DEV_T_ANY, dip, 1269 DDI_PROP_DONTPASS, "assigned-addresses", (caddr_t)&assigned, 1270 &assigned_len) == DDI_PROP_SUCCESS) { 1271 1272 entries = assigned_len / (sizeof (pci_regspec_t)); 1273 1274 /* 1275 * Walk through the assigned-addresses entries. If there is 1276 * a match, there is no need to allocate the resource. 1277 */ 1278 for (i = 0; i < entries; i++) { 1279 if (assigned[i].pci_phys_hi == phys_spec.pci_phys_hi) { 1280 if (assigned[i].pci_size_low >= 1281 phys_spec.pci_size_low) { 1282 kmem_free(assigned, assigned_len); 1283 return (0); 1284 } 1285 /* 1286 * Fcode wants to assign more than what 1287 * probe found. 1288 */ 1289 (void) pci_free_resource(dip, assigned[i]); 1290 /* 1291 * Go on to allocate resources. 1292 */ 1293 break; 1294 } 1295 /* 1296 * Check if Fcode wants to map using different 1297 * NPT bits. 1298 */ 1299 if (PCI_REG_BDFR_G(assigned[i].pci_phys_hi) == 1300 PCI_REG_BDFR_G(phys_spec.pci_phys_hi)) { 1301 /* 1302 * It is an error to change SS bits 1303 */ 1304 if (PCI_REG_ADDR_G(assigned[i].pci_phys_hi) != 1305 PCI_REG_ADDR_G(phys_spec.pci_phys_hi)) { 1306 1307 cmn_err(CE_WARN, "Fcode changing ss " 1308 "bits in reg %x -- %x", 1309 assigned[i].pci_phys_hi, 1310 phys_spec.pci_phys_hi); 1311 1312 kmem_free(assigned, assigned_len); 1313 return (1); 1314 } 1315 1316 /* 1317 * Allocate enough 1318 */ 1319 l = MAX(assigned[i].pci_size_low, 1320 phys_spec.pci_size_low); 1321 1322 (void) pci_free_resource(dip, assigned[i]); 1323 /* 1324 * Go on to allocate resources. 1325 */ 1326 break; 1327 } 1328 } 1329 kmem_free(assigned, assigned_len); 1330 } 1331 1332 bzero((caddr_t)&request, sizeof (ndi_ra_request_t)); 1333 1334 config.pci_phys_hi = PCI_CONF_ADDR_MASK & phys_spec.pci_phys_hi; 1335 config.pci_phys_hi &= ~PCI_REG_REG_M; 1336 config.pci_phys_mid = config.pci_phys_low = 0; 1337 config.pci_size_hi = config.pci_size_low = 0; 1338 1339 /* 1340 * Map in configuration space (temporarily) 1341 */ 1342 acc.devacc_attr_version = DDI_DEVICE_ATTR_V0; 1343 acc.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC; 1344 acc.devacc_attr_dataorder = DDI_STRICTORDER_ACC; 1345 1346 if (error = pci_map_phys(dip, &config, &virt, &acc, &h)) { 1347 return (1); 1348 } 1349 1350 if (fcpci_indirect_map(dip) == DDI_SUCCESS) 1351 flags |= PCICFG_CONF_INDIRECT_MAP; 1352 1353 if (flags & PCICFG_CONF_INDIRECT_MAP) { 1354 tmp = (int32_t)ddi_get32(h, (uint32_t *)virt); 1355 error = DDI_SUCCESS; 1356 } else 1357 error = ddi_peek32(dip, (int32_t *)virt, (int32_t *)&tmp); 1358 1359 if (error == DDI_SUCCESS) 1360 if ((tmp == (int32_t)0xffffffff) || (tmp == -1)) { 1361 error = DDI_FAILURE; 1362 } 1363 1364 if (error != DDI_SUCCESS) { 1365 return (1); 1366 } 1367 1368 request.ra_flags |= NDI_RA_ALIGN_SIZE; 1369 request.ra_boundbase = 0; 1370 request.ra_boundlen = PCI_4GIG_LIMIT; 1371 1372 offset = PCI_REG_REG_G(phys_spec.pci_phys_hi); 1373 1374 v = virt + offset; 1375 1376 if (PCI_REG_REG_G(phys_spec.pci_phys_hi) == PCI_CONF_ROM) { 1377 request.ra_len = l; 1378 request.ra_flags ^= NDI_RA_ALLOC_BOUNDED; 1379 1380 /* allocate memory space from the allocator */ 1381 1382 if (ndi_ra_alloc(ddi_get_parent(dip), 1383 &request, &answer, &alen, 1384 NDI_RA_TYPE_MEM, NDI_RA_PASS) 1385 != NDI_SUCCESS) { 1386 pci_unmap_phys(&h, &config); 1387 return (1); 1388 } 1389 FC_DEBUG3(1, CE_CONT, "ROM addr = [0x%x.%x] len [0x%x]\n", 1390 HIADDR(answer), 1391 LOADDR(answer), 1392 alen); 1393 1394 /* program the low word */ 1395 1396 ddi_put32(h, (uint32_t *)v, LOADDR(answer)); 1397 1398 phys_spec.pci_phys_low = LOADDR(answer); 1399 phys_spec.pci_phys_mid = HIADDR(answer); 1400 } else { 1401 request.ra_len = l; 1402 1403 switch (PCI_REG_ADDR_G(phys_spec.pci_phys_hi)) { 1404 case PCI_REG_ADDR_G(PCI_ADDR_MEM64): 1405 request.ra_flags ^= NDI_RA_ALLOC_BOUNDED; 1406 1407 if (phys_spec.pci_phys_hi & PCI_REG_REL_M) { 1408 /* 1409 * If it is a non relocatable address, 1410 * then specify the address we want. 1411 */ 1412 request.ra_flags = NDI_RA_ALLOC_SPECIFIED; 1413 request.ra_addr = (uint64_t)LADDR( 1414 phys_spec.pci_phys_low, 1415 phys_spec.pci_phys_mid); 1416 } 1417 1418 /* allocate memory space from the allocator */ 1419 1420 if (ndi_ra_alloc(ddi_get_parent(dip), 1421 &request, &answer, &alen, 1422 NDI_RA_TYPE_MEM, NDI_RA_PASS) 1423 != NDI_SUCCESS) { 1424 pci_unmap_phys(&h, &config); 1425 if (request.ra_flags == 1426 NDI_RA_ALLOC_SPECIFIED) 1427 cmn_err(CE_WARN, "Unable to allocate " 1428 "non relocatable address 0x%p\n", 1429 (void *) request.ra_addr); 1430 return (1); 1431 } 1432 FC_DEBUG3(1, CE_CONT, 1433 "64 addr = [0x%x.%x] len [0x%x]\n", 1434 HIADDR(answer), 1435 LOADDR(answer), 1436 alen); 1437 1438 /* program the low word */ 1439 1440 ddi_put32(h, (uint32_t *)v, LOADDR(answer)); 1441 1442 /* program the high word with value zero */ 1443 v += 4; 1444 ddi_put32(h, (uint32_t *)v, HIADDR(answer)); 1445 1446 phys_spec.pci_phys_low = LOADDR(answer); 1447 phys_spec.pci_phys_mid = HIADDR(answer); 1448 1449 break; 1450 1451 case PCI_REG_ADDR_G(PCI_ADDR_MEM32): 1452 request.ra_flags |= NDI_RA_ALLOC_BOUNDED; 1453 1454 if (phys_spec.pci_phys_hi & PCI_REG_REL_M) { 1455 /* 1456 * If it is a non relocatable address, 1457 * then specify the address we want. 1458 */ 1459 request.ra_flags = NDI_RA_ALLOC_SPECIFIED; 1460 request.ra_addr = (uint64_t) 1461 phys_spec.pci_phys_low; 1462 } 1463 1464 /* allocate memory space from the allocator */ 1465 1466 if (ndi_ra_alloc(ddi_get_parent(dip), 1467 &request, &answer, &alen, 1468 NDI_RA_TYPE_MEM, NDI_RA_PASS) 1469 != NDI_SUCCESS) { 1470 pci_unmap_phys(&h, &config); 1471 if (request.ra_flags == 1472 NDI_RA_ALLOC_SPECIFIED) 1473 cmn_err(CE_WARN, "Unable to allocate " 1474 "non relocatable address 0x%p\n", 1475 (void *) request.ra_addr); 1476 return (1); 1477 } 1478 1479 FC_DEBUG3(1, CE_CONT, 1480 "32 addr = [0x%x.%x] len [0x%x]\n", 1481 HIADDR(answer), 1482 LOADDR(answer), 1483 alen); 1484 1485 /* program the low word */ 1486 1487 ddi_put32(h, (uint32_t *)v, LOADDR(answer)); 1488 1489 phys_spec.pci_phys_low = LOADDR(answer); 1490 1491 break; 1492 case PCI_REG_ADDR_G(PCI_ADDR_IO): 1493 request.ra_flags |= NDI_RA_ALLOC_BOUNDED; 1494 1495 if (phys_spec.pci_phys_hi & PCI_REG_REL_M) { 1496 /* 1497 * If it is a non relocatable address, 1498 * then specify the address we want. 1499 */ 1500 request.ra_flags = NDI_RA_ALLOC_SPECIFIED; 1501 request.ra_addr = (uint64_t) 1502 phys_spec.pci_phys_low; 1503 } 1504 1505 /* allocate I/O space from the allocator */ 1506 1507 if (ndi_ra_alloc(ddi_get_parent(dip), 1508 &request, &answer, &alen, 1509 NDI_RA_TYPE_IO, NDI_RA_PASS) 1510 != NDI_SUCCESS) { 1511 pci_unmap_phys(&h, &config); 1512 if (request.ra_flags == 1513 NDI_RA_ALLOC_SPECIFIED) 1514 cmn_err(CE_WARN, "Unable to allocate " 1515 "non relocatable IO Space 0x%p\n", 1516 (void *) request.ra_addr); 1517 return (1); 1518 } 1519 FC_DEBUG3(1, CE_CONT, 1520 "I/O addr = [0x%x.%x] len [0x%x]\n", 1521 HIADDR(answer), 1522 LOADDR(answer), 1523 alen); 1524 1525 ddi_put32(h, (uint32_t *)v, LOADDR(answer)); 1526 1527 phys_spec.pci_phys_low = LOADDR(answer); 1528 1529 break; 1530 default: 1531 pci_unmap_phys(&h, &config); 1532 return (1); 1533 } /* switch */ 1534 } 1535 1536 /* 1537 * Now that memory locations are assigned, 1538 * update the assigned address property. 1539 */ 1540 if (pfc_update_assigned_prop(dip, &phys_spec)) { 1541 pci_unmap_phys(&h, &config); 1542 return (1); 1543 } 1544 1545 pci_unmap_phys(&h, &config); 1546 1547 return (0); 1548 } 1549 1550 int 1551 pci_free_resource(dev_info_t *dip, pci_regspec_t phys_spec) 1552 { 1553 int offset, tmp; 1554 pci_regspec_t config; 1555 caddr_t virt, v; 1556 ddi_device_acc_attr_t acc; 1557 ddi_acc_handle_t h; 1558 ndi_ra_request_t request; 1559 int l, error, flags = 0; 1560 1561 bzero((caddr_t)&request, sizeof (ndi_ra_request_t)); 1562 1563 config.pci_phys_hi = PCI_CONF_ADDR_MASK & phys_spec.pci_phys_hi; 1564 config.pci_phys_hi &= ~PCI_REG_REG_M; 1565 config.pci_phys_mid = config.pci_phys_low = 0; 1566 config.pci_size_hi = config.pci_size_low = 0; 1567 1568 /* 1569 * Map in configuration space (temporarily) 1570 */ 1571 acc.devacc_attr_version = DDI_DEVICE_ATTR_V0; 1572 acc.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC; 1573 acc.devacc_attr_dataorder = DDI_STRICTORDER_ACC; 1574 1575 if (error = pci_map_phys(dip, &config, &virt, &acc, &h)) { 1576 return (1); 1577 } 1578 if (fcpci_indirect_map(dip) == DDI_SUCCESS) 1579 flags |= PCICFG_CONF_INDIRECT_MAP; 1580 1581 if (flags & PCICFG_CONF_INDIRECT_MAP) { 1582 tmp = (int32_t)ddi_get32(h, (uint32_t *)virt); 1583 error = DDI_SUCCESS; 1584 } else 1585 error = ddi_peek32(dip, (int32_t *)virt, (int32_t *)&tmp); 1586 1587 if (error == DDI_SUCCESS) 1588 if ((tmp == (int32_t)0xffffffff) || (tmp == -1)) { 1589 error = DDI_FAILURE; 1590 } 1591 if (error != DDI_SUCCESS) { 1592 return (1); 1593 } 1594 1595 1596 offset = PCI_REG_REG_G(phys_spec.pci_phys_hi); 1597 1598 v = virt + offset; 1599 1600 /* 1601 * Pick up the size to be freed. It may be different from 1602 * what probe finds. 1603 */ 1604 l = phys_spec.pci_size_low; 1605 1606 if (PCI_REG_REG_G(phys_spec.pci_phys_hi) == PCI_CONF_ROM) { 1607 /* free memory back to the allocator */ 1608 if (ndi_ra_free(ddi_get_parent(dip), phys_spec.pci_phys_low, 1609 l, NDI_RA_TYPE_MEM, 1610 NDI_RA_PASS) != NDI_SUCCESS) { 1611 pci_unmap_phys(&h, &config); 1612 return (1); 1613 } 1614 1615 /* Unmap the BAR by writing a zero */ 1616 1617 ddi_put32(h, (uint32_t *)v, 0); 1618 } else { 1619 switch (PCI_REG_ADDR_G(phys_spec.pci_phys_hi)) { 1620 case PCI_REG_ADDR_G(PCI_ADDR_MEM64): 1621 /* free memory back to the allocator */ 1622 if (ndi_ra_free(ddi_get_parent(dip), 1623 LADDR(phys_spec.pci_phys_low, 1624 phys_spec.pci_phys_mid), 1625 l, NDI_RA_TYPE_MEM, 1626 NDI_RA_PASS) != NDI_SUCCESS) { 1627 pci_unmap_phys(&h, &config); 1628 return (1); 1629 } 1630 1631 break; 1632 1633 case PCI_REG_ADDR_G(PCI_ADDR_MEM32): 1634 /* free memory back to the allocator */ 1635 if (ndi_ra_free(ddi_get_parent(dip), 1636 phys_spec.pci_phys_low, 1637 l, NDI_RA_TYPE_MEM, 1638 NDI_RA_PASS) != NDI_SUCCESS) { 1639 pci_unmap_phys(&h, &config); 1640 return (1); 1641 } 1642 1643 break; 1644 case PCI_REG_ADDR_G(PCI_ADDR_IO): 1645 /* free I/O space back to the allocator */ 1646 if (ndi_ra_free(ddi_get_parent(dip), 1647 phys_spec.pci_phys_low, 1648 l, NDI_RA_TYPE_IO, 1649 NDI_RA_PASS) != NDI_SUCCESS) { 1650 pci_unmap_phys(&h, &config); 1651 return (1); 1652 } 1653 break; 1654 default: 1655 pci_unmap_phys(&h, &config); 1656 return (1); 1657 } /* switch */ 1658 } 1659 1660 /* 1661 * Now that memory locations are assigned, 1662 * update the assigned address property. 1663 */ 1664 1665 FC_DEBUG1(1, CE_CONT, "updating assigned-addresss for %x\n", 1666 phys_spec.pci_phys_hi); 1667 1668 if (pfc_remove_assigned_prop(dip, &phys_spec)) { 1669 pci_unmap_phys(&h, &config); 1670 return (1); 1671 } 1672 1673 pci_unmap_phys(&h, &config); 1674 1675 return (0); 1676 } 1677 1678 1679 int 1680 pci_map_phys(dev_info_t *dip, pci_regspec_t *phys_spec, 1681 caddr_t *addrp, ddi_device_acc_attr_t *accattrp, 1682 ddi_acc_handle_t *handlep) 1683 { 1684 ddi_map_req_t mr; 1685 ddi_acc_hdl_t *hp; 1686 int result; 1687 1688 *handlep = impl_acc_hdl_alloc(KM_SLEEP, NULL); 1689 hp = impl_acc_hdl_get(*handlep); 1690 hp->ah_vers = VERS_ACCHDL; 1691 hp->ah_dip = dip; 1692 hp->ah_rnumber = 0; 1693 hp->ah_offset = 0; 1694 hp->ah_len = 0; 1695 hp->ah_acc = *accattrp; 1696 1697 mr.map_op = DDI_MO_MAP_LOCKED; 1698 mr.map_type = DDI_MT_REGSPEC; 1699 mr.map_obj.rp = (struct regspec *)phys_spec; 1700 mr.map_prot = PROT_READ | PROT_WRITE; 1701 mr.map_flags = DDI_MF_KERNEL_MAPPING; 1702 mr.map_handlep = hp; 1703 mr.map_vers = DDI_MAP_VERSION; 1704 1705 result = ddi_map(dip, &mr, 0, 0, addrp); 1706 1707 if (result != DDI_SUCCESS) { 1708 impl_acc_hdl_free(*handlep); 1709 *handlep = (ddi_acc_handle_t)NULL; 1710 } else { 1711 hp->ah_addr = *addrp; 1712 } 1713 1714 return (result); 1715 } 1716 1717 void 1718 pci_unmap_phys(ddi_acc_handle_t *handlep, pci_regspec_t *ph) 1719 { 1720 ddi_map_req_t mr; 1721 ddi_acc_hdl_t *hp; 1722 1723 hp = impl_acc_hdl_get(*handlep); 1724 ASSERT(hp); 1725 1726 mr.map_op = DDI_MO_UNMAP; 1727 mr.map_type = DDI_MT_REGSPEC; 1728 mr.map_obj.rp = (struct regspec *)ph; 1729 mr.map_prot = PROT_READ | PROT_WRITE; 1730 mr.map_flags = DDI_MF_KERNEL_MAPPING; 1731 mr.map_handlep = hp; 1732 mr.map_vers = DDI_MAP_VERSION; 1733 1734 (void) ddi_map(hp->ah_dip, &mr, hp->ah_offset, 1735 hp->ah_len, &hp->ah_addr); 1736 1737 impl_acc_hdl_free(*handlep); 1738 1739 1740 *handlep = (ddi_acc_handle_t)NULL; 1741 } 1742 1743 int 1744 pfc_update_assigned_prop(dev_info_t *dip, pci_regspec_t *newone) 1745 { 1746 int alen; 1747 pci_regspec_t *assigned; 1748 caddr_t newreg; 1749 uint_t status; 1750 1751 status = ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 1752 "assigned-addresses", (caddr_t)&assigned, &alen); 1753 switch (status) { 1754 case DDI_PROP_SUCCESS: 1755 break; 1756 case DDI_PROP_NO_MEMORY: 1757 return (1); 1758 default: 1759 (void) ndi_prop_update_int_array(DDI_DEV_T_NONE, dip, 1760 "assigned-addresses", (int *)newone, 1761 sizeof (*newone)/sizeof (int)); 1762 return (0); 1763 } 1764 1765 /* 1766 * Allocate memory for the existing 1767 * assigned-addresses(s) plus one and then 1768 * build it. 1769 */ 1770 1771 newreg = kmem_zalloc(alen+sizeof (*newone), KM_SLEEP); 1772 1773 bcopy(assigned, newreg, alen); 1774 bcopy(newone, newreg + alen, sizeof (*newone)); 1775 1776 /* 1777 * Write out the new "assigned-addresses" spec 1778 */ 1779 (void) ndi_prop_update_int_array(DDI_DEV_T_NONE, dip, 1780 "assigned-addresses", (int *)newreg, 1781 (alen + sizeof (*newone))/sizeof (int)); 1782 1783 kmem_free((caddr_t)newreg, alen+sizeof (*newone)); 1784 1785 return (0); 1786 } 1787 int 1788 pfc_remove_assigned_prop(dev_info_t *dip, pci_regspec_t *oldone) 1789 { 1790 int alen, new_len, num_entries, i; 1791 pci_regspec_t *assigned; 1792 uint_t status; 1793 1794 status = ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 1795 "assigned-addresses", (caddr_t)&assigned, &alen); 1796 switch (status) { 1797 case DDI_PROP_SUCCESS: 1798 break; 1799 case DDI_PROP_NO_MEMORY: 1800 return (1); 1801 default: 1802 return (0); 1803 } 1804 1805 num_entries = alen / sizeof (pci_regspec_t); 1806 new_len = alen - sizeof (pci_regspec_t); 1807 1808 /* 1809 * Search for the memory being removed. 1810 */ 1811 for (i = 0; i < num_entries; i++) { 1812 if (assigned[i].pci_phys_hi == oldone->pci_phys_hi) { 1813 if (new_len == 0) { 1814 (void) ndi_prop_remove(DDI_DEV_T_NONE, dip, 1815 "assigned-addresses"); 1816 break; 1817 } 1818 if ((new_len - (i * sizeof (pci_regspec_t))) 1819 == 0) { 1820 FC_DEBUG1(1, CE_CONT, "assigned-address entry " 1821 "%x removed from property (last entry)\n", 1822 oldone->pci_phys_hi); 1823 } else { 1824 bcopy((void *)(assigned + i + 1), 1825 (void *)(assigned + i), 1826 (new_len - (i * sizeof (pci_regspec_t)))); 1827 1828 FC_DEBUG1(1, CE_CONT, "assigned-address entry " 1829 "%x removed from property\n", 1830 oldone->pci_phys_hi); 1831 } 1832 (void) ndi_prop_update_int_array(DDI_DEV_T_NONE, 1833 dip, "assigned-addresses", (int *)assigned, 1834 (new_len/sizeof (int))); 1835 1836 break; 1837 } 1838 } 1839 1840 return (0); 1841 } 1842 /* 1843 * we recognize the non transparent bridge child nodes with the 1844 * following property. This is specific to this implementation only. 1845 * This property is specific to AP nodes only. 1846 */ 1847 #define PCICFG_DEV_CONF_MAP_PROP "pci-parent-indirect" 1848 1849 /* 1850 * If a non transparent bridge drives a hotplug/hotswap bus, then 1851 * the following property must be defined for the node either by 1852 * the driver or the OBP. 1853 */ 1854 #define PCICFG_BUS_CONF_MAP_PROP "pci-conf-indirect" 1855 1856 /* 1857 * this function is called only for SPARC platforms, where we may have 1858 * a mix n' match of direct vs indirectly mapped configuration space. 1859 */ 1860 /*ARGSUSED*/ 1861 static int 1862 fcpci_indirect_map(dev_info_t *dip) 1863 { 1864 int rc = DDI_FAILURE; 1865 1866 if (ddi_getprop(DDI_DEV_T_ANY, ddi_get_parent(dip), DDI_PROP_DONTPASS, 1867 PCICFG_DEV_CONF_MAP_PROP, DDI_FAILURE) != DDI_FAILURE) 1868 rc = DDI_SUCCESS; 1869 else 1870 if (ddi_getprop(DDI_DEV_T_ANY, ddi_get_parent(dip), 1871 DDI_PROP_DONTPASS, PCICFG_BUS_CONF_MAP_PROP, 1872 DDI_FAILURE) != DDI_FAILURE) 1873 rc = DDI_SUCCESS; 1874 1875 return (rc); 1876 } 1877