コード例 #1
0
ファイル: drm_os_freebsd.c プロジェクト: cyrilmagsuci/freebsd
int
drm_generic_detach(device_t kdev)
{
	struct drm_device *dev;
	int i;

	dev = device_get_softc(kdev);

	drm_put_dev(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 (pci_disable_busmaster(dev->dev))
		DRM_ERROR("Request to disable bus-master failed.\n");

	return (0);
}
コード例 #2
0
ファイル: bhndb_pci.c プロジェクト: FreeBSDFoundation/freebsd
static int
bhndb_pci_detach(device_t dev)
{
	struct bhndb_pci_softc	*sc;
	int			 error;

	sc = device_get_softc(dev);

	/* Attempt to detach our children */
	if ((error = bus_generic_detach(dev)))
		return (error);

	/* Perform generic bridge detach */
	if ((error = bhndb_generic_detach(dev)))
		return (error);

	/* Disable clocks (if required by this hardware) */
	if ((error = bhndb_disable_pci_clocks(sc->dev)))
		return (error);

	/* Free our interrupt resources */
	bhndb_free_intr_isrc(sc->isrc);

	/* Release MSI interrupts */
	if (sc->msi_count > 0)
		pci_release_msi(sc->parent);

	/* Disable PCI bus mastering */
	pci_disable_busmaster(sc->parent);

	BHNDB_PCI_LOCK_DESTROY(sc);

	return (0);
}
コード例 #3
0
static int
vga_pci_disable_busmaster(device_t dev, device_t child)
{

	device_printf(dev, "child %s requested pci_disable_busmaster\n",
	    device_get_nameunit(child));
	return (pci_disable_busmaster(dev));
}
コード例 #4
0
ファイル: nvme.c プロジェクト: fengsi/freebsd
static int
nvme_detach (device_t dev)
{
	struct nvme_controller	*ctrlr = DEVICE2SOFTC(dev);

	nvme_ctrlr_destruct(ctrlr, dev);
	pci_disable_busmaster(dev);
	return (0);
}
コード例 #5
0
ファイル: uhci_pci.c プロジェクト: cyrilmagsuci/freebsd
int
uhci_pci_detach(device_t self)
{
	uhci_softc_t *sc = device_get_softc(self);
	device_t bdev;

	if (sc->sc_bus.bdev) {
		bdev = sc->sc_bus.bdev;
		device_detach(bdev);
		device_delete_child(self, bdev);
	}
	/* during module unload there are lots of children leftover */
	device_delete_children(self);

	/*
	 * disable interrupts that might have been switched on in
	 * uhci_init.
	 */
	if (sc->sc_io_res) {
		USB_BUS_LOCK(&sc->sc_bus);

		/* stop the controller */
		uhci_reset(sc);

		USB_BUS_UNLOCK(&sc->sc_bus);
	}
	pci_disable_busmaster(self);

	if (sc->sc_irq_res && sc->sc_intr_hdl) {
		int err = bus_teardown_intr(self, sc->sc_irq_res, sc->sc_intr_hdl);

		if (err) {
			/* XXX or should we panic? */
			device_printf(self, "Could not tear down irq, %d\n",
			    err);
		}
		sc->sc_intr_hdl = NULL;
	}
	if (sc->sc_irq_res) {
		bus_release_resource(self, SYS_RES_IRQ, 0, sc->sc_irq_res);
		sc->sc_irq_res = NULL;
	}
	if (sc->sc_io_res) {
		bus_release_resource(self, SYS_RES_IOPORT, PCI_UHCI_BASE_REG,
		    sc->sc_io_res);
		sc->sc_io_res = NULL;
	}
	usb_bus_mem_free_all(&sc->sc_bus, &uhci_iterate_hw_softc);

	return (0);
}
コード例 #6
0
ファイル: ismt.c プロジェクト: 2asoft/freebsd
static int
ismt_detach(device_t dev)
{
	struct ismt_softc	*sc;
	int			error;

	ISMT_DEBUG(dev, "%s\n", __func__);
	sc = device_get_softc(dev);

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

	device_delete_child(dev, sc->smbdev);

	if (sc->intr_handle != NULL) {
		bus_teardown_intr(dev, sc->intr_res, sc->intr_handle);
		sc->intr_handle = NULL;
	}
	if (sc->intr_res != NULL) {
		bus_release_resource(dev,
		    SYS_RES_IRQ, sc->intr_rid, sc->intr_res);
		sc->intr_res = NULL;
	}
	if (sc->using_msi == 1)
		pci_release_msi(dev);

	if (sc->mmio_res != NULL) {
		bus_release_resource(dev,
		    SYS_RES_MEMORY, sc->mmio_rid, sc->mmio_res);
		sc->mmio_res = NULL;
	}

	bus_dmamap_unload(sc->desc_dma_tag, sc->desc_dma_map);
	bus_dmamap_unload(sc->dma_buffer_dma_tag, sc->dma_buffer_dma_map);

	bus_dmamem_free(sc->desc_dma_tag, sc->desc,
	    sc->desc_dma_map);
	bus_dmamem_free(sc->dma_buffer_dma_tag, sc->dma_buffer,
	    sc->dma_buffer_dma_map);

	bus_dma_tag_destroy(sc->desc_dma_tag);
	bus_dma_tag_destroy(sc->dma_buffer_dma_tag);

	pci_disable_busmaster(dev);

	return 0;
}
コード例 #7
0
ファイル: sfxge.c プロジェクト: AhmadTux/freebsd
static void
sfxge_destroy(struct sfxge_softc *sc)
{
	efx_nic_t *enp;

	/* Clean up port state. */
	sfxge_port_fini(sc);

	/* Clean up transmit state. */
	sfxge_tx_fini(sc);

	/* Clean up receive state. */
	sfxge_rx_fini(sc);

	/* Clean up event processing state. */
	sfxge_ev_fini(sc);

	/* Clean up interrupts. */
	sfxge_intr_fini(sc);

	/* Tear down common code subsystems. */
	efx_nic_reset(sc->enp);
	efx_vpd_fini(sc->enp);
	efx_nvram_fini(sc->enp);
	efx_nic_unprobe(sc->enp);

	/* Tear down MCDI. */
	sfxge_mcdi_fini(sc);

	/* Destroy common code context. */
	enp = sc->enp;
	sc->enp = NULL;
	efx_nic_destroy(enp);

	/* Free DMA memory. */
	sfxge_dma_fini(sc);

	/* Free mapped BARs. */
	sfxge_bar_fini(sc);

	(void) pci_disable_busmaster(sc->dev);

	taskqueue_drain(taskqueue_thread, &sc->task_reset);

	/* Destroy the softc lock. */
	sx_destroy(&sc->softc_lock);
}
コード例 #8
0
ファイル: siba_bwn.c プロジェクト: zenny/DragonFlyBSD
static int
siba_bwn_detach(device_t dev)
{
	struct siba_bwn_softc *ssc = device_get_softc(dev);
	struct siba_softc *siba = &ssc->ssc_siba;

	/* check if device was removed */
	siba->siba_invalid = !bus_child_present(dev);

	pci_disable_busmaster(dev);
	bus_generic_detach(dev);
	siba_core_detach(siba);

	bus_release_resource(dev, SYS_RES_MEMORY, BS_BAR, siba->siba_mem_res);

	return (0);
}
コード例 #9
0
static int
ohci_pci_detach(device_t self)
{
	ohci_softc_t *sc = device_get_softc(self);
	device_t bdev;

	if (sc->sc_bus.bdev) {
		bdev = sc->sc_bus.bdev;
		device_detach(bdev);
		device_delete_child(self, bdev);
	}
	/* during module unload there are lots of children leftover */
	device_delete_all_children(self);

	pci_disable_busmaster(self);

	if (sc->sc_irq_res && sc->sc_intr_hdl) {
		/*
		 * only call ohci_detach() after ohci_init()
		 */
		ohci_detach(sc);

		int err = bus_teardown_intr(self, sc->sc_irq_res, sc->sc_intr_hdl);

		if (err) {
			/* XXX or should we panic? */
			device_printf(self, "Could not tear down irq, %d\n",
			    err);
		}
		sc->sc_intr_hdl = NULL;
	}
	if (sc->sc_irq_res) {
		bus_release_resource(self, SYS_RES_IRQ, 0, sc->sc_irq_res);
		sc->sc_irq_res = NULL;
	}
	if (sc->sc_io_res) {
		bus_release_resource(self, SYS_RES_MEMORY, PCI_CBMEM,
		    sc->sc_io_res);
		sc->sc_io_res = NULL;
	}
	usb_bus_mem_free_all(&sc->sc_bus, &ohci_iterate_hw_softc);

	return (0);
}
コード例 #10
0
ファイル: xhci_pci.c プロジェクト: ele7enxxh/dtrace-pf
static int
xhci_pci_detach(device_t self)
{
	struct xhci_softc *sc = device_get_softc(self);
	device_t bdev;

	if (sc->sc_bus.bdev != NULL) {
		bdev = sc->sc_bus.bdev;
		device_detach(bdev);
		device_delete_child(self, bdev);
	}
	/* during module unload there are lots of children leftover */
	device_delete_children(self);

	if (sc->sc_io_res) {
		usb_callout_drain(&sc->sc_callout);
		xhci_halt_controller(sc);
	}

	pci_disable_busmaster(self);

	if (sc->sc_irq_res && sc->sc_intr_hdl) {
		bus_teardown_intr(self, sc->sc_irq_res, sc->sc_intr_hdl);
		sc->sc_intr_hdl = NULL;
	}
	if (sc->sc_irq_res) {
		if (sc->sc_irq_rid == 1)
			pci_release_msi(self);
		bus_release_resource(self, SYS_RES_IRQ, sc->sc_irq_rid,
		    sc->sc_irq_res);
		sc->sc_irq_res = NULL;
	}
	if (sc->sc_io_res) {
		bus_release_resource(self, SYS_RES_MEMORY, PCI_XHCI_CBMEM,
		    sc->sc_io_res);
		sc->sc_io_res = NULL;
	}

	xhci_uninit(sc);

	return (0);
}
コード例 #11
0
static int
bhndb_pci_detach(device_t dev)
{
	struct bhndb_pci_softc	*sc;
	int			 error;

	sc = device_get_softc(dev);

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

	/* Apply any hardware workarounds. This may disable the clock, and
	 * thus must be called *after* any children have been detached. */
	if ((error = bhndb_pci_wars_hwdown(sc)))
		return (error);

	/* Disable PCI bus mastering */
	pci_disable_busmaster(device_get_parent(dev));

	return (0);
}
コード例 #12
0
ファイル: ioat.c プロジェクト: cyrilmagsuci/freebsd
static int
ioat_detach(device_t device)
{
	struct ioat_softc *ioat;

	ioat = DEVICE2SOFTC(device);

	ioat_test_detach();

	mtx_lock(IOAT_REFLK);
	ioat->quiescing = TRUE;
	ioat_channel[ioat->chan_idx] = NULL;

	ioat_drain_locked(ioat);
	mtx_unlock(IOAT_REFLK);

	ioat_teardown_intr(ioat);
	callout_drain(&ioat->timer);

	pci_disable_busmaster(device);

	if (ioat->pci_resource != NULL)
		bus_release_resource(device, SYS_RES_MEMORY,
		    ioat->pci_resource_id, ioat->pci_resource);

	if (ioat->ring != NULL)
		ioat_free_ring(ioat, 1 << ioat->ring_size_order, ioat->ring);

	if (ioat->comp_update != NULL) {
		bus_dmamap_unload(ioat->comp_update_tag, ioat->comp_update_map);
		bus_dmamem_free(ioat->comp_update_tag, ioat->comp_update,
		    ioat->comp_update_map);
		bus_dma_tag_destroy(ioat->comp_update_tag);
	}

	bus_dma_tag_destroy(ioat->hw_desc_tag);

	return (0);
}
コード例 #13
0
ファイル: vga_pci.c プロジェクト: rchander/freebsd
static int
vga_pci_disable_busmaster(device_t dev, device_t child)
{

	return (pci_disable_busmaster(dev));
}
コード例 #14
0
ファイル: bhndb_pci.c プロジェクト: FreeBSDFoundation/freebsd
static int
bhndb_pci_attach(device_t dev)
{
	struct bhndb_pci_softc	*sc;
	struct bhnd_chipid	 cid;
	struct bhnd_core_info	*cores, hostb_core;
	bhnd_erom_class_t	*erom_class;
	struct bhndb_pci_probe	*probe;
	u_int			 ncores;
	int			 irq_rid;
	int			 error;

	sc = device_get_softc(dev);
	sc->dev = dev;
	sc->parent = device_get_parent(dev);
	sc->pci_devclass = bhndb_expected_pci_devclass(dev);
	sc->pci_quirks = 0;
	sc->set_regwin = NULL;

	BHNDB_PCI_LOCK_INIT(sc);

	probe = NULL;
	cores = NULL;

	/* Enable PCI bus mastering */
	pci_enable_busmaster(sc->parent);

	/* Enable clocks (if required by this hardware) */
	if ((error = bhndb_enable_pci_clocks(sc->dev)))
		goto cleanup;

	/* Identify the chip and enumerate the bridged cores */
	error = bhndb_pci_probe_alloc(&probe, dev, sc->pci_devclass);
	if (error)
		goto cleanup;

	sc->pci_quirks = bhndb_pci_get_core_quirks(&probe->cid,
	    &probe->hostb_core);

	/* Select the appropriate register window handler */
	if (probe->cid.chip_type == BHND_CHIPTYPE_SIBA) {
		sc->set_regwin = bhndb_pci_compat_setregwin;
	} else {
		sc->set_regwin = bhndb_pci_fast_setregwin;
	}

	/*
	 * Fix up our PCI base address in the SPROM shadow, if necessary.
	 * 
	 * This must be done prior to accessing any static register windows
	 * that map the PCI core.
	 */
	if ((error = bhndb_pci_srsh_pi_war(sc, probe)))
		goto cleanup;

	/* Set up PCI interrupt handling */
	if (bhndb_pci_alloc_msi(sc, &sc->msi_count) == 0) {
		/* MSI uses resource IDs starting at 1 */
		irq_rid = 1;

		device_printf(dev, "Using MSI interrupts on %s\n",
		    device_get_nameunit(sc->parent));
	} else {
		sc->msi_count = 0;
		irq_rid = 0;

		device_printf(dev, "Using INTx interrupts on %s\n",
		    device_get_nameunit(sc->parent));
	}

	sc->isrc = bhndb_alloc_intr_isrc(sc->parent, irq_rid, 0, RM_MAX_END, 1,
	    RF_SHAREABLE | RF_ACTIVE);
	if (sc->isrc == NULL) {
		device_printf(sc->dev, "failed to allocate interrupt "
		    "resource\n");
		error = ENXIO;
		goto cleanup;
	}

	/*
	 * Copy out the probe results and then free our probe state, releasing
	 * its exclusive ownership of host bridge resources.
	 * 
	 * This must be done prior to full configuration of the bridge via
	 * bhndb_attach().
	 */
	cid = probe->cid;
	erom_class = probe->erom_class;
	hostb_core = probe->hostb_core;

	error = bhndb_pci_probe_copy_core_table(probe, &cores, &ncores);
	if (error) {
		cores = NULL;
		goto cleanup;
	}

	bhndb_pci_probe_free(probe);
	probe = NULL;

	/* Perform bridge attach */
	error = bhndb_attach(dev, &cid, cores, ncores, &hostb_core, erom_class);
	if (error)
		goto cleanup;

	/* Add any additional child devices */
	if ((error = bhndb_pci_add_children(sc)))
		goto cleanup;

	/* Probe and attach our children */
	if ((error = bus_generic_attach(dev)))
		goto cleanup;

	bhndb_pci_probe_free_core_table(cores);

	return (0);

cleanup:
	device_delete_children(dev);

	if (sc->isrc != NULL)
		bhndb_free_intr_isrc(sc->isrc);

	if (sc->msi_count > 0)
		pci_release_msi(sc->parent);

	if (cores != NULL)
		bhndb_pci_probe_free_core_table(cores);

	if (probe != NULL)
		bhndb_pci_probe_free(probe);

	bhndb_disable_pci_clocks(sc->dev);

	pci_disable_busmaster(sc->parent);

	BHNDB_PCI_LOCK_DESTROY(sc);

	return (error);
}
コード例 #15
0
ファイル: isci.c プロジェクト: tomtor/freebsd
static int
isci_detach(device_t device)
{
    struct isci_softc *isci = DEVICE2SOFTC(device);
    int i, phy;

    for (i = 0; i < isci->controller_count; i++) {
        struct ISCI_CONTROLLER *controller = &isci->controllers[i];
        SCI_STATUS status;
        void *unmap_buffer;

        if (controller->scif_controller_handle != NULL) {
            scic_controller_disable_interrupts(
                scif_controller_get_scic_handle(controller->scif_controller_handle));

            mtx_lock(&controller->lock);
            status = scif_controller_stop(controller->scif_controller_handle, 0);
            mtx_unlock(&controller->lock);

            while (controller->is_started == TRUE) {
                /* Now poll for interrupts until the controller stop complete
                 *  callback is received.
                 */
                mtx_lock(&controller->lock);
                isci_interrupt_poll_handler(controller);
                mtx_unlock(&controller->lock);
                pause("isci", 1);
            }

            if(controller->sim != NULL) {
                mtx_lock(&controller->lock);
                xpt_free_path(controller->path);
                xpt_bus_deregister(cam_sim_path(controller->sim));
                cam_sim_free(controller->sim, TRUE);
                mtx_unlock(&controller->lock);
            }
        }

        if (controller->timer_memory != NULL)
            free(controller->timer_memory, M_ISCI);

        if (controller->remote_device_memory != NULL)
            free(controller->remote_device_memory, M_ISCI);

        for (phy = 0; phy < SCI_MAX_PHYS; phy++) {
            if (controller->phys[phy].cdev_fault)
                led_destroy(controller->phys[phy].cdev_fault);

            if (controller->phys[phy].cdev_locate)
                led_destroy(controller->phys[phy].cdev_locate);
        }

        while (1) {
            sci_pool_get(controller->unmap_buffer_pool, unmap_buffer);
            if (unmap_buffer == NULL)
                break;
            contigfree(unmap_buffer, PAGE_SIZE, M_ISCI);
        }
    }

    /* The SCIF controllers have been stopped, so we can now
     *  free the SCI library memory.
     */
    if (isci->sci_library_memory != NULL)
        free(isci->sci_library_memory, M_ISCI);

    for (i = 0; i < ISCI_NUM_PCI_BARS; i++)
    {
        struct ISCI_PCI_BAR *pci_bar = &isci->pci_bar[i];

        if (pci_bar->resource != NULL)
            bus_release_resource(device, SYS_RES_MEMORY,
                                 pci_bar->resource_id, pci_bar->resource);
    }

    for (i = 0; i < isci->num_interrupts; i++)
    {
        struct ISCI_INTERRUPT_INFO *interrupt_info;

        interrupt_info = &isci->interrupt_info[i];

        if(interrupt_info->tag != NULL)
            bus_teardown_intr(device, interrupt_info->res,
                              interrupt_info->tag);

        if(interrupt_info->res != NULL)
            bus_release_resource(device, SYS_RES_IRQ,
                                 rman_get_rid(interrupt_info->res),
                                 interrupt_info->res);

        pci_release_msi(device);
    }
    pci_disable_busmaster(device);

    return (0);
}
コード例 #16
0
ファイル: sfxge.c プロジェクト: AhmadTux/freebsd
static int
sfxge_create(struct sfxge_softc *sc)
{
	device_t dev;
	efx_nic_t *enp;
	int error;

	dev = sc->dev;

	sx_init(&sc->softc_lock, "sfxge_softc");

	sc->stats_node = SYSCTL_ADD_NODE(
		device_get_sysctl_ctx(dev),
		SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
		OID_AUTO, "stats", CTLFLAG_RD, NULL, "Statistics");
	if (!sc->stats_node) {
		error = ENOMEM;
		goto fail;
	}

	TASK_INIT(&sc->task_reset, 0, sfxge_reset, sc);

	(void) pci_enable_busmaster(dev);

	/* Initialize DMA mappings. */
	if ((error = sfxge_dma_init(sc)) != 0)
		goto fail;

	/* Map the device registers. */
	if ((error = sfxge_bar_init(sc)) != 0)
		goto fail;

	error = efx_family(pci_get_vendor(dev), pci_get_device(dev),
	    &sc->family);
	KASSERT(error == 0, ("Family should be filtered by sfxge_probe()"));

	/* Create the common code nic object. */
	mtx_init(&sc->enp_lock, "sfxge_nic", NULL, MTX_DEF);
	if ((error = efx_nic_create(sc->family, (efsys_identifier_t *)sc,
	    &sc->bar, &sc->enp_lock, &enp)) != 0)
		goto fail3;
	sc->enp = enp;

	/* Initialize MCDI to talk to the microcontroller. */
	if ((error = sfxge_mcdi_init(sc)) != 0)
		goto fail4;

	/* Probe the NIC and build the configuration data area. */
	if ((error = efx_nic_probe(enp)) != 0)
		goto fail5;

	/* Initialize the NVRAM. */
	if ((error = efx_nvram_init(enp)) != 0)
		goto fail6;

	/* Initialize the VPD. */
	if ((error = efx_vpd_init(enp)) != 0)
		goto fail7;

	/* Reset the NIC. */
	if ((error = efx_nic_reset(enp)) != 0)
		goto fail8;

	/* Initialize buffer table allocation. */
	sc->buffer_table_next = 0;

	/* Set up interrupts. */
	if ((error = sfxge_intr_init(sc)) != 0)
		goto fail8;

	/* Initialize event processing state. */
	if ((error = sfxge_ev_init(sc)) != 0)
		goto fail11;

	/* Initialize receive state. */
	if ((error = sfxge_rx_init(sc)) != 0)
		goto fail12;

	/* Initialize transmit state. */
	if ((error = sfxge_tx_init(sc)) != 0)
		goto fail13;

	/* Initialize port state. */
	if ((error = sfxge_port_init(sc)) != 0)
		goto fail14;

	sc->init_state = SFXGE_INITIALIZED;

	return (0);

fail14:
	sfxge_tx_fini(sc);

fail13:
	sfxge_rx_fini(sc);

fail12:
	sfxge_ev_fini(sc);

fail11:
	sfxge_intr_fini(sc);

fail8:
	efx_vpd_fini(enp);

fail7:
	efx_nvram_fini(enp);

fail6:
	efx_nic_unprobe(enp);

fail5:
	sfxge_mcdi_fini(sc);

fail4:
	sc->enp = NULL;
	efx_nic_destroy(enp);
	mtx_destroy(&sc->enp_lock);

fail3:
	sfxge_bar_fini(sc);
	(void) pci_disable_busmaster(sc->dev);

fail:
	sc->dev = NULL;
	sx_destroy(&sc->softc_lock);
	return (error);
}
コード例 #17
0
ファイル: drm_fops.c プロジェクト: wan721/DragonFlyBSD
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);
}