示例#1
0
/*
 * Bus independant device detachment routine.  Makes sure all
 * allocated resources are freed, callouts disabled and waiting
 * processes unblocked.
 */
int
cmx_detach(device_t dev)
{
	struct cmx_softc *sc = device_get_softc(dev);

	DEBUG_printf(dev, "called\n");

	sc->dying = 1;

	CMX_LOCK(sc);
	if (sc->polling) {
		DEBUG_printf(sc->dev, "disabling polling\n");
		callout_stop(&sc->ch);
		sc->polling = 0;
		CMX_UNLOCK(sc);
		KNOTE(&sc->kq.ki_note, 0);
	} else {
		CMX_UNLOCK(sc);
	}

	wakeup(sc);
	DEBUG_printf(dev, "releasing resources\n");
	cmx_release_resources(dev);
	dev_ops_remove_minor(&cmx_ops, device_get_unit(dev));

	return 0;
}
示例#2
0
static int
urio_detach(device_t self)
{
    DPRINTF(("%s: disconnected\n", device_get_nameunit(self)));
    dev_ops_remove_minor(&urio_ops, /*-1, */device_get_unit(self));
    /* XXX not implemented yet */
    device_set_desc(self, NULL);
    return 0;
}
示例#3
0
void
mps_detach_user(struct mps_softc *sc)
{

	/* XXX: do a purge of pending requests? */
	destroy_dev(sc->mps_cdev);
	dev_ops_remove_minor(&mps_ops, device_get_unit(sc->mps_dev));

}
示例#4
0
static void
ptdtor(struct cam_periph *periph)
{
	struct pt_softc *softc;

	softc = (struct pt_softc *)periph->softc;

	devstat_remove_entry(&softc->device_stats);

	cam_extend_release(ptperiphs, periph->unit_number);
	xpt_print(periph->path, "removing device entry\n");
	dev_ops_remove_minor(&pt_ops, periph->unit_number);
	kfree(softc, M_DEVBUF);
}
示例#5
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));
}
示例#6
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);
}
示例#7
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);
}