예제 #1
0
int
ata_detach(device_t dev)
{
    struct ata_channel *ch = device_get_softc(dev);
    device_t *children;
    int nchildren, i;

    /* check that we have a valid channel to detach */
    if (!ch->r_irq)
	return ENXIO;

    /* grap the channel lock so no new requests gets launched */
    lockmgr(&ch->state_mtx, LK_EXCLUSIVE);
    ch->state |= ATA_STALL_QUEUE;
    lockmgr(&ch->state_mtx, LK_RELEASE);

    /* detach & delete all children */
    if (!device_get_children(dev, &children, &nchildren)) {
	for (i = 0; i < nchildren; i++)
	    if (children[i])
		device_delete_child(dev, children[i]);
	kfree(children, M_TEMP);
    } 

    /* release resources */
    bus_teardown_intr(dev, ch->r_irq, ch->ih);
    bus_release_resource(dev, SYS_RES_IRQ, ATA_IRQ_RID, ch->r_irq);
    ch->r_irq = NULL;
    lockuninit(&ch->state_mtx);
    lockuninit(&ch->queue_mtx);
    return 0;
}
예제 #2
0
int
ubt_detach(device_t dev)
{
	struct ubt_softc	*sc = device_get_softc(dev);
	node_p			node = sc->sc_node;

	/* Destroy Netgraph node */
	if (node != NULL) {
		sc->sc_node = NULL;
		NG_NODE_REALLY_DIE(node);
		ng_rmnode_self(node);
	}

	/* Make sure ubt_task in gone */
	taskqueue_drain(taskqueue_swi, &sc->sc_task);

	/* Free USB transfers, if any */
	usbd_transfer_unsetup(sc->sc_xfer, UBT_N_TRANSFER);

	/* Destroy queues */
	UBT_NG_LOCK(sc);
	NG_BT_MBUFQ_DESTROY(&sc->sc_cmdq);
	NG_BT_MBUFQ_DESTROY(&sc->sc_aclq);
	NG_BT_MBUFQ_DESTROY(&sc->sc_scoq);
	UBT_NG_UNLOCK(sc);

	lockuninit(&sc->sc_if_lock);
	lockuninit(&sc->sc_ng_lock);

	return (0);
} /* ubt_detach */
예제 #3
0
/*
 * Release the resources allocated by cmx_allocate_resources.
 */
void
cmx_release_resources(device_t dev)
{
	struct cmx_softc *sc = device_get_softc(dev);

	lockuninit(&sc->mtx);

#ifdef CMX_INTR
	if (sc->ih) {
		bus_teardown_intr(dev, sc->irq, sc->ih);
		sc->ih = NULL;
	}
	if (sc->irq) {
		bus_release_resource(dev, SYS_RES_IRQ,
				sc->irq_rid, sc->irq);
		sc->irq = NULL;
	}
#endif

	if (sc->ioport) {
		bus_deactivate_resource(dev, SYS_RES_IOPORT,
				sc->ioport_rid, sc->ioport);
		bus_release_resource(dev, SYS_RES_IOPORT,
				sc->ioport_rid, sc->ioport);
		sc->ioport = NULL;
	}
	return;
}
예제 #4
0
static int
ndisusb_detach(device_t self)
{
	int i;
	struct ndis_softc       *sc = device_get_softc(self);
	struct ndisusb_ep	*ne;

	sc->ndisusb_status |= NDISUSB_STATUS_DETACH;

	ndis_pnpevent_nic(self, NDIS_PNP_EVENT_SURPRISE_REMOVED);

	if (sc->ndisusb_status & NDISUSB_STATUS_SETUP_EP) {
		usbd_transfer_unsetup(sc->ndisusb_dread_ep.ne_xfer, 1);
		usbd_transfer_unsetup(sc->ndisusb_dwrite_ep.ne_xfer, 1);
	}
	for (i = 0; i < NDISUSB_ENDPT_MAX; i++) {
		ne = &sc->ndisusb_ep[i];
		usbd_transfer_unsetup(ne->ne_xfer, 1);
	}

	(void)ndis_detach(self);

	lockuninit(&sc->ndisusb_lock);
	return (0);
}
예제 #5
0
static
int
ig4iic_pci_detach(device_t dev)
{
	ig4iic_softc_t *sc = device_get_softc(dev);
	int error;

	if (sc->pci_attached) {
		error = ig4iic_detach(sc);
		if (error)
			return error;
		sc->pci_attached = 0;
	}

	if (sc->intr_res) {
		bus_release_resource(dev, SYS_RES_IRQ,
				     sc->intr_rid, sc->intr_res);
		sc->intr_res = NULL;
	}
	if (sc->intr_type == PCI_INTR_TYPE_MSI)
		pci_release_msi(dev);
	if (sc->regs_res) {
		bus_release_resource(dev, SYS_RES_MEMORY,
				     sc->regs_rid, sc->regs_res);
		sc->regs_res = NULL;
	}
	sc->regs_t = 0;
	sc->regs_h = 0;
	lockuninit(&sc->lk);

	return 0;
}
예제 #6
0
static void
nukepark(void *obj, void *privdata)
{
	struct puffs_msgpark *park = obj;

	cv_destroy(&park->park_cv);
	lockuninit(&park->park_mtx);
}
예제 #7
0
void drm_global_release(void)
{
	int i;
	for (i = 0; i < DRM_GLOBAL_NUM; ++i) {
		struct drm_global_item *item = &glob[i];
		KKASSERT(item->object == NULL);
		KKASSERT(item->refcount == 0);
		lockuninit(&item->mutex);
	}
}
예제 #8
0
/*
 * Destroy all variables in table_head
 */
void
dm_table_head_destroy(dm_table_head_t * head)
{
	KKASSERT(lockcount(&head->table_mtx) == 0);

	/* tables doens't exists when I call this routine, therefore it
	 * doesn't make sense to have io_cnt != 0 */
	KKASSERT(head->io_cnt == 0);

	lockuninit(&head->table_mtx);
}
예제 #9
0
/*------------------------------------------------------------------------*
 *	usb_bus_mem_free_all - factored out code
 *------------------------------------------------------------------------*/
void
usb_bus_mem_free_all(struct usb_bus *bus, usb_bus_mem_cb_t *cb)
{
#if USB_HAVE_BUSDMA
	if (cb) {
		cb(bus, &usb_bus_mem_free_all_cb);
	}
	usb_dma_tag_unsetup(bus->dma_parent_tag);
#endif

	lockuninit(&bus->bus_lock);
}
예제 #10
0
static void
ucom_uninit(void *arg)
{
	struct unrhdr *hdr;
	hdr = ucom_unrhdr;
	ucom_unrhdr = NULL;

	DPRINTF("\n");

	if (hdr != NULL)
		delete_unrhdr(hdr);

	lockuninit(&ucom_lock);
}
예제 #11
0
static int
ipheth_detach(device_t dev)
{
	struct ipheth_softc *sc = device_get_softc(dev);
	struct usb_ether *ue = &sc->sc_ue;

	/* stop all USB transfers first */
	usbd_transfer_unsetup(sc->sc_xfer, IPHETH_N_TRANSFER);

	uether_ifdetach(ue);

	lockuninit(&sc->sc_lock);

	return (0);
}
예제 #12
0
int
ichsmb_detach(device_t dev)
{
	const sc_p sc = device_get_softc(dev);
	int error;

	error = bus_generic_detach(dev);
	if (error)
		return (error);
	device_delete_child(dev, sc->smb);
	ichsmb_release_resources(sc);
	lockuninit(&sc->mutex);

	return 0;
}
예제 #13
0
/*
 * Terminate a thread.  This function will silently return if the thread
 * was never initialized or has already been deleted.
 *
 * This is accomplished by setting the STOP flag and waiting for the td
 * structure to become NULL.
 */
void
hammer2_thr_delete(hammer2_thread_t *thr)
{
	if (thr->td == NULL)
		return;
	lockmgr(&thr->lk, LK_EXCLUSIVE);
	atomic_set_int(&thr->flags, HAMMER2_THREAD_STOP);
	wakeup(&thr->flags);
	while (thr->td) {
		lksleep(thr, &thr->lk, 0, "h2thr", hz);
	}
	lockmgr(&thr->lk, LK_RELEASE);
	thr->pmp = NULL;
	lockuninit(&thr->lk);
}
예제 #14
0
static int
alpm_detach(device_t dev)
{
	struct alpm_softc *alpm = device_get_softc(dev);

	if (alpm->smbus) {
		device_delete_child(dev, alpm->smbus);
		alpm->smbus = NULL;
	}
	lockuninit(&alpm->lock);

	if (alpm->res)
		bus_release_resource(dev, SYS_RES_IOPORT, SMBBA, alpm->res);

	return (0);
}
예제 #15
0
/*
 * Stop the OS-specific port helper thread and kill the per-port lock.
 */
void
sili_os_stop_port(struct sili_port *ap)
{
	if (ap->ap_thread) {
		sili_os_signal_port_thread(ap, AP_SIGF_STOP);
		sili_os_sleep(10);
		if (ap->ap_thread) {
			kprintf("%s: Waiting for thread to terminate\n",
				PORTNAME(ap));
			while (ap->ap_thread)
				sili_os_sleep(100);
			kprintf("%s: thread terminated\n",
				PORTNAME(ap));
		}
	}
	lockuninit(&ap->ap_lock);
}
예제 #16
0
/*
 * Function name:	tw_osli_cam_detach
 * Description:		Detaches the driver from CAM.
 *
 * Input:		sc	-- ptr to OSL internal ctlr context
 * Output:		None
 * Return value:	None
 */
TW_VOID
tw_osli_cam_detach(struct twa_softc *sc)
{
	tw_osli_dbg_dprintf(3, sc, "entered");

	lockmgr(sc->sim_lock, LK_EXCLUSIVE);

	if (sc->path)
		xpt_free_path(sc->path);
	if (sc->sim) {
		xpt_bus_deregister(cam_sim_path(sc->sim));
		/* Passing TRUE to cam_sim_free will free the devq as well. */
		cam_sim_free(sc->sim);
	}
	/* It's ok have 1 hold count while destroying the mutex */
	lockuninit(sc->sim_lock);
}
예제 #17
0
static int
amdsmb_detach(device_t dev)
{
	struct amdsmb_softc *amdsmb_sc = device_get_softc(dev);

	if (amdsmb_sc->smbus) {
		device_delete_child(dev, amdsmb_sc->smbus);
		amdsmb_sc->smbus = NULL;
	}

	lockuninit(&amdsmb_sc->lock);
	if (amdsmb_sc->res)
		bus_release_resource(dev, SYS_RES_IOPORT, amdsmb_sc->rid,
		    amdsmb_sc->res);

	return (0);
}
예제 #18
0
static int
g_modem_detach(device_t dev)
{
	struct g_modem_softc *sc = device_get_softc(dev);

	DPRINTF("\n");

	lockmgr(&sc->sc_lock, LK_EXCLUSIVE);
	usb_callout_stop(&sc->sc_callout);
	usb_callout_stop(&sc->sc_watchdog);
	lockmgr(&sc->sc_lock, LK_RELEASE);

	usbd_transfer_unsetup(sc->sc_xfer, G_MODEM_N_TRANSFER);

	usb_callout_drain(&sc->sc_callout);
	usb_callout_drain(&sc->sc_watchdog);

	lockuninit(&sc->sc_lock);

	return (0);
}
예제 #19
0
/*
 * Handle attach-time duties that are independent of the bus
 * our device lives on.
 */
int
ichsmb_attach(device_t dev)
{
	const sc_p sc = device_get_softc(dev);
	int error;

	/* Create mutex */
	lockinit(&sc->mutex, "ichsmb", 0, LK_CANRECURSE);

	/* Add child: an instance of the "smbus" device */
	if ((sc->smb = device_add_child(dev, DRIVER_SMBUS, -1)) == NULL) {
		device_printf(dev, "no \"%s\" child found\n", DRIVER_SMBUS);
		error = ENXIO;
		goto fail;
	}

	/* Clear interrupt conditions */
	bus_write_1(sc->io_res, ICH_HST_STA, 0xff);

	/* Set up interrupt handler */
	error = bus_setup_intr(dev, sc->irq_res, 0,
	    ichsmb_device_intr, sc, &sc->irq_handle, NULL);
	if (error != 0) {
		device_printf(dev, "can't setup irq\n");
		goto fail;
	}

	/* Attach "smbus" child */
	if ((error = bus_generic_attach(dev)) != 0) {
		device_printf(dev, "failed to attach child: %d\n", error);
		goto fail;
	}

	return (0);

fail:
	lockuninit(&sc->mutex);
	return (error);
}
예제 #20
0
static int
intsmb_detach(device_t dev)
{
	struct intsmb_softc *sc = device_get_softc(dev);
	int error;

	error = bus_generic_detach(dev);
	if (error)
		return (error);

	if (sc->smbus)
		device_delete_child(dev, sc->smbus);
	if (sc->irq_hand)
		bus_teardown_intr(dev, sc->irq_res, sc->irq_hand);
	if (sc->irq_res)
		bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
	if (sc->io_res)
		bus_release_resource(dev, SYS_RES_IOPORT, PCI_BASE_ADDR_SMB,
		    sc->io_res);
	lockuninit(&sc->lock);
	return (0);
}
예제 #21
0
/*
 * Stop the OS-specific port helper thread and kill the per-port lock.
 */
void
ahci_os_stop_port(struct ahci_port *ap)
{
	if (ap->sysctl_tree) {
		sysctl_ctx_free(&ap->sysctl_ctx);
		ap->sysctl_tree = NULL;
	}

	if (ap->ap_thread) {
		ahci_os_signal_port_thread(ap, AP_SIGF_STOP);
		ahci_os_sleep(10);
		if (ap->ap_thread) {
			kprintf("%s: Waiting for thread to terminate\n",
				PORTNAME(ap));
			while (ap->ap_thread)
				ahci_os_sleep(100);
			kprintf("%s: thread terminated\n",
				PORTNAME(ap));
		}
	}
	lockuninit(&ap->ap_lock);
}
예제 #22
0
/*
 * Function name:	tw_osli_free_resources
 * Description:		Performs clean-up at the time of going down.
 *
 * Input:		sc	-- ptr to OSL internal ctlr context
 * Output:		None
 * Return value:	None
 */
static TW_VOID
tw_osli_free_resources(struct twa_softc *sc)
{
	struct tw_osli_req_context	*req;
	TW_INT32			error = 0;

	tw_osli_dbg_dprintf(3, sc, "entered");

	/* Detach from CAM */
	tw_osli_cam_detach(sc);

	if (sc->req_ctx_buf)
		while ((req = tw_osli_req_q_remove_head(sc, TW_OSLI_FREE_Q)) !=
			NULL) {
			lockuninit(req->ioctl_wake_timeout_lock);

			if ((error = bus_dmamap_destroy(sc->dma_tag,
					req->dma_map)))
				tw_osli_dbg_dprintf(1, sc,
					"dmamap_destroy(dma) returned %d",
					error);
		}

	if ((sc->ioctl_tag) && (sc->ioctl_map))
		if ((error = bus_dmamap_destroy(sc->ioctl_tag, sc->ioctl_map)))
			tw_osli_dbg_dprintf(1, sc,
				"dmamap_destroy(ioctl) returned %d", error);

	/* Free all memory allocated so far. */
	if (sc->req_ctx_buf)
		kfree(sc->req_ctx_buf, TW_OSLI_MALLOC_CLASS);

	if (sc->non_dma_mem)
		kfree(sc->non_dma_mem, TW_OSLI_MALLOC_CLASS);

	if (sc->dma_mem) {
		bus_dmamap_unload(sc->cmd_tag, sc->cmd_map);
		bus_dmamem_free(sc->cmd_tag, sc->dma_mem,
			sc->cmd_map);
	}
	if (sc->cmd_tag)
		if ((error = bus_dma_tag_destroy(sc->cmd_tag)))
			tw_osli_dbg_dprintf(1, sc,
				"dma_tag_destroy(cmd) returned %d", error);

	if (sc->dma_tag)
		if ((error = bus_dma_tag_destroy(sc->dma_tag)))
			tw_osli_dbg_dprintf(1, sc,
				"dma_tag_destroy(dma) returned %d", error);

	if (sc->ioctl_tag)
		if ((error = bus_dma_tag_destroy(sc->ioctl_tag)))
			tw_osli_dbg_dprintf(1, sc,
				"dma_tag_destroy(ioctl) returned %d", error);

	if (sc->parent_tag)
		if ((error = bus_dma_tag_destroy(sc->parent_tag)))
			tw_osli_dbg_dprintf(1, sc,
				"dma_tag_destroy(parent) returned %d", error);


	/* Disconnect the interrupt handler. */
	if ((error = twa_teardown_intr(sc)))
			tw_osli_dbg_dprintf(1, sc,
				"teardown_intr returned %d", error);

	if (sc->irq_res != NULL)
		if ((error = bus_release_resource(sc->bus_dev,
				SYS_RES_IRQ, sc->irq_res_id, sc->irq_res)))
			tw_osli_dbg_dprintf(1, sc,
				"release_resource(irq) returned %d", error);

	if (sc->irq_type == PCI_INTR_TYPE_MSI)
		pci_release_msi(sc->bus_dev);

	/* Release the register window mapping. */
	if (sc->reg_res != NULL)
		if ((error = bus_release_resource(sc->bus_dev,
				SYS_RES_MEMORY, sc->reg_res_id, sc->reg_res)))
			tw_osli_dbg_dprintf(1, sc,
				"release_resource(io) returned %d", error);

	/* Destroy the control device. */
	if (sc->ctrl_dev != NULL)
		destroy_dev(sc->ctrl_dev);
	dev_ops_remove_minor(&twa_ops, device_get_unit(sc->bus_dev));
}
예제 #23
0
static int
tws_detach(device_t dev)
{
    struct tws_softc *sc = device_get_softc(dev);
    int error, i;
    u_int32_t reg;

    TWS_TRACE_DEBUG(sc, "entry", 0, 0);

    lockmgr(&sc->gen_lock, LK_EXCLUSIVE);
    tws_send_event(sc, TWS_UNINIT_START);
    lockmgr(&sc->gen_lock, LK_RELEASE);

    /* needs to disable interrupt before detaching from cam */
    tws_turn_off_interrupts(sc);
    /* clear door bell */
    tws_write_reg(sc, TWS_I2O0_HOBDBC, ~0, 4);
    reg = tws_read_reg(sc, TWS_I2O0_HIMASK, 4);
    TWS_TRACE_DEBUG(sc, "turn-off-intr", reg, 0);
    sc->obfl_q_overrun = false;
    tws_init_connect(sc, 1);

    /* Teardown the state in our softc created in our attach routine. */
    /* Disconnect the interrupt handler. */
    for(i=0;i<sc->irqs;i++) {
        if (sc->intr_handle[i]) {
            if ((error = bus_teardown_intr(sc->tws_dev,
                         sc->irq_res[i], sc->intr_handle[i])))
                TWS_TRACE(sc, "bus teardown intr", 0, error);
        }
    }
    /* Release irq resource */
    for(i=0;i<sc->irqs;i++) {
        if ( sc->irq_res[i] ){
            if (bus_release_resource(sc->tws_dev,
                     SYS_RES_IRQ, sc->irq_res_id[i], sc->irq_res[i]))
                TWS_TRACE(sc, "bus release irq resource",
                                       i, sc->irq_res_id[i]);
        }
    }
    if ( sc->intr_type == TWS_MSI ) {
        pci_release_msi(sc->tws_dev);
    }

    tws_cam_detach(sc);

    /* Release memory resource */
    if ( sc->mfa_res ){
        if (bus_release_resource(sc->tws_dev,
                 SYS_RES_MEMORY, sc->mfa_res_id, sc->mfa_res))
            TWS_TRACE(sc, "bus release mem resource", 0, sc->mfa_res_id);
    }
    if ( sc->reg_res ){
        if (bus_release_resource(sc->tws_dev,
                 SYS_RES_MEMORY, sc->reg_res_id, sc->reg_res))
            TWS_TRACE(sc, "bus release mem resource", 0, sc->reg_res_id);
    }

    kfree(sc->reqs, M_TWS);
    kfree(sc->sense_bufs, M_TWS);
    kfree(sc->scan_ccb, M_TWS);
    kfree(sc->aen_q.q, M_TWS);
    kfree(sc->trace_q.q, M_TWS);
    lockuninit(&sc->q_lock);
    lockuninit(&sc->sim_lock);
    lockuninit(&sc->gen_lock);
    lockuninit(&sc->io_lock);
    destroy_dev(sc->tws_cdev);
    dev_ops_remove_minor(&tws_ops, device_get_unit(sc->tws_dev));
    sysctl_ctx_free(&sc->tws_clist);
    return (0);
}
예제 #24
0
static int
tws_attach(device_t dev)
{
    struct tws_softc *sc = device_get_softc(dev);
    u_int32_t cmd, bar;
    int error=0,i;

    /* no tracing yet */
    /* Look up our softc and initialize its fields. */
    sc->tws_dev = dev;
    sc->device_id = pci_get_device(dev);
    sc->subvendor_id = pci_get_subvendor(dev);
    sc->subdevice_id = pci_get_subdevice(dev);

    /* Intialize mutexes */
    lockinit(&sc->q_lock, "tws_q_lock", 0, LK_CANRECURSE);
    lockinit(&sc->sim_lock, "tws_sim_lock", 0, LK_CANRECURSE);
    lockinit(&sc->gen_lock, "tws_gen_lock", 0, LK_CANRECURSE);
    lockinit(&sc->io_lock, "tws_io_lock", 0, LK_CANRECURSE);

    if ( tws_init_trace_q(sc) == FAILURE )
        kprintf("trace init failure\n");
    /* send init event */
    lockmgr(&sc->gen_lock, LK_EXCLUSIVE);
    tws_send_event(sc, TWS_INIT_START);
    lockmgr(&sc->gen_lock, LK_RELEASE);


#if _BYTE_ORDER == _BIG_ENDIAN
    TWS_TRACE(sc, "BIG endian", 0, 0);
#endif
    /* sysctl context setup */
    sysctl_ctx_init(&sc->tws_clist);
    sc->tws_oidp = SYSCTL_ADD_NODE(&sc->tws_clist,
                                   SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO,
                                   device_get_nameunit(dev),
                                   CTLFLAG_RD, 0, "");
    if ( sc->tws_oidp == NULL ) {
        tws_log(sc, SYSCTL_TREE_NODE_ADD);
        goto attach_fail_1;
    }
    SYSCTL_ADD_STRING(&sc->tws_clist, SYSCTL_CHILDREN(sc->tws_oidp),
                      OID_AUTO, "driver_version", CTLFLAG_RD,
                      TWS_DRIVER_VERSION_STRING, 0, "TWS driver version");

    cmd = pci_read_config(dev, PCIR_COMMAND, 2);
    if ( (cmd & PCIM_CMD_PORTEN) == 0) {
        tws_log(sc, PCI_COMMAND_READ);
        goto attach_fail_1;
    }
    /* Force the busmaster enable bit on. */
    cmd |= PCIM_CMD_BUSMASTEREN;
    pci_write_config(dev, PCIR_COMMAND, cmd, 2);

    bar = pci_read_config(dev, TWS_PCI_BAR0, 4);
    TWS_TRACE_DEBUG(sc, "bar0 ", bar, 0);
    bar = pci_read_config(dev, TWS_PCI_BAR1, 4);
    bar = bar & ~TWS_BIT2;
    TWS_TRACE_DEBUG(sc, "bar1 ", bar, 0);

    /* MFA base address is BAR2 register used for
     * push mode. Firmware will evatualy move to
     * pull mode during witch this needs to change
     */
#ifndef TWS_PULL_MODE_ENABLE
    sc->mfa_base = (u_int64_t)pci_read_config(dev, TWS_PCI_BAR2, 4);
    sc->mfa_base = sc->mfa_base & ~TWS_BIT2;
    TWS_TRACE_DEBUG(sc, "bar2 ", sc->mfa_base, 0);
#endif

    /* allocate MMIO register space */
    sc->reg_res_id = TWS_PCI_BAR1; /* BAR1 offset */
    if ((sc->reg_res = bus_alloc_resource(dev, SYS_RES_MEMORY,
                                &(sc->reg_res_id), 0, ~0, 1, RF_ACTIVE))
                                == NULL) {
        tws_log(sc, ALLOC_MEMORY_RES);
        goto attach_fail_1;
    }
    sc->bus_tag = rman_get_bustag(sc->reg_res);
    sc->bus_handle = rman_get_bushandle(sc->reg_res);

#ifndef TWS_PULL_MODE_ENABLE
    /* Allocate bus space for inbound mfa */
    sc->mfa_res_id = TWS_PCI_BAR2; /* BAR2 offset */
    if ((sc->mfa_res = bus_alloc_resource(dev, SYS_RES_MEMORY,
                          &(sc->mfa_res_id), 0, ~0, 0x100000, RF_ACTIVE))
                                == NULL) {
        tws_log(sc, ALLOC_MEMORY_RES);
        goto attach_fail_2;
    }
    sc->bus_mfa_tag = rman_get_bustag(sc->mfa_res);
    sc->bus_mfa_handle = rman_get_bushandle(sc->mfa_res);
#endif

    /* Allocate and register our interrupt. */
    sc->intr_type = TWS_INTx; /* default */

    if ( tws_enable_msi )
        sc->intr_type = TWS_MSI;
    if ( tws_setup_irq(sc) == FAILURE ) {
        tws_log(sc, ALLOC_MEMORY_RES);
        goto attach_fail_3;
    }

    /* Init callouts. */
    callout_init(&sc->print_stats_handle);
    callout_init(&sc->reset_cb_handle);
    callout_init(&sc->reinit_handle);

    /*
     * Create a /dev entry for this device.  The kernel will assign us
     * a major number automatically.  We use the unit number of this
     * device as the minor number and name the character device
     * "tws<unit>".
     */
    sc->tws_cdev = make_dev(&tws_ops, device_get_unit(dev),
        UID_ROOT, GID_OPERATOR, S_IRUSR | S_IWUSR, "tws%u",
        device_get_unit(dev));
    sc->tws_cdev->si_drv1 = sc;

    if ( tws_init(sc) == FAILURE ) {
        tws_log(sc, TWS_INIT_FAILURE);
        goto attach_fail_4;
    }
    if ( tws_init_ctlr(sc) == FAILURE ) {
        tws_log(sc, TWS_CTLR_INIT_FAILURE);
        goto attach_fail_4;
    }
    if ((error = tws_cam_attach(sc))) {
        tws_log(sc, TWS_CAM_ATTACH);
        goto attach_fail_4;
    }
    /* send init complete event */
    lockmgr(&sc->gen_lock, LK_EXCLUSIVE);
    tws_send_event(sc, TWS_INIT_COMPLETE);
    lockmgr(&sc->gen_lock, LK_RELEASE);

    TWS_TRACE_DEBUG(sc, "attached successfully", 0, sc->device_id);
    return(0);

attach_fail_4:
    for(i=0;i<sc->irqs;i++) {
        if (sc->intr_handle[i]) {
            if ((error = bus_teardown_intr(sc->tws_dev,
                         sc->irq_res[i], sc->intr_handle[i])))
                TWS_TRACE(sc, "bus teardown intr", 0, error);
        }
    }
    destroy_dev(sc->tws_cdev);
    dev_ops_remove_minor(&tws_ops, device_get_unit(sc->tws_dev));
attach_fail_3:
    for(i=0;i<sc->irqs;i++) {
        if ( sc->irq_res[i] ){
            if (bus_release_resource(sc->tws_dev,
                 SYS_RES_IRQ, sc->irq_res_id[i], sc->irq_res[i]))
                TWS_TRACE(sc, "bus irq res", 0, 0);
        }
    }
#ifndef TWS_PULL_MODE_ENABLE
attach_fail_2:
#endif
    if ( sc->mfa_res ){
        if (bus_release_resource(sc->tws_dev,
                 SYS_RES_MEMORY, sc->mfa_res_id, sc->mfa_res))
            TWS_TRACE(sc, "bus release ", 0, sc->mfa_res_id);
    }
    if ( sc->reg_res ){
        if (bus_release_resource(sc->tws_dev,
                 SYS_RES_MEMORY, sc->reg_res_id, sc->reg_res))
            TWS_TRACE(sc, "bus release2 ", 0, sc->reg_res_id);
    }
attach_fail_1:
    lockuninit(&sc->q_lock);
    lockuninit(&sc->sim_lock);
    lockuninit(&sc->gen_lock);
    lockuninit(&sc->io_lock);
    sysctl_ctx_free(&sc->tws_clist);
    return (ENXIO);
}
예제 #25
0
static void drm_unload(struct drm_device *dev)
{
	int i;

	DRM_DEBUG("\n");

	drm_sysctl_cleanup(dev);
	if (dev->devnode != NULL)
		destroy_dev(dev->devnode);

	drm_ctxbitmap_cleanup(dev);

	if (dev->driver->driver_features & DRIVER_GEM)
		drm_gem_destroy(dev);

	if (dev->agp && dev->agp->agp_mtrr) {
		int __unused retcode;

		retcode = drm_mtrr_del(0, dev->agp->agp_info.ai_aperture_base,
		    dev->agp->agp_info.ai_aperture_size, DRM_MTRR_WC);
		DRM_DEBUG("mtrr_del = %d", retcode);
	}

	drm_vblank_cleanup(dev);

	DRM_LOCK(dev);
	drm_lastclose(dev);
	DRM_UNLOCK(dev);

	/* Clean up PCI resources allocated by drm_bufs.c.  We're not really
	 * worried about resource consumption while the DRM is inactive (between
	 * lastclose and firstopen or unload) because these aren't actually
	 * taking up KVA, just keeping the PCI resource allocated.
	 */
	for (i = 0; i < DRM_MAX_PCI_RESOURCE; i++) {
		if (dev->pcir[i] == NULL)
			continue;
		bus_release_resource(dev->dev, SYS_RES_MEMORY,
		    dev->pcirid[i], dev->pcir[i]);
		dev->pcir[i] = NULL;
	}

	if (dev->agp) {
		drm_free(dev->agp, M_DRM);
		dev->agp = NULL;
	}

	if (dev->driver->unload != NULL) {
		DRM_LOCK(dev);
		dev->driver->unload(dev);
		DRM_UNLOCK(dev);
	}

	drm_mem_uninit();

	if (pci_disable_busmaster(dev->dev))
		DRM_ERROR("Request to disable bus-master failed.\n");

	lockuninit(&dev->vbl_lock);
	lockuninit(&dev->dev_lock);
	lockuninit(&dev->event_lock);
	lockuninit(&dev->struct_mutex);
}