Пример #1
0
static void
pcn_teardown(pcn_t *pcnp)
{
	ASSERT(!(pcnp->pcn_flags & PCN_RUNNING));

	if (pcnp->pcn_mii != NULL) {
		mii_free(pcnp->pcn_mii);
		pcnp->pcn_mii = NULL;
	}

	if (pcnp->pcn_flags & PCN_INTR_ENABLED)
		ddi_remove_intr(pcnp->pcn_dip, 0, pcnp->pcn_icookie);

	/* These will exit gracefully if not yet allocated */
	pcn_freerxring(pcnp);
	pcn_freetxring(pcnp);

	if (pcnp->pcn_regshandle != NULL)
		ddi_regs_map_free(&pcnp->pcn_regshandle);


	mutex_destroy(&pcnp->pcn_xmtlock);
	mutex_destroy(&pcnp->pcn_intrlock);
	mutex_destroy(&pcnp->pcn_reglock);

	ddi_soft_state_free(pcn_ssp, ddi_get_instance(pcnp->pcn_dip));
}
Пример #2
0
/*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);
	}
}
Пример #3
0
/*
 * hci1394_isr_handler_fini()
 *    un-register our interrupt service routine.
 */
void
hci1394_isr_handler_fini(hci1394_state_t *soft_state)
{
	ASSERT(soft_state != NULL);

	/* Remove interrupt handler */
	ddi_remove_intr(soft_state->drvinfo.di_dip, 0,
	    soft_state->drvinfo.di_iblock_cookie);
}
Пример #4
0
void
ghd_unregister(ccc_t *cccp)
{
	ghd_timer_detach(cccp);
	ddi_remove_intr(cccp->ccc_hba_dip, 0, cccp->ccc_iblock);
	ddi_remove_softintr(cccp->ccc_doneq_softid);
	mutex_destroy(&cccp->ccc_hba_mutex);
	mutex_destroy(&cccp->ccc_waitq_mutex);
	mutex_destroy(&cccp->ccc_doneq_mutex);
}
Пример #5
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);
	}
}
Пример #6
0
static void
kb8042_cleanup(struct kb8042 *kb8042)
{
	ASSERT(kb8042_dip != NULL);

	if (kb8042->init_state & KB8042_HW_MUTEX_INITTED)
		mutex_destroy(&kb8042->w_hw_mutex);

	if (kb8042->init_state & KB8042_INTR_ADDED)
		ddi_remove_intr(kb8042_dip, 0, kb8042->w_iblock);

	if (kb8042->init_state & KB8042_REGS_MAPPED)
		ddi_regs_map_free(&kb8042->handle);

	if (kb8042->init_state & KB8042_MINOR_NODE_CREATED)
		ddi_remove_minor_node(kb8042_dip, NULL);

	kb8042->init_state = KB8042_UNINITIALIZED;
	kb8042_dip = NULL;
}
Пример #7
0
void
rmc_comm_serdev_fini(struct rmc_comm_state *rcs, dev_info_t *dip)
{
	rmc_comm_hw_reset(rcs);

	if (rcs->sd_state.cycid != CYCLIC_NONE) {
		mutex_enter(&cpu_lock);
		cyclic_remove(rcs->sd_state.cycid);
		mutex_exit(&cpu_lock);

		if (rcs->sd_state.sio_handle != NULL)
			ddi_remove_intr(dip, 0, rcs->sd_state.hw_iblk);

		ddi_remove_softintr(rcs->sd_state.softid);

		mutex_destroy(rcs->sd_state.hw_mutex);

		mutex_destroy(rcs->dp_state.dp_mutex);
	}
	rmc_comm_offline(rcs);
}
Пример #8
0
/*
 * audioixp_destroy()
 *
 * Description:
 *	This routine releases all resources held by the device instance,
 *	as part of either detach or a failure in attach.
 *
 * Arguments:
 *	audioixp_state_t	*state	The device soft state.
 */
void
audioixp_destroy(audioixp_state_t *statep)
{
	if (!statep->suspended) {
		PUT32(IXP_AUDIO_INT, GET32(IXP_AUDIO_INT));
		PUT32(IXP_AUDIO_INT_EN, 0);

		/*
		 * put the audio controller into quiet state, everything off
		 */
		CLR32(IXP_AUDIO_CMD, IXP_AUDIO_CMD_EN_OUT_DMA);
		CLR32(IXP_AUDIO_CMD, IXP_AUDIO_CMD_EN_IN_DMA);
	}

	if (statep->intr_added) {
		ddi_remove_intr(statep->dip, 0, statep->iblock);
	}
	if (statep->ksp) {
		kstat_delete(statep->ksp);
	}

	audioixp_free_port(statep->play_port);
	audioixp_free_port(statep->rec_port);

	audioixp_unmap_regs(statep);

	if (statep->ac97) {
		ac97_free(statep->ac97);
	}

	if (statep->adev) {
		audio_dev_free(statep->adev);
	}

	mutex_destroy(&statep->inst_lock);
	kmem_free(statep, sizeof (*statep));
}
Пример #9
0
int
ghd_register(char *labelp,
	ccc_t	*cccp,
	dev_info_t *dip,
	int	inumber,
	void	*hba_handle,
	int	(*ccballoc)(gtgt_t *, gcmd_t *, int, int, int, int),
	void	(*ccbfree)(gcmd_t *),
	void	(*sg_func)(gcmd_t *, ddi_dma_cookie_t *, int, int),
	int	(*hba_start)(void *, gcmd_t *),
	void    (*hba_complete)(void *, gcmd_t *, int),
	uint_t	(*int_handler)(caddr_t),
	int	(*get_status)(void *, void *),
	void	(*process_intr)(void *, void *),
	int	(*timeout_func)(void *, gcmd_t *, gtgt_t *, gact_t, int),
	tmr_t	*tmrp,
	void 	(*hba_reset_notify_callback)(gtgt_t *,
			void (*)(caddr_t), caddr_t))
{

	cccp->ccc_label = labelp;
	cccp->ccc_hba_dip = dip;
	cccp->ccc_ccballoc = ccballoc;
	cccp->ccc_ccbfree = ccbfree;
	cccp->ccc_sg_func = sg_func;
	cccp->ccc_hba_start = hba_start;
	cccp->ccc_hba_complete = hba_complete;
	cccp->ccc_process_intr = process_intr;
	cccp->ccc_get_status = get_status;
	cccp->ccc_hba_handle = hba_handle;
	cccp->ccc_hba_reset_notify_callback = hba_reset_notify_callback;

	/* initialize the HBA's list headers */
	CCCP_INIT(cccp);

	if (ddi_get_iblock_cookie(dip, inumber, &cccp->ccc_iblock)
	    != DDI_SUCCESS) {

		return (FALSE);
	}

	mutex_init(&cccp->ccc_hba_mutex, NULL, MUTEX_DRIVER, cccp->ccc_iblock);

	mutex_init(&cccp->ccc_waitq_mutex, NULL, MUTEX_DRIVER,
	    cccp->ccc_iblock);

	mutex_init(&cccp->ccc_reset_notify_mutex, NULL, MUTEX_DRIVER,
	    cccp->ccc_iblock);

	/* Establish interrupt handler */
	if (ddi_add_intr(dip, inumber, &cccp->ccc_iblock, NULL,
	    int_handler, (caddr_t)hba_handle) != DDI_SUCCESS) {
		mutex_destroy(&cccp->ccc_hba_mutex);
		mutex_destroy(&cccp->ccc_waitq_mutex);
		mutex_destroy(&cccp->ccc_reset_notify_mutex);

		return (FALSE);
	}

	if (ghd_timer_attach(cccp, tmrp, timeout_func) == FALSE) {
		ddi_remove_intr(cccp->ccc_hba_dip, 0, cccp->ccc_iblock);
		mutex_destroy(&cccp->ccc_hba_mutex);
		mutex_destroy(&cccp->ccc_waitq_mutex);
		mutex_destroy(&cccp->ccc_reset_notify_mutex);

		return (FALSE);
	}

	if (ghd_doneq_init(cccp)) {

		return (TRUE);
	}

	/*
	 * ghd_doneq_init() returned error:
	 */

	ghd_timer_detach(cccp);
	ddi_remove_intr(cccp->ccc_hba_dip, 0, cccp->ccc_iblock);
	mutex_destroy(&cccp->ccc_hba_mutex);
	mutex_destroy(&cccp->ccc_waitq_mutex);
	mutex_destroy(&cccp->ccc_reset_notify_mutex);

	return (FALSE);

}
Пример #10
0
static int
ds1287_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
{
	struct ds1287 *softsp;

	DPRINTF("ds1287_attach\n");
	switch (cmd) {
	case DDI_ATTACH:
		break;
	case DDI_RESUME:
		return (DDI_SUCCESS);
	default:
		return (DDI_FAILURE);
	}

	if (instance != -1) {
		cmn_err(CE_WARN, "ds1287_attach: Another instance is already "
		    "attached.");
		return (DDI_FAILURE);
	}

	instance = ddi_get_instance(dip);

	if (v_rtc_addr_reg == NULL) {
		cmn_err(CE_WARN, "ds1287_attach: v_rtc_addr_reg is NULL");
		return (DDI_FAILURE);
	}

	/*
	 * Allocate softc information.
	 */
	if (ddi_soft_state_zalloc(ds1287_state, instance) != DDI_SUCCESS) {
		cmn_err(CE_WARN, "ds1287_attach: Failed to allocate "
		    "soft states.");
		return (DDI_FAILURE);
	}

	softsp = ddi_get_soft_state(ds1287_state, instance);
	DPRINTF("ds1287_attach: instance=%d softsp=0x%p\n", instance,
	    (void *)softsp);

	softsp->dip = dip;

	if (ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP,
	    "interrupt-priorities", (caddr_t)&ds1287_interrupt_priority,
	    sizeof (int)) != DDI_PROP_SUCCESS) {
		cmn_err(CE_WARN, "ds1287_attach: Failed to create \""
		    "interrupt-priorities\" property.");
		goto error;
	}

	/* add the softint */
	ds1287_lo_iblock = (ddi_iblock_cookie_t)(uintptr_t)
	    ipltospl(ds1287_softint_priority);

	if (ddi_add_softintr(dip, DDI_SOFTINT_FIXED, &ds1287_softintr_id,
	    &ds1287_lo_iblock, NULL, ds1287_softintr, (caddr_t)softsp) !=
	    DDI_SUCCESS) {
		cmn_err(CE_WARN, "ds1287_attach: Failed to add low interrupt.");
		goto error1;
	}

	/* add the hi interrupt */
	if (ddi_add_intr(dip, 0, NULL, (ddi_idevice_cookie_t *)
	    &ds1287_hi_iblock, ds1287_intr, NULL) != DDI_SUCCESS) {
		cmn_err(CE_WARN, "ds1287_attach: Failed to add high "
		    "interrupt.");
		goto error2;
	}

	/*
	 * Combination of instance number and clone number 0 is used for
	 * creating the minor node.
	 */
	if (ddi_create_minor_node(dip, "power_button", S_IFCHR,
	    (instance << 8) + 0, "ddi_power_button", NULL) == DDI_FAILURE) {
		cmn_err(CE_WARN, "ds1287_attach: Failed to create minor node");
		goto error3;
	}

	ddi_report_dev(dip);

	return (DDI_SUCCESS);

error3:
	ddi_remove_intr(dip, 0, NULL);
error2:
	ddi_remove_softintr(ds1287_softintr_id);
error1:
	(void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "interrupt-priorities");
error:
	ddi_soft_state_free(ds1287_state, instance);
	return (DDI_FAILURE);
}
Пример #11
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);
}
Пример #12
0
/*
 * attach(9E) -- Attach a device to the system
 *
 * Called once for each board successfully probed.
 */
static int
SMCG_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
{
	gld_mac_info_t	*macinfo;
	Adapter_Struc	*pAd;
	smcg_t		*smcg;
	int		rc;
	ddi_acc_handle_t pcihandle;

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

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

	/*
	 * Allocate gld_mac_info_t and Lower MAC Adapter_Struc structures
	 */
	if ((macinfo = gld_mac_alloc(devinfo)) == NULL)
		return (DDI_FAILURE);
	if ((pAd = kmem_zalloc(sizeof (Adapter_Struc), KM_NOSLEEP)) == NULL) {
		gld_mac_free(macinfo);
		return (DDI_FAILURE);
	}
	if ((smcg = kmem_zalloc(sizeof (smcg_t), KM_NOSLEEP)) == NULL) {
		gld_mac_free(macinfo);
		kmem_free(pAd, sizeof (Adapter_Struc));
		return (DDI_FAILURE);
	}

	pAd->pc_bus = SMCG_PCI_BUS;

	/* create pci handle for UM_PCI_Service */
	if (pci_config_setup(devinfo, (ddi_acc_handle_t *)&pcihandle)
	    != DDI_SUCCESS) {
		goto attach_fail_cleanup;
	}

	/*
	 * Query the LMAC for the device information
	 */
	pAd->pcihandle = (void *) pcihandle;
	rc = LM_GetCnfg(pAd);

	pci_config_teardown((ddi_acc_handle_t *)&pcihandle);
	pAd->pcihandle = NULL;

	if (rc != ADAPTER_AND_CONFIG) {
		cmn_err(CE_WARN,
		    SMCG_NAME "_attach: LM_GetCnfg failed (0x%x)", rc);
		goto attach_fail_cleanup;
	}

	/*
	 * Initialize pointers to device specific functions which will be
	 * used by the generic layer.
	 */
	macinfo->gldm_reset   = SMCG_reset;
	macinfo->gldm_start   = SMCG_start_board;
	macinfo->gldm_stop    = SMCG_stop_board;
	macinfo->gldm_set_mac_addr   = SMCG_set_mac_addr;
	macinfo->gldm_set_multicast = SMCG_set_multicast;
	macinfo->gldm_set_promiscuous = SMCG_set_promiscuous;
	macinfo->gldm_get_stats   = SMCG_get_stats;
	macinfo->gldm_send    = SMCG_send;
	macinfo->gldm_intr    = SMCG_intr;
	macinfo->gldm_ioctl   = NULL;

	/*
	 * Initialize board characteristics needed by the generic layer.
	 */
	macinfo->gldm_ident = SMCG_IDENT;
	macinfo->gldm_type = DL_ETHER;
	macinfo->gldm_minpkt = 0;	/* assumes we pad ourselves */
	macinfo->gldm_maxpkt = SMCGMAXPKT;
	macinfo->gldm_addrlen = ETHERADDRL;
	macinfo->gldm_saplen = -2;
	macinfo->gldm_ppa = ddi_get_instance(devinfo);

	pAd->receive_mask = ACCEPT_BROADCAST;
	pAd->max_packet_size = SMMAXPKT;

	macinfo->gldm_broadcast_addr = SMCG_broadcastaddr;

	/* Get the board's vendor-assigned hardware network address. */
	LM_Get_Addr(pAd);
	macinfo->gldm_vendor_addr = (unsigned char *)pAd->node_address;

	/* Link macinfo, smcg, and LMAC Adapter Structs */
	macinfo->gldm_private = (caddr_t)smcg;
	pAd->sm_private = (void *)smcg;
	smcg->smcg_pAd = pAd;
	smcg->smcg_macinfo = macinfo;

	pAd->ptr_rx_CRC_errors = &smcg->rx_CRC_errors;
	pAd->ptr_rx_too_big = &smcg->rx_too_big;
	pAd->ptr_rx_lost_pkts = &smcg->rx_lost_pkts;
	pAd->ptr_rx_align_errors = &smcg->rx_align_errors;
	pAd->ptr_rx_overruns = &smcg->rx_overruns;
	pAd->ptr_tx_deferred = &smcg->tx_deferred;
	pAd->ptr_tx_total_collisions = &smcg->tx_total_collisions;
	pAd->ptr_tx_max_collisions = &smcg->tx_max_collisions;
	pAd->ptr_tx_one_collision = &smcg->tx_one_collision;
	pAd->ptr_tx_mult_collisions = &smcg->tx_mult_collisions;
	pAd->ptr_tx_ow_collision = &smcg->tx_ow_collision;
	pAd->ptr_tx_CD_heartbeat = &smcg->tx_CD_heartbeat;
	pAd->ptr_tx_carrier_lost = &smcg->tx_carrier_lost;
	pAd->ptr_tx_underruns = &smcg->tx_underruns;
	pAd->ptr_ring_OVW = &smcg->ring_OVW;

	macinfo->gldm_devinfo = smcg->smcg_devinfo = devinfo;

	pAd->num_of_tx_buffs = ddi_getprop(DDI_DEV_T_ANY, devinfo,
	    DDI_PROP_DONTPASS, "num-tx-bufs", SMTRANSMIT_BUFS);
	if (pAd->num_of_tx_buffs > SMCG_MAX_TXDESCS) {
		pAd->num_of_tx_buffs = SMCG_MAX_TXDESCS;
		cmn_err(CE_WARN, SMCG_NAME
		    "Max number_of_tx_buffs is %d", SMCG_MAX_TXDESCS);
	}
	if (pAd->num_of_tx_buffs < 2) {
		pAd->num_of_tx_buffs = 2;
	}
	pAd->num_of_rx_buffs = ddi_getprop(DDI_DEV_T_ANY, devinfo,
	    DDI_PROP_DONTPASS, "num-rx-bufs", SMRECEIVE_BUFS);
	if (pAd->num_of_rx_buffs > SMCG_MAX_RXDESCS) {
		pAd->num_of_rx_buffs = SMCG_MAX_RXDESCS;
		cmn_err(CE_WARN, SMCG_NAME
		    "Max number_of_rx_buffs is %d", SMCG_MAX_RXDESCS);
	}
	if (pAd->num_of_rx_buffs < 2) {
		pAd->num_of_rx_buffs = 2;
	}

	if (ddi_get_iblock_cookie(devinfo, 0, &macinfo->gldm_cookie)
		!= DDI_SUCCESS)
		goto attach_fail_cleanup;

	/*
	 * rbuf_lock	Protects receive data structures
	 * txbuf_lock	Protects transmit data structures
	 * lm_lock	Protects all calls to LMAC layer
	 * rlist_lock	Protects receive buffer list
	 * Note: Locks should be acquired in the above order.
	 */
	mutex_init(&smcg->rbuf_lock, NULL, MUTEX_DRIVER, NULL);
	mutex_init(&smcg->txbuf_lock, NULL, MUTEX_DRIVER, NULL);
	mutex_init(&smcg->lm_lock, NULL, MUTEX_DRIVER, NULL);
	mutex_init(&smcg->rlist_lock, NULL, MUTEX_DRIVER, NULL);

	/*
	 * SMCG_dma_alloc is called before it is possible to get
	 * any interrupts, send or receive packets... Therefore I'm
	 * not going to take rlist_lock for it.
	 */
	if (SMCG_dma_alloc(smcg) != DDI_SUCCESS)
		goto attach_fail_cleanup1;

#ifdef SAFE
	LM_Reset_Adapter(pAd);
#endif
	/* Add the interrupt handler */
	if (ddi_add_intr(devinfo, 0,  NULL, NULL, gld_intr, (caddr_t)macinfo)
	    != DDI_SUCCESS) {
		SMCG_dma_unalloc(smcg);
		goto attach_fail_cleanup1;
	}

	/*
	 * Register ourselves with the GLD interface
	 *
	 * gld_register will:
	 *	link us with the GLD system;
	 *	create the minor node.
	 */
	if (gld_register(devinfo, SMCG_NAME, macinfo) != DDI_SUCCESS) {
		ddi_remove_intr(devinfo, 0, macinfo->gldm_cookie);
		SMCG_dma_unalloc(smcg);
		goto attach_fail_cleanup1;
	}

	return (DDI_SUCCESS);

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

attach_fail_cleanup:
	kmem_free(pAd, sizeof (Adapter_Struc));
	kmem_free(smcg, sizeof (smcg_t));
	gld_mac_free(macinfo);
	return (DDI_FAILURE);
}
Пример #13
0
/*
 * heci_remove - Device Removal Routine
 *
 * @pdev: PCI device information struct
 *
 * heci_remove is called by the PCI subsystem to alert the driver
 * that it should release a PCI device.
 */
static int
heci_detach(dev_info_t *dip,  ddi_detach_cmd_t cmd)
{
	struct iamt_heci_device	*dev;
	int err;

	dev = ddi_get_soft_state(heci_soft_state_p, ddi_get_instance(dip));
	ASSERT(dev != NULL);

	switch (cmd) {
	case DDI_SUSPEND:
		err = heci_suspend(dip);
		if (err)
			return (DDI_FAILURE);
		else
			return (DDI_SUCCESS);

	case DDI_DETACH:
		break;

	default:
		return (DDI_FAILURE);
	}

	if (dev->wd_timer)
		(void) untimeout(dev->wd_timer);

	mutex_enter(&dev->device_lock);
	if (dev->wd_file_ext.state == HECI_FILE_CONNECTED &&
	    dev->wd_timeout) {
		dev->wd_timeout = 0;
		dev->wd_due_counter = 0;
		(void) memcpy(dev->wd_data, stop_wd_params,
		    HECI_WD_PARAMS_SIZE);
		dev->stop = 1;
		if (dev->host_buffer_is_empty &&
		    flow_ctrl_creds(dev, &dev->wd_file_ext)) {
			dev->host_buffer_is_empty = 0;

			if (!heci_send_wd(dev)) {
				DBG("send stop WD failed\n");
			} else
				flow_ctrl_reduce(dev, &dev->wd_file_ext);

			dev->wd_pending = 0;
		} else
			dev->wd_pending = 1;

		dev->wd_stoped = 0;

		err = 0;
		while (!dev->wd_stoped && err != -1) {
			err = cv_reltimedwait(&dev->wait_stop_wd,
			    &dev->device_lock, 10*HZ, TR_CLOCK_TICK);
		}

		if (!dev->wd_stoped) {
			DBG("stop wd failed to complete.\n");
		} else {
			DBG("stop wd complete.\n");
		}

	}

	mutex_exit(&dev->device_lock);

	if (dev->iamthif_file_ext.state == HECI_FILE_CONNECTED) {
		dev->iamthif_file_ext.state = HECI_FILE_DISCONNECTING;
		(void) heci_disconnect_host_client(dev,
		    &dev->iamthif_file_ext);
	}
	if (dev->wd_file_ext.state == HECI_FILE_CONNECTED) {
		dev->wd_file_ext.state = HECI_FILE_DISCONNECTING;
		(void) heci_disconnect_host_client(dev,
		    &dev->wd_file_ext);
	}


	/* remove entry if already in list */
	DBG("list del iamthif and wd file list.\n");
	heci_remove_client_from_file_list(dev, dev->wd_file_ext.
	    host_client_id);
	heci_remove_client_from_file_list(dev,
	    dev->iamthif_file_ext.host_client_id);

	dev->iamthif_current_cb = NULL;
	dev->iamthif_file_ext.file = NULL;

	/* disable interrupts */
	heci_csr_disable_interrupts(dev);

	ddi_remove_intr(dip, 0, dev->sc_iblk);

	if (dev->work)
		ddi_taskq_destroy(dev->work);
	if (dev->reinit_tsk)
		ddi_taskq_destroy(dev->reinit_tsk);
	if (dev->mem_addr)
		ddi_regs_map_free(&dev->io_handle);

	if (dev->me_clients && dev->num_heci_me_clients > 0) {
		kmem_free(dev->me_clients, sizeof (struct heci_me_client) *
		    dev->num_heci_me_clients);
	}

	dev->num_heci_me_clients = 0;

	heci_destroy_locks(dev);

	ddi_remove_minor_node(dip, NULL);
	ddi_soft_state_free(heci_soft_state_p, ddi_get_instance(dip));

	return (DDI_SUCCESS);
}
Пример #14
0
/*
 * heci_probe - Device Initialization Routine
 */
static int
heci_initialize(dev_info_t *dip, struct iamt_heci_device *device)
{
	int err;
	ddi_device_acc_attr_t attr;

	err = ddi_get_iblock_cookie(dip, 0, &device->sc_iblk);
	if (err != DDI_SUCCESS) {
		cmn_err(CE_WARN, "heci_probe():"
		    " ddi_get_iblock_cookie() failed\n");
		goto end;
	}
	/* initializes the heci device structure */
	init_heci_device(dip, device);

	attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
	attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
	attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;

	if (ddi_regs_map_setup(dip, 1, (caddr_t *)&device->mem_addr, 0, 0,
	    &attr, &device->io_handle) != DDI_SUCCESS) {
		cmn_err(CE_WARN, "heci%d: unable to map PCI regs\n",
		    ddi_get_instance(dip));
		goto fini_heci_device;
	}

	err = ddi_add_intr(dip, 0, &device->sc_iblk, NULL,
	    heci_isr_interrupt, (caddr_t)device);
	if (err != DDI_SUCCESS) {
		cmn_err(CE_WARN, "heci_probe(): ddi_add_intr() failed\n");
		goto unmap_memory;
	}

	if (heci_hw_init(device)) {
		cmn_err(CE_WARN, "init hw failure.\n");
		err = -ENODEV;
		goto release_irq;
	}
	(void) heci_initialize_clients(device);
	if (device->heci_state != HECI_ENABLED) {
		err = -ENODEV;
		goto release_hw;
	}
	if (device->wd_timeout)
		device->wd_timer = timeout(heci_wd_timer, device, 1);

	DBG("heci driver initialization successful.\n");
	return (0);

release_hw:
	/* disable interrupts */
	device->host_hw_state = read_heci_register(device, H_CSR);
	heci_csr_disable_interrupts(device);

release_irq:
	ddi_remove_intr(dip, 0, device->sc_iblk);
unmap_memory:
	if (device->mem_addr)
		ddi_regs_map_free(&device->io_handle);
fini_heci_device:
	fini_heci_device(device);
end:
	cmn_err(CE_WARN, "heci driver initialization failed.\n");
	return (err);
}