summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2006-01-13 19:25:46 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2006-01-13 19:25:46 +0000
commit03959db78243c44e5fb94b00244e5466c025c0af (patch)
treecf363aa2652deca96e666555598c48f6c15ef5f0 /sys
parent9b3ea61729df8fb14778b06dbbf377e15cf2f55e (diff)
Allow proper detaching of wdc, so that detaching a mediabay device properly
releases resources and works as expected. Thanks to Thomas Maschutznig for testing.
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/macppc/dev/dbdma.c28
-rw-r--r--sys/arch/macppc/dev/dbdma.h4
-rw-r--r--sys/arch/macppc/dev/wdc_obio.c57
3 files changed, 64 insertions, 25 deletions
diff --git a/sys/arch/macppc/dev/dbdma.c b/sys/arch/macppc/dev/dbdma.c
index c1142127299..d6622654072 100644
--- a/sys/arch/macppc/dev/dbdma.c
+++ b/sys/arch/macppc/dev/dbdma.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dbdma.c,v 1.7 2003/10/16 03:31:25 drahn Exp $ */
+/* $OpenBSD: dbdma.c,v 1.8 2006/01/13 19:25:44 miod Exp $ */
/* $NetBSD: dbdma.c,v 1.2 1998/08/21 16:13:28 tsubai Exp $ */
/*
@@ -117,7 +117,7 @@ dbdma_t
dbdma_alloc(bus_dma_tag_t dmat, int size)
{
dbdma_t dt;
- int error, nsegs = 0;
+ int error;
dt = malloc(sizeof *dt, M_DEVBUF, M_NOWAIT);
if (!dt)
@@ -125,28 +125,34 @@ dbdma_alloc(bus_dma_tag_t dmat, int size)
bzero(dt, sizeof *dt);
dt->d_size = size *= sizeof(dbdma_command_t);
+ dt->d_dmat = dmat;
if ((error = bus_dmamem_alloc(dmat, size, NBPG, 0, dt->d_segs,
- 1, &nsegs, BUS_DMA_NOWAIT)) != 0) {
+ 1, &dt->d_nsegs, BUS_DMA_NOWAIT)) != 0) {
printf("dbdma: unable to allocate dma, error = %d\n", error);
- } else if ((error = bus_dmamem_map(dmat, dt->d_segs, nsegs, size,
+ } else if ((error = bus_dmamem_map(dmat, dt->d_segs, dt->d_nsegs, size,
(caddr_t *)&dt->d_addr, BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) {
printf("dbdma: unable to map dma, error = %d\n", error);
} else if ((error = bus_dmamap_create(dmat, dt->d_size, 1,
dt->d_size, 0, BUS_DMA_NOWAIT, &dt->d_map)) != 0) {
printf("dbdma: unable to create dma map, error = %d\n", error);
} else if ((error = bus_dmamap_load_raw(dmat, dt->d_map,
- dt->d_segs, nsegs, size, BUS_DMA_NOWAIT)) != 0) {
+ dt->d_segs, dt->d_nsegs, size, BUS_DMA_NOWAIT)) != 0) {
printf("dbdma: unable to load dma map, error = %d\n", error);
} else
return dt;
+ dbdma_free(dt);
+ return (NULL);
+}
+
+void
+dbdma_free(dbdma_t dt)
+{
if (dt->d_map)
- bus_dmamap_destroy(dmat, dt->d_map);
+ bus_dmamap_destroy(dt->d_dmat, dt->d_map);
if (dt->d_addr)
- bus_dmamem_unmap(dmat, (caddr_t)dt->d_addr, size);
- if (nsegs)
- bus_dmamem_free(dmat, dt->d_segs, nsegs);
+ bus_dmamem_unmap(dt->d_dmat, (caddr_t)dt->d_addr, dt->d_size);
+ if (dt->d_nsegs)
+ bus_dmamem_free(dt->d_dmat, dt->d_segs, dt->d_nsegs);
free(dt, M_DEVBUF);
-
- return (NULL);
}
diff --git a/sys/arch/macppc/dev/dbdma.h b/sys/arch/macppc/dev/dbdma.h
index dad8dda54a4..922533017bc 100644
--- a/sys/arch/macppc/dev/dbdma.h
+++ b/sys/arch/macppc/dev/dbdma.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: dbdma.h,v 1.3 2002/09/06 13:35:00 drahn Exp $ */
+/* $OpenBSD: dbdma.h,v 1.4 2006/01/13 19:25:44 miod Exp $ */
/* $NetBSD: dbdma.h,v 1.2 1998/08/21 16:13:28 tsubai Exp $ */
/*
@@ -221,10 +221,12 @@ typedef volatile struct dbdma_regmap dbdma_regmap_t;
/* DBDMA routines */
typedef
struct dbdma_desc {
+ bus_dma_tag_t d_dmat;
bus_dmamap_t d_map;
dbdma_command_t *d_addr;
#define d_paddr d_segs->ds_addr
bus_dma_segment_t d_segs[1];
+ int d_nsegs;
size_t d_size;
} *dbdma_t;
diff --git a/sys/arch/macppc/dev/wdc_obio.c b/sys/arch/macppc/dev/wdc_obio.c
index b96184253fd..0c7d9ab3af4 100644
--- a/sys/arch/macppc/dev/wdc_obio.c
+++ b/sys/arch/macppc/dev/wdc_obio.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: wdc_obio.c,v 1.23 2004/10/17 08:58:56 grange Exp $ */
+/* $OpenBSD: wdc_obio.c,v 1.24 2006/01/13 19:25:45 miod Exp $ */
/* $NetBSD: wdc_obio.c,v 1.15 2001/07/25 20:26:33 bouyer Exp $ */
/*-
@@ -73,6 +73,11 @@ struct wdc_obio_softc {
dbdma_regmap_t *sc_dmareg;
dbdma_command_t *sc_dmacmd;
dbdma_t sc_dbdma;
+
+ void *sc_ih;
+ int sc_use_dma;
+ bus_size_t sc_cmdsize;
+ size_t sc_dmasize;
};
u_int8_t wdc_obio_read_reg(struct channel_softc *, enum wdc_regs);
@@ -89,9 +94,11 @@ struct channel_softc_vtbl wdc_obio_vtbl = {
int wdc_obio_probe(struct device *, void *, void *);
void wdc_obio_attach(struct device *, struct device *, void *);
+int wdc_obio_detach(struct device *, int);
struct cfattach wdc_obio_ca = {
- sizeof(struct wdc_obio_softc), wdc_obio_probe, wdc_obio_attach
+ sizeof(struct wdc_obio_softc), wdc_obio_probe, wdc_obio_attach,
+ wdc_obio_detach, wdcactivate
};
int wdc_obio_dma_init(void *, int, int, void *, size_t, int);
@@ -128,12 +135,12 @@ wdc_obio_attach(struct device *parent, struct device *self, void *aux)
struct wdc_obio_softc *sc = (void *)self;
struct confargs *ca = aux;
struct channel_softc *chp = &sc->wdc_channel;
- int intr, error, use_dma = 0;
+ int intr, error;
bus_addr_t cmdbase;
- bus_size_t cmdsize;
+ sc->sc_use_dma = 0;
if (ca->ca_nreg >= 16 || ca->ca_nintr == -1)
- use_dma = 1; /* Enable dma */
+ sc->sc_use_dma = 1; /* Enable dma */
sc->sc_dmat = ca->ca_dmat;
if ((error = bus_dmamap_create(sc->sc_dmat,
@@ -154,7 +161,7 @@ wdc_obio_attach(struct device *parent, struct device *self, void *aux)
return;
}
- if (use_dma)
+ if (sc->sc_use_dma)
printf(": DMA");
printf("\n");
@@ -163,10 +170,10 @@ wdc_obio_attach(struct device *parent, struct device *self, void *aux)
chp->_vtbl = &wdc_obio_vtbl;
cmdbase = ca->ca_reg[0];
- cmdsize = ca->ca_reg[1];
+ sc->sc_cmdsize = ca->ca_reg[1];
- if (bus_space_map(chp->cmd_iot, cmdbase, cmdsize, 0, &chp->cmd_ioh) ||
- bus_space_subregion(chp->cmd_iot, chp->cmd_ioh,
+ if (bus_space_map(chp->cmd_iot, cmdbase, sc->sc_cmdsize, 0,
+ &chp->cmd_ioh) || bus_space_subregion(chp->cmd_iot, chp->cmd_ioh,
/* WDC_AUXREG_OFFSET<<4 */ 0x160, 1, &chp->ctl_ioh)) {
printf("%s: couldn't map registers\n",
sc->sc_wdcdev.sc_dev.dv_xname);
@@ -175,16 +182,16 @@ wdc_obio_attach(struct device *parent, struct device *self, void *aux)
chp->data32iot = chp->cmd_iot;
chp->data32ioh = chp->cmd_ioh;
- mac_intr_establish(parent, intr, IST_LEVEL, IPL_BIO, wdcintr, chp,
- sc->sc_wdcdev.sc_dev.dv_xname);
+ sc->sc_ih = mac_intr_establish(parent, intr, IST_LEVEL, IPL_BIO,
+ wdcintr, chp, sc->sc_wdcdev.sc_dev.dv_xname);
sc->sc_wdcdev.set_modes = wdc_obio_adjust_timing;
- if (use_dma) {
+ if (sc->sc_use_dma) {
sc->sc_dbdma = dbdma_alloc(sc->sc_dmat, WDC_DMALIST_MAX + 1);
sc->sc_dmacmd = sc->sc_dbdma->d_addr;
sc->sc_dmareg = mapiodev(ca->ca_baseaddr + ca->ca_reg[2],
- ca->ca_reg[3]);
+ sc->sc_dmasize = ca->ca_reg[3]);
sc->sc_wdcdev.cap |= WDC_CAPABILITY_DMA;
sc->sc_wdcdev.DMA_cap = 2;
@@ -226,6 +233,30 @@ wdc_obio_attach(struct device *parent, struct device *self, void *aux)
wdc_print_current_modes(chp);
}
+int
+wdc_obio_detach(struct device *self, int flags)
+{
+ struct wdc_obio_softc *sc = (struct wdc_obio_softc *)self;
+ struct channel_softc *chp = &sc->wdc_channel;
+ int error;
+
+ if ((error = wdcdetach(chp, flags)) != 0)
+ return (error);
+
+ free(chp->ch_queue, M_DEVBUF);
+
+ if (sc->sc_use_dma) {
+ unmapiodev((void *)sc->sc_dmareg, sc->sc_dmasize);
+ dbdma_free(sc->sc_dbdma);
+ }
+ mac_intr_disestablish(NULL, sc->sc_ih);
+
+ bus_space_unmap(chp->cmd_iot, chp->cmd_ioh, sc->sc_cmdsize);
+ bus_dmamap_destroy(sc->sc_dmat, sc->sc_dmamap);
+
+ return (0);
+}
+
/* Multiword DMA transfer timings */
struct ide_timings {
int cycle; /* minimum cycle time [ns] */