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.
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.
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]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 * Copyright 2012 Garrett D'Amore <garrett@damore.org>. All rights reserved.
31 * PCI to PCI bus bridge nexus driver
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>
46 #include <sys/pci/pci_nexus.h>
47 #include <sys/pci/pci_regs.h>
48 #include <sys/pci/pci_simba.h>
50 #include <sys/sunddi.h>
51 #include <sys/sunndi.h>
52 #include <sys/promif.h> /* prom_printf */
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
69 #define DEBUG0(f, s) if ((f)& simba_debug_flags) \
70 prom_printf("simba: " s "\n")
72 #define DEBUG1(f, s, a) if ((f)& simba_debug_flags) \
73 prom_printf("simba: " s "\n", a)
75 #define DEBUG2(f, s, a, b) if ((f)& simba_debug_flags) \
76 prom_printf("simba: " s "\n", a, b)
78 #define DEBUG3(f, s, a, b, c) if ((f)& simba_debug_flags) \
79 prom_printf("simba: " s "\n", a, b, c)
81 #define DEBUG4(f, s, a, b, c, d) if ((f)& simba_debug_flags) \
82 prom_printf("simba: " s "\n", a, b, c, d)
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)
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)
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)
103 * The variable controls the default setting of the command register
104 * for pci devices. See simba_initchild() for details.
106 static ushort_t simba_command_default
= PCI_COMM_SERR_ENABLE
|
107 PCI_COMM_WAIT_CYC_ENAB
|
108 PCI_COMM_PARITY_DETECT
|
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
,
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
);
122 struct bus_ops simba_bus_ops
= {
139 ndi_busop_get_eventcookie
,
140 ndi_busop_add_eventcall
,
141 ndi_busop_remove_eventcall
,
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
);
159 static struct cb_ops simba_cb_ops
= {
160 simba_open
, /* open */
161 simba_close
, /* close */
162 nulldev
, /* strategy */
167 simba_ioctl
, /* ioctl */
172 ddi_prop_op
, /* cb_prop_op */
173 NULL
, /* streamtab */
174 D_NEW
| D_MP
| D_HOTPLUG
, /* Driver compatibility flag */
176 nodev
, /* int (*cb_aread)() */
177 nodev
/* int (*cb_awrite)() */
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
);
186 struct dev_ops simba_ops
= {
187 DEVO_REV
, /* devo_rev */
189 simba_info
, /* info */
190 nulldev
, /* identify */
191 simba_probe
, /* probe */
192 simba_attach
, /* attach */
193 simba_detach
, /* detach */
195 &simba_cb_ops
, /* driver operations */
196 &simba_bus_ops
, /* bus operations */
198 ddi_quiesce_not_supported
, /* devo_quiesce */
202 * Module linkage information for the kernel.
205 static struct modldrv modldrv
= {
206 &mod_driverops
, /* Type of module */
207 "SIMBA PCI to PCI bridge nexus driver",
208 &simba_ops
, /* driver ops */
211 static struct modlinkage modlinkage
= {
218 * Simba specific error state structure
220 struct simba_errstate
{
222 ushort_t pci_cfg_stat
;
223 ushort_t pci_cfg_sec_stat
;
226 int bridge_secondary
;
229 struct simba_cfg_state
{
232 uchar_t cache_line_size
;
233 uchar_t latency_timer
;
236 uchar_t sec_bus_number
;
237 uchar_t sub_bus_number
;
238 uchar_t sec_latency_timer
;
239 ushort_t bridge_control
;
243 * soft state pointer and structure template:
245 static void *simba_state
;
252 * configuration register state for the bus:
254 ddi_acc_handle_t config_handle
;
255 uchar_t simba_cache_line_size
;
256 uchar_t simba_latency_timer
;
261 uint_t config_state_index
;
262 struct simba_cfg_state
*simba_config_state_p
;
263 ddi_iblock_cookie_t fm_ibc
;
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
273 * The following variable enables a workaround for the following obp bug:
275 * 1234181 - obp should set latency timer registers in pci
276 * configuration header
278 * Until this bug gets fixed in the obp, the following workaround should
281 static uint_t simba_set_latency_timer_register
= 1;
284 * The following variable enables a workaround for an obp bug to be
285 * submitted. A bug requesting a workaround fof this problem has
288 * 1235094 - need workarounds on positron nexus drivers to set cache
289 * line size registers
291 * Until this bug gets fixed in the obp, the following workaround should
294 static uint_t simba_set_cache_line_size_register
= 1;
298 * forward function declarations:
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
);
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
);
317 DEBUG0(D_ATTACH
, "_init() module installed\n");
325 DEBUG0(D_ATTACH
, "_fini() removing module...\n");
326 if ((e
= mod_remove(&modlinkage
)) == 0)
327 ddi_soft_state_fini(&simba_state
);
332 _info(struct modinfo
*modinfop
)
334 DEBUG0(D_ATTACH
, "_info() called.\n");
335 return (mod_info(&modlinkage
, modinfop
));
340 simba_info(dev_info_t
*dip
, ddi_info_cmd_t infocmd
, void *arg
, void **result
)
342 simba_devstate_t
*simba_p
; /* per simba state pointer */
345 instance
= getminor((dev_t
)arg
);
346 simba_p
= (simba_devstate_t
*)ddi_get_soft_state(simba_state
,
351 return (DDI_FAILURE
);
353 case DDI_INFO_DEVT2INSTANCE
:
354 *result
= (void *)(uintptr_t)instance
;
355 return (DDI_SUCCESS
);
357 case DDI_INFO_DEVT2DEVINFO
:
359 return (DDI_FAILURE
);
360 *result
= (void *)simba_p
->dip
;
361 return (DDI_SUCCESS
);
367 simba_probe(register dev_info_t
*devi
)
369 DEBUG0(D_ATTACH
, "simba_probe() called.\n");
370 return (DDI_PROBE_SUCCESS
);
375 simba_attach(dev_info_t
*devi
, ddi_attach_cmd_t cmd
)
378 simba_devstate_t
*simba
;
383 DEBUG1(D_ATTACH
, "attach(%p) ATTACH\n", devi
);
386 * Make sure the "device_type" property exists.
388 (void) ddi_prop_update_string(DDI_DEV_T_NONE
, devi
,
389 "device_type", "pci");
392 * Allocate and get soft state structure.
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
,
400 mutex_init(&simba
->simba_mutex
, NULL
, MUTEX_DRIVER
, NULL
);
401 simba
->simba_soft_state
= SIMBA_SOFT_STATE_CLOSED
;
404 * create minor node for devctl interfaces
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
);
413 if (pci_config_setup(devi
, &simba
->config_handle
) !=
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
);
422 * Simba cache line size is 64 bytes and hardwired.
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
);
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);
435 DEBUG2(D_ATTACH
, "simba_attach(): clsz=%x, lt=%x\n",
436 simba
->simba_cache_line_size
,
437 simba
->simba_latency_timer
);
440 * Initialize FMA support
442 simba
->fm_cap
= DDI_FM_EREPORT_CAPABLE
| DDI_FM_ERRCB_CAPABLE
|
443 DDI_FM_ACCCHK_CAPABLE
| DDI_FM_DMACHK_CAPABLE
;
446 * Call parent to get it's capablity
448 ddi_fm_init(devi
, &simba
->fm_cap
, &simba
->fm_ibc
);
450 ASSERT((simba
->fm_cap
& DDI_FM_ERRCB_CAPABLE
) &&
451 (simba
->fm_cap
& DDI_FM_EREPORT_CAPABLE
));
453 pci_ereport_setup(devi
);
455 ddi_fm_handler_register(devi
, simba_err_callback
, simba
);
457 ddi_report_dev(devi
);
458 DEBUG0(D_ATTACH
, "attach(): ATTACH done\n");
459 return (DDI_SUCCESS
);
464 * Get the soft state structure for the bridge.
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
);
471 return (DDI_FAILURE
);
476 simba_detach(dev_info_t
*devi
, ddi_detach_cmd_t cmd
)
478 simba_devstate_t
*simba
;
479 simba
= (simba_devstate_t
*)
480 ddi_get_soft_state(simba_state
, ddi_get_instance(devi
));
484 DEBUG0(D_DETACH
, "detach() called\n");
485 ddi_fm_handler_unregister(devi
);
486 pci_ereport_teardown(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
);
496 simba_save_config_regs(simba
);
497 return (DDI_SUCCESS
);
499 return (DDI_FAILURE
);
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
)
507 register dev_info_t
*pdip
;
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
);
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
));
519 * Registered error handling callback with our parent
522 simba_err_callback(dev_info_t
*dip
, ddi_fm_error_t
*derr
, const void *impl_data
)
524 simba_devstate_t
*simba
= (simba_devstate_t
*)impl_data
;
525 struct simba_errstate simba_err
;
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
);
533 pci_ereport_post(dip
, derr
, NULL
);
534 ret
= derr
->fme_status
;
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
);
545 #if defined(DEBUG) && !defined(lint)
548 "DDI_CTLOPS_DMAPMAPC",
549 "DDI_CTLOPS_INITCHILD",
550 "DDI_CTLOPS_UNINITCHILD",
551 "DDI_CTLOPS_REPORTDEV",
552 "DDI_CTLOPS_REPORTINT",
553 "DDI_CTLOPS_REGSIZE",
555 "DDI_CTLOPS_RESERVED0",
557 "DDI_CTLOPS_SLAVEONLY",
558 "DDI_CTLOPS_AFFINITY",
563 "DDI_CTLOPS_RESERVED1",
564 "DDI_CTLOPS_RESERVED2",
565 "DDI_CTLOPS_RESERVED3",
566 "DDI_CTLOPS_RESERVED4",
567 "DDI_CTLOPS_RESERVED5",
568 "DDI_CTLOPS_DVMAPAGESIZE",
579 simba_ctlops(dev_info_t
*dip
, dev_info_t
*rdip
, ddi_ctl_enum_t ctlop
,
580 void *arg
, void *result
)
585 pci_regspec_t
*drv_regp
;
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
);
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
);
602 case DDI_CTLOPS_INITCHILD
:
603 return (simba_initchild((dev_info_t
*)arg
));
605 case DDI_CTLOPS_UNINITCHILD
:
606 simba_uninitchild((dev_info_t
*)arg
);
607 return (DDI_SUCCESS
);
609 case DDI_CTLOPS_SIDDEV
:
610 return (DDI_SUCCESS
);
612 case DDI_CTLOPS_REGSIZE
:
613 case DDI_CTLOPS_NREGS
:
614 if (rdip
== (dev_info_t
*)0)
615 return (DDI_FAILURE
);
619 DEBUG0(D_CTLOPS
, "simba_ctlops(): calling ddi_ctlops()");
620 return (ddi_ctlops(dip
, rdip
, ctlop
, arg
, result
));
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
);
629 totreg
= reglen
/ sizeof (pci_regspec_t
);
630 if (ctlop
== DDI_CTLOPS_NREGS
)
631 *(int *)result
= totreg
;
632 else if (ctlop
== DDI_CTLOPS_REGSIZE
) {
635 kmem_free(drv_regp
, reglen
);
636 return (DDI_FAILURE
);
638 *(off_t
*)result
= drv_regp
[rn
].pci_size_low
|
639 ((uint64_t)drv_regp
[rn
].pci_size_hi
<< 32);
642 kmem_free(drv_regp
, reglen
);
643 DEBUG1(D_CTLOPS
, "simba_ctlops(): *result=%lx\n", *(off_t
*)result
);
644 return (DDI_SUCCESS
);
648 simba_name_child(dev_info_t
*child
, char *name
, int namelen
)
650 uint_t n
, slot
, func
;
651 pci_regspec_t
*pci_rp
;
653 if (ndi_dev_is_persistent_node(child
) == 0) {
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
) !=
660 cmn_err(CE_WARN
, "cannot name node from %s.conf",
661 ddi_driver_name(child
));
662 return (DDI_FAILURE
);
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
);
671 (void) snprintf(name
, namelen
, "%s", *unit_addr
);
672 ddi_prop_free(unit_addr
);
673 return (DDI_SUCCESS
);
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
);
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
);
686 (void) snprintf(name
, namelen
, "%x,%x", slot
, func
);
688 (void) snprintf(name
, namelen
, "%x", slot
);
690 ddi_prop_free(pci_rp
);
691 return (DDI_SUCCESS
);
695 simba_initchild(dev_info_t
*child
)
697 char name
[MAXNAMELEN
];
699 ddi_acc_handle_t config_handle
;
700 ushort_t command_preserve
, command
;
702 uchar_t min_gnt
, latency_timer
;
703 simba_devstate_t
*simba
;
706 DEBUG1(D_INIT_CLD
, "simba_initchild(): child=%p\n", child
);
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.
714 if (ndi_dev_is_persistent_node(child
) == 0) {
715 extern int pci_allow_pseudo_children
;
716 pci_regspec_t
*pci_rp
;
718 if (ddi_getlongprop(DDI_DEV_T_ANY
, child
,
719 DDI_PROP_DONTPASS
, "reg", (caddr_t
)&pci_rp
, &i
) ==
722 "cannot merge prototype from %s.conf",
723 ddi_driver_name(child
));
724 kmem_free(pci_rp
, i
);
725 return (DDI_NOT_WELL_FORMED
);
728 if (simba_name_child(child
, name
, MAXNAMELEN
) != DDI_SUCCESS
)
729 return (DDI_NOT_WELL_FORMED
);
731 ddi_set_name_addr(child
, name
);
732 ddi_set_parent_data(child
, NULL
);
735 * Try to merge the properties from this prototype
736 * node into real h/w nodes.
738 if (ndi_merge_node(child
, simba_name_child
) == DDI_SUCCESS
) {
740 * Merged ok - return failure to remove the node.
742 simba_uninitchild(child
);
743 return (DDI_FAILURE
);
746 /* workaround for ddivs to run under PCI */
747 if (pci_allow_pseudo_children
)
748 return (DDI_SUCCESS
);
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.
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
);
763 * Initialize real h/w nodes
765 if (simba_name_child(child
, name
, MAXNAMELEN
) != DDI_SUCCESS
)
766 return (DDI_FAILURE
);
768 ddi_set_name_addr(child
, name
);
769 ddi_set_parent_data(child
, NULL
);
771 if (pci_config_setup(child
, &config_handle
) != DDI_SUCCESS
) {
772 simba_uninitchild(child
);
773 return (DDI_FAILURE
);
776 DEBUG0(D_INIT_CLD
, "simba_initchild(): pci_config_setup success!\n");
779 * Determine the configuration header type.
781 header_type
= pci_config_get8(config_handle
, PCI_CONF_HEADER
);
784 * Support for the "command-preserve" property.
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
);
793 /* clean up all PCI child devices status register */
794 pci_config_put16(config_handle
, PCI_CONF_STAT
, 0xffff);
797 * If the device has a primary bus control register then program it
798 * based on the settings in the command register.
800 if ((header_type
& PCI_HEADER_TYPE_M
) == PCI_HEADER_ONE
) {
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
);
811 simba
= (simba_devstate_t
*)ddi_get_soft_state(simba_state
,
812 ddi_get_instance(ddi_get_parent(child
)));
814 * Initialize cache-line-size configuration register if needed.
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
);
823 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, child
,
824 "cache-line-size", n
);
828 * Initialize latency timer configuration registers if needed.
830 if (simba_set_latency_timer_register
&&
831 ddi_getprop(DDI_DEV_T_ANY
, child
, DDI_PROP_DONTPASS
,
832 "latency-timer", 0) == 0) {
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
);
839 min_gnt
= pci_config_get8(config_handle
,
841 latency_timer
= min_gnt
* 8;
843 pci_config_put8(config_handle
, PCI_CONF_LATENCY_TIMER
,
845 n
= pci_config_get8(config_handle
, PCI_CONF_LATENCY_TIMER
);
847 (void) ndi_prop_update_int(DDI_DEV_T_NONE
, child
,
851 pci_config_teardown(&config_handle
);
852 DEBUG0(D_INIT_CLD
, "simba_initchild(): pci_config_teardown called\n");
853 return (DDI_SUCCESS
);
857 simba_uninitchild(dev_info_t
*dip
)
859 ddi_set_name_addr(dip
, NULL
);
862 * Strip the node to properly convert it back to prototype form
864 impl_rem_dev_props(dip
);
868 * simba_save_config_regs
870 * This routine saves the state of the configuration registers of all
871 * the child nodes of each PBM.
873 * used by: simba_detach() on suspends
878 simba_save_config_regs(simba_devstate_t
*simba_p
)
883 struct simba_cfg_state
*statep
;
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
))
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");
898 simba_p
->config_state_index
= i
;
900 for (statep
= simba_p
->simba_config_state_p
,
901 dip
= ddi_get_child(simba_p
->dip
);
903 dip
= ddi_get_next_sibling(dip
)) {
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
));
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
));
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
));
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
),
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
);
950 if (pci_config_get16(ch
, PCI_CONF_VENID
) == PCI_SIMBA_VENID
&&
951 pci_config_get16(ch
, PCI_CONF_DEVID
) == PCI_SIMBA_DEVID
) {
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
);
962 pci_config_teardown(&ch
);
969 * simba_restore_config_regs
971 * This routine restores the state of the configuration registers of all
972 * the child nodes of each PBM.
974 * used by: simba_attach() on resume
979 simba_restore_config_regs(simba_devstate_t
*simba_p
)
984 struct simba_cfg_state
*statep
= simba_p
->simba_config_state_p
;
985 if (!simba_p
->config_state_index
)
988 for (i
= 0; i
< simba_p
->config_state_index
; i
++, statep
++) {
992 "%s%d: skipping bad dev info (%d)\n",
993 ddi_driver_name(simba_p
->dip
),
994 ddi_get_instance(simba_p
->dip
),
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
),
1003 ddi_driver_name(dip
),
1004 ddi_get_instance(dip
));
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
));
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
);
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
);
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
);
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;
1051 simba_open(dev_t
*devp
, int flags
, int otyp
, cred_t
*credp
)
1053 simba_devstate_t
*simba_p
;
1056 * Make sure the open is for the right file type.
1058 if (otyp
!= OTYP_CHR
)
1062 * Get the soft state structure for the device.
1064 simba_p
= (simba_devstate_t
*)ddi_get_soft_state(simba_state
,
1066 if (simba_p
== NULL
)
1070 * Handle the open by tracking the device state.
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
);
1078 simba_p
->simba_soft_state
= SIMBA_SOFT_STATE_OPEN_EXCL
;
1080 if (simba_p
->simba_soft_state
== SIMBA_SOFT_STATE_OPEN_EXCL
) {
1081 mutex_exit(&simba_p
->simba_mutex
);
1084 simba_p
->simba_soft_state
= SIMBA_SOFT_STATE_OPEN
;
1086 mutex_exit(&simba_p
->simba_mutex
);
1093 simba_close(dev_t dev
, int flags
, int otyp
, cred_t
*credp
)
1095 simba_devstate_t
*simba_p
;
1097 if (otyp
!= OTYP_CHR
)
1100 simba_p
= (simba_devstate_t
*)ddi_get_soft_state(simba_state
,
1102 if (simba_p
== NULL
)
1105 mutex_enter(&simba_p
->simba_mutex
);
1106 simba_p
->simba_soft_state
= SIMBA_SOFT_STATE_CLOSED
;
1107 mutex_exit(&simba_p
->simba_mutex
);
1113 * simba_ioctl: devctl hotplug controls
1117 simba_ioctl(dev_t dev
, int cmd
, intptr_t arg
, int mode
, cred_t
*credp
,
1120 simba_devstate_t
*simba_p
;
1122 struct devctl_iocdata
*dcp
;
1126 simba_p
= (simba_devstate_t
*)ddi_get_soft_state(simba_state
,
1128 if (simba_p
== NULL
)
1131 self
= simba_p
->dip
;
1134 * We can use the generic implementation for these ioctls
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));
1145 * read devctl ioctl data
1147 if (ndi_dc_allochdl((void *)arg
, &dcp
) != NDI_SUCCESS
)
1152 case DEVCTL_DEVICE_RESET
:
1157 case DEVCTL_BUS_QUIESCE
:
1158 if (ndi_get_bus_state(self
, &bus_state
) == NDI_SUCCESS
)
1159 if (bus_state
== BUS_QUIESCED
)
1161 (void) ndi_set_bus_state(self
, BUS_QUIESCED
);
1164 case DEVCTL_BUS_UNQUIESCE
:
1165 if (ndi_get_bus_state(self
, &bus_state
) == NDI_SUCCESS
)
1166 if (bus_state
== BUS_ACTIVE
)
1168 (void) ndi_set_bus_state(self
, BUS_ACTIVE
);
1171 case DEVCTL_BUS_RESET
:
1175 case DEVCTL_BUS_RESETALL
:
1183 ndi_dc_freehdl(dcp
);
1188 * Initialize FMA resources for children devices. Called when
1189 * child calls ddi_fm_init().
1193 simba_fm_init_child(dev_info_t
*dip
, dev_info_t
*tdip
, int cap
,
1194 ddi_iblock_cookie_t
*ibc
)
1196 simba_devstate_t
*simba_p
= ddi_get_soft_state(simba_state
,
1197 ddi_get_instance(dip
));
1199 *ibc
= simba_p
->fm_ibc
;
1200 return (simba_p
->fm_cap
);
1204 simba_bus_enter(dev_info_t
*dip
, ddi_acc_handle_t handle
)
1206 i_ndi_busop_access_enter(dip
, handle
);
1211 simba_bus_exit(dev_info_t
*dip
, ddi_acc_handle_t handle
)
1213 i_ndi_busop_access_exit(dip
, handle
);