10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
51865Sdilpreet * Common Development and Distribution License (the "License").
61865Sdilpreet * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
22*11412SStephen.Hanson@Sun.COM * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate /*
270Sstevel@tonic-gate * Host to PCI local bus driver
280Sstevel@tonic-gate */
290Sstevel@tonic-gate
300Sstevel@tonic-gate #include <sys/conf.h>
310Sstevel@tonic-gate #include <sys/modctl.h>
320Sstevel@tonic-gate #include <sys/pci.h>
330Sstevel@tonic-gate #include <sys/pci_impl.h>
34881Sjohnny #include <sys/sysmacros.h>
350Sstevel@tonic-gate #include <sys/sunndi.h>
361865Sdilpreet #include <sys/ddifm.h>
371865Sdilpreet #include <sys/ndifm.h>
381865Sdilpreet #include <sys/fm/protocol.h>
390Sstevel@tonic-gate #include <sys/hotplug/pci/pcihp.h>
40881Sjohnny #include <io/pci/pci_common.h>
41881Sjohnny #include <io/pci/pci_tools_ext.h>
420Sstevel@tonic-gate
430Sstevel@tonic-gate /* Save minimal state. */
440Sstevel@tonic-gate void *pci_statep;
450Sstevel@tonic-gate
460Sstevel@tonic-gate /*
470Sstevel@tonic-gate * Bus Operation functions
480Sstevel@tonic-gate */
490Sstevel@tonic-gate static int pci_bus_map(dev_info_t *, dev_info_t *, ddi_map_req_t *,
500Sstevel@tonic-gate off_t, off_t, caddr_t *);
510Sstevel@tonic-gate static int pci_ctlops(dev_info_t *, dev_info_t *, ddi_ctl_enum_t,
520Sstevel@tonic-gate void *, void *);
530Sstevel@tonic-gate static int pci_intr_ops(dev_info_t *, dev_info_t *, ddi_intr_op_t,
540Sstevel@tonic-gate ddi_intr_handle_impl_t *, void *);
551865Sdilpreet static int pci_fm_init(dev_info_t *, dev_info_t *, int,
561865Sdilpreet ddi_iblock_cookie_t *);
571865Sdilpreet static int pci_fm_callback(dev_info_t *, ddi_fm_error_t *, const void *);
580Sstevel@tonic-gate
590Sstevel@tonic-gate struct bus_ops pci_bus_ops = {
600Sstevel@tonic-gate BUSO_REV,
610Sstevel@tonic-gate pci_bus_map,
620Sstevel@tonic-gate NULL,
630Sstevel@tonic-gate NULL,
640Sstevel@tonic-gate NULL,
650Sstevel@tonic-gate i_ddi_map_fault,
660Sstevel@tonic-gate ddi_dma_map,
670Sstevel@tonic-gate ddi_dma_allochdl,
680Sstevel@tonic-gate ddi_dma_freehdl,
690Sstevel@tonic-gate ddi_dma_bindhdl,
700Sstevel@tonic-gate ddi_dma_unbindhdl,
710Sstevel@tonic-gate ddi_dma_flush,
720Sstevel@tonic-gate ddi_dma_win,
730Sstevel@tonic-gate ddi_dma_mctl,
740Sstevel@tonic-gate pci_ctlops,
750Sstevel@tonic-gate ddi_bus_prop_op,
760Sstevel@tonic-gate 0, /* (*bus_get_eventcookie)(); */
770Sstevel@tonic-gate 0, /* (*bus_add_eventcall)(); */
780Sstevel@tonic-gate 0, /* (*bus_remove_eventcall)(); */
790Sstevel@tonic-gate 0, /* (*bus_post_event)(); */
800Sstevel@tonic-gate 0, /* (*bus_intr_ctl)(); */
810Sstevel@tonic-gate 0, /* (*bus_config)(); */
820Sstevel@tonic-gate 0, /* (*bus_unconfig)(); */
831865Sdilpreet pci_fm_init, /* (*bus_fm_init)(); */
840Sstevel@tonic-gate NULL, /* (*bus_fm_fini)(); */
850Sstevel@tonic-gate NULL, /* (*bus_fm_access_enter)(); */
860Sstevel@tonic-gate NULL, /* (*bus_fm_access_exit)(); */
870Sstevel@tonic-gate NULL, /* (*bus_power)(); */
880Sstevel@tonic-gate pci_intr_ops /* (*bus_intr_op)(); */
890Sstevel@tonic-gate };
900Sstevel@tonic-gate
910Sstevel@tonic-gate /*
920Sstevel@tonic-gate * One goal here is to leverage off of the pcihp.c source without making
930Sstevel@tonic-gate * changes to it. Call into it's cb_ops directly if needed, piggybacking
940Sstevel@tonic-gate * anything else needed by the pci_tools.c module. Only pci_tools and pcihp
95117Sschwartz * will be opening PCI nexus driver file descriptors.
960Sstevel@tonic-gate */
97881Sjohnny static int pci_open(dev_t *, int, int, cred_t *);
98881Sjohnny static int pci_close(dev_t, int, int, cred_t *);
99881Sjohnny static int pci_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
100881Sjohnny static int pci_prop_op(dev_t, dev_info_t *, ddi_prop_op_t, int, char *,
101881Sjohnny caddr_t, int *);
102881Sjohnny static int pci_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
1036313Skrishnae static void pci_peekpoke_cb(dev_info_t *, ddi_fm_error_t *);
1040Sstevel@tonic-gate
1050Sstevel@tonic-gate struct cb_ops pci_cb_ops = {
1060Sstevel@tonic-gate pci_open, /* open */
1070Sstevel@tonic-gate pci_close, /* close */
1080Sstevel@tonic-gate nodev, /* strategy */
1090Sstevel@tonic-gate nodev, /* print */
1100Sstevel@tonic-gate nodev, /* dump */
1110Sstevel@tonic-gate nodev, /* read */
1120Sstevel@tonic-gate nodev, /* write */
1130Sstevel@tonic-gate pci_ioctl, /* ioctl */
1140Sstevel@tonic-gate nodev, /* devmap */
1150Sstevel@tonic-gate nodev, /* mmap */
1160Sstevel@tonic-gate nodev, /* segmap */
1170Sstevel@tonic-gate nochpoll, /* poll */
1180Sstevel@tonic-gate pci_prop_op, /* cb_prop_op */
1190Sstevel@tonic-gate NULL, /* streamtab */
1200Sstevel@tonic-gate D_NEW | D_MP | D_HOTPLUG, /* Driver compatibility flag */
1210Sstevel@tonic-gate CB_REV, /* rev */
1220Sstevel@tonic-gate nodev, /* int (*cb_aread)() */
1230Sstevel@tonic-gate nodev /* int (*cb_awrite)() */
1240Sstevel@tonic-gate };
1250Sstevel@tonic-gate
1260Sstevel@tonic-gate /*
1270Sstevel@tonic-gate * Device Node Operation functions
1280Sstevel@tonic-gate */
1290Sstevel@tonic-gate static int pci_attach(dev_info_t *devi, ddi_attach_cmd_t cmd);
1300Sstevel@tonic-gate static int pci_detach(dev_info_t *devi, ddi_detach_cmd_t cmd);
1310Sstevel@tonic-gate
1320Sstevel@tonic-gate struct dev_ops pci_ops = {
1330Sstevel@tonic-gate DEVO_REV, /* devo_rev */
1340Sstevel@tonic-gate 0, /* refcnt */
1350Sstevel@tonic-gate pci_info, /* info */
1360Sstevel@tonic-gate nulldev, /* identify */
1370Sstevel@tonic-gate nulldev, /* probe */
1380Sstevel@tonic-gate pci_attach, /* attach */
1390Sstevel@tonic-gate pci_detach, /* detach */
1400Sstevel@tonic-gate nulldev, /* reset */
1410Sstevel@tonic-gate &pci_cb_ops, /* driver operations */
1427656SSherry.Moore@Sun.COM &pci_bus_ops, /* bus operations */
1437656SSherry.Moore@Sun.COM NULL, /* power */
1447656SSherry.Moore@Sun.COM ddi_quiesce_not_needed /* quiesce */
1450Sstevel@tonic-gate };
1460Sstevel@tonic-gate
1470Sstevel@tonic-gate /*
148354Smyers * This variable controls the default setting of the command register
149354Smyers * for pci devices. See pci_initchild() for details.
150354Smyers */
151354Smyers static ushort_t pci_command_default = PCI_COMM_ME |
152354Smyers PCI_COMM_MAE |
153354Smyers PCI_COMM_IO;
154354Smyers
155354Smyers /*
1560Sstevel@tonic-gate * Internal routines in support of particular pci_ctlops.
1570Sstevel@tonic-gate */
1580Sstevel@tonic-gate static int pci_removechild(dev_info_t *child);
1590Sstevel@tonic-gate static int pci_initchild(dev_info_t *child);
1600Sstevel@tonic-gate
1610Sstevel@tonic-gate /*
1620Sstevel@tonic-gate * Module linkage information for the kernel.
1630Sstevel@tonic-gate */
1640Sstevel@tonic-gate
1650Sstevel@tonic-gate static struct modldrv modldrv = {
16610923SEvan.Yan@Sun.COM &mod_driverops, /* Type of module */
16710923SEvan.Yan@Sun.COM "x86 Host to PCI nexus driver", /* Name of module */
16810923SEvan.Yan@Sun.COM &pci_ops, /* driver ops */
1690Sstevel@tonic-gate };
1700Sstevel@tonic-gate
1710Sstevel@tonic-gate static struct modlinkage modlinkage = {
1720Sstevel@tonic-gate MODREV_1,
1730Sstevel@tonic-gate (void *)&modldrv,
1740Sstevel@tonic-gate NULL
1750Sstevel@tonic-gate };
1760Sstevel@tonic-gate
1770Sstevel@tonic-gate int
_init(void)1780Sstevel@tonic-gate _init(void)
1790Sstevel@tonic-gate {
1800Sstevel@tonic-gate int e;
1810Sstevel@tonic-gate
1820Sstevel@tonic-gate /*
1830Sstevel@tonic-gate * Initialize per-pci bus soft state pointer.
1840Sstevel@tonic-gate */
1850Sstevel@tonic-gate e = ddi_soft_state_init(&pci_statep, sizeof (pci_state_t), 1);
1860Sstevel@tonic-gate if (e != 0)
1870Sstevel@tonic-gate return (e);
1880Sstevel@tonic-gate
1890Sstevel@tonic-gate if ((e = mod_install(&modlinkage)) != 0)
1900Sstevel@tonic-gate ddi_soft_state_fini(&pci_statep);
1910Sstevel@tonic-gate
1920Sstevel@tonic-gate return (e);
1930Sstevel@tonic-gate }
1940Sstevel@tonic-gate
1950Sstevel@tonic-gate int
_fini(void)1960Sstevel@tonic-gate _fini(void)
1970Sstevel@tonic-gate {
1980Sstevel@tonic-gate int rc;
1990Sstevel@tonic-gate
2000Sstevel@tonic-gate rc = mod_remove(&modlinkage);
2010Sstevel@tonic-gate if (rc != 0)
2020Sstevel@tonic-gate return (rc);
2030Sstevel@tonic-gate
2040Sstevel@tonic-gate ddi_soft_state_fini(&pci_statep);
2050Sstevel@tonic-gate
2060Sstevel@tonic-gate return (rc);
2070Sstevel@tonic-gate }
2080Sstevel@tonic-gate
2090Sstevel@tonic-gate int
_info(struct modinfo * modinfop)2100Sstevel@tonic-gate _info(struct modinfo *modinfop)
2110Sstevel@tonic-gate {
2120Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop));
2130Sstevel@tonic-gate }
2140Sstevel@tonic-gate
2150Sstevel@tonic-gate /*ARGSUSED*/
2160Sstevel@tonic-gate static int
pci_attach(dev_info_t * devi,ddi_attach_cmd_t cmd)2170Sstevel@tonic-gate pci_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
2180Sstevel@tonic-gate {
2190Sstevel@tonic-gate /*
2200Sstevel@tonic-gate * Use the minor number as constructed by pcihp, as the index value to
2210Sstevel@tonic-gate * ddi_soft_state_zalloc.
2220Sstevel@tonic-gate */
223117Sschwartz int instance = ddi_get_instance(devi);
2240Sstevel@tonic-gate pci_state_t *pcip = NULL;
2255295Srandyf switch (cmd) {
2265295Srandyf case DDI_ATTACH:
2275295Srandyf break;
2285295Srandyf
2295295Srandyf case DDI_RESUME:
2305295Srandyf return (DDI_SUCCESS);
2315295Srandyf
2325295Srandyf default:
2335295Srandyf return (DDI_FAILURE);
2345295Srandyf }
2350Sstevel@tonic-gate
2360Sstevel@tonic-gate if (ddi_prop_update_string(DDI_DEV_T_NONE, devi, "device_type", "pci")
2370Sstevel@tonic-gate != DDI_PROP_SUCCESS) {
2380Sstevel@tonic-gate cmn_err(CE_WARN, "pci: 'device_type' prop create failed");
2390Sstevel@tonic-gate }
2400Sstevel@tonic-gate
241117Sschwartz if (ddi_soft_state_zalloc(pci_statep, instance) == DDI_SUCCESS) {
242117Sschwartz pcip = ddi_get_soft_state(pci_statep, instance);
2430Sstevel@tonic-gate }
2440Sstevel@tonic-gate
2450Sstevel@tonic-gate if (pcip == NULL) {
246117Sschwartz goto bad_soft_state;
2470Sstevel@tonic-gate }
2480Sstevel@tonic-gate
2490Sstevel@tonic-gate pcip->pci_dip = devi;
25010923SEvan.Yan@Sun.COM pcip->pci_soft_state = PCI_SOFT_STATE_CLOSED;
2510Sstevel@tonic-gate
2520Sstevel@tonic-gate /*
2530Sstevel@tonic-gate * Initialize hotplug support on this bus. At minimum
2540Sstevel@tonic-gate * (for non hotplug bus) this would create ":devctl" minor
2550Sstevel@tonic-gate * node to support DEVCTL_DEVICE_* and DEVCTL_BUS_* ioctls
2560Sstevel@tonic-gate * to this bus.
2570Sstevel@tonic-gate */
2580Sstevel@tonic-gate if (pcihp_init(devi) != DDI_SUCCESS) {
2590Sstevel@tonic-gate cmn_err(CE_WARN, "pci: Failed to setup hotplug framework");
260117Sschwartz goto bad_pcihp_init;
261117Sschwartz }
262117Sschwartz
263777Sschwartz /* Second arg: initialize for pci, not pci_express */
264777Sschwartz if (pcitool_init(devi, B_FALSE) != DDI_SUCCESS) {
265117Sschwartz goto bad_pcitool_init;
2660Sstevel@tonic-gate }
2670Sstevel@tonic-gate
2681865Sdilpreet pcip->pci_fmcap = DDI_FM_ERRCB_CAPABLE |
2691865Sdilpreet DDI_FM_ACCCHK_CAPABLE | DDI_FM_DMACHK_CAPABLE;
2701865Sdilpreet ddi_fm_init(devi, &pcip->pci_fmcap, &pcip->pci_fm_ibc);
27110923SEvan.Yan@Sun.COM mutex_init(&pcip->pci_mutex, NULL, MUTEX_DRIVER, NULL);
2721865Sdilpreet mutex_init(&pcip->pci_err_mutex, NULL, MUTEX_DRIVER,
2731865Sdilpreet (void *)pcip->pci_fm_ibc);
2741865Sdilpreet mutex_init(&pcip->pci_peek_poke_mutex, NULL, MUTEX_DRIVER,
2751865Sdilpreet (void *)pcip->pci_fm_ibc);
2761865Sdilpreet if (pcip->pci_fmcap & DDI_FM_ERRCB_CAPABLE) {
2771865Sdilpreet pci_ereport_setup(devi);
2781865Sdilpreet ddi_fm_handler_register(devi, pci_fm_callback, NULL);
2791865Sdilpreet }
2801865Sdilpreet
2810Sstevel@tonic-gate ddi_report_dev(devi);
2820Sstevel@tonic-gate
2830Sstevel@tonic-gate return (DDI_SUCCESS);
284117Sschwartz
285117Sschwartz bad_pcitool_init:
286117Sschwartz (void) pcihp_uninit(devi);
287117Sschwartz bad_pcihp_init:
288117Sschwartz ddi_soft_state_free(pci_statep, instance);
289117Sschwartz bad_soft_state:
290117Sschwartz return (DDI_FAILURE);
2910Sstevel@tonic-gate }
2920Sstevel@tonic-gate
2930Sstevel@tonic-gate /*ARGSUSED*/
2940Sstevel@tonic-gate static int
pci_detach(dev_info_t * devi,ddi_detach_cmd_t cmd)2950Sstevel@tonic-gate pci_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
2960Sstevel@tonic-gate {
297916Sschwartz int instance = ddi_get_instance(devi);
2981865Sdilpreet pci_state_t *pcip;
2991865Sdilpreet
3001865Sdilpreet pcip = ddi_get_soft_state(pci_statep, ddi_get_instance(devi));
3015295Srandyf
302916Sschwartz
3035295Srandyf switch (cmd) {
3045295Srandyf case DDI_DETACH:
3055295Srandyf if (pcip->pci_fmcap & DDI_FM_ERRCB_CAPABLE) {
3065295Srandyf ddi_fm_handler_unregister(devi);
3075295Srandyf pci_ereport_teardown(devi);
3085295Srandyf }
3095295Srandyf mutex_destroy(&pcip->pci_peek_poke_mutex);
3105295Srandyf mutex_destroy(&pcip->pci_err_mutex);
31110923SEvan.Yan@Sun.COM mutex_destroy(&pcip->pci_mutex);
3125295Srandyf ddi_fm_fini(devi); /* Uninitialize pcitool support. */
3135295Srandyf pcitool_uninit(devi);
314117Sschwartz
3155295Srandyf /* Uninitialize hotplug support on this bus. */
3165295Srandyf (void) pcihp_uninit(devi);
3175295Srandyf
3185295Srandyf ddi_soft_state_free(pci_statep, instance);
319117Sschwartz
3205295Srandyf return (DDI_SUCCESS);
3215295Srandyf case DDI_SUSPEND:
3225295Srandyf return (DDI_SUCCESS);
3235295Srandyf default:
3245295Srandyf return (DDI_FAILURE);
3255295Srandyf }
3260Sstevel@tonic-gate }
3270Sstevel@tonic-gate
3280Sstevel@tonic-gate static int
pci_bus_map(dev_info_t * dip,dev_info_t * rdip,ddi_map_req_t * mp,off_t offset,off_t len,caddr_t * vaddrp)3290Sstevel@tonic-gate pci_bus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
3300Sstevel@tonic-gate off_t offset, off_t len, caddr_t *vaddrp)
3310Sstevel@tonic-gate {
3320Sstevel@tonic-gate struct regspec reg;
3330Sstevel@tonic-gate ddi_map_req_t mr;
3340Sstevel@tonic-gate ddi_acc_hdl_t *hp;
33511236SStephen.Hanson@Sun.COM ddi_acc_impl_t *hdlp;
3360Sstevel@tonic-gate pci_regspec_t pci_reg;
3370Sstevel@tonic-gate pci_regspec_t *pci_rp;
3380Sstevel@tonic-gate int rnumber;
3390Sstevel@tonic-gate int length;
3400Sstevel@tonic-gate pci_acc_cfblk_t *cfp;
3410Sstevel@tonic-gate int space;
34211236SStephen.Hanson@Sun.COM pci_state_t *pcip;
3430Sstevel@tonic-gate
3440Sstevel@tonic-gate mr = *mp; /* Get private copy of request */
3450Sstevel@tonic-gate mp = &mr;
3460Sstevel@tonic-gate
347*11412SStephen.Hanson@Sun.COM if (mp->map_handlep != NULL) {
348*11412SStephen.Hanson@Sun.COM pcip = ddi_get_soft_state(pci_statep, ddi_get_instance(dip));
349*11412SStephen.Hanson@Sun.COM hdlp = (ddi_acc_impl_t *)(mp->map_handlep)->ah_platform_private;
350*11412SStephen.Hanson@Sun.COM hdlp->ahi_err_mutexp = &pcip->pci_err_mutex;
351*11412SStephen.Hanson@Sun.COM hdlp->ahi_peekpoke_mutexp = &pcip->pci_peek_poke_mutex;
352*11412SStephen.Hanson@Sun.COM hdlp->ahi_scan_dip = dip;
353*11412SStephen.Hanson@Sun.COM hdlp->ahi_scan = pci_peekpoke_cb;
354*11412SStephen.Hanson@Sun.COM }
35511236SStephen.Hanson@Sun.COM
3560Sstevel@tonic-gate /*
3570Sstevel@tonic-gate * check for register number
3580Sstevel@tonic-gate */
3590Sstevel@tonic-gate switch (mp->map_type) {
3600Sstevel@tonic-gate case DDI_MT_REGSPEC:
3610Sstevel@tonic-gate pci_reg = *(pci_regspec_t *)(mp->map_obj.rp);
3620Sstevel@tonic-gate pci_rp = &pci_reg;
363881Sjohnny if (pci_common_get_reg_prop(rdip, pci_rp) != DDI_SUCCESS)
3640Sstevel@tonic-gate return (DDI_FAILURE);
3650Sstevel@tonic-gate break;
3660Sstevel@tonic-gate case DDI_MT_RNUMBER:
3670Sstevel@tonic-gate rnumber = mp->map_obj.rnumber;
3680Sstevel@tonic-gate /*
3690Sstevel@tonic-gate * get ALL "reg" properties for dip, select the one of
3700Sstevel@tonic-gate * of interest. In x86, "assigned-addresses" property
3710Sstevel@tonic-gate * is identical to the "reg" property, so there is no
3720Sstevel@tonic-gate * need to cross check the two to determine the physical
3730Sstevel@tonic-gate * address of the registers.
3740Sstevel@tonic-gate * This routine still performs some validity checks to
3750Sstevel@tonic-gate * make sure that everything is okay.
3760Sstevel@tonic-gate */
377881Sjohnny if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, rdip,
378881Sjohnny DDI_PROP_DONTPASS, "reg", (int **)&pci_rp,
379881Sjohnny (uint_t *)&length) != DDI_PROP_SUCCESS)
3800Sstevel@tonic-gate return (DDI_FAILURE);
3810Sstevel@tonic-gate
3820Sstevel@tonic-gate /*
3830Sstevel@tonic-gate * validate the register number.
3840Sstevel@tonic-gate */
3850Sstevel@tonic-gate length /= (sizeof (pci_regspec_t) / sizeof (int));
3860Sstevel@tonic-gate if (rnumber >= length) {
3870Sstevel@tonic-gate ddi_prop_free(pci_rp);
3880Sstevel@tonic-gate return (DDI_FAILURE);
3890Sstevel@tonic-gate }
3900Sstevel@tonic-gate
3910Sstevel@tonic-gate /*
3920Sstevel@tonic-gate * copy the required entry.
3930Sstevel@tonic-gate */
3940Sstevel@tonic-gate pci_reg = pci_rp[rnumber];
3950Sstevel@tonic-gate
3960Sstevel@tonic-gate /*
3970Sstevel@tonic-gate * free the memory allocated by ddi_prop_lookup_int_array
3980Sstevel@tonic-gate */
3990Sstevel@tonic-gate ddi_prop_free(pci_rp);
4000Sstevel@tonic-gate
4010Sstevel@tonic-gate pci_rp = &pci_reg;
402881Sjohnny if (pci_common_get_reg_prop(rdip, pci_rp) != DDI_SUCCESS)
4030Sstevel@tonic-gate return (DDI_FAILURE);
4040Sstevel@tonic-gate mp->map_type = DDI_MT_REGSPEC;
4050Sstevel@tonic-gate break;
4060Sstevel@tonic-gate default:
4070Sstevel@tonic-gate return (DDI_ME_INVAL);
4080Sstevel@tonic-gate }
4090Sstevel@tonic-gate
4100Sstevel@tonic-gate space = pci_rp->pci_phys_hi & PCI_REG_ADDR_M;
4110Sstevel@tonic-gate
4120Sstevel@tonic-gate /*
4130Sstevel@tonic-gate * check for unmap and unlock of address space
4140Sstevel@tonic-gate */
4150Sstevel@tonic-gate if ((mp->map_op == DDI_MO_UNMAP) || (mp->map_op == DDI_MO_UNLOCK)) {
4160Sstevel@tonic-gate /*
4170Sstevel@tonic-gate * Adjust offset and length
4180Sstevel@tonic-gate * A non-zero length means override the one in the regspec.
4190Sstevel@tonic-gate */
4200Sstevel@tonic-gate pci_rp->pci_phys_low += (uint_t)offset;
4210Sstevel@tonic-gate if (len != 0)
4220Sstevel@tonic-gate pci_rp->pci_size_low = len;
4230Sstevel@tonic-gate
4240Sstevel@tonic-gate switch (space) {
4250Sstevel@tonic-gate case PCI_ADDR_CONFIG:
4260Sstevel@tonic-gate /* No work required on unmap of Config space */
4270Sstevel@tonic-gate return (DDI_SUCCESS);
4280Sstevel@tonic-gate
4290Sstevel@tonic-gate case PCI_ADDR_IO:
4300Sstevel@tonic-gate reg.regspec_bustype = 1;
4310Sstevel@tonic-gate break;
4320Sstevel@tonic-gate
4330Sstevel@tonic-gate case PCI_ADDR_MEM64:
4340Sstevel@tonic-gate /*
4350Sstevel@tonic-gate * MEM64 requires special treatment on map, to check
4360Sstevel@tonic-gate * that the device is below 4G. On unmap, however,
4370Sstevel@tonic-gate * we can assume that everything is OK... the map
4380Sstevel@tonic-gate * must have succeeded.
4390Sstevel@tonic-gate */
4400Sstevel@tonic-gate /* FALLTHROUGH */
4410Sstevel@tonic-gate case PCI_ADDR_MEM32:
4420Sstevel@tonic-gate reg.regspec_bustype = 0;
4430Sstevel@tonic-gate break;
4440Sstevel@tonic-gate
4450Sstevel@tonic-gate default:
4460Sstevel@tonic-gate return (DDI_FAILURE);
4470Sstevel@tonic-gate }
4480Sstevel@tonic-gate reg.regspec_addr = pci_rp->pci_phys_low;
4490Sstevel@tonic-gate reg.regspec_size = pci_rp->pci_size_low;
4500Sstevel@tonic-gate
4510Sstevel@tonic-gate mp->map_obj.rp = ®
4520Sstevel@tonic-gate return (ddi_map(dip, mp, (off_t)0, (off_t)0, vaddrp));
4530Sstevel@tonic-gate
4540Sstevel@tonic-gate }
4550Sstevel@tonic-gate
4560Sstevel@tonic-gate /* check for user mapping request - not legal for Config */
4570Sstevel@tonic-gate if (mp->map_op == DDI_MO_MAP_HANDLE && space == PCI_ADDR_CONFIG) {
4580Sstevel@tonic-gate return (DDI_FAILURE);
4590Sstevel@tonic-gate }
4600Sstevel@tonic-gate
4610Sstevel@tonic-gate /*
4620Sstevel@tonic-gate * check for config space
4630Sstevel@tonic-gate * On x86, CONFIG is not mapped via MMU and there is
4640Sstevel@tonic-gate * no endian-ness issues. Set the attr field in the handle to
4650Sstevel@tonic-gate * indicate that the common routines to call the nexus driver.
4660Sstevel@tonic-gate */
4670Sstevel@tonic-gate if (space == PCI_ADDR_CONFIG) {
4681865Sdilpreet /* Can't map config space without a handle */
4690Sstevel@tonic-gate hp = (ddi_acc_hdl_t *)mp->map_handlep;
470881Sjohnny if (hp == NULL)
4710Sstevel@tonic-gate return (DDI_FAILURE);
4720Sstevel@tonic-gate
4730Sstevel@tonic-gate /* record the device address for future reference */
4740Sstevel@tonic-gate cfp = (pci_acc_cfblk_t *)&hp->ah_bus_private;
4750Sstevel@tonic-gate cfp->c_busnum = PCI_REG_BUS_G(pci_rp->pci_phys_hi);
4760Sstevel@tonic-gate cfp->c_devnum = PCI_REG_DEV_G(pci_rp->pci_phys_hi);
4770Sstevel@tonic-gate cfp->c_funcnum = PCI_REG_FUNC_G(pci_rp->pci_phys_hi);
4780Sstevel@tonic-gate
4791865Sdilpreet *vaddrp = (caddr_t)offset;
4801865Sdilpreet return (pci_fm_acc_setup(hp, offset, len));
4810Sstevel@tonic-gate }
4820Sstevel@tonic-gate
4830Sstevel@tonic-gate /*
4840Sstevel@tonic-gate * range check
4850Sstevel@tonic-gate */
4860Sstevel@tonic-gate if ((offset >= pci_rp->pci_size_low) ||
4870Sstevel@tonic-gate (len > pci_rp->pci_size_low) ||
4880Sstevel@tonic-gate (offset + len > pci_rp->pci_size_low)) {
4890Sstevel@tonic-gate return (DDI_FAILURE);
4900Sstevel@tonic-gate }
4910Sstevel@tonic-gate
4920Sstevel@tonic-gate /*
4930Sstevel@tonic-gate * Adjust offset and length
4940Sstevel@tonic-gate * A non-zero length means override the one in the regspec.
4950Sstevel@tonic-gate */
4960Sstevel@tonic-gate pci_rp->pci_phys_low += (uint_t)offset;
4970Sstevel@tonic-gate if (len != 0)
4980Sstevel@tonic-gate pci_rp->pci_size_low = len;
4990Sstevel@tonic-gate
5000Sstevel@tonic-gate /*
5010Sstevel@tonic-gate * convert the pci regsec into the generic regspec used by the
5020Sstevel@tonic-gate * parent root nexus driver.
5030Sstevel@tonic-gate */
5040Sstevel@tonic-gate switch (space) {
5050Sstevel@tonic-gate case PCI_ADDR_IO:
5060Sstevel@tonic-gate reg.regspec_bustype = 1;
5070Sstevel@tonic-gate break;
5080Sstevel@tonic-gate case PCI_ADDR_MEM64:
5090Sstevel@tonic-gate /*
5100Sstevel@tonic-gate * We can't handle 64-bit devices that are mapped above
5110Sstevel@tonic-gate * 4G or that are larger than 4G.
5120Sstevel@tonic-gate */
5130Sstevel@tonic-gate if (pci_rp->pci_phys_mid != 0 ||
5140Sstevel@tonic-gate pci_rp->pci_size_hi != 0)
5150Sstevel@tonic-gate return (DDI_FAILURE);
5160Sstevel@tonic-gate /*
5170Sstevel@tonic-gate * Other than that, we can treat them as 32-bit mappings
5180Sstevel@tonic-gate */
5190Sstevel@tonic-gate /* FALLTHROUGH */
5200Sstevel@tonic-gate case PCI_ADDR_MEM32:
5210Sstevel@tonic-gate reg.regspec_bustype = 0;
5220Sstevel@tonic-gate break;
5230Sstevel@tonic-gate default:
5240Sstevel@tonic-gate return (DDI_FAILURE);
5250Sstevel@tonic-gate }
5260Sstevel@tonic-gate reg.regspec_addr = pci_rp->pci_phys_low;
5270Sstevel@tonic-gate reg.regspec_size = pci_rp->pci_size_low;
5280Sstevel@tonic-gate
5290Sstevel@tonic-gate mp->map_obj.rp = ®
5300Sstevel@tonic-gate return (ddi_map(dip, mp, (off_t)0, (off_t)0, vaddrp));
5310Sstevel@tonic-gate }
5320Sstevel@tonic-gate
5330Sstevel@tonic-gate
5340Sstevel@tonic-gate /*ARGSUSED*/
5350Sstevel@tonic-gate static int
pci_ctlops(dev_info_t * dip,dev_info_t * rdip,ddi_ctl_enum_t ctlop,void * arg,void * result)5360Sstevel@tonic-gate pci_ctlops(dev_info_t *dip, dev_info_t *rdip,
5370Sstevel@tonic-gate ddi_ctl_enum_t ctlop, void *arg, void *result)
5380Sstevel@tonic-gate {
5390Sstevel@tonic-gate pci_regspec_t *drv_regp;
5400Sstevel@tonic-gate uint_t reglen;
5410Sstevel@tonic-gate int rn;
5420Sstevel@tonic-gate int totreg;
5431865Sdilpreet pci_state_t *pcip;
5445295Srandyf struct attachspec *asp;
5450Sstevel@tonic-gate
5460Sstevel@tonic-gate switch (ctlop) {
5470Sstevel@tonic-gate case DDI_CTLOPS_REPORTDEV:
5480Sstevel@tonic-gate if (rdip == (dev_info_t *)0)
5490Sstevel@tonic-gate return (DDI_FAILURE);
5500Sstevel@tonic-gate cmn_err(CE_CONT, "?PCI-device: %s@%s, %s%d\n",
5510Sstevel@tonic-gate ddi_node_name(rdip), ddi_get_name_addr(rdip),
5520Sstevel@tonic-gate ddi_driver_name(rdip),
5530Sstevel@tonic-gate ddi_get_instance(rdip));
5540Sstevel@tonic-gate return (DDI_SUCCESS);
5550Sstevel@tonic-gate
5560Sstevel@tonic-gate case DDI_CTLOPS_INITCHILD:
5570Sstevel@tonic-gate return (pci_initchild((dev_info_t *)arg));
5580Sstevel@tonic-gate
5590Sstevel@tonic-gate case DDI_CTLOPS_UNINITCHILD:
5600Sstevel@tonic-gate return (pci_removechild((dev_info_t *)arg));
5610Sstevel@tonic-gate
5620Sstevel@tonic-gate case DDI_CTLOPS_SIDDEV:
5630Sstevel@tonic-gate return (DDI_SUCCESS);
5640Sstevel@tonic-gate
5650Sstevel@tonic-gate case DDI_CTLOPS_REGSIZE:
5660Sstevel@tonic-gate case DDI_CTLOPS_NREGS:
5670Sstevel@tonic-gate if (rdip == (dev_info_t *)0)
5680Sstevel@tonic-gate return (DDI_FAILURE);
5690Sstevel@tonic-gate
5700Sstevel@tonic-gate *(int *)result = 0;
5710Sstevel@tonic-gate if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, rdip,
5725295Srandyf DDI_PROP_DONTPASS, "reg", (int **)&drv_regp,
5735295Srandyf ®len) != DDI_PROP_SUCCESS) {
5740Sstevel@tonic-gate return (DDI_FAILURE);
5750Sstevel@tonic-gate }
5760Sstevel@tonic-gate
5770Sstevel@tonic-gate totreg = (reglen * sizeof (int)) / sizeof (pci_regspec_t);
5780Sstevel@tonic-gate if (ctlop == DDI_CTLOPS_NREGS)
5790Sstevel@tonic-gate *(int *)result = totreg;
5800Sstevel@tonic-gate else if (ctlop == DDI_CTLOPS_REGSIZE) {
5810Sstevel@tonic-gate rn = *(int *)arg;
5820Sstevel@tonic-gate if (rn >= totreg) {
5830Sstevel@tonic-gate ddi_prop_free(drv_regp);
5840Sstevel@tonic-gate return (DDI_FAILURE);
5850Sstevel@tonic-gate }
5860Sstevel@tonic-gate *(off_t *)result = drv_regp[rn].pci_size_low;
5870Sstevel@tonic-gate }
5880Sstevel@tonic-gate ddi_prop_free(drv_regp);
5890Sstevel@tonic-gate
5900Sstevel@tonic-gate return (DDI_SUCCESS);
5910Sstevel@tonic-gate
5920Sstevel@tonic-gate case DDI_CTLOPS_POWER: {
5930Sstevel@tonic-gate power_req_t *reqp = (power_req_t *)arg;
5940Sstevel@tonic-gate /*
5950Sstevel@tonic-gate * We currently understand reporting of PCI_PM_IDLESPEED
5960Sstevel@tonic-gate * capability. Everything else is passed up.
5970Sstevel@tonic-gate */
5980Sstevel@tonic-gate if ((reqp->request_type == PMR_REPORT_PMCAP) &&
5990Sstevel@tonic-gate (reqp->req.report_pmcap_req.cap == PCI_PM_IDLESPEED)) {
6000Sstevel@tonic-gate
6010Sstevel@tonic-gate return (DDI_SUCCESS);
6020Sstevel@tonic-gate }
6030Sstevel@tonic-gate return (ddi_ctlops(dip, rdip, ctlop, arg, result));
6040Sstevel@tonic-gate }
6050Sstevel@tonic-gate
6061865Sdilpreet case DDI_CTLOPS_PEEK:
6071865Sdilpreet case DDI_CTLOPS_POKE:
6081865Sdilpreet pcip = ddi_get_soft_state(pci_statep, ddi_get_instance(dip));
6091865Sdilpreet return (pci_peekpoke_check(dip, rdip, ctlop, arg, result,
6101865Sdilpreet pci_common_peekpoke, &pcip->pci_err_mutex,
6116313Skrishnae &pcip->pci_peek_poke_mutex, pci_peekpoke_cb));
6121865Sdilpreet
6135295Srandyf /* for now only X86 systems support PME wakeup from suspended state */
6145295Srandyf case DDI_CTLOPS_ATTACH:
6155295Srandyf asp = (struct attachspec *)arg;
6165295Srandyf if (asp->cmd == DDI_RESUME && asp->when == DDI_PRE)
6175295Srandyf if (pci_pre_resume(rdip) != DDI_SUCCESS)
6185295Srandyf return (DDI_FAILURE);
6195295Srandyf return (ddi_ctlops(dip, rdip, ctlop, arg, result));
6205295Srandyf
6215295Srandyf case DDI_CTLOPS_DETACH:
6225295Srandyf asp = (struct attachspec *)arg;
6235295Srandyf if (asp->cmd == DDI_SUSPEND && asp->when == DDI_POST)
6245295Srandyf if (pci_post_suspend(rdip) != DDI_SUCCESS)
6255295Srandyf return (DDI_FAILURE);
6265295Srandyf return (ddi_ctlops(dip, rdip, ctlop, arg, result));
6275295Srandyf
6280Sstevel@tonic-gate default:
6290Sstevel@tonic-gate return (ddi_ctlops(dip, rdip, ctlop, arg, result));
6300Sstevel@tonic-gate }
6310Sstevel@tonic-gate
6320Sstevel@tonic-gate /* NOTREACHED */
6330Sstevel@tonic-gate
6340Sstevel@tonic-gate }
6350Sstevel@tonic-gate
6360Sstevel@tonic-gate /*
637881Sjohnny * pci_intr_ops
6380Sstevel@tonic-gate */
6390Sstevel@tonic-gate static int
pci_intr_ops(dev_info_t * pdip,dev_info_t * rdip,ddi_intr_op_t intr_op,ddi_intr_handle_impl_t * hdlp,void * result)640881Sjohnny pci_intr_ops(dev_info_t *pdip, dev_info_t *rdip, ddi_intr_op_t intr_op,
641881Sjohnny ddi_intr_handle_impl_t *hdlp, void *result)
6420Sstevel@tonic-gate {
643881Sjohnny return (pci_common_intr_ops(pdip, rdip, intr_op, hdlp, result));
644881Sjohnny }
6450Sstevel@tonic-gate
6460Sstevel@tonic-gate
6470Sstevel@tonic-gate static int
pci_initchild(dev_info_t * child)6480Sstevel@tonic-gate pci_initchild(dev_info_t *child)
6490Sstevel@tonic-gate {
6500Sstevel@tonic-gate char name[80];
651354Smyers ddi_acc_handle_t config_handle;
652354Smyers ushort_t command_preserve, command;
6530Sstevel@tonic-gate
654881Sjohnny if (pci_common_name_child(child, name, 80) != DDI_SUCCESS) {
6550Sstevel@tonic-gate return (DDI_FAILURE);
6560Sstevel@tonic-gate }
6570Sstevel@tonic-gate ddi_set_name_addr(child, name);
6580Sstevel@tonic-gate
6590Sstevel@tonic-gate /*
6600Sstevel@tonic-gate * Pseudo nodes indicate a prototype node with per-instance
6610Sstevel@tonic-gate * properties to be merged into the real h/w device node.
6620Sstevel@tonic-gate * The interpretation of the unit-address is DD[,F]
6630Sstevel@tonic-gate * where DD is the device id and F is the function.
6640Sstevel@tonic-gate */
6650Sstevel@tonic-gate if (ndi_dev_is_persistent_node(child) == 0) {
6660Sstevel@tonic-gate extern int pci_allow_pseudo_children;
6670Sstevel@tonic-gate
6680Sstevel@tonic-gate ddi_set_parent_data(child, NULL);
6690Sstevel@tonic-gate
6700Sstevel@tonic-gate /*
6710Sstevel@tonic-gate * Try to merge the properties from this prototype
6720Sstevel@tonic-gate * node into real h/w nodes.
6730Sstevel@tonic-gate */
674881Sjohnny if (ndi_merge_node(child, pci_common_name_child) ==
675881Sjohnny DDI_SUCCESS) {
6760Sstevel@tonic-gate /*
6770Sstevel@tonic-gate * Merged ok - return failure to remove the node.
6780Sstevel@tonic-gate */
6790Sstevel@tonic-gate ddi_set_name_addr(child, NULL);
6800Sstevel@tonic-gate return (DDI_FAILURE);
6810Sstevel@tonic-gate }
6820Sstevel@tonic-gate
6830Sstevel@tonic-gate /* workaround for ddivs to run under PCI */
6840Sstevel@tonic-gate if (pci_allow_pseudo_children) {
6850Sstevel@tonic-gate /*
6860Sstevel@tonic-gate * If the "interrupts" property doesn't exist,
6870Sstevel@tonic-gate * this must be the ddivs no-intr case, and it returns
6880Sstevel@tonic-gate * DDI_SUCCESS instead of DDI_FAILURE.
6890Sstevel@tonic-gate */
6900Sstevel@tonic-gate if (ddi_prop_get_int(DDI_DEV_T_ANY, child,
6910Sstevel@tonic-gate DDI_PROP_DONTPASS, "interrupts", -1) == -1)
6920Sstevel@tonic-gate return (DDI_SUCCESS);
6930Sstevel@tonic-gate /*
6940Sstevel@tonic-gate * Create the ddi_parent_private_data for a pseudo
6950Sstevel@tonic-gate * child.
6960Sstevel@tonic-gate */
697881Sjohnny pci_common_set_parent_private_data(child);
6980Sstevel@tonic-gate return (DDI_SUCCESS);
6990Sstevel@tonic-gate }
7000Sstevel@tonic-gate
7010Sstevel@tonic-gate /*
7020Sstevel@tonic-gate * The child was not merged into a h/w node,
7030Sstevel@tonic-gate * but there's not much we can do with it other
7040Sstevel@tonic-gate * than return failure to cause the node to be removed.
7050Sstevel@tonic-gate */
7060Sstevel@tonic-gate cmn_err(CE_WARN, "!%s@%s: %s.conf properties not merged",
7070Sstevel@tonic-gate ddi_get_name(child), ddi_get_name_addr(child),
7080Sstevel@tonic-gate ddi_get_name(child));
7090Sstevel@tonic-gate ddi_set_name_addr(child, NULL);
7100Sstevel@tonic-gate return (DDI_NOT_WELL_FORMED);
7110Sstevel@tonic-gate }
7120Sstevel@tonic-gate
7130Sstevel@tonic-gate if (ddi_prop_get_int(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
714881Sjohnny "interrupts", -1) != -1)
715881Sjohnny pci_common_set_parent_private_data(child);
716881Sjohnny else
7170Sstevel@tonic-gate ddi_set_parent_data(child, NULL);
7180Sstevel@tonic-gate
719354Smyers /*
720354Smyers * initialize command register
721354Smyers */
722354Smyers if (pci_config_setup(child, &config_handle) != DDI_SUCCESS)
723354Smyers return (DDI_FAILURE);
724354Smyers
725354Smyers /*
726354Smyers * Support for the "command-preserve" property.
727354Smyers */
728354Smyers command_preserve = ddi_prop_get_int(DDI_DEV_T_ANY, child,
7295295Srandyf DDI_PROP_DONTPASS, "command-preserve", 0);
730354Smyers command = pci_config_get16(config_handle, PCI_CONF_COMM);
731354Smyers command &= (command_preserve | PCI_COMM_BACK2BACK_ENAB);
732354Smyers command |= (pci_command_default & ~command_preserve);
733354Smyers pci_config_put16(config_handle, PCI_CONF_COMM, command);
734354Smyers
735354Smyers pci_config_teardown(&config_handle);
7360Sstevel@tonic-gate return (DDI_SUCCESS);
7370Sstevel@tonic-gate }
7380Sstevel@tonic-gate
7390Sstevel@tonic-gate static int
pci_removechild(dev_info_t * dip)7400Sstevel@tonic-gate pci_removechild(dev_info_t *dip)
7410Sstevel@tonic-gate {
7420Sstevel@tonic-gate struct ddi_parent_private_data *pdptr;
7430Sstevel@tonic-gate
7440Sstevel@tonic-gate if ((pdptr = ddi_get_parent_data(dip)) != NULL) {
7450Sstevel@tonic-gate kmem_free(pdptr, (sizeof (*pdptr) + sizeof (struct intrspec)));
7460Sstevel@tonic-gate ddi_set_parent_data(dip, NULL);
7470Sstevel@tonic-gate }
7480Sstevel@tonic-gate ddi_set_name_addr(dip, NULL);
7490Sstevel@tonic-gate
7500Sstevel@tonic-gate /*
7510Sstevel@tonic-gate * Strip the node to properly convert it back to prototype form
7520Sstevel@tonic-gate */
7530Sstevel@tonic-gate ddi_remove_minor_node(dip, NULL);
7540Sstevel@tonic-gate
7550Sstevel@tonic-gate impl_rem_dev_props(dip);
7560Sstevel@tonic-gate
7570Sstevel@tonic-gate return (DDI_SUCCESS);
7580Sstevel@tonic-gate }
7590Sstevel@tonic-gate
7600Sstevel@tonic-gate
7610Sstevel@tonic-gate /*
7620Sstevel@tonic-gate * When retrofitting this module for pci_tools, functions such as open, close,
7630Sstevel@tonic-gate * and ioctl are now pulled into this module. Before this, the functions in
7640Sstevel@tonic-gate * the pcihp module were referenced directly. Now they are called or
7650Sstevel@tonic-gate * referenced through the pcihp cb_ops structure from functions in this module.
7660Sstevel@tonic-gate */
7670Sstevel@tonic-gate
7680Sstevel@tonic-gate static int
pci_open(dev_t * devp,int flags,int otyp,cred_t * credp)7690Sstevel@tonic-gate pci_open(dev_t *devp, int flags, int otyp, cred_t *credp)
7700Sstevel@tonic-gate {
771881Sjohnny return ((pcihp_get_cb_ops())->cb_open(devp, flags, otyp, credp));
7720Sstevel@tonic-gate }
7730Sstevel@tonic-gate
7740Sstevel@tonic-gate static int
pci_close(dev_t dev,int flags,int otyp,cred_t * credp)7750Sstevel@tonic-gate pci_close(dev_t dev, int flags, int otyp, cred_t *credp)
7760Sstevel@tonic-gate {
777881Sjohnny return ((pcihp_get_cb_ops())->cb_close(dev, flags, otyp, credp));
7780Sstevel@tonic-gate }
7790Sstevel@tonic-gate
7800Sstevel@tonic-gate static int
pci_ioctl(dev_t dev,int cmd,intptr_t arg,int mode,cred_t * credp,int * rvalp)781881Sjohnny pci_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, int *rvalp)
7820Sstevel@tonic-gate {
783777Sschwartz minor_t minor = getminor(dev);
78410923SEvan.Yan@Sun.COM int instance = PCI_MINOR_NUM_TO_INSTANCE(minor);
785777Sschwartz pci_state_t *pci_p = ddi_get_soft_state(pci_statep, instance);
78610923SEvan.Yan@Sun.COM int ret = ENOTTY;
7870Sstevel@tonic-gate
788881Sjohnny if (pci_p == NULL)
789881Sjohnny return (ENXIO);
790117Sschwartz
79110923SEvan.Yan@Sun.COM switch (PCI_MINOR_NUM_TO_PCI_DEVNUM(minor)) {
79210923SEvan.Yan@Sun.COM case PCI_TOOL_REG_MINOR_NUM:
79310923SEvan.Yan@Sun.COM case PCI_TOOL_INTR_MINOR_NUM:
79410923SEvan.Yan@Sun.COM /* To handle pcitool related ioctls */
79510923SEvan.Yan@Sun.COM ret = pci_common_ioctl(pci_p->pci_dip, dev, cmd, arg, mode,
79610923SEvan.Yan@Sun.COM credp, rvalp);
79710923SEvan.Yan@Sun.COM break;
79810923SEvan.Yan@Sun.COM default:
79910923SEvan.Yan@Sun.COM /* To handle devctl and hotplug related ioctls */
80010923SEvan.Yan@Sun.COM ret = (pcihp_get_cb_ops())->cb_ioctl(dev, cmd, arg, mode,
80110923SEvan.Yan@Sun.COM credp, rvalp);
80210923SEvan.Yan@Sun.COM break;
80310923SEvan.Yan@Sun.COM }
80410923SEvan.Yan@Sun.COM
80510923SEvan.Yan@Sun.COM return (ret);
806881Sjohnny }
8070Sstevel@tonic-gate
8080Sstevel@tonic-gate
8090Sstevel@tonic-gate static int
pci_prop_op(dev_t dev,dev_info_t * dip,ddi_prop_op_t prop_op,int flags,char * name,caddr_t valuep,int * lengthp)8100Sstevel@tonic-gate pci_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
811117Sschwartz int flags, char *name, caddr_t valuep, int *lengthp)
8120Sstevel@tonic-gate {
813881Sjohnny return ((pcihp_get_cb_ops())->cb_prop_op(dev, dip, prop_op, flags,
8140Sstevel@tonic-gate name, valuep, lengthp));
8150Sstevel@tonic-gate }
8160Sstevel@tonic-gate
8170Sstevel@tonic-gate static int
pci_info(dev_info_t * dip,ddi_info_cmd_t cmd,void * arg,void ** result)8180Sstevel@tonic-gate pci_info(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
8190Sstevel@tonic-gate {
8200Sstevel@tonic-gate return (pcihp_info(dip, cmd, arg, result));
8210Sstevel@tonic-gate }
8221865Sdilpreet
pci_peekpoke_cb(dev_info_t * dip,ddi_fm_error_t * derr)8236313Skrishnae void pci_peekpoke_cb(dev_info_t *dip, ddi_fm_error_t *derr) {
8246313Skrishnae (void) pci_ereport_post(dip, derr, NULL);
8256313Skrishnae }
8266313Skrishnae
8271865Sdilpreet /*ARGSUSED*/
8281865Sdilpreet static int
pci_fm_init(dev_info_t * dip,dev_info_t * tdip,int cap,ddi_iblock_cookie_t * ibc)8291865Sdilpreet pci_fm_init(dev_info_t *dip, dev_info_t *tdip, int cap,
8301865Sdilpreet ddi_iblock_cookie_t *ibc)
8311865Sdilpreet {
8321865Sdilpreet pci_state_t *pcip = ddi_get_soft_state(pci_statep,
8331865Sdilpreet ddi_get_instance(dip));
8341865Sdilpreet
8351865Sdilpreet ASSERT(ibc != NULL);
8361865Sdilpreet *ibc = pcip->pci_fm_ibc;
8371865Sdilpreet
8381865Sdilpreet return (pcip->pci_fmcap);
8391865Sdilpreet }
8401865Sdilpreet
8411865Sdilpreet /*ARGSUSED*/
8421865Sdilpreet static int
pci_fm_callback(dev_info_t * dip,ddi_fm_error_t * derr,const void * no_used)8431865Sdilpreet pci_fm_callback(dev_info_t *dip, ddi_fm_error_t *derr, const void *no_used)
8441865Sdilpreet {
8451865Sdilpreet pci_state_t *pcip = ddi_get_soft_state(pci_statep,
8461865Sdilpreet ddi_get_instance(dip));
8471865Sdilpreet
8481865Sdilpreet mutex_enter(&pcip->pci_err_mutex);
8491865Sdilpreet pci_ereport_post(dip, derr, NULL);
8501865Sdilpreet mutex_exit(&pcip->pci_err_mutex);
8511865Sdilpreet return (derr->fme_status);
8521865Sdilpreet }
853