1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 /* 26 * Copyright 2012 Garrett D'Amore <garrett@damore.org>. All rights reserved. 27 */ 28 29 30 /* 31 * PCI to PCI bus bridge nexus driver 32 */ 33 34 #include <sys/conf.h> 35 #include <sys/kmem.h> 36 #include <sys/debug.h> 37 #include <sys/modctl.h> 38 #include <sys/autoconf.h> 39 #include <sys/ddi_impldefs.h> 40 #include <sys/ddi_subrdefs.h> 41 #include <sys/ddifm.h> 42 #include <sys/fm/util.h> 43 #include <sys/fm/protocol.h> 44 #include <sys/fm/io/pci.h> 45 #include <sys/pci.h> 46 #include <sys/pci/pci_nexus.h> 47 #include <sys/pci/pci_regs.h> 48 #include <sys/pci/pci_simba.h> 49 #include <sys/ddi.h> 50 #include <sys/sunddi.h> 51 #include <sys/sunndi.h> 52 #include <sys/promif.h> /* prom_printf */ 53 #include <sys/open.h> 54 #include <sys/stat.h> 55 #include <sys/file.h> 56 57 #if defined(DEBUG) && !defined(lint) 58 static uint_t simba_debug_flags = 0; 59 #define D_IDENTIFY 0x00000001 60 #define D_ATTACH 0x00000002 61 #define D_DETACH 0x00000004 62 #define D_MAP 0x00000008 63 #define D_CTLOPS 0x00000010 64 #define D_G_ISPEC 0x00000020 65 #define D_A_ISPEC 0x00000040 66 #define D_INIT_CLD 0x00400000 67 #define D_FAULT 0x00000080 68 69 #define DEBUG0(f, s) if ((f)& simba_debug_flags) \ 70 prom_printf("simba: " s "\n") 71 72 #define DEBUG1(f, s, a) if ((f)& simba_debug_flags) \ 73 prom_printf("simba: " s "\n", a) 74 75 #define DEBUG2(f, s, a, b) if ((f)& simba_debug_flags) \ 76 prom_printf("simba: " s "\n", a, b) 77 78 #define DEBUG3(f, s, a, b, c) if ((f)& simba_debug_flags) \ 79 prom_printf("simba: " s "\n", a, b, c) 80 81 #define DEBUG4(f, s, a, b, c, d) if ((f)& simba_debug_flags) \ 82 prom_printf("simba: " s "\n", a, b, c, d) 83 84 #define DEBUG5(f, s, a, b, c, d, e) if ((f)& simba_debug_flags) \ 85 prom_printf("simba: " s "\n", a, b, c, d, e) 86 87 #define DEBUG6(f, s, a, b, c, d, e, ff) if ((f)& simba_debug_flags) \ 88 prom_printf("simba: " s "\n", a, b, c, d, e, ff) 89 90 #else 91 92 #define DEBUG0(f, s) 93 #define DEBUG1(f, s, a) 94 #define DEBUG2(f, s, a, b) 95 #define DEBUG3(f, s, a, b, c) 96 #define DEBUG4(f, s, a, b, c, d) 97 #define DEBUG5(f, s, a, b, c, d, e) 98 #define DEBUG6(f, s, a, b, c, d, e, ff) 99 100 #endif 101 102 /* 103 * The variable controls the default setting of the command register 104 * for pci devices. See simba_initchild() for details. 105 */ 106 static ushort_t simba_command_default = PCI_COMM_SERR_ENABLE | 107 PCI_COMM_WAIT_CYC_ENAB | 108 PCI_COMM_PARITY_DETECT | 109 PCI_COMM_ME | 110 PCI_COMM_MAE | 111 PCI_COMM_IO; 112 113 static int simba_bus_map(dev_info_t *, dev_info_t *, ddi_map_req_t *, 114 off_t, off_t, caddr_t *); 115 static int simba_ctlops(dev_info_t *, dev_info_t *, ddi_ctl_enum_t, 116 void *, void *); 117 static int simba_fm_init_child(dev_info_t *dip, dev_info_t *tdip, int cap, 118 ddi_iblock_cookie_t *ibc); 119 static void simba_bus_enter(dev_info_t *dip, ddi_acc_handle_t handle); 120 static void simba_bus_exit(dev_info_t *dip, ddi_acc_handle_t handle); 121 122 struct bus_ops simba_bus_ops = { 123 BUSO_REV, 124 simba_bus_map, 125 0, 126 0, 127 0, 128 i_ddi_map_fault, 129 0, 130 ddi_dma_allochdl, 131 ddi_dma_freehdl, 132 ddi_dma_bindhdl, 133 ddi_dma_unbindhdl, 134 ddi_dma_flush, 135 ddi_dma_win, 136 ddi_dma_mctl, 137 simba_ctlops, 138 ddi_bus_prop_op, 139 ndi_busop_get_eventcookie, 140 ndi_busop_add_eventcall, 141 ndi_busop_remove_eventcall, 142 ndi_post_event, 143 0, 144 0, 145 0, 146 simba_fm_init_child, 147 NULL, 148 simba_bus_enter, 149 simba_bus_exit, 150 0, 151 i_ddi_intr_ops 152 }; 153 154 static int simba_open(dev_t *devp, int flags, int otyp, cred_t *credp); 155 static int simba_close(dev_t dev, int flags, int otyp, cred_t *credp); 156 static int simba_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, 157 cred_t *credp, int *rvalp); 158 159 static struct cb_ops simba_cb_ops = { 160 simba_open, /* open */ 161 simba_close, /* close */ 162 nulldev, /* strategy */ 163 nulldev, /* print */ 164 nulldev, /* dump */ 165 nulldev, /* read */ 166 nulldev, /* write */ 167 simba_ioctl, /* ioctl */ 168 nodev, /* devmap */ 169 nodev, /* mmap */ 170 nodev, /* segmap */ 171 nochpoll, /* poll */ 172 ddi_prop_op, /* cb_prop_op */ 173 NULL, /* streamtab */ 174 D_NEW | D_MP | D_HOTPLUG, /* Driver compatibility flag */ 175 CB_REV, /* rev */ 176 nodev, /* int (*cb_aread)() */ 177 nodev /* int (*cb_awrite)() */ 178 }; 179 180 static int simba_probe(dev_info_t *); 181 static int simba_attach(dev_info_t *devi, ddi_attach_cmd_t cmd); 182 static int simba_detach(dev_info_t *devi, ddi_detach_cmd_t cmd); 183 static int simba_info(dev_info_t *dip, ddi_info_cmd_t infocmd, 184 void *arg, void **result); 185 186 struct dev_ops simba_ops = { 187 DEVO_REV, /* devo_rev */ 188 0, /* refcnt */ 189 simba_info, /* info */ 190 nulldev, /* identify */ 191 simba_probe, /* probe */ 192 simba_attach, /* attach */ 193 simba_detach, /* detach */ 194 nulldev, /* reset */ 195 &simba_cb_ops, /* driver operations */ 196 &simba_bus_ops, /* bus operations */ 197 NULL, 198 ddi_quiesce_not_supported, /* devo_quiesce */ 199 }; 200 201 /* 202 * Module linkage information for the kernel. 203 */ 204 205 static struct modldrv modldrv = { 206 &mod_driverops, /* Type of module */ 207 "SIMBA PCI to PCI bridge nexus driver", 208 &simba_ops, /* driver ops */ 209 }; 210 211 static struct modlinkage modlinkage = { 212 MODREV_1, 213 (void *)&modldrv, 214 NULL 215 }; 216 217 /* 218 * Simba specific error state structure 219 */ 220 struct simba_errstate { 221 char *error; 222 ushort_t pci_cfg_stat; 223 ushort_t pci_cfg_sec_stat; 224 uint64_t afsr; 225 uint64_t afar; 226 int bridge_secondary; 227 }; 228 229 struct simba_cfg_state { 230 dev_info_t *dip; 231 ushort_t command; 232 uchar_t cache_line_size; 233 uchar_t latency_timer; 234 uchar_t header_type; 235 uchar_t bus_number; 236 uchar_t sec_bus_number; 237 uchar_t sub_bus_number; 238 uchar_t sec_latency_timer; 239 ushort_t bridge_control; 240 }; 241 242 /* 243 * soft state pointer and structure template: 244 */ 245 static void *simba_state; 246 247 typedef struct { 248 249 dev_info_t *dip; 250 251 /* 252 * configuration register state for the bus: 253 */ 254 ddi_acc_handle_t config_handle; 255 uchar_t simba_cache_line_size; 256 uchar_t simba_latency_timer; 257 258 /* 259 * cpr support: 260 */ 261 uint_t config_state_index; 262 struct simba_cfg_state *simba_config_state_p; 263 ddi_iblock_cookie_t fm_ibc; 264 int fm_cap; 265 kmutex_t simba_mutex; 266 uint_t simba_soft_state; 267 #define SIMBA_SOFT_STATE_CLOSED 0x00 268 #define SIMBA_SOFT_STATE_OPEN 0x01 269 #define SIMBA_SOFT_STATE_OPEN_EXCL 0x02 270 } simba_devstate_t; 271 272 /* 273 * The following variable enables a workaround for the following obp bug: 274 * 275 * 1234181 - obp should set latency timer registers in pci 276 * configuration header 277 * 278 * Until this bug gets fixed in the obp, the following workaround should 279 * be enabled. 280 */ 281 static uint_t simba_set_latency_timer_register = 1; 282 283 /* 284 * The following variable enables a workaround for an obp bug to be 285 * submitted. A bug requesting a workaround fof this problem has 286 * been filed: 287 * 288 * 1235094 - need workarounds on positron nexus drivers to set cache 289 * line size registers 290 * 291 * Until this bug gets fixed in the obp, the following workaround should 292 * be enabled. 293 */ 294 static uint_t simba_set_cache_line_size_register = 1; 295 296 297 /* 298 * forward function declarations: 299 */ 300 static void simba_uninitchild(dev_info_t *); 301 static int simba_initchild(dev_info_t *child); 302 static void simba_save_config_regs(simba_devstate_t *simba_p); 303 static void simba_restore_config_regs(simba_devstate_t *simba_p); 304 static int simba_err_callback(dev_info_t *dip, ddi_fm_error_t *derr, 305 const void *impl_data); 306 307 int 308 _init(void) 309 { 310 int e; 311 312 DEBUG0(D_ATTACH, "_init() installing module...\n"); 313 if ((e = ddi_soft_state_init(&simba_state, sizeof (simba_devstate_t), 314 1)) == 0 && (e = mod_install(&modlinkage)) != 0) 315 ddi_soft_state_fini(&simba_state); 316 317 DEBUG0(D_ATTACH, "_init() module installed\n"); 318 return (e); 319 } 320 321 int 322 _fini(void) 323 { 324 int e; 325 DEBUG0(D_ATTACH, "_fini() removing module...\n"); 326 if ((e = mod_remove(&modlinkage)) == 0) 327 ddi_soft_state_fini(&simba_state); 328 return (e); 329 } 330 331 int 332 _info(struct modinfo *modinfop) 333 { 334 DEBUG0(D_ATTACH, "_info() called.\n"); 335 return (mod_info(&modlinkage, modinfop)); 336 } 337 338 /*ARGSUSED*/ 339 static int 340 simba_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) 341 { 342 simba_devstate_t *simba_p; /* per simba state pointer */ 343 int instance; 344 345 instance = getminor((dev_t)arg); 346 simba_p = (simba_devstate_t *)ddi_get_soft_state(simba_state, 347 instance); 348 349 switch (infocmd) { 350 default: 351 return (DDI_FAILURE); 352 353 case DDI_INFO_DEVT2INSTANCE: 354 *result = (void *)(uintptr_t)instance; 355 return (DDI_SUCCESS); 356 357 case DDI_INFO_DEVT2DEVINFO: 358 if (simba_p == NULL) 359 return (DDI_FAILURE); 360 *result = (void *)simba_p->dip; 361 return (DDI_SUCCESS); 362 } 363 } 364 365 /*ARGSUSED*/ 366 static int 367 simba_probe(register dev_info_t *devi) 368 { 369 DEBUG0(D_ATTACH, "simba_probe() called.\n"); 370 return (DDI_PROBE_SUCCESS); 371 } 372 373 /*ARGSUSED*/ 374 static int 375 simba_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) 376 { 377 int instance; 378 simba_devstate_t *simba; 379 380 switch (cmd) { 381 case DDI_ATTACH: 382 383 DEBUG1(D_ATTACH, "attach(%p) ATTACH\n", devi); 384 385 /* 386 * Make sure the "device_type" property exists. 387 */ 388 (void) ddi_prop_update_string(DDI_DEV_T_NONE, devi, 389 "device_type", "pci"); 390 391 /* 392 * Allocate and get soft state structure. 393 */ 394 instance = ddi_get_instance(devi); 395 if (ddi_soft_state_zalloc(simba_state, instance) != DDI_SUCCESS) 396 return (DDI_FAILURE); 397 simba = (simba_devstate_t *)ddi_get_soft_state(simba_state, 398 instance); 399 simba->dip = devi; 400 mutex_init(&simba->simba_mutex, NULL, MUTEX_DRIVER, NULL); 401 simba->simba_soft_state = SIMBA_SOFT_STATE_CLOSED; 402 403 /* 404 * create minor node for devctl interfaces 405 */ 406 if (ddi_create_minor_node(devi, "devctl", S_IFCHR, instance, 407 DDI_NT_NEXUS, 0) != DDI_SUCCESS) { 408 mutex_destroy(&simba->simba_mutex); 409 ddi_soft_state_free(simba_state, instance); 410 return (DDI_FAILURE); 411 } 412 413 if (pci_config_setup(devi, &simba->config_handle) != 414 DDI_SUCCESS) { 415 ddi_remove_minor_node(devi, "devctl"); 416 mutex_destroy(&simba->simba_mutex); 417 ddi_soft_state_free(simba_state, instance); 418 return (DDI_FAILURE); 419 } 420 421 /* 422 * Simba cache line size is 64 bytes and hardwired. 423 */ 424 simba->simba_cache_line_size = 425 pci_config_get8(simba->config_handle, 426 PCI_CONF_CACHE_LINESZ); 427 simba->simba_latency_timer = 428 pci_config_get8(simba->config_handle, 429 PCI_CONF_LATENCY_TIMER); 430 431 /* simba specific, clears up the pri/sec status registers */ 432 pci_config_put16(simba->config_handle, 0x6, 0xffff); 433 pci_config_put16(simba->config_handle, 0x1e, 0xffff); 434 435 DEBUG2(D_ATTACH, "simba_attach(): clsz=%x, lt=%x\n", 436 simba->simba_cache_line_size, 437 simba->simba_latency_timer); 438 439 /* 440 * Initialize FMA support 441 */ 442 simba->fm_cap = DDI_FM_EREPORT_CAPABLE | DDI_FM_ERRCB_CAPABLE | 443 DDI_FM_ACCCHK_CAPABLE | DDI_FM_DMACHK_CAPABLE; 444 445 /* 446 * Call parent to get it's capablity 447 */ 448 ddi_fm_init(devi, &simba->fm_cap, &simba->fm_ibc); 449 450 ASSERT((simba->fm_cap & DDI_FM_ERRCB_CAPABLE) && 451 (simba->fm_cap & DDI_FM_EREPORT_CAPABLE)); 452 453 pci_ereport_setup(devi); 454 455 ddi_fm_handler_register(devi, simba_err_callback, simba); 456 457 ddi_report_dev(devi); 458 DEBUG0(D_ATTACH, "attach(): ATTACH done\n"); 459 return (DDI_SUCCESS); 460 461 case DDI_RESUME: 462 463 /* 464 * Get the soft state structure for the bridge. 465 */ 466 simba = (simba_devstate_t *) 467 ddi_get_soft_state(simba_state, ddi_get_instance(devi)); 468 simba_restore_config_regs(simba); 469 return (DDI_SUCCESS); 470 } 471 return (DDI_FAILURE); 472 } 473 474 /*ARGSUSED*/ 475 static int 476 simba_detach(dev_info_t *devi, ddi_detach_cmd_t cmd) 477 { 478 simba_devstate_t *simba; 479 simba = (simba_devstate_t *) 480 ddi_get_soft_state(simba_state, ddi_get_instance(devi)); 481 482 switch (cmd) { 483 case DDI_DETACH: 484 DEBUG0(D_DETACH, "detach() called\n"); 485 ddi_fm_handler_unregister(devi); 486 pci_ereport_teardown(devi); 487 ddi_fm_fini(devi); 488 pci_config_teardown(&simba->config_handle); 489 (void) ddi_prop_remove(DDI_DEV_T_NONE, devi, "device_type"); 490 ddi_remove_minor_node(devi, "devctl"); 491 mutex_destroy(&simba->simba_mutex); 492 ddi_soft_state_free(simba_state, ddi_get_instance(devi)); 493 return (DDI_SUCCESS); 494 495 case DDI_SUSPEND: 496 simba_save_config_regs(simba); 497 return (DDI_SUCCESS); 498 } 499 return (DDI_FAILURE); 500 } 501 502 /*ARGSUSED*/ 503 static int 504 simba_bus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp, 505 off_t offset, off_t len, caddr_t *vaddrp) 506 { 507 register dev_info_t *pdip; 508 509 DEBUG3(D_MAP, "simba_bus_map(): dip=%p, rdip=%p, mp=%p", dip, rdip, mp); 510 DEBUG3(D_MAP, "simba_bus_map(): offset=%lx, len=%lx, vaddrp=%p", 511 offset, len, vaddrp); 512 513 pdip = (dev_info_t *)DEVI(dip)->devi_parent; 514 return ((DEVI(pdip)->devi_ops->devo_bus_ops->bus_map) 515 (pdip, rdip, mp, offset, len, vaddrp)); 516 } 517 518 /* 519 * Registered error handling callback with our parent 520 */ 521 static int 522 simba_err_callback(dev_info_t *dip, ddi_fm_error_t *derr, const void *impl_data) 523 { 524 simba_devstate_t *simba = (simba_devstate_t *)impl_data; 525 struct simba_errstate simba_err; 526 int ret = 0; 527 528 bzero(&simba_err, sizeof (struct simba_errstate)); 529 simba_err.afsr = pci_config_get64(simba->config_handle, 0xe8); 530 simba_err.afar = pci_config_get64(simba->config_handle, 0xf0); 531 derr->fme_ena = fm_ena_generate(0, FM_ENA_FMT1); 532 533 pci_ereport_post(dip, derr, NULL); 534 ret = derr->fme_status; 535 536 DEBUG6(D_FAULT, "%s-%d: cleaning up fault bits %x %x %x.%8x\n", 537 ddi_driver_name(simba->dip), ddi_get_instance(simba->dip), 538 simba_err.pci_cfg_stat, simba_err.pci_cfg_sec_stat, 539 (uint_t)(simba_err.afsr >> 32), (uint_t)simba_err.afsr); 540 pci_config_put64(simba->config_handle, 0xe8, simba_err.afsr); 541 542 return (ret); 543 } 544 545 #if defined(DEBUG) && !defined(lint) 546 static char *ops[] = 547 { 548 "DDI_CTLOPS_DMAPMAPC", 549 "DDI_CTLOPS_INITCHILD", 550 "DDI_CTLOPS_UNINITCHILD", 551 "DDI_CTLOPS_REPORTDEV", 552 "DDI_CTLOPS_REPORTINT", 553 "DDI_CTLOPS_REGSIZE", 554 "DDI_CTLOPS_NREGS", 555 "DDI_CTLOPS_RESERVED0", 556 "DDI_CTLOPS_SIDDEV", 557 "DDI_CTLOPS_SLAVEONLY", 558 "DDI_CTLOPS_AFFINITY", 559 "DDI_CTLOPS_IOMIN", 560 "DDI_CTLOPS_PTOB", 561 "DDI_CTLOPS_BTOP", 562 "DDI_CTLOPS_BTOPR", 563 "DDI_CTLOPS_RESERVED1", 564 "DDI_CTLOPS_RESERVED2", 565 "DDI_CTLOPS_RESERVED3", 566 "DDI_CTLOPS_RESERVED4", 567 "DDI_CTLOPS_RESERVED5", 568 "DDI_CTLOPS_DVMAPAGESIZE", 569 "DDI_CTLOPS_POWER", 570 "DDI_CTLOPS_ATTACH", 571 "DDI_CTLOPS_DETACH", 572 "DDI_CTLOPS_POKE", 573 "DDI_CTLOPS_PEEK" 574 }; 575 #endif 576 577 /*ARGSUSED*/ 578 static int 579 simba_ctlops(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t ctlop, 580 void *arg, void *result) 581 { 582 int reglen; 583 int rn; 584 int totreg; 585 pci_regspec_t *drv_regp; 586 587 DEBUG6(D_CTLOPS, 588 "simba_ctlops(): dip=%p rdip=%p ctlop=%x-%s arg=%p result=%p", 589 dip, rdip, ctlop, ctlop < (sizeof (ops) / sizeof (ops[0])) ? 590 ops[ctlop] : "Unknown", arg, result); 591 592 switch (ctlop) { 593 case DDI_CTLOPS_REPORTDEV: 594 if (rdip == (dev_info_t *)0) 595 return (DDI_FAILURE); 596 cmn_err(CE_CONT, "?PCI-device: %s@%s, %s%d\n", 597 ddi_node_name(rdip), ddi_get_name_addr(rdip), 598 ddi_driver_name(rdip), 599 ddi_get_instance(rdip)); 600 return (DDI_SUCCESS); 601 602 case DDI_CTLOPS_INITCHILD: 603 return (simba_initchild((dev_info_t *)arg)); 604 605 case DDI_CTLOPS_UNINITCHILD: 606 simba_uninitchild((dev_info_t *)arg); 607 return (DDI_SUCCESS); 608 609 case DDI_CTLOPS_SIDDEV: 610 return (DDI_SUCCESS); 611 612 case DDI_CTLOPS_REGSIZE: 613 case DDI_CTLOPS_NREGS: 614 if (rdip == (dev_info_t *)0) 615 return (DDI_FAILURE); 616 break; 617 618 default: 619 DEBUG0(D_CTLOPS, "simba_ctlops(): calling ddi_ctlops()"); 620 return (ddi_ctlops(dip, rdip, ctlop, arg, result)); 621 } 622 623 *(int *)result = 0; 624 if (ddi_getlongprop(DDI_DEV_T_ANY, rdip, 625 DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, "reg", 626 (caddr_t)&drv_regp, ®len) != DDI_SUCCESS) 627 return (DDI_FAILURE); 628 629 totreg = reglen / sizeof (pci_regspec_t); 630 if (ctlop == DDI_CTLOPS_NREGS) 631 *(int *)result = totreg; 632 else if (ctlop == DDI_CTLOPS_REGSIZE) { 633 rn = *(int *)arg; 634 if (rn >= totreg) { 635 kmem_free(drv_regp, reglen); 636 return (DDI_FAILURE); 637 } 638 *(off_t *)result = drv_regp[rn].pci_size_low | 639 ((uint64_t)drv_regp[rn].pci_size_hi << 32); 640 } 641 642 kmem_free(drv_regp, reglen); 643 DEBUG1(D_CTLOPS, "simba_ctlops(): *result=%lx\n", *(off_t *)result); 644 return (DDI_SUCCESS); 645 } 646 647 static int 648 simba_name_child(dev_info_t *child, char *name, int namelen) 649 { 650 uint_t n, slot, func; 651 pci_regspec_t *pci_rp; 652 653 if (ndi_dev_is_persistent_node(child) == 0) { 654 char **unit_addr; 655 656 /* name .conf nodes by "unit-address" property" */ 657 if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, child, 658 DDI_PROP_DONTPASS, "unit-address", &unit_addr, &n) != 659 DDI_PROP_SUCCESS) { 660 cmn_err(CE_WARN, "cannot name node from %s.conf", 661 ddi_driver_name(child)); 662 return (DDI_FAILURE); 663 } 664 if (n != 1 || *unit_addr == NULL || **unit_addr == 0) { 665 cmn_err(CE_WARN, "unit-address property in %s.conf" 666 " not well-formed", ddi_driver_name(child)); 667 ddi_prop_free(unit_addr); 668 return (DDI_FAILURE); 669 } 670 671 (void) snprintf(name, namelen, "%s", *unit_addr); 672 ddi_prop_free(unit_addr); 673 return (DDI_SUCCESS); 674 } 675 676 /* name hardware nodes by "reg" property */ 677 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, child, 0, "reg", 678 (int **)&pci_rp, &n) != DDI_SUCCESS) 679 return (DDI_FAILURE); 680 681 /* get the device identifications */ 682 slot = PCI_REG_DEV_G(pci_rp->pci_phys_hi); 683 func = PCI_REG_FUNC_G(pci_rp->pci_phys_hi); 684 685 if (func != 0) 686 (void) snprintf(name, namelen, "%x,%x", slot, func); 687 else 688 (void) snprintf(name, namelen, "%x", slot); 689 690 ddi_prop_free(pci_rp); 691 return (DDI_SUCCESS); 692 } 693 694 static int 695 simba_initchild(dev_info_t *child) 696 { 697 char name[MAXNAMELEN]; 698 int i; 699 ddi_acc_handle_t config_handle; 700 ushort_t command_preserve, command; 701 uchar_t header_type; 702 uchar_t min_gnt, latency_timer; 703 simba_devstate_t *simba; 704 uint_t n; 705 706 DEBUG1(D_INIT_CLD, "simba_initchild(): child=%p\n", child); 707 708 /* 709 * Pseudo nodes indicate a prototype node with per-instance 710 * properties to be merged into the real h/w device node. 711 * The interpretation of the unit-address is DD[,F] 712 * where DD is the device id and F is the function. 713 */ 714 if (ndi_dev_is_persistent_node(child) == 0) { 715 extern int pci_allow_pseudo_children; 716 pci_regspec_t *pci_rp; 717 718 if (ddi_getlongprop(DDI_DEV_T_ANY, child, 719 DDI_PROP_DONTPASS, "reg", (caddr_t)&pci_rp, &i) == 720 DDI_SUCCESS) { 721 cmn_err(CE_WARN, 722 "cannot merge prototype from %s.conf", 723 ddi_driver_name(child)); 724 kmem_free(pci_rp, i); 725 return (DDI_NOT_WELL_FORMED); 726 } 727 728 if (simba_name_child(child, name, MAXNAMELEN) != DDI_SUCCESS) 729 return (DDI_NOT_WELL_FORMED); 730 731 ddi_set_name_addr(child, name); 732 ddi_set_parent_data(child, NULL); 733 734 /* 735 * Try to merge the properties from this prototype 736 * node into real h/w nodes. 737 */ 738 if (ndi_merge_node(child, simba_name_child) == DDI_SUCCESS) { 739 /* 740 * Merged ok - return failure to remove the node. 741 */ 742 simba_uninitchild(child); 743 return (DDI_FAILURE); 744 } 745 746 /* workaround for ddivs to run under PCI */ 747 if (pci_allow_pseudo_children) 748 return (DDI_SUCCESS); 749 750 /* 751 * The child was not merged into a h/w node, 752 * but there's not much we can do with it other 753 * than return failure to cause the node to be removed. 754 */ 755 cmn_err(CE_WARN, "!%s@%s: %s.conf properties not merged", 756 ddi_driver_name(child), ddi_get_name_addr(child), 757 ddi_driver_name(child)); 758 simba_uninitchild(child); 759 return (DDI_NOT_WELL_FORMED); 760 } 761 762 /* 763 * Initialize real h/w nodes 764 */ 765 if (simba_name_child(child, name, MAXNAMELEN) != DDI_SUCCESS) 766 return (DDI_FAILURE); 767 768 ddi_set_name_addr(child, name); 769 ddi_set_parent_data(child, NULL); 770 771 if (pci_config_setup(child, &config_handle) != DDI_SUCCESS) { 772 simba_uninitchild(child); 773 return (DDI_FAILURE); 774 } 775 776 DEBUG0(D_INIT_CLD, "simba_initchild(): pci_config_setup success!\n"); 777 778 /* 779 * Determine the configuration header type. 780 */ 781 header_type = pci_config_get8(config_handle, PCI_CONF_HEADER); 782 783 /* 784 * Support for the "command-preserve" property. 785 */ 786 command_preserve = ddi_prop_get_int(DDI_DEV_T_ANY, child, 787 DDI_PROP_DONTPASS, "command-preserve", 0); 788 command = pci_config_get16(config_handle, PCI_CONF_COMM); 789 command &= (command_preserve | PCI_COMM_BACK2BACK_ENAB); 790 command |= (simba_command_default & ~command_preserve); 791 pci_config_put16(config_handle, PCI_CONF_COMM, command); 792 793 /* clean up all PCI child devices status register */ 794 pci_config_put16(config_handle, PCI_CONF_STAT, 0xffff); 795 796 /* 797 * If the device has a primary bus control register then program it 798 * based on the settings in the command register. 799 */ 800 if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_ONE) { 801 ushort_t bcr = 802 pci_config_get16(config_handle, PCI_BCNF_BCNTRL); 803 if (simba_command_default & PCI_COMM_PARITY_DETECT) 804 bcr |= PCI_BCNF_BCNTRL_PARITY_ENABLE; 805 if (simba_command_default & PCI_COMM_SERR_ENABLE) 806 bcr |= PCI_BCNF_BCNTRL_SERR_ENABLE; 807 bcr |= PCI_BCNF_BCNTRL_MAST_AB_MODE; 808 pci_config_put8(config_handle, PCI_BCNF_BCNTRL, bcr); 809 } 810 811 simba = (simba_devstate_t *)ddi_get_soft_state(simba_state, 812 ddi_get_instance(ddi_get_parent(child))); 813 /* 814 * Initialize cache-line-size configuration register if needed. 815 */ 816 if (simba_set_cache_line_size_register && 817 ddi_getprop(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS, 818 "cache-line-size", 0) == 0) { 819 pci_config_put8(config_handle, PCI_CONF_CACHE_LINESZ, 820 simba->simba_cache_line_size); 821 n = pci_config_get8(config_handle, PCI_CONF_CACHE_LINESZ); 822 if (n != 0) 823 (void) ndi_prop_update_int(DDI_DEV_T_NONE, child, 824 "cache-line-size", n); 825 } 826 827 /* 828 * Initialize latency timer configuration registers if needed. 829 */ 830 if (simba_set_latency_timer_register && 831 ddi_getprop(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS, 832 "latency-timer", 0) == 0) { 833 834 if ((header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_ONE) { 835 latency_timer = simba->simba_latency_timer; 836 pci_config_put8(config_handle, PCI_BCNF_LATENCY_TIMER, 837 simba->simba_latency_timer); 838 } else { 839 min_gnt = pci_config_get8(config_handle, 840 PCI_CONF_MIN_G); 841 latency_timer = min_gnt * 8; 842 } 843 pci_config_put8(config_handle, PCI_CONF_LATENCY_TIMER, 844 latency_timer); 845 n = pci_config_get8(config_handle, PCI_CONF_LATENCY_TIMER); 846 if (n != 0) 847 (void) ndi_prop_update_int(DDI_DEV_T_NONE, child, 848 "latency-timer", n); 849 } 850 851 pci_config_teardown(&config_handle); 852 DEBUG0(D_INIT_CLD, "simba_initchild(): pci_config_teardown called\n"); 853 return (DDI_SUCCESS); 854 } 855 856 static void 857 simba_uninitchild(dev_info_t *dip) 858 { 859 ddi_set_name_addr(dip, NULL); 860 861 /* 862 * Strip the node to properly convert it back to prototype form 863 */ 864 impl_rem_dev_props(dip); 865 } 866 867 /* 868 * simba_save_config_regs 869 * 870 * This routine saves the state of the configuration registers of all 871 * the child nodes of each PBM. 872 * 873 * used by: simba_detach() on suspends 874 * 875 * return value: none 876 */ 877 static void 878 simba_save_config_regs(simba_devstate_t *simba_p) 879 { 880 int i; 881 dev_info_t *dip; 882 ddi_acc_handle_t ch; 883 struct simba_cfg_state *statep; 884 885 for (i = 0, dip = ddi_get_child(simba_p->dip); dip != NULL; 886 dip = ddi_get_next_sibling(dip)) { 887 if (i_ddi_devi_attached(dip)) 888 i++; 889 } 890 if (!i) 891 return; 892 simba_p->simba_config_state_p = 893 kmem_zalloc(i * sizeof (struct simba_cfg_state), KM_NOSLEEP); 894 if (!simba_p->simba_config_state_p) { 895 cmn_err(CE_WARN, "not enough memrory to save simba child\n"); 896 return; 897 } 898 simba_p->config_state_index = i; 899 900 for (statep = simba_p->simba_config_state_p, 901 dip = ddi_get_child(simba_p->dip); 902 dip != NULL; 903 dip = ddi_get_next_sibling(dip)) { 904 905 if (!i_ddi_devi_attached(dip)) { 906 DEBUG4(D_DETACH, "%s%d: skipping unattached %s%d\n", 907 ddi_driver_name(simba_p->dip), 908 ddi_get_instance(simba_p->dip), 909 ddi_driver_name(dip), 910 ddi_get_instance(dip)); 911 continue; 912 } 913 914 DEBUG4(D_DETACH, "%s%d: saving regs for %s%d\n", 915 ddi_driver_name(simba_p->dip), 916 ddi_get_instance(simba_p->dip), 917 ddi_driver_name(dip), 918 ddi_get_instance(dip)); 919 920 if (pci_config_setup(dip, &ch) != DDI_SUCCESS) { 921 DEBUG4(D_DETACH, "%s%d: can't config space for %s%d\n", 922 ddi_driver_name(simba_p->dip), 923 ddi_get_instance(simba_p->dip), 924 ddi_driver_name(dip), 925 ddi_get_instance(dip)); 926 continue; 927 } 928 929 DEBUG3(D_DETACH, "%s%d: saving child dip=%p\n", 930 ddi_driver_name(simba_p->dip), 931 ddi_get_instance(simba_p->dip), 932 dip); 933 934 statep->dip = dip; 935 statep->command = pci_config_get16(ch, PCI_CONF_COMM); 936 statep->header_type = pci_config_get8(ch, PCI_CONF_HEADER); 937 if ((statep->header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_ONE) 938 statep->bridge_control = 939 pci_config_get16(ch, PCI_BCNF_BCNTRL); 940 statep->cache_line_size = 941 pci_config_get8(ch, PCI_CONF_CACHE_LINESZ); 942 statep->latency_timer = 943 pci_config_get8(ch, PCI_CONF_LATENCY_TIMER); 944 if ((statep->header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_ONE) 945 statep->sec_latency_timer = 946 pci_config_get8(ch, PCI_BCNF_LATENCY_TIMER); 947 /* 948 * Simba specific. 949 */ 950 if (pci_config_get16(ch, PCI_CONF_VENID) == PCI_SIMBA_VENID && 951 pci_config_get16(ch, PCI_CONF_DEVID) == PCI_SIMBA_DEVID) { 952 953 statep->bus_number = 954 pci_config_get8(ch, PCI_BCNF_PRIBUS); 955 statep->sec_bus_number = 956 pci_config_get8(ch, PCI_BCNF_SECBUS); 957 statep->sub_bus_number = 958 pci_config_get8(ch, PCI_BCNF_SUBBUS); 959 statep->bridge_control = 960 pci_config_get16(ch, PCI_BCNF_BCNTRL); 961 } 962 pci_config_teardown(&ch); 963 statep++; 964 } 965 } 966 967 968 /* 969 * simba_restore_config_regs 970 * 971 * This routine restores the state of the configuration registers of all 972 * the child nodes of each PBM. 973 * 974 * used by: simba_attach() on resume 975 * 976 * return value: none 977 */ 978 static void 979 simba_restore_config_regs(simba_devstate_t *simba_p) 980 { 981 int i; 982 dev_info_t *dip; 983 ddi_acc_handle_t ch; 984 struct simba_cfg_state *statep = simba_p->simba_config_state_p; 985 if (!simba_p->config_state_index) 986 return; 987 988 for (i = 0; i < simba_p->config_state_index; i++, statep++) { 989 dip = statep->dip; 990 if (!dip) { 991 cmn_err(CE_WARN, 992 "%s%d: skipping bad dev info (%d)\n", 993 ddi_driver_name(simba_p->dip), 994 ddi_get_instance(simba_p->dip), 995 i); 996 continue; 997 } 998 999 DEBUG5(D_ATTACH, "%s%d: restoring regs for %p-%s%d\n", 1000 ddi_driver_name(simba_p->dip), 1001 ddi_get_instance(simba_p->dip), 1002 dip, 1003 ddi_driver_name(dip), 1004 ddi_get_instance(dip)); 1005 1006 if (pci_config_setup(dip, &ch) != DDI_SUCCESS) { 1007 DEBUG4(D_ATTACH, "%s%d: can't config space for %s%d\n", 1008 ddi_driver_name(simba_p->dip), 1009 ddi_get_instance(simba_p->dip), 1010 ddi_driver_name(dip), 1011 ddi_get_instance(dip)); 1012 continue; 1013 } 1014 pci_config_put16(ch, PCI_CONF_COMM, statep->command); 1015 if ((statep->header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_ONE) 1016 pci_config_put16(ch, PCI_BCNF_BCNTRL, 1017 statep->bridge_control); 1018 /* 1019 * Simba specific. 1020 */ 1021 if (pci_config_get16(ch, PCI_CONF_VENID) == PCI_SIMBA_VENID && 1022 pci_config_get16(ch, PCI_CONF_DEVID) == PCI_SIMBA_DEVID) { 1023 pci_config_put8(ch, PCI_BCNF_PRIBUS, 1024 statep->bus_number); 1025 pci_config_put8(ch, PCI_BCNF_SECBUS, 1026 statep->sec_bus_number); 1027 pci_config_put8(ch, PCI_BCNF_SUBBUS, 1028 statep->sub_bus_number); 1029 pci_config_put16(ch, PCI_BCNF_BCNTRL, 1030 statep->bridge_control); 1031 } 1032 1033 pci_config_put8(ch, PCI_CONF_CACHE_LINESZ, 1034 statep->cache_line_size); 1035 pci_config_put8(ch, PCI_CONF_LATENCY_TIMER, 1036 statep->latency_timer); 1037 if ((statep->header_type & PCI_HEADER_TYPE_M) == PCI_HEADER_ONE) 1038 pci_config_put8(ch, PCI_BCNF_LATENCY_TIMER, 1039 statep->sec_latency_timer); 1040 pci_config_teardown(&ch); 1041 } 1042 1043 kmem_free(simba_p->simba_config_state_p, 1044 simba_p->config_state_index * sizeof (struct simba_cfg_state)); 1045 simba_p->simba_config_state_p = NULL; 1046 simba_p->config_state_index = 0; 1047 } 1048 1049 /* ARGSUSED */ 1050 static int 1051 simba_open(dev_t *devp, int flags, int otyp, cred_t *credp) 1052 { 1053 simba_devstate_t *simba_p; 1054 1055 /* 1056 * Make sure the open is for the right file type. 1057 */ 1058 if (otyp != OTYP_CHR) 1059 return (EINVAL); 1060 1061 /* 1062 * Get the soft state structure for the device. 1063 */ 1064 simba_p = (simba_devstate_t *)ddi_get_soft_state(simba_state, 1065 getminor(*devp)); 1066 if (simba_p == NULL) 1067 return (ENXIO); 1068 1069 /* 1070 * Handle the open by tracking the device state. 1071 */ 1072 mutex_enter(&simba_p->simba_mutex); 1073 if (flags & FEXCL) { 1074 if (simba_p->simba_soft_state != SIMBA_SOFT_STATE_CLOSED) { 1075 mutex_exit(&simba_p->simba_mutex); 1076 return (EBUSY); 1077 } 1078 simba_p->simba_soft_state = SIMBA_SOFT_STATE_OPEN_EXCL; 1079 } else { 1080 if (simba_p->simba_soft_state == SIMBA_SOFT_STATE_OPEN_EXCL) { 1081 mutex_exit(&simba_p->simba_mutex); 1082 return (EBUSY); 1083 } 1084 simba_p->simba_soft_state = SIMBA_SOFT_STATE_OPEN; 1085 } 1086 mutex_exit(&simba_p->simba_mutex); 1087 return (0); 1088 } 1089 1090 1091 /* ARGSUSED */ 1092 static int 1093 simba_close(dev_t dev, int flags, int otyp, cred_t *credp) 1094 { 1095 simba_devstate_t *simba_p; 1096 1097 if (otyp != OTYP_CHR) 1098 return (EINVAL); 1099 1100 simba_p = (simba_devstate_t *)ddi_get_soft_state(simba_state, 1101 getminor(dev)); 1102 if (simba_p == NULL) 1103 return (ENXIO); 1104 1105 mutex_enter(&simba_p->simba_mutex); 1106 simba_p->simba_soft_state = SIMBA_SOFT_STATE_CLOSED; 1107 mutex_exit(&simba_p->simba_mutex); 1108 return (0); 1109 } 1110 1111 1112 /* 1113 * simba_ioctl: devctl hotplug controls 1114 */ 1115 /* ARGSUSED */ 1116 static int 1117 simba_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, 1118 int *rvalp) 1119 { 1120 simba_devstate_t *simba_p; 1121 dev_info_t *self; 1122 struct devctl_iocdata *dcp; 1123 uint_t bus_state; 1124 int rv = 0; 1125 1126 simba_p = (simba_devstate_t *)ddi_get_soft_state(simba_state, 1127 getminor(dev)); 1128 if (simba_p == NULL) 1129 return (ENXIO); 1130 1131 self = simba_p->dip; 1132 1133 /* 1134 * We can use the generic implementation for these ioctls 1135 */ 1136 switch (cmd) { 1137 case DEVCTL_DEVICE_GETSTATE: 1138 case DEVCTL_DEVICE_ONLINE: 1139 case DEVCTL_DEVICE_OFFLINE: 1140 case DEVCTL_BUS_GETSTATE: 1141 return (ndi_devctl_ioctl(self, cmd, arg, mode, 0)); 1142 } 1143 1144 /* 1145 * read devctl ioctl data 1146 */ 1147 if (ndi_dc_allochdl((void *)arg, &dcp) != NDI_SUCCESS) 1148 return (EFAULT); 1149 1150 switch (cmd) { 1151 1152 case DEVCTL_DEVICE_RESET: 1153 rv = ENOTSUP; 1154 break; 1155 1156 1157 case DEVCTL_BUS_QUIESCE: 1158 if (ndi_get_bus_state(self, &bus_state) == NDI_SUCCESS) 1159 if (bus_state == BUS_QUIESCED) 1160 break; 1161 (void) ndi_set_bus_state(self, BUS_QUIESCED); 1162 break; 1163 1164 case DEVCTL_BUS_UNQUIESCE: 1165 if (ndi_get_bus_state(self, &bus_state) == NDI_SUCCESS) 1166 if (bus_state == BUS_ACTIVE) 1167 break; 1168 (void) ndi_set_bus_state(self, BUS_ACTIVE); 1169 break; 1170 1171 case DEVCTL_BUS_RESET: 1172 rv = ENOTSUP; 1173 break; 1174 1175 case DEVCTL_BUS_RESETALL: 1176 rv = ENOTSUP; 1177 break; 1178 1179 default: 1180 rv = ENOTTY; 1181 } 1182 1183 ndi_dc_freehdl(dcp); 1184 return (rv); 1185 } 1186 1187 /* 1188 * Initialize FMA resources for children devices. Called when 1189 * child calls ddi_fm_init(). 1190 */ 1191 /*ARGSUSED*/ 1192 static int 1193 simba_fm_init_child(dev_info_t *dip, dev_info_t *tdip, int cap, 1194 ddi_iblock_cookie_t *ibc) 1195 { 1196 simba_devstate_t *simba_p = ddi_get_soft_state(simba_state, 1197 ddi_get_instance(dip)); 1198 1199 *ibc = simba_p->fm_ibc; 1200 return (simba_p->fm_cap); 1201 } 1202 1203 static void 1204 simba_bus_enter(dev_info_t *dip, ddi_acc_handle_t handle) 1205 { 1206 i_ndi_busop_access_enter(dip, handle); 1207 } 1208 1209 /* ARGSUSED */ 1210 static void 1211 simba_bus_exit(dev_info_t *dip, ddi_acc_handle_t handle) 1212 { 1213 i_ndi_busop_access_exit(dip, handle); 1214 } 1215