Example #1
0
/*ARGSUSED*/
static int
logidetach(dev_info_t *dip, ddi_detach_cmd_t cmd)
{
	dev_info_t	*ldevi;
	struct strmseinfo *logiptr;
	int instance;

	switch (cmd) {

	case DDI_DETACH:

		/*
		 * check if every instance can be unloaded before actually
		 * starting to unload this one; this prevents the needless
		 * detach/re-attach sequence
		 */
		for (instance = 0; instance < LOGI_MAXUNIT; instance++) {
			if (((ldevi = logiunits[instance]) == NULL) ||
			    (logiptr = ddi_get_driver_private(ldevi)) == NULL)
				continue;
		}

/*
 * 		Undo what we did in logiattach & logiprobe, freeing resources
 * 		and removing things we installed.  The system
 * 		framework guarantees we are not active with this devinfo
 * 		node in any other entry points at this time.
 */
		instance = ddi_get_instance(dip);
		if ((instance >= LOGI_MAXUNIT) ||
		    (logiptr = ddi_get_driver_private(dip)) == NULL)
			return (DDI_FAILURE);


		logiunits[instance] = 0;
		ddi_prop_remove_all(dip);
		ddi_remove_minor_node(dip, NULL);
		mutex_destroy(&logiptr->lock);
		ddi_remove_intr(dip, 0, logiptr->iblock);
		kmem_free(logiptr, sizeof (struct strmseinfo));
		return (DDI_SUCCESS);

	default:
#ifdef LOGI_DEBUG
		if (logi_debug) {
			PRF("logidetach: cmd = %d unknown\n", cmd);
		}
#endif
		return (DDI_FAILURE);
	}
}
Example #2
0
/*
 * audio1575_resume()
 *
 * Description:
 *	Resume operation of the device after sleeping or hibernating.
 *	Note that this should never fail, even if hardware goes wonky,
 *	because the current PM framework will panic if it does.
 *
 * Arguments:
 *	dev_info_t	*dip	Pointer to the device's dev_info struct
 *
 * Returns:
 *	DDI_SUCCESS		The driver was resumed
 */
static int
audio1575_resume(dev_info_t *dip)
{
	audio1575_state_t	*statep;
	audio_dev_t		*adev;

	/* we've already allocated the state structure so get ptr */
	statep = ddi_get_driver_private(dip);
	adev = statep->adev;
	ASSERT(!mutex_owned(&statep->lock));

	if (audio1575_chip_init(statep) != DDI_SUCCESS) {
		/*
		 * Note that PM gurus say we should return
		 * success here.  Failure of audio shouldn't
		 * be considered FATAL to the system.  The
		 * upshot is that audio will not progress.
		 */
		audio_dev_warn(adev, "DDI_RESUME failed to init chip");
		return (DDI_SUCCESS);
	}

	/* allow ac97 operations again */
	ac97_reset(statep->ac97);

	audio_dev_resume(adev);

	return (DDI_SUCCESS);
}
/*ARGSUSED*/
static int
mouse8042_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
{
	struct mouse_state *state;

	state = ddi_get_driver_private(dip);

	switch (cmd) {
	case DDI_SUSPEND:
		/* Ignore all data from mouse8042_intr until we fully resume */
		state->ready = 0;
		return (DDI_SUCCESS);

	case DDI_DETACH:
		ddi_remove_intr(dip, 0, state->ms_iblock_cookie);
		mouse8042_dip = NULL;
		cv_destroy(&state->reset_cv);
		mutex_destroy(&state->reset_mutex);
		mutex_destroy(&state->ms_mutex);
		ddi_prop_remove_all(dip);
		ddi_regs_map_free(&state->ms_handle);
		ddi_remove_minor_node(dip, NULL);
		kmem_free(state, sizeof (struct mouse_state));
		return (DDI_SUCCESS);

	default:
		return (DDI_FAILURE);
	}
}
/**
 * Virtio Detach routine that should be called from all Virtio drivers' detach
 * routines.
 *
 * @param pDip              The module structure instance.
 * @param enmCmd            Operation type (detach/suspend).
 *
 * @return Solaris DDI error code. DDI_SUCCESS or DDI_FAILURE.
 */
int VirtioDetach(dev_info_t *pDip, ddi_detach_cmd_t enmCmd)
{
    LogFlowFunc((VIRTIOLOGNAME ":VirtioDetach pDip=%p enmCmd=%d\n", pDip, enmCmd));

    PVIRTIODEVICE pDevice = ddi_get_driver_private(pDip);
    if (RT_UNLIKELY(!pDevice))
        return DDI_FAILURE;

    if (enmCmd != DDI_DETACH)
    {
        LogRel((VIRTIOLOGNAME ":VirtioDetach: Invalid enmCmd=%#x expected DDI_DETACH.\n", enmCmd));
        return DDI_FAILURE;
    }

    int rc = pDevice->pDeviceOps->pfnDetach(pDevice);
    if (rc == DDI_SUCCESS)
    {
        pDevice->pHyperOps->pfnDetach(pDevice);
        pDevice->pDeviceOps->pfnFree(pDevice);
        pDevice->pvDevice = NULL;
        pDevice->pHyperOps->pfnFree(pDevice);
        pDevice->pvHyper = NULL;

        ddi_set_driver_private(pDevice->pDip, NULL);
        RTMemFree(pDevice);
        return DDI_SUCCESS;
    }
    else
        LogRel((VIRTIOLOGNAME ":VirtioDetach: DeviceOps pfnDetach failed. rc=%d\n", rc));

    return DDI_FAILURE;
}
static int
audio_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
{
	audio_dev_t	*adev;

	/* pseudo devices don't need S/R support */
	if (cmd != DDI_DETACH) {
		return (DDI_FAILURE);
	}

	if (dip == NULL) {
		return (DDI_FAILURE);
	}

	if ((adev = ddi_get_driver_private(dip)) == NULL) {
		return (DDI_FAILURE);
	}

	if (audio_dev_unregister(adev) != DDI_SUCCESS) {
		return (DDI_FAILURE);
	}

	audio_dev_free(adev);

	return (DDI_SUCCESS);
}
static int
audioixp_resume(dev_info_t *dip)
{
	audioixp_state_t		*statep;
	audio_dev_t			*adev;
	audioixp_port_t			*rec_port, *play_port;

	statep = ddi_get_driver_private(dip);
	adev = statep->adev;
	ASSERT(statep != NULL);

	if (audioixp_chip_init(statep) != DDI_SUCCESS) {
		audio_dev_warn(adev, "DDI_RESUME failed to init chip");
		return (DDI_SUCCESS);
	}

	ac97_resume(statep->ac97);
	mutex_enter(&statep->inst_lock);
	statep->suspended = B_FALSE;

	rec_port = statep->rec_port;
	play_port = statep->play_port;

	audioixp_resume_port(rec_port);
	audioixp_resume_port(play_port);

	mutex_exit(&statep->inst_lock);
	return (DDI_SUCCESS);
}
Example #7
0
/*
 * audio1575_ddi_quiesce()
 *
 * Description:
 *	Implements the quiesce(9e) entry point.
 *
 * Arguments:
 *	dev_info_t		*dip	Pointer to the device's dev_info struct
 *
 * Returns:
 *	DDI_SUCCESS	The driver was quiesced
 *	DDI_FAILURE	The driver couldn't be quiesced
 */
static int
audio1575_ddi_quiesce(dev_info_t *dip)
{
	audio1575_state_t	*statep;

	if ((statep = ddi_get_driver_private(dip)) == NULL)
		return (DDI_FAILURE);

	audio1575_dma_stop(statep, B_TRUE);
	return (DDI_SUCCESS);
}
Example #8
0
/*
 * audio1575_suspend()
 *
 * Description:
 *	Suspend an instance of the audio1575 driver.
 *
 * Arguments:
 *	dev_info_t	*dip	Pointer to the device's dev_info struct
 *
 * Returns:
 *	DDI_SUCCESS	The driver was suspended
 */
static int
audio1575_suspend(dev_info_t *dip)
{
	audio1575_state_t	*statep;

	statep = ddi_get_driver_private(dip);

	audio_dev_suspend(statep->adev);

	return (DDI_SUCCESS);
}
Example #9
0
int
efe_quiesce(dev_info_t *dip)
{
	efe_t *efep = ddi_get_driver_private(dip);

	PUTCSR(efep, CSR_GENCTL, GENCTL_RESET);
	drv_usecwait(RESET_DELAY);

	PUTCSR(efep, CSR_GENCTL, GENCTL_PWRDWN);

	return (DDI_SUCCESS);
}
Example #10
0
/*ARGSUSED2*/
static int
logiopen(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *cred_p)
{
	struct strmseinfo *logiptr;
	int unit;
	dev_info_t *dip;
#ifdef LOGI_DEBUG
	if (logi_debug)
		printf("logiopen:entered\n");
#endif
	if (((unit = LOGIUNIT(*devp)) >= LOGI_MAXUNIT) ||
		(dip = logiunits[unit]) == NULL)
		return (ENODEV);

	if (!mse_config.present)
		return (EIO);
	if ((logiptr = ddi_get_driver_private(dip)) == NULL)
		return (EIO);
	if (logiptr->state & M_OPEN)
		return (EBUSY);
	mutex_enter(&logiptr->lock);
	if (q->q_ptr != NULL) {
#ifdef LOGI_DEBUG
	if (logi_debug)
		printf("logiopen:already open\n");
#endif
		mutex_exit(&logiptr->lock);
		return (EBUSY);		/* already attached */
	}


	q->q_ptr = (caddr_t)logiptr;
	WR(q)->q_ptr = (caddr_t)logiptr;
	logiptr->rqp = q;
	logiptr->wqp = WR(q);
	qprocson(q);
#ifdef LOGI_DEBUG
	if (logi_debug)
		printf("logiopen:Enable interrupts ioaddr %x\n", BASE_IOA);
#endif
	control_port(0);	/* Enable interrupts */

#ifdef LOGI_DEBUG
	if (logi_debug)
		printf("logiopen:leaving\n");
#endif
	oldbuttons = 0;
	logiptr->state = M_OPEN;
	mutex_exit(&logiptr->lock);
	return (0);
}
Example #11
0
/*ARGSUSED*/
static int
emul64_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
{
	struct emul64	*emul64;
	scsi_hba_tran_t	*tran;
	int		instance = ddi_get_instance(dip);


	/* get transport structure pointer from the dip */
	if (!(tran = (scsi_hba_tran_t *)ddi_get_driver_private(dip))) {
		return (DDI_FAILURE);
	}

	/* get soft state from transport structure */
	emul64 = TRAN2EMUL64(tran);

	if (!emul64) {
		return (DDI_FAILURE);
	}

	EMUL64_DEBUG(emul64, SCSI_DEBUG, "emul64_detach: cmd = %d", cmd);

	switch (cmd) {
	case DDI_DETACH:
		EMUL64_MUTEX_ENTER(emul64);

		taskq_destroy(emul64->emul64_taskq);
		(void) scsi_hba_detach(dip);

		scsi_hba_tran_free(emul64->emul64_tran);


		EMUL64_MUTEX_EXIT(emul64);

		mutex_destroy(EMUL64_REQ_MUTEX(emul64));
		mutex_destroy(EMUL64_RESP_MUTEX(emul64));


		EMUL64_DEBUG(emul64, SCSI_DEBUG, "emul64_detach: done");
		ddi_soft_state_free(emul64_state, instance);

		return (DDI_SUCCESS);

	case DDI_SUSPEND:
		return (DDI_SUCCESS);

	default:
		return (DDI_FAILURE);
	}
}
Example #12
0
/*
 * audioixp_detach()
 *
 * Description:
 *	Detach an instance of the audioixp driver.
 *
 * Arguments:
 *	dev_info_t	*dip	Pointer to the device's dev_info struct
 *
 * Returns:
 *	DDI_SUCCESS	The driver was detached
 *	DDI_FAILURE	The driver couldn't be detached
 */
static int
audioixp_detach(dev_info_t *dip)
{
	audioixp_state_t	*statep;

	statep = ddi_get_driver_private(dip);

	if (audio_dev_unregister(statep->adev) != DDI_SUCCESS) {
		return (DDI_FAILURE);
	}

	audioixp_destroy(statep);
	return (DDI_SUCCESS);
}
Example #13
0
/**
 * Detach entry point, to detach a device to the system or suspend it.
 *
 * @param   pDip            The module structure instance.
 * @param   enmCmd          Operation type (detach/suspend).
 *
 * @returns corresponding solaris error code.
 */
static int VBoxNetAdpSolarisDetach(dev_info_t *pDip, ddi_detach_cmd_t enmCmd)
{
    LogFunc((DEVICE_NAME ":VBoxNetAdpSolarisDetach pDip=%p enmCmd=%d\n", pDip, enmCmd));

    switch (enmCmd)
    {
        case DDI_DETACH:
        {
            /*
             * Unregister and clean up.
             */
            gld_mac_info_t *pMacInfo = ddi_get_driver_private(pDip);
            if (pMacInfo)
            {
                vboxnetadp_state_t *pState = (vboxnetadp_state_t *)pMacInfo->gldm_private;
                if (pState)
                {
                    gld_linkstate(pMacInfo, GLD_LINKSTATE_DOWN);
                    int rc = gld_unregister(pMacInfo);
                    if (rc == DDI_SUCCESS)
                    {
                        gld_mac_free(pMacInfo);
                        RTMemFree(pState);
                        return DDI_SUCCESS;
                    }
                    else
                        LogRel((DEVICE_NAME ":VBoxNetAdpSolarisDetach failed to unregister GLD from MAC layer.rc=%d\n", rc));
                }
                else
                    LogRel((DEVICE_NAME ":VBoxNetAdpSolarisDetach failed to get internal state.\n"));
            }
            else
                LogRel((DEVICE_NAME ":VBoxNetAdpSolarisDetach failed to get driver private GLD data.\n"));

            return DDI_FAILURE;
        }

        case DDI_RESUME:
        {
            /* Nothing to do here... */
            return DDI_SUCCESS;
        }

        /* case DDI_SUSPEND: */
        /* case DDI_HOTPLUG_DETACH: */
        default:
            return DDI_FAILURE;
    }
}
static int
ddksample_detach (dev_info_t * dip, ddi_detach_cmd_t cmd)
{
  oss_device_t *osdev;
  int err;

  ddksample_devc *devc;

  if (cmd != DDI_DETACH)
    {
      cmn_err (CE_WARN, "bad attach cmd %d\n", cmd);
      return 0;
    }

  if (dip == NULL)
    {
      cmn_err (CE_WARN, "ddksample_detach: dip==NULL\n");
      return DDI_FAILURE;
    }

  cmn_err (CE_CONT, "Detach started " DRIVER_NICK "\n");
  if ((osdev = ddi_get_driver_private (dip)) == NULL)
    {
      cmn_err (CE_WARN, "ddi_get_driver_private() failed\n");
      return DDI_SUCCESS;
    }

/*
 * Check if the device can be removed (not busy) and make sure it will not be
 * opened any more.
 */
  if ((err = ossddk_disable_device (osdev)) < 0)
    return DDI_FAILURE;

  devc = ossddk_osdev_get_devc (osdev);

/*
 * Stop the device and make sure it will not raise any
 * interrupts any morfe.
 */

  ossddk_unregister_device (osdev);

  mutex_destroy (&devc->mutex);
  kmem_free (devc, sizeof (*devc));

  return DDI_SUCCESS;
}
Example #15
0
static int
usbser_keyspan_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
{

	if (ddi_get_driver_private(dip) == NULL) {

		return (keyspan_pre_detach(dip, cmd, usbser_keyspan_statep));
	} else {


		return (usbser_detach(dip, cmd, usbser_keyspan_statep));


	}

}
Example #16
0
/*
 * quiesce(9E) entry point.
 *
 * This function is called when the system is single-threaded at high
 * PIL with preemption disabled. Therefore, this function must not be blocked.
 *
 * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
 * DDI_FAILURE indicates an error condition and should almost never happen.
 */
static int
audioixp_quiesce(dev_info_t *dip)
{
	audioixp_state_t		*statep;

	statep = ddi_get_driver_private(dip);
	ASSERT(statep != NULL);

	/* disable HW interrupt */
	audioixp_disable_intr(statep);

	/* stop DMA engines */
	audioixp_stop_dma(statep);

	return (DDI_SUCCESS);
}
Example #17
0
int
efe_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
{
	efe_t *efep = ddi_get_driver_private(dip);

	switch (cmd) {
	case DDI_DETACH:
		break;

	case DDI_SUSPEND:
		return (efe_suspend(efep));

	default:
		return (DDI_FAILURE);
	}

	if (mac_unregister(efep->efe_mh) != 0) {
		efe_error(dip, "unable to unregister from mac!");
		return (DDI_FAILURE);
	}

	mii_free(efep->efe_miih);

	(void) ddi_intr_disable(efep->efe_intrh);
	(void) ddi_intr_remove_handler(efep->efe_intrh);
	(void) ddi_intr_free(efep->efe_intrh);

	mutex_destroy(&efep->efe_txlock);
	mutex_destroy(&efep->efe_intrlock);

	if (efep->efe_tx_ring != NULL) {
		efe_ring_free(&efep->efe_tx_ring);
	}
	if (efep->efe_rx_ring != NULL) {
		efe_ring_free(&efep->efe_rx_ring);
	}

	ddi_regs_map_free(&efep->efe_regs_acch);

	kmem_free(efep, sizeof (efe_t));

	return (DDI_SUCCESS);
}
Example #18
0
static int
audioixp_suspend(dev_info_t *dip)
{
	audioixp_state_t		*statep;

	statep = ddi_get_driver_private(dip);
	ASSERT(statep != NULL);

	ac97_suspend(statep->ac97);
	mutex_enter(&statep->inst_lock);

	statep->suspended = B_TRUE;

	audioixp_disable_intr(statep);
	audioixp_stop_dma(statep);

	mutex_exit(&statep->inst_lock);
	return (DDI_SUCCESS);
}
Example #19
0
static int
iidetach(dev_info_t *dip, ddi_detach_cmd_t cmd)
{
	struct ii_state *xsp;
	int instance;
	intptr_t flags;

	if (cmd != DDI_DETACH) {
		return (DDI_FAILURE);
	}

	if (_ii_info_top) {
		return (DDI_FAILURE);	/* busy */
	}

	instance = ddi_get_instance(dip);
	xsp = ddi_get_soft_state(ii_statep, instance);
	if (xsp == NULL) {
		cmn_err(CE_WARN,
		    "!ii: detach: could not get state for instance %d.",
		    instance);
		return (DDI_FAILURE);
	}

	flags = (intptr_t)ddi_get_driver_private(dip);
	if (flags & DIDNODES)
		ddi_remove_minor_node(dip, NULL);
	if (flags & DIDINIT)
		_ii_deinit_dev();

	ddi_soft_state_free(ii_statep, instance);

	if (ii_gkstat) {
		kstat_delete(ii_gkstat);
		ii_gkstat = NULL;
	}

	return (DDI_SUCCESS);
}
Example #20
0
static int
bd_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
{
	bd_t	*bd;

	bd = ddi_get_driver_private(dip);

	switch (cmd) {
	case DDI_DETACH:
		break;
	case DDI_SUSPEND:
		/* We don't suspend, but our parent does */
		return (DDI_SUCCESS);
	default:
		return (DDI_FAILURE);
	}
	if (bd->d_ksp != NULL) {
		kstat_delete(bd->d_ksp);
		bd->d_ksp = NULL;
	} else {
		kmem_free(bd->d_kiop, sizeof (kstat_io_t));
	}
	cmlb_detach(bd->d_cmlbh, 0);
	cmlb_free_handle(&bd->d_cmlbh);
	if (bd->d_devid)
		ddi_devid_free(bd->d_devid);
	kmem_cache_destroy(bd->d_cache);
	mutex_destroy(&bd->d_iomutex);
	mutex_destroy(&bd->d_ocmutex);
	mutex_destroy(&bd->d_statemutex);
	cv_destroy(&bd->d_statecv);
	list_destroy(&bd->d_waitq);
	list_destroy(&bd->d_runq);
	ddi_soft_state_free(bd_state, ddi_get_instance(dip));
	return (DDI_SUCCESS);
}
Example #21
0
/*
 * Autoconfiguration entry points.
 */
int
efe_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
{
	ddi_acc_handle_t pci;
	int types;
	int count;
	int actual;
	uint_t pri;
	efe_t *efep;
	mac_register_t *macp;

	switch (cmd) {
	case DDI_ATTACH:
		break;

	case DDI_RESUME:
		efep = ddi_get_driver_private(dip);
		return (efe_resume(efep));

	default:
		return (DDI_FAILURE);
	}

	/*
	 * PCI configuration.
	 */
	if (pci_config_setup(dip, &pci) != DDI_SUCCESS) {
		efe_error(dip, "unable to setup PCI configuration!");
		return (DDI_FAILURE);
	}

	pci_config_put16(pci, PCI_CONF_COMM,
	    pci_config_get16(pci, PCI_CONF_COMM) | PCI_COMM_MAE | PCI_COMM_ME);

	pci_config_teardown(&pci);

	if (ddi_intr_get_supported_types(dip, &types)
	    != DDI_SUCCESS || !(types & DDI_INTR_TYPE_FIXED)) {
		efe_error(dip, "fixed interrupts not supported!");
		return (DDI_FAILURE);
	}

	if (ddi_intr_get_nintrs(dip, DDI_INTR_TYPE_FIXED, &count)
	    != DDI_SUCCESS || count != 1) {
		efe_error(dip, "no fixed interrupts available!");
		return (DDI_FAILURE);
	}

	/*
	 * Initialize soft state.
	 */
	efep = kmem_zalloc(sizeof (efe_t), KM_SLEEP);
	ddi_set_driver_private(dip, efep);

	efep->efe_dip = dip;

	if (ddi_regs_map_setup(dip, 1, (caddr_t *)&efep->efe_regs, 0, 0,
	    &efe_regs_acc_attr, &efep->efe_regs_acch) != DDI_SUCCESS) {
		efe_error(dip, "unable to setup register mapping!");
		goto failure;
	}

	efep->efe_rx_ring = efe_ring_alloc(efep->efe_dip, RXDESCL);
	if (efep->efe_rx_ring == NULL) {
		efe_error(efep->efe_dip, "unable to allocate rx ring!");
		goto failure;
	}

	efep->efe_tx_ring = efe_ring_alloc(efep->efe_dip, TXDESCL);
	if (efep->efe_tx_ring == NULL) {
		efe_error(efep->efe_dip, "unable to allocate tx ring!");
		goto failure;
	}

	if (ddi_intr_alloc(dip, &efep->efe_intrh, DDI_INTR_TYPE_FIXED, 0,
	    count, &actual, DDI_INTR_ALLOC_STRICT) != DDI_SUCCESS ||
	    actual != count) {
		efe_error(dip, "unable to allocate fixed interrupt!");
		goto failure;
	}

	if (ddi_intr_get_pri(efep->efe_intrh, &pri) != DDI_SUCCESS ||
	    pri >= ddi_intr_get_hilevel_pri()) {
		efe_error(dip, "unable to get valid interrupt priority!");
		goto failure;
	}

	mutex_init(&efep->efe_intrlock, NULL, MUTEX_DRIVER,
	    DDI_INTR_PRI(pri));

	mutex_init(&efep->efe_txlock, NULL, MUTEX_DRIVER,
	    DDI_INTR_PRI(pri));

	/*
	 * Initialize device.
	 */
	mutex_enter(&efep->efe_intrlock);
	mutex_enter(&efep->efe_txlock);

	efe_reset(efep);

	mutex_exit(&efep->efe_txlock);
	mutex_exit(&efep->efe_intrlock);

	/* Use factory address as default */
	efe_getaddr(efep, efep->efe_macaddr);

	/*
	 * Enable the ISR.
	 */
	if (ddi_intr_add_handler(efep->efe_intrh, efe_intr, efep, NULL)
	    != DDI_SUCCESS) {
		efe_error(dip, "unable to add interrupt handler!");
		goto failure;
	}

	if (ddi_intr_enable(efep->efe_intrh) != DDI_SUCCESS) {
		efe_error(dip, "unable to enable interrupt!");
		goto failure;
	}

	/*
	 * Allocate MII resources.
	 */
	if ((efep->efe_miih = mii_alloc(efep, dip, &efe_mii_ops)) == NULL) {
		efe_error(dip, "unable to allocate mii resources!");
		goto failure;
	}

	/*
	 * Allocate MAC resources.
	 */
	if ((macp = mac_alloc(MAC_VERSION)) == NULL) {
		efe_error(dip, "unable to allocate mac resources!");
		goto failure;
	}

	macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
	macp->m_driver = efep;
	macp->m_dip = dip;
	macp->m_src_addr = efep->efe_macaddr;
	macp->m_callbacks = &efe_m_callbacks;
	macp->m_min_sdu = 0;
	macp->m_max_sdu = ETHERMTU;
	macp->m_margin = VLAN_TAGSZ;

	if (mac_register(macp, &efep->efe_mh) != 0) {
		efe_error(dip, "unable to register with mac!");
		goto failure;
	}
	mac_free(macp);

	ddi_report_dev(dip);

	return (DDI_SUCCESS);

failure:
	if (macp != NULL) {
		mac_free(macp);
	}

	if (efep->efe_miih != NULL) {
		mii_free(efep->efe_miih);
	}

	if (efep->efe_intrh != NULL) {
		(void) ddi_intr_disable(efep->efe_intrh);
		(void) ddi_intr_remove_handler(efep->efe_intrh);
		(void) ddi_intr_free(efep->efe_intrh);
	}

	mutex_destroy(&efep->efe_txlock);
	mutex_destroy(&efep->efe_intrlock);

	if (efep->efe_tx_ring != NULL) {
		efe_ring_free(&efep->efe_tx_ring);
	}
	if (efep->efe_rx_ring != NULL) {
		efe_ring_free(&efep->efe_rx_ring);
	}

	if (efep->efe_regs_acch != NULL) {
		ddi_regs_map_free(&efep->efe_regs_acch);
	}

	kmem_free(efep, sizeof (efe_t));

	return (DDI_FAILURE);
}
Example #22
0
/*ARGSUSED*/
static int
emul64_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
{
	int		mutex_initted = 0;
	struct emul64	*emul64;
	int		instance;
	scsi_hba_tran_t	*tran = NULL;
	ddi_dma_attr_t	tmp_dma_attr;

	emul64_bsd_get_props(dip);

	bzero((void *) &tmp_dma_attr, sizeof (tmp_dma_attr));
	instance = ddi_get_instance(dip);

	switch (cmd) {
	case DDI_ATTACH:
		break;

	case DDI_RESUME:
		tran = (scsi_hba_tran_t *)ddi_get_driver_private(dip);
		if (!tran) {
			return (DDI_FAILURE);
		}
		emul64 = TRAN2EMUL64(tran);

		return (DDI_SUCCESS);

	default:
		emul64_i_log(NULL, CE_WARN,
		    "emul64%d: Cmd != DDI_ATTACH/DDI_RESUME", instance);
		return (DDI_FAILURE);
	}

	/*
	 * Allocate emul64 data structure.
	 */
	if (ddi_soft_state_zalloc(emul64_state, instance) != DDI_SUCCESS) {
		emul64_i_log(NULL, CE_WARN,
		    "emul64%d: Failed to alloc soft state",
		    instance);
		return (DDI_FAILURE);
	}

	emul64 = (struct emul64 *)ddi_get_soft_state(emul64_state, instance);
	if (emul64 == (struct emul64 *)NULL) {
		emul64_i_log(NULL, CE_WARN, "emul64%d: Bad soft state",
		    instance);
		ddi_soft_state_free(emul64_state, instance);
		return (DDI_FAILURE);
	}


	/*
	 * Allocate a transport structure
	 */
	tran = scsi_hba_tran_alloc(dip, SCSI_HBA_CANSLEEP);
	if (tran == NULL) {
		cmn_err(CE_WARN, "emul64: scsi_hba_tran_alloc failed\n");
		goto fail;
	}

	emul64->emul64_tran			= tran;
	emul64->emul64_dip			= dip;

	tran->tran_hba_private		= emul64;
	tran->tran_tgt_private		= NULL;
	tran->tran_tgt_init		= emul64_tran_tgt_init;
	tran->tran_tgt_probe		= scsi_hba_probe;
	tran->tran_tgt_free		= NULL;

	tran->tran_start		= emul64_scsi_start;
	tran->tran_abort		= emul64_scsi_abort;
	tran->tran_reset		= emul64_scsi_reset;
	tran->tran_getcap		= emul64_scsi_getcap;
	tran->tran_setcap		= emul64_scsi_setcap;
	tran->tran_init_pkt		= emul64_scsi_init_pkt;
	tran->tran_destroy_pkt		= emul64_scsi_destroy_pkt;
	tran->tran_dmafree		= emul64_scsi_dmafree;
	tran->tran_sync_pkt		= emul64_scsi_sync_pkt;
	tran->tran_reset_notify 	= emul64_scsi_reset_notify;

	tmp_dma_attr.dma_attr_minxfer = 0x1;
	tmp_dma_attr.dma_attr_burstsizes = 0x7f;

	/*
	 * Attach this instance of the hba
	 */
	if (scsi_hba_attach_setup(dip, &tmp_dma_attr, tran,
	    0) != DDI_SUCCESS) {
		cmn_err(CE_WARN, "emul64: scsi_hba_attach failed\n");
		goto fail;
	}

	emul64->emul64_initiator_id = 2;

	/*
	 * Look up the scsi-options property
	 */
	emul64->emul64_scsi_options =
	    ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, "scsi-options",
	    EMUL64_DEFAULT_SCSI_OPTIONS);
	EMUL64_DEBUG(emul64, SCSI_DEBUG, "emul64 scsi-options=%x",
	    emul64->emul64_scsi_options);


	/* mutexes to protect the emul64 request and response queue */
	mutex_init(EMUL64_REQ_MUTEX(emul64), NULL, MUTEX_DRIVER,
	    emul64->emul64_iblock);
	mutex_init(EMUL64_RESP_MUTEX(emul64), NULL, MUTEX_DRIVER,
	    emul64->emul64_iblock);

	mutex_initted = 1;

	EMUL64_MUTEX_ENTER(emul64);

	/*
	 * Initialize the default Target Capabilities and Sync Rates
	 */
	emul64_i_initcap(emul64);

	EMUL64_MUTEX_EXIT(emul64);


	ddi_report_dev(dip);
	emul64->emul64_taskq = taskq_create("emul64_comp",
	    emul64_task_nthreads, MINCLSYSPRI, 1, emul64_max_task, 0);

	return (DDI_SUCCESS);

fail:
	emul64_i_log(NULL, CE_WARN, "emul64%d: Unable to attach", instance);

	if (mutex_initted) {
		mutex_destroy(EMUL64_REQ_MUTEX(emul64));
		mutex_destroy(EMUL64_RESP_MUTEX(emul64));
	}
	if (tran) {
		scsi_hba_tran_free(tran);
	}
	ddi_soft_state_free(emul64_state, instance);
	return (DDI_FAILURE);
}
static int
mouse8042_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
{
	struct mouse_state *state;
	mblk_t *mp;
	int instance = ddi_get_instance(dip);
	static ddi_device_acc_attr_t attr = {
		DDI_DEVICE_ATTR_V0,
		DDI_NEVERSWAP_ACC,
		DDI_STRICTORDER_ACC,
	};
	int rc;


	if (cmd == DDI_RESUME) {
		state = (struct mouse_state *)ddi_get_driver_private(dip);

		/* Ready to handle inbound data from mouse8042_intr */
		state->ready = 1;

		/*
		 * Send a 0xaa 0x00 upstream.
		 * This causes the vuid module to reset the mouse.
		 */
		if (state->ms_rqp != NULL) {
			if (mp = allocb(1, BPRI_MED)) {
				*mp->b_wptr++ = 0xaa;
				putnext(state->ms_rqp, mp);
			}
			if (mp = allocb(1, BPRI_MED)) {
				*mp->b_wptr++ = 0x0;
				putnext(state->ms_rqp, mp);
			}
		}
		return (DDI_SUCCESS);
	}

	if (cmd != DDI_ATTACH)
		return (DDI_FAILURE);

	if (mouse8042_dip != NULL)
		return (DDI_FAILURE);

	/* allocate and initialize state structure */
	state = kmem_zalloc(sizeof (struct mouse_state), KM_SLEEP);
	state->ms_opened = B_FALSE;
	state->reset_state = MSE_RESET_IDLE;
	state->reset_tid = 0;
	state->bc_id = 0;
	ddi_set_driver_private(dip, state);

	/*
	 * In order to support virtual keyboard/mouse, we should distinguish
	 * between internal virtual open and external physical open.
	 *
	 * When the physical devices are opened by application, they will
	 * be unlinked from the virtual device and their data stream will
	 * not be sent to the virtual device. When the opened physical
	 * devices are closed, they will be relinked to the virtual devices.
	 *
	 * All these automatic switch between virtual and physical are
	 * transparent.
	 *
	 * So we change minor node numbering scheme to be:
	 * 	external node minor num == instance * 2
	 *	internal node minor num == instance * 2 + 1
	 */
	rc = ddi_create_minor_node(dip, "mouse", S_IFCHR, instance * 2,
	    DDI_NT_MOUSE, NULL);
	if (rc != DDI_SUCCESS) {
		goto fail_1;
	}

	if (ddi_create_internal_pathname(dip, "internal_mouse", S_IFCHR,
	    instance * 2 + 1) != DDI_SUCCESS) {
		goto fail_2;
	}

	rc = ddi_regs_map_setup(dip, 0, (caddr_t *)&state->ms_addr,
	    (offset_t)0, (offset_t)0, &attr, &state->ms_handle);
	if (rc != DDI_SUCCESS) {
		goto fail_2;
	}

	rc = ddi_get_iblock_cookie(dip, 0, &state->ms_iblock_cookie);
	if (rc != DDI_SUCCESS) {
		goto fail_3;
	}

	mutex_init(&state->ms_mutex, NULL, MUTEX_DRIVER,
	    state->ms_iblock_cookie);
	mutex_init(&state->reset_mutex, NULL, MUTEX_DRIVER,
	    state->ms_iblock_cookie);
	cv_init(&state->reset_cv, NULL, CV_DRIVER, NULL);

	rc = ddi_add_intr(dip, 0,
	    (ddi_iblock_cookie_t *)NULL, (ddi_idevice_cookie_t *)NULL,
	    mouse8042_intr, (caddr_t)state);
	if (rc != DDI_SUCCESS) {
		goto fail_3;
	}

	mouse8042_dip = dip;

	/* Ready to handle inbound data from mouse8042_intr */
	state->ready = 1;

	/* Now that we're attached, announce our presence to the world. */
	ddi_report_dev(dip);
	return (DDI_SUCCESS);

fail_3:
	ddi_regs_map_free(&state->ms_handle);

fail_2:
	ddi_remove_minor_node(dip, NULL);

fail_1:
	kmem_free(state, sizeof (struct mouse_state));
	return (rc);
}
Example #24
0
/* detach(9E) -- Detach a device from the system */
static int
SMCG_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd)
{
	gld_mac_info_t	*macinfo;
	Adapter_Struc	*pAd;
	smcg_t		*smcg;
	int		i;

#ifdef	DEBUG
	if (SMCG_debug & SMCGDDI)
		cmn_err(CE_CONT, SMCG_NAME "_detach(0x%p)", (void *)devinfo);
#endif

	if (cmd != DDI_DETACH)
		return (DDI_FAILURE);

	macinfo = ddi_get_driver_private(devinfo);
	smcg = (smcg_t *)macinfo->gldm_private;
	pAd = smcg->smcg_pAd;

	i = 50;

	mutex_enter(&smcg->rlist_lock);
	while (smcg->rx_bufs_outstanding > 0) {
		mutex_exit(&smcg->rlist_lock);
		delay(drv_usectohz(100000));
		if (--i == 0) {
			cmn_err(CE_WARN,
			    SMCG_NAME "%d: %d buffers not reclaimed",
			    macinfo->gldm_ppa, smcg->rx_bufs_outstanding);
			return (DDI_FAILURE);
		}
		mutex_enter(&smcg->rlist_lock);
	}
	smcg->detaching_flag = 1;
	mutex_exit(&smcg->rlist_lock);

	/*
	 * Unregister ourselves from the GLD interface
	 *
	 * gld_unregister will:
	 *	remove the minor node;
	 *	unlink us from the GLD system.
	 */
	if (gld_unregister(macinfo) != DDI_SUCCESS) {
		mutex_enter(&smcg->rlist_lock);
		smcg->detaching_flag = 0;
		mutex_exit(&smcg->rlist_lock);
		return (DDI_FAILURE);
	}

	ddi_remove_intr(devinfo, 0, macinfo->gldm_cookie);

	SMCG_dma_unalloc(smcg);

	mutex_destroy(&smcg->rbuf_lock);
	mutex_destroy(&smcg->txbuf_lock);
	mutex_destroy(&smcg->lm_lock);
	mutex_destroy(&smcg->rlist_lock);

	kmem_free(pAd, sizeof (Adapter_Struc));
	kmem_free(smcg, sizeof (smcg_t));
	gld_mac_free(macinfo);
	return (DDI_SUCCESS);
}
/*ARGSUSED*/
static int
mouse8042_open(
	queue_t	*q,
	dev_t	*devp,
	int	flag,
	int	sflag,
	cred_t	*cred_p)
{
	struct mouse_state *state;
	minor_t	minor = getminor(*devp);
	int rval;

	if (mouse8042_dip == NULL)
		return (ENXIO);

	state = ddi_get_driver_private(mouse8042_dip);

	mutex_enter(&state->ms_mutex);

	if (state->ms_opened) {
		/*
		 * Exit if the same minor node is already open
		 */
		if (state->ms_minor == minor) {
			mutex_exit(&state->ms_mutex);
			return (0);
		}

		/*
		 * Check whether it is switch between physical and virtual
		 *
		 * Opening from virtual while the device is being physically
		 * opened by an application should not happen. So we ASSERT
		 * this in DEBUG version, and return error in the non-DEBUG
		 * case.
		 */
		ASSERT(!MOUSE8042_INTERNAL_OPEN(minor));

		if (MOUSE8042_INTERNAL_OPEN(minor)) {
			mutex_exit(&state->ms_mutex);
			return (EINVAL);
		}

		/*
		 * Opening the physical one while it is being underneath
		 * the virtual one.
		 *
		 * consconfig_unlink is called to unlink this device from
		 * the virtual one, thus the old stream serving for this
		 * device under the virtual one is closed, and then the
		 * lower driver's close routine (here is mouse8042_close)
		 * is also called to accomplish the whole stream close.
		 * Here we have to drop the lock because mouse8042_close
		 * also needs the lock.
		 *
		 * For mouse, the old stream is:
		 *	consms->["pushmod"->]"mouse_vp driver"
		 *
		 * After the consconfig_unlink returns, the old stream is closed
		 * and we grab the lock again to reopen this device as normal.
		 */
		mutex_exit(&state->ms_mutex);

		/*
		 * If unlink fails, fail the physical open.
		 */
		if ((rval = consconfig_unlink(ddi_driver_major(mouse8042_dip),
		    MOUSE8042_INTERNAL_MINOR(minor))) != 0) {
			return (rval);
		}

		mutex_enter(&state->ms_mutex);
	}


	q->q_ptr = (caddr_t)state;
	WR(q)->q_ptr = (caddr_t)state;
	state->ms_rqp = q;
	state->ms_wqp = WR(q);

	qprocson(q);

	state->ms_minor = minor;
	state->ms_opened = B_TRUE;

	mutex_exit(&state->ms_mutex);

	return (0);
}