static int
auich_detach(device_t self, int flags)
{
	struct auich_softc *sc = device_private(self);

	/* audio */
	if (sc->sc_audiodev != NULL)
		config_detach(sc->sc_audiodev, flags);

	/* sysctl */
	sysctl_teardown(&sc->sc_log);

	mutex_enter(&sc->sc_lock);

	/* audio_encoding_set */
	auconv_delete_encodings(sc->sc_encodings);
	auconv_delete_encodings(sc->sc_spdif_encodings);

	/* ac97 */
	if (sc->codec_if != NULL)
		sc->codec_if->vtbl->detach(sc->codec_if);

	mutex_exit(&sc->sc_lock);
	mutex_destroy(&sc->sc_lock);
	mutex_destroy(&sc->sc_intr_lock);

	/* PCI */
	if (sc->sc_ih != NULL)
		pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
	if (sc->mix_size != 0)
		bus_space_unmap(sc->iot, sc->mix_ioh, sc->mix_size);
	if (sc->aud_size != 0)
		bus_space_unmap(sc->iot, sc->aud_ioh, sc->aud_size);
	return 0;
}
示例#2
0
static int
auvia_detach(device_t self, int flags)
{
	int rc;
	struct auvia_softc *sc = device_private(self);

	if ((rc = config_detach_children(self, flags)) != 0)
		return rc;
	pmf_device_deregister(self);

	mutex_enter(&sc->sc_lock);
	auconv_delete_encodings(sc->sc_encodings);
	auconv_delete_encodings(sc->sc_spdif_encodings);
	if (sc->codec_if != NULL)
		sc->codec_if->vtbl->detach(sc->codec_if);
	mutex_exit(&sc->sc_lock);

	/* XXX restore compatibility? */
	if (sc->sc_ih != NULL)
		pci_intr_disestablish(sc->sc_pc, sc->sc_ih);

	bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_iosize);
	if (sc->sc_play.sc_dma_ops != NULL) {
		auvia_free(sc, sc->sc_play.sc_dma_ops,
		    sc->sc_play.sc_dma_op_count *
		    sizeof(struct auvia_dma_op));
	}
	if (sc->sc_record.sc_dma_ops != NULL) {
		auvia_free(sc, sc->sc_record.sc_dma_ops,
		    sc->sc_play.sc_dma_op_count *
		    sizeof(struct auvia_dma_op));
	}
	mutex_destroy(&sc->sc_lock);
	mutex_destroy(&sc->sc_intr_lock);

	return 0;
}