tphci.c revision 193974072f41a843678abf5f61979c748687e66b
99653d4ee642c6528e88224f12409a5f23060994eschrock * CDDL HEADER START
99653d4ee642c6528e88224f12409a5f23060994eschrock * The contents of this file are subject to the terms of the
99653d4ee642c6528e88224f12409a5f23060994eschrock * Common Development and Distribution License (the "License").
99653d4ee642c6528e88224f12409a5f23060994eschrock * You may not use this file except in compliance with the License.
99653d4ee642c6528e88224f12409a5f23060994eschrock * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
99653d4ee642c6528e88224f12409a5f23060994eschrock * See the License for the specific language governing permissions
99653d4ee642c6528e88224f12409a5f23060994eschrock * and limitations under the License.
99653d4ee642c6528e88224f12409a5f23060994eschrock * When distributing Covered Code, include this CDDL HEADER in each
99653d4ee642c6528e88224f12409a5f23060994eschrock * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
99653d4ee642c6528e88224f12409a5f23060994eschrock * If applicable, add the following below this CDDL HEADER, with the
99653d4ee642c6528e88224f12409a5f23060994eschrock * fields enclosed by brackets "[]" replaced with your own identifying
99653d4ee642c6528e88224f12409a5f23060994eschrock * information: Portions Copyright [yyyy] [name of copyright owner]
99653d4ee642c6528e88224f12409a5f23060994eschrock * CDDL HEADER END
cbf75e67acb6c32a2f4884f28a839d59f7988d37Stephen Hanson * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
99653d4ee642c6528e88224f12409a5f23060994eschrock * Use is subject to license terms.
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock * The tphci driver can be used to exercise the mpxio framework together
99653d4ee642c6528e88224f12409a5f23060994eschrock/* cb_ops entry points */
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrockstatic int tphci_open(dev_t *, int, int, cred_t *);
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrockstatic int tphci_close(dev_t, int, int, cred_t *);
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrockstatic int tphci_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrockstatic int tphci_attach(dev_info_t *, ddi_attach_cmd_t);
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrockstatic int tphci_detach(dev_info_t *, ddi_detach_cmd_t);
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrockstatic int tphci_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrock/* bus_ops entry points */
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrockstatic int tphci_ctl(dev_info_t *, dev_info_t *, ddi_ctl_enum_t, void *,
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrockstatic int tphci_initchild(dev_info_t *, dev_info_t *);
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrockstatic int tphci_uninitchild(dev_info_t *, dev_info_t *);
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrockstatic int tphci_bus_config(dev_info_t *, uint_t, ddi_bus_config_op_t, void *,
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrockstatic int tphci_bus_unconfig(dev_info_t *, uint_t, ddi_bus_config_op_t,
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrockstatic int tphci_intr_op(dev_info_t *dip, dev_info_t *rdip,
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrock ddi_intr_op_t op, ddi_intr_handle_impl_t *hdlp, void *result);
99653d4ee642c6528e88224f12409a5f23060994eschrock 0, /* streamtab */
c5904d138f3bdf0762dbf452a43d5a5c387ea6a8eschrock tphci_attach, /* attach and detach are mandatory */
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock "test phci driver",
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrock * don't start cleaning up until we know that the module remove
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrock * has worked -- if this works, then we know that each instance
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrock * has successfully been detached
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrock/* ARGSUSED */
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrocktphci_open(dev_t *devp, int flag, int otype, cred_t *credp)
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrock phci = ddi_get_soft_state(tphci_state, getminor(*devp));
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrock/* ARGSUSED */
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrocktphci_close(dev_t dev, int flag, int otype, cred_t *credp)
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock phci = ddi_get_soft_state(tphci_state, getminor(dev));
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock return (0);
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock/* ARGSUSED */
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrocktphci_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock return (0);
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock * attach the module
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrocktphci_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock return (0); /* nothing to do */
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock * Allocate phci data structure.
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock if (ddi_soft_state_zalloc(tphci_state, instance) != DDI_SUCCESS) {
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrock /* bus_addr has the form #,<vhci_class> */
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrock * Attach this instance with the mpxio framework
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrock if (mdi_phci_register(vclass + 1, dip, 0) != MDI_SUCCESS) {
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrock cmn_err(CE_WARN, "%s mdi_phci_register failed",
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrock if (ddi_create_minor_node(dip, "devctl", S_IFCHR,
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrock instance, DDI_NT_SCSI_NEXUS, 0) != DDI_SUCCESS) {
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrock cmn_err(CE_NOTE, "%s ddi_create_minor_node failed",
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrock (void) ddi_prop_update_int(DDI_DEV_T_NONE, dip, DDI_NO_AUTODETACH, 1);
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrocktphci_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrock return (0); /* nothing to do */
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrock if (mdi_phci_unregister(dip, 0) != MDI_SUCCESS)
eb04386ee9658c0271a7af93e0595582e2235689Eric Schrock * tphci_getinfo()
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrock * Given the device number, return the devinfo pointer or the
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrock * instance number.
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrock * Note: always succeed DDI_INFO_DEVT2INSTANCE, even before attach.
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrocktphci_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock * Interrupt stuff. NO OP for pseudo drivers.
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock/*ARGSUSED*/
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrocktphci_intr_op(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t op,
99653d4ee642c6528e88224f12409a5f23060994eschrock * These ops correspond to functions that "shouldn't" be called
99653d4ee642c6528e88224f12409a5f23060994eschrock * by a pseudo driver. So we whine when we're called.
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock cmn_err(CE_CONT, "%s%d: invalid op (%d) from %s%d\n",
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock ctlop, ddi_get_name(rdip), ddi_get_instance(rdip));
99653d4ee642c6528e88224f12409a5f23060994eschrock * The ops that we pass up (default). We pass up memory
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrock * allocation oriented ops that we receive - these may be
3d7072f8bd27709dba14f6fe336f149d25d9e207eschrock * associated with pseudo HBA drivers below us with target
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrock * drivers below them that use ddi memory allocation
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrock * interfaces like scsi_alloc_consistent_buf.
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrock return (ddi_ctlops(dip, rdip, ctlop, arg, result));
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrocktphci_initchild(dev_info_t *dip, dev_info_t *child)
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrocktphci_uninitchild(dev_info_t *dip, dev_info_t *child)
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrocktp_decode_name(char *devnm, char **cname, char **paddr, char **guid)
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrock (strcmp(*cname, "tphci") != 0) || *paddr == NULL)
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrock return (-1);
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrock return (-1);
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrocktphci_bus_config(dev_info_t *parent, uint_t flags,
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrock ddi_bus_config_op_t op, void *arg, dev_info_t **childp)
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrock case BUS_CONFIG_DRIVER: /* no direct children to configure */
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrock /* only implement BUS_CONFIG_ONE */
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrock /* caddr is hardcoded in the form *,<guid> */
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrock if (tp_decode_name(devnm, &cname, &paddr, &guid) != 0) {
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrock cmn_err(CE_NOTE, "tphci_bus_config -- invalid device %s",
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrock rval = mdi_pi_alloc(parent, cname, guid, paddr, 0, &pip);
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrock cmn_err(CE_NOTE, "tphci_bus_config -- mdi_pi_alloc failed");
99653d4ee642c6528e88224f12409a5f23060994eschrock * Hold the path and exit the pHCI while calling mdi_pi_online
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrock * to avoid deadlock with power management of pHCI.
99653d4ee642c6528e88224f12409a5f23060994eschrock cmn_err(CE_NOTE, "tphci_bus_config -- mdi_pi_online failed");
99653d4ee642c6528e88224f12409a5f23060994eschrocktphci_bus_unconfig(dev_info_t *parent, uint_t flags,
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrock return (rval == MDI_SUCCESS ? NDI_SUCCESS : NDI_FAILURE);
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrock return (rval == MDI_SUCCESS ? NDI_SUCCESS : NDI_FAILURE);
return (NDI_FAILURE);