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 2010 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.
30 * Host to PCI local bus driver
34 #include <sys/modctl.h>
36 #include <sys/pci_impl.h>
37 #include <sys/sysmacros.h>
38 #include <sys/sunndi.h>
39 #include <sys/ddifm.h>
40 #include <sys/ndifm.h>
41 #include <sys/fm/protocol.h>
42 #include <sys/hotplug/pci/pcihp.h>
43 #include <io/pci/pci_common.h>
44 #include <io/pci/pci_tools_ext.h>
46 /* Save minimal state. */
50 * Bus Operation functions
52 static int pci_bus_map(dev_info_t
*, dev_info_t
*, ddi_map_req_t
*,
53 off_t
, off_t
, caddr_t
*);
54 static int pci_ctlops(dev_info_t
*, dev_info_t
*, ddi_ctl_enum_t
,
56 static int pci_intr_ops(dev_info_t
*, dev_info_t
*, ddi_intr_op_t
,
57 ddi_intr_handle_impl_t
*, void *);
58 static int pci_fm_init(dev_info_t
*, dev_info_t
*, int,
59 ddi_iblock_cookie_t
*);
60 static int pci_fm_callback(dev_info_t
*, ddi_fm_error_t
*, const void *);
62 struct bus_ops pci_bus_ops
= {
79 0, /* (*bus_get_eventcookie)(); */
80 0, /* (*bus_add_eventcall)(); */
81 0, /* (*bus_remove_eventcall)(); */
82 0, /* (*bus_post_event)(); */
83 0, /* (*bus_intr_ctl)(); */
84 0, /* (*bus_config)(); */
85 0, /* (*bus_unconfig)(); */
86 pci_fm_init
, /* (*bus_fm_init)(); */
87 NULL
, /* (*bus_fm_fini)(); */
88 NULL
, /* (*bus_fm_access_enter)(); */
89 NULL
, /* (*bus_fm_access_exit)(); */
90 NULL
, /* (*bus_power)(); */
91 pci_intr_ops
/* (*bus_intr_op)(); */
95 * One goal here is to leverage off of the pcihp.c source without making
96 * changes to it. Call into it's cb_ops directly if needed, piggybacking
97 * anything else needed by the pci_tools.c module. Only pci_tools and pcihp
98 * will be opening PCI nexus driver file descriptors.
100 static int pci_open(dev_t
*, int, int, cred_t
*);
101 static int pci_close(dev_t
, int, int, cred_t
*);
102 static int pci_ioctl(dev_t
, int, intptr_t, int, cred_t
*, int *);
103 static int pci_prop_op(dev_t
, dev_info_t
*, ddi_prop_op_t
, int, char *,
105 static int pci_info(dev_info_t
*, ddi_info_cmd_t
, void *, void **);
106 static void pci_peekpoke_cb(dev_info_t
*, ddi_fm_error_t
*);
108 struct cb_ops pci_cb_ops
= {
110 pci_close
, /* close */
111 nodev
, /* strategy */
116 pci_ioctl
, /* ioctl */
121 pci_prop_op
, /* cb_prop_op */
122 NULL
, /* streamtab */
123 D_NEW
| D_MP
| D_HOTPLUG
, /* Driver compatibility flag */
125 nodev
, /* int (*cb_aread)() */
126 nodev
/* int (*cb_awrite)() */
130 * Device Node Operation functions
132 static int pci_attach(dev_info_t
*devi
, ddi_attach_cmd_t cmd
);
133 static int pci_detach(dev_info_t
*devi
, ddi_detach_cmd_t cmd
);
135 struct dev_ops pci_ops
= {
136 DEVO_REV
, /* devo_rev */
139 nulldev
, /* identify */
141 pci_attach
, /* attach */
142 pci_detach
, /* detach */
144 &pci_cb_ops
, /* driver operations */
145 &pci_bus_ops
, /* bus operations */
147 ddi_quiesce_not_needed
/* quiesce */
151 * This variable controls the default setting of the command register
152 * for pci devices. See pci_initchild() for details.
154 static ushort_t pci_command_default
= PCI_COMM_ME
|
159 * Internal routines in support of particular pci_ctlops.
161 static int pci_removechild(dev_info_t
*child
);
162 static int pci_initchild(dev_info_t
*child
);
165 * Module linkage information for the kernel.
168 static struct modldrv modldrv
= {
169 &mod_driverops
, /* Type of module */
170 "x86 Host to PCI nexus driver", /* Name of module */
171 &pci_ops
, /* driver ops */
174 static struct modlinkage modlinkage
= {
186 * Initialize per-pci bus soft state pointer.
188 e
= ddi_soft_state_init(&pci_statep
, sizeof (pci_state_t
), 1);
192 if ((e
= mod_install(&modlinkage
)) != 0)
193 ddi_soft_state_fini(&pci_statep
);
203 rc
= mod_remove(&modlinkage
);
207 ddi_soft_state_fini(&pci_statep
);
213 _info(struct modinfo
*modinfop
)
215 return (mod_info(&modlinkage
, modinfop
));
220 pci_attach(dev_info_t
*devi
, ddi_attach_cmd_t cmd
)
223 * Use the minor number as constructed by pcihp, as the index value to
224 * ddi_soft_state_zalloc.
226 int instance
= ddi_get_instance(devi
);
227 pci_state_t
*pcip
= NULL
;
233 return (DDI_SUCCESS
);
236 return (DDI_FAILURE
);
239 if (ddi_prop_update_string(DDI_DEV_T_NONE
, devi
, "device_type", "pci")
240 != DDI_PROP_SUCCESS
) {
241 cmn_err(CE_WARN
, "pci: 'device_type' prop create failed");
244 if (ddi_soft_state_zalloc(pci_statep
, instance
) == DDI_SUCCESS
) {
245 pcip
= ddi_get_soft_state(pci_statep
, instance
);
252 pcip
->pci_dip
= devi
;
253 pcip
->pci_soft_state
= PCI_SOFT_STATE_CLOSED
;
256 * Initialize hotplug support on this bus. At minimum
257 * (for non hotplug bus) this would create ":devctl" minor
258 * node to support DEVCTL_DEVICE_* and DEVCTL_BUS_* ioctls
261 if (pcihp_init(devi
) != DDI_SUCCESS
) {
262 cmn_err(CE_WARN
, "pci: Failed to setup hotplug framework");
266 /* Second arg: initialize for pci, not pci_express */
267 if (pcitool_init(devi
, B_FALSE
) != DDI_SUCCESS
) {
268 goto bad_pcitool_init
;
271 pcip
->pci_fmcap
= DDI_FM_ERRCB_CAPABLE
|
272 DDI_FM_ACCCHK_CAPABLE
| DDI_FM_DMACHK_CAPABLE
;
273 ddi_fm_init(devi
, &pcip
->pci_fmcap
, &pcip
->pci_fm_ibc
);
274 mutex_init(&pcip
->pci_mutex
, NULL
, MUTEX_DRIVER
, NULL
);
275 mutex_init(&pcip
->pci_err_mutex
, NULL
, MUTEX_DRIVER
,
276 (void *)pcip
->pci_fm_ibc
);
277 mutex_init(&pcip
->pci_peek_poke_mutex
, NULL
, MUTEX_DRIVER
,
278 (void *)pcip
->pci_fm_ibc
);
279 if (pcip
->pci_fmcap
& DDI_FM_ERRCB_CAPABLE
) {
280 pci_ereport_setup(devi
);
281 ddi_fm_handler_register(devi
, pci_fm_callback
, NULL
);
284 ddi_report_dev(devi
);
286 return (DDI_SUCCESS
);
289 (void) pcihp_uninit(devi
);
291 ddi_soft_state_free(pci_statep
, instance
);
293 return (DDI_FAILURE
);
298 pci_detach(dev_info_t
*devi
, ddi_detach_cmd_t cmd
)
300 int instance
= ddi_get_instance(devi
);
303 pcip
= ddi_get_soft_state(pci_statep
, ddi_get_instance(devi
));
308 if (pcip
->pci_fmcap
& DDI_FM_ERRCB_CAPABLE
) {
309 ddi_fm_handler_unregister(devi
);
310 pci_ereport_teardown(devi
);
312 mutex_destroy(&pcip
->pci_peek_poke_mutex
);
313 mutex_destroy(&pcip
->pci_err_mutex
);
314 mutex_destroy(&pcip
->pci_mutex
);
315 ddi_fm_fini(devi
); /* Uninitialize pcitool support. */
316 pcitool_uninit(devi
);
318 /* Uninitialize hotplug support on this bus. */
319 (void) pcihp_uninit(devi
);
321 ddi_soft_state_free(pci_statep
, instance
);
323 return (DDI_SUCCESS
);
325 return (DDI_SUCCESS
);
327 return (DDI_FAILURE
);
332 pci_bus_map(dev_info_t
*dip
, dev_info_t
*rdip
, ddi_map_req_t
*mp
,
333 off_t offset
, off_t len
, caddr_t
*vaddrp
)
338 ddi_acc_impl_t
*hdlp
;
339 pci_regspec_t pci_reg
;
340 pci_regspec_t
*pci_rp
;
343 pci_acc_cfblk_t
*cfp
;
347 mr
= *mp
; /* Get private copy of request */
350 if (mp
->map_handlep
!= NULL
) {
351 pcip
= ddi_get_soft_state(pci_statep
, ddi_get_instance(dip
));
352 hdlp
= (ddi_acc_impl_t
*)(mp
->map_handlep
)->ah_platform_private
;
353 hdlp
->ahi_err_mutexp
= &pcip
->pci_err_mutex
;
354 hdlp
->ahi_peekpoke_mutexp
= &pcip
->pci_peek_poke_mutex
;
355 hdlp
->ahi_scan_dip
= dip
;
356 hdlp
->ahi_scan
= pci_peekpoke_cb
;
360 * check for register number
362 switch (mp
->map_type
) {
364 pci_reg
= *(pci_regspec_t
*)(mp
->map_obj
.rp
);
366 if (pci_common_get_reg_prop(rdip
, pci_rp
) != DDI_SUCCESS
)
367 return (DDI_FAILURE
);
370 rnumber
= mp
->map_obj
.rnumber
;
372 * get ALL "reg" properties for dip, select the one of
373 * of interest. In x86, "assigned-addresses" property
374 * is identical to the "reg" property, so there is no
375 * need to cross check the two to determine the physical
376 * address of the registers.
377 * This routine still performs some validity checks to
378 * make sure that everything is okay.
380 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY
, rdip
,
381 DDI_PROP_DONTPASS
, "reg", (int **)&pci_rp
,
382 (uint_t
*)&length
) != DDI_PROP_SUCCESS
)
383 return (DDI_FAILURE
);
386 * validate the register number.
388 length
/= (sizeof (pci_regspec_t
) / sizeof (int));
389 if (rnumber
>= length
) {
390 ddi_prop_free(pci_rp
);
391 return (DDI_FAILURE
);
395 * copy the required entry.
397 pci_reg
= pci_rp
[rnumber
];
400 * free the memory allocated by ddi_prop_lookup_int_array
402 ddi_prop_free(pci_rp
);
405 if (pci_common_get_reg_prop(rdip
, pci_rp
) != DDI_SUCCESS
)
406 return (DDI_FAILURE
);
407 mp
->map_type
= DDI_MT_REGSPEC
;
410 return (DDI_ME_INVAL
);
413 space
= pci_rp
->pci_phys_hi
& PCI_REG_ADDR_M
;
416 * check for unmap and unlock of address space
418 if ((mp
->map_op
== DDI_MO_UNMAP
) || (mp
->map_op
== DDI_MO_UNLOCK
)) {
420 * Adjust offset and length
421 * A non-zero length means override the one in the regspec.
423 pci_rp
->pci_phys_low
+= (uint_t
)offset
;
425 pci_rp
->pci_size_low
= len
;
428 case PCI_ADDR_CONFIG
:
429 /* No work required on unmap of Config space */
430 return (DDI_SUCCESS
);
433 reg
.regspec_bustype
= 1;
438 * MEM64 requires special treatment on map, to check
439 * that the device is below 4G. On unmap, however,
440 * we can assume that everything is OK... the map
441 * must have succeeded.
445 reg
.regspec_bustype
= 0;
449 return (DDI_FAILURE
);
451 reg
.regspec_addr
= pci_rp
->pci_phys_low
;
452 reg
.regspec_size
= pci_rp
->pci_size_low
;
454 mp
->map_obj
.rp
= ®
;
455 return (ddi_map(dip
, mp
, (off_t
)0, (off_t
)0, vaddrp
));
459 /* check for user mapping request - not legal for Config */
460 if (mp
->map_op
== DDI_MO_MAP_HANDLE
&& space
== PCI_ADDR_CONFIG
) {
461 return (DDI_FAILURE
);
465 * check for config space
466 * On x86, CONFIG is not mapped via MMU and there is
467 * no endian-ness issues. Set the attr field in the handle to
468 * indicate that the common routines to call the nexus driver.
470 if (space
== PCI_ADDR_CONFIG
) {
471 /* Can't map config space without a handle */
472 hp
= (ddi_acc_hdl_t
*)mp
->map_handlep
;
474 return (DDI_FAILURE
);
476 /* record the device address for future reference */
477 cfp
= (pci_acc_cfblk_t
*)&hp
->ah_bus_private
;
478 cfp
->c_busnum
= PCI_REG_BUS_G(pci_rp
->pci_phys_hi
);
479 cfp
->c_devnum
= PCI_REG_DEV_G(pci_rp
->pci_phys_hi
);
480 cfp
->c_funcnum
= PCI_REG_FUNC_G(pci_rp
->pci_phys_hi
);
482 *vaddrp
= (caddr_t
)offset
;
483 return (pci_fm_acc_setup(hp
, offset
, len
));
489 if ((offset
>= pci_rp
->pci_size_low
) ||
490 (len
> pci_rp
->pci_size_low
) ||
491 (offset
+ len
> pci_rp
->pci_size_low
)) {
492 return (DDI_FAILURE
);
496 * Adjust offset and length
497 * A non-zero length means override the one in the regspec.
499 pci_rp
->pci_phys_low
+= (uint_t
)offset
;
501 pci_rp
->pci_size_low
= len
;
504 * convert the pci regsec into the generic regspec used by the
505 * parent root nexus driver.
509 reg
.regspec_bustype
= 1;
513 * We can't handle 64-bit devices that are mapped above
514 * 4G or that are larger than 4G.
516 if (pci_rp
->pci_phys_mid
!= 0 ||
517 pci_rp
->pci_size_hi
!= 0)
518 return (DDI_FAILURE
);
520 * Other than that, we can treat them as 32-bit mappings
524 reg
.regspec_bustype
= 0;
527 return (DDI_FAILURE
);
529 reg
.regspec_addr
= pci_rp
->pci_phys_low
;
530 reg
.regspec_size
= pci_rp
->pci_size_low
;
532 mp
->map_obj
.rp
= ®
;
533 return (ddi_map(dip
, mp
, (off_t
)0, (off_t
)0, vaddrp
));
539 pci_ctlops(dev_info_t
*dip
, dev_info_t
*rdip
,
540 ddi_ctl_enum_t ctlop
, void *arg
, void *result
)
542 pci_regspec_t
*drv_regp
;
547 struct attachspec
*asp
;
548 struct detachspec
*dsp
;
551 case DDI_CTLOPS_REPORTDEV
:
552 if (rdip
== (dev_info_t
*)0)
553 return (DDI_FAILURE
);
554 cmn_err(CE_CONT
, "?PCI-device: %s@%s, %s%d\n",
555 ddi_node_name(rdip
), ddi_get_name_addr(rdip
),
556 ddi_driver_name(rdip
),
557 ddi_get_instance(rdip
));
558 return (DDI_SUCCESS
);
560 case DDI_CTLOPS_INITCHILD
:
561 return (pci_initchild((dev_info_t
*)arg
));
563 case DDI_CTLOPS_UNINITCHILD
:
564 return (pci_removechild((dev_info_t
*)arg
));
566 case DDI_CTLOPS_SIDDEV
:
567 return (DDI_SUCCESS
);
569 case DDI_CTLOPS_REGSIZE
:
570 case DDI_CTLOPS_NREGS
:
571 if (rdip
== (dev_info_t
*)0)
572 return (DDI_FAILURE
);
575 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY
, rdip
,
576 DDI_PROP_DONTPASS
, "reg", (int **)&drv_regp
,
577 ®len
) != DDI_PROP_SUCCESS
) {
578 return (DDI_FAILURE
);
581 totreg
= (reglen
* sizeof (int)) / sizeof (pci_regspec_t
);
582 if (ctlop
== DDI_CTLOPS_NREGS
)
583 *(int *)result
= totreg
;
584 else if (ctlop
== DDI_CTLOPS_REGSIZE
) {
587 ddi_prop_free(drv_regp
);
588 return (DDI_FAILURE
);
590 *(off_t
*)result
= drv_regp
[rn
].pci_size_low
;
592 ddi_prop_free(drv_regp
);
594 return (DDI_SUCCESS
);
596 case DDI_CTLOPS_POWER
: {
597 power_req_t
*reqp
= (power_req_t
*)arg
;
599 * We currently understand reporting of PCI_PM_IDLESPEED
600 * capability. Everything else is passed up.
602 if ((reqp
->request_type
== PMR_REPORT_PMCAP
) &&
603 (reqp
->req
.report_pmcap_req
.cap
== PCI_PM_IDLESPEED
)) {
605 return (DDI_SUCCESS
);
607 return (ddi_ctlops(dip
, rdip
, ctlop
, arg
, result
));
610 case DDI_CTLOPS_PEEK
:
611 case DDI_CTLOPS_POKE
:
612 pcip
= ddi_get_soft_state(pci_statep
, ddi_get_instance(dip
));
613 return (pci_peekpoke_check(dip
, rdip
, ctlop
, arg
, result
,
614 pci_common_peekpoke
, &pcip
->pci_err_mutex
,
615 &pcip
->pci_peek_poke_mutex
, pci_peekpoke_cb
));
617 /* for now only X86 systems support PME wakeup from suspended state */
618 case DDI_CTLOPS_ATTACH
:
619 asp
= (struct attachspec
*)arg
;
620 if (asp
->cmd
== DDI_RESUME
&& asp
->when
== DDI_PRE
)
621 if (pci_pre_resume(rdip
) != DDI_SUCCESS
)
622 return (DDI_FAILURE
);
623 return (ddi_ctlops(dip
, rdip
, ctlop
, arg
, result
));
625 case DDI_CTLOPS_DETACH
:
626 dsp
= (struct detachspec
*)arg
;
627 if (dsp
->cmd
== DDI_SUSPEND
&& dsp
->when
== DDI_POST
)
628 if (pci_post_suspend(rdip
) != DDI_SUCCESS
)
629 return (DDI_FAILURE
);
630 return (ddi_ctlops(dip
, rdip
, ctlop
, arg
, result
));
633 return (ddi_ctlops(dip
, rdip
, ctlop
, arg
, result
));
644 pci_intr_ops(dev_info_t
*pdip
, dev_info_t
*rdip
, ddi_intr_op_t intr_op
,
645 ddi_intr_handle_impl_t
*hdlp
, void *result
)
647 return (pci_common_intr_ops(pdip
, rdip
, intr_op
, hdlp
, result
));
652 pci_initchild(dev_info_t
*child
)
655 ddi_acc_handle_t config_handle
;
656 ushort_t command_preserve
, command
;
658 if (pci_common_name_child(child
, name
, 80) != DDI_SUCCESS
) {
659 return (DDI_FAILURE
);
661 ddi_set_name_addr(child
, name
);
664 * Pseudo nodes indicate a prototype node with per-instance
665 * properties to be merged into the real h/w device node.
666 * The interpretation of the unit-address is DD[,F]
667 * where DD is the device id and F is the function.
669 if (ndi_dev_is_persistent_node(child
) == 0) {
670 extern int pci_allow_pseudo_children
;
672 ddi_set_parent_data(child
, NULL
);
675 * Try to merge the properties from this prototype
676 * node into real h/w nodes.
678 if (ndi_merge_node(child
, pci_common_name_child
) ==
681 * Merged ok - return failure to remove the node.
683 ddi_set_name_addr(child
, NULL
);
684 return (DDI_FAILURE
);
687 /* workaround for ddivs to run under PCI */
688 if (pci_allow_pseudo_children
) {
690 * If the "interrupts" property doesn't exist,
691 * this must be the ddivs no-intr case, and it returns
692 * DDI_SUCCESS instead of DDI_FAILURE.
694 if (ddi_prop_get_int(DDI_DEV_T_ANY
, child
,
695 DDI_PROP_DONTPASS
, "interrupts", -1) == -1)
696 return (DDI_SUCCESS
);
698 * Create the ddi_parent_private_data for a pseudo
701 pci_common_set_parent_private_data(child
);
702 return (DDI_SUCCESS
);
706 * The child was not merged into a h/w node,
707 * but there's not much we can do with it other
708 * than return failure to cause the node to be removed.
710 cmn_err(CE_WARN
, "!%s@%s: %s.conf properties not merged",
711 ddi_get_name(child
), ddi_get_name_addr(child
),
712 ddi_get_name(child
));
713 ddi_set_name_addr(child
, NULL
);
714 return (DDI_NOT_WELL_FORMED
);
717 if (ddi_prop_get_int(DDI_DEV_T_ANY
, child
, DDI_PROP_DONTPASS
,
718 "interrupts", -1) != -1)
719 pci_common_set_parent_private_data(child
);
721 ddi_set_parent_data(child
, NULL
);
724 * initialize command register
726 if (pci_config_setup(child
, &config_handle
) != DDI_SUCCESS
)
727 return (DDI_FAILURE
);
730 * Support for the "command-preserve" property.
732 command_preserve
= ddi_prop_get_int(DDI_DEV_T_ANY
, child
,
733 DDI_PROP_DONTPASS
, "command-preserve", 0);
734 command
= pci_config_get16(config_handle
, PCI_CONF_COMM
);
735 command
&= (command_preserve
| PCI_COMM_BACK2BACK_ENAB
);
736 command
|= (pci_command_default
& ~command_preserve
);
737 pci_config_put16(config_handle
, PCI_CONF_COMM
, command
);
739 pci_config_teardown(&config_handle
);
740 return (DDI_SUCCESS
);
744 pci_removechild(dev_info_t
*dip
)
746 struct ddi_parent_private_data
*pdptr
;
748 if ((pdptr
= ddi_get_parent_data(dip
)) != NULL
) {
749 kmem_free(pdptr
, (sizeof (*pdptr
) + sizeof (struct intrspec
)));
750 ddi_set_parent_data(dip
, NULL
);
752 ddi_set_name_addr(dip
, NULL
);
755 * Strip the node to properly convert it back to prototype form
757 ddi_remove_minor_node(dip
, NULL
);
759 impl_rem_dev_props(dip
);
761 return (DDI_SUCCESS
);
766 * When retrofitting this module for pci_tools, functions such as open, close,
767 * and ioctl are now pulled into this module. Before this, the functions in
768 * the pcihp module were referenced directly. Now they are called or
769 * referenced through the pcihp cb_ops structure from functions in this module.
773 pci_open(dev_t
*devp
, int flags
, int otyp
, cred_t
*credp
)
775 return ((pcihp_get_cb_ops())->cb_open(devp
, flags
, otyp
, credp
));
779 pci_close(dev_t dev
, int flags
, int otyp
, cred_t
*credp
)
781 return ((pcihp_get_cb_ops())->cb_close(dev
, flags
, otyp
, credp
));
785 pci_ioctl(dev_t dev
, int cmd
, intptr_t arg
, int mode
, cred_t
*credp
, int *rvalp
)
787 minor_t minor
= getminor(dev
);
788 int instance
= PCI_MINOR_NUM_TO_INSTANCE(minor
);
789 pci_state_t
*pci_p
= ddi_get_soft_state(pci_statep
, instance
);
795 switch (PCI_MINOR_NUM_TO_PCI_DEVNUM(minor
)) {
796 case PCI_TOOL_REG_MINOR_NUM
:
797 case PCI_TOOL_INTR_MINOR_NUM
:
798 /* To handle pcitool related ioctls */
799 ret
= pci_common_ioctl(pci_p
->pci_dip
, dev
, cmd
, arg
, mode
,
803 /* To handle devctl and hotplug related ioctls */
804 ret
= (pcihp_get_cb_ops())->cb_ioctl(dev
, cmd
, arg
, mode
,
814 pci_prop_op(dev_t dev
, dev_info_t
*dip
, ddi_prop_op_t prop_op
,
815 int flags
, char *name
, caddr_t valuep
, int *lengthp
)
817 return ((pcihp_get_cb_ops())->cb_prop_op(dev
, dip
, prop_op
, flags
,
818 name
, valuep
, lengthp
));
822 pci_info(dev_info_t
*dip
, ddi_info_cmd_t cmd
, void *arg
, void **result
)
824 return (pcihp_info(dip
, cmd
, arg
, result
));
827 void pci_peekpoke_cb(dev_info_t
*dip
, ddi_fm_error_t
*derr
) {
828 (void) pci_ereport_post(dip
, derr
, NULL
);
833 pci_fm_init(dev_info_t
*dip
, dev_info_t
*tdip
, int cap
,
834 ddi_iblock_cookie_t
*ibc
)
836 pci_state_t
*pcip
= ddi_get_soft_state(pci_statep
,
837 ddi_get_instance(dip
));
840 *ibc
= pcip
->pci_fm_ibc
;
842 return (pcip
->pci_fmcap
);
847 pci_fm_callback(dev_info_t
*dip
, ddi_fm_error_t
*derr
, const void *no_used
)
849 pci_state_t
*pcip
= ddi_get_soft_state(pci_statep
,
850 ddi_get_instance(dip
));
852 mutex_enter(&pcip
->pci_err_mutex
);
853 pci_ereport_post(dip
, derr
, NULL
);
854 mutex_exit(&pcip
->pci_err_mutex
);
855 return (derr
->fme_status
);