summaryrefslogtreecommitdiff
path: root/sys/dev/pci
diff options
context:
space:
mode:
authorJonathan Gray <jsg@cvs.openbsd.org>2009-10-05 20:01:41 +0000
committerJonathan Gray <jsg@cvs.openbsd.org>2009-10-05 20:01:41 +0000
commitdd45a3275d4b23dbeb5221af6552cfd89867cb30 (patch)
tree62f6de1327bcba864eb51de0fc4d951b520a8339 /sys/dev/pci
parent29452034d1c8798d9724795177c9678f7f7913ad (diff)
Add some minimalistic detach/unmap bits for pciide,
done using a chipset unmap callback. Still needs to work to distinguish between compat register mappings and compat interrupts so we don't get caught out. Tested with a diskless sii3112 CardBus eSATA controller by me, and testing and feedback by deraadt@ with a phison based expresscard SSD.
Diffstat (limited to 'sys/dev/pci')
-rw-r--r--sys/dev/pci/pciide.c99
-rw-r--r--sys/dev/pci/pciidevar.h16
2 files changed, 110 insertions, 5 deletions
diff --git a/sys/dev/pci/pciide.c b/sys/dev/pci/pciide.c
index fe224f6b17d..6afcf51c379 100644
--- a/sys/dev/pci/pciide.c
+++ b/sys/dev/pci/pciide.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pciide.c,v 1.299 2009/09/29 17:51:07 deraadt Exp $ */
+/* $OpenBSD: pciide.c,v 1.300 2009/10/05 20:01:40 jsg Exp $ */
/* $NetBSD: pciide.c,v 1.127 2001/08/03 01:31:08 tsutsui Exp $ */
/*
@@ -1228,13 +1228,14 @@ const struct pciide_vendor_desc pciide_vendors[] = {
int pciide_match(struct device *, void *, void *);
void pciide_attach(struct device *, struct device *, void *);
+int pciide_detach(struct device *, int);
struct cfattach pciide_pci_ca = {
- sizeof(struct pciide_softc), pciide_match, pciide_attach
+ sizeof(struct pciide_softc), pciide_match, pciide_attach, pciide_detach,
};
struct cfattach pciide_jmb_ca = {
- sizeof(struct pciide_softc), pciide_match, pciide_attach
+ sizeof(struct pciide_softc), pciide_match, pciide_attach, pciide_detach,
};
struct cfdriver pciide_cd = {
@@ -1354,6 +1355,18 @@ pciide_attach(struct device *parent, struct device *self, void *aux)
}
int
+pciide_detach(struct device *self, int flags)
+{
+ struct pciide_softc *sc = (struct pciide_softc *)self;
+ if (sc->chip_unmap == NULL)
+ panic("unmap not yet implemented for this chipset");
+ else
+ sc->chip_unmap(sc, flags);
+
+ return 0;
+}
+
+int
pciide_mapregs_compat(struct pci_attach_args *pa, struct pciide_channel *cp,
int compatchan, bus_size_t *cmdsizep, bus_size_t *ctlsizep)
{
@@ -1393,6 +1406,12 @@ pciide_mapregs_compat(struct pci_attach_args *pa, struct pciide_channel *cp,
}
int
+pciide_unmapregs_compat(struct pciide_softc *sc, struct pciide_channel *cp)
+{
+ panic("unmapregs_compat not implemented");
+}
+
+int
pciide_mapregs_native(struct pci_attach_args *pa, struct pciide_channel *cp,
bus_size_t *cmdsizep, bus_size_t *ctlsizep, int (*pci_intr)(void *))
{
@@ -1428,6 +1447,7 @@ pciide_mapregs_native(struct pci_attach_args *pa, struct pciide_channel *cp,
}
}
cp->ih = sc->sc_pci_ih;
+ sc->sc_pc = pa->pa_pc;
maptype = pci_mapreg_type(pa->pa_pc, pa->pa_tag,
PCIIDE_REG_CMD_BASE(wdc_cp->channel));
@@ -1468,9 +1488,30 @@ pciide_mapregs_native(struct pci_attach_args *pa, struct pciide_channel *cp,
bus_space_unmap(wdc_cp->cmd_iot, cp->ctl_baseioh, *ctlsizep);
return (0);
}
+ wdc_cp->cmd_iosz = *cmdsizep;
+ wdc_cp->ctl_iosz = *ctlsizep;
+
return (1);
}
+int
+pciide_unmapregs_native(struct pciide_softc *sc, struct pciide_channel *cp)
+{
+ struct channel_softc *wdc_cp = &cp->wdc_channel;
+
+ bus_space_unmap(wdc_cp->cmd_iot, wdc_cp->cmd_ioh, wdc_cp->cmd_iosz);
+
+ /* Unmap the whole control space, not just the sub-region */
+ bus_space_unmap(wdc_cp->ctl_iot, cp->ctl_baseioh, wdc_cp->ctl_iosz);
+
+ if (sc->sc_pci_ih != NULL) {
+ pci_intr_disestablish(sc->sc_pc, sc->sc_pci_ih);
+ sc->sc_pci_ih = NULL;
+ }
+
+ return (0);
+}
+
void
pciide_mapreg_dma(struct pciide_softc *sc, struct pci_attach_args *pa)
{
@@ -1516,7 +1557,8 @@ pciide_mapreg_dma(struct pciide_softc *sc, struct pci_attach_args *pa)
case PCI_MAPREG_MEM_TYPE_32BIT:
sc->sc_dma_ok = (pci_mapreg_map(pa,
PCIIDE_REG_BUS_MASTER_DMA, maptype, 0,
- &sc->sc_dma_iot, &sc->sc_dma_ioh, NULL, NULL, 0) == 0);
+ &sc->sc_dma_iot, &sc->sc_dma_ioh, NULL, &sc->sc_dma_iosz,
+ 0) == 0);
sc->sc_dmat = pa->pa_dmat;
if (sc->sc_dma_ok == 0) {
printf(", unused (couldn't map registers)");
@@ -1535,6 +1577,12 @@ pciide_mapreg_dma(struct pciide_softc *sc, struct pci_attach_args *pa)
}
}
+void
+pciide_unmapreg_dma(struct pciide_softc *sc)
+{
+ bus_space_unmap(sc->sc_dma_iot, sc->sc_dma_ioh, sc->sc_dma_iosz);
+}
+
int
pciide_intr_flag(struct pciide_channel *cp)
{
@@ -1929,6 +1977,14 @@ pciide_chansetup(struct pciide_softc *sc, int channel, pcireg_t interface)
return (1);
}
+void
+pciide_chanfree(struct pciide_softc *sc, int channel)
+{
+ struct pciide_channel *cp = &sc->pciide_channels[channel];
+ if (cp->wdc_channel.ch_queue)
+ free(cp->wdc_channel.ch_queue, M_DEVBUF);
+}
+
/* some common code used by several chip channel_map */
void
pciide_mapchan(struct pci_attach_args *pa, struct pciide_channel *cp,
@@ -1950,6 +2006,19 @@ pciide_mapchan(struct pci_attach_args *pa, struct pciide_channel *cp,
wdcattach(wdc_cp);
}
+void
+pciide_unmap_chan(struct pciide_softc *sc, struct pciide_channel *cp, int flags)
+{
+ struct channel_softc *wdc_cp = &cp->wdc_channel;
+
+ wdcdetach(wdc_cp, flags);
+
+ if (cp->compat != 0)
+ pciide_unmapregs_compat(sc, cp);
+ else
+ pciide_unmapregs_native(sc, cp);
+}
+
/*
* Generic code to call to know if a channel can be disabled. Return 1
* if channel can be disabled, 0 if not
@@ -2169,6 +2238,24 @@ next:
}
void
+default_chip_unmap(struct pciide_softc *sc, int flags)
+{
+ struct pciide_channel *cp;
+ int channel;
+
+ for (channel = 0; channel < sc->sc_wdcdev.nchannels; channel++) {
+ cp = &sc->pciide_channels[channel];
+ pciide_unmap_chan(sc, cp, flags);
+ pciide_chanfree(sc, channel);
+ }
+
+ pciide_unmapreg_dma(sc);
+
+ if (sc->sc_cookie)
+ free(sc->sc_cookie, M_DEVBUF);
+}
+
+void
sata_chip_map(struct pciide_softc *sc, struct pci_attach_args *pa)
{
struct pciide_channel *cp;
@@ -3876,6 +3963,8 @@ sii3112_chip_map(struct pciide_softc *sc, struct pci_attach_args *pa)
sc->sc_cookie = malloc(sizeof(*sl), M_DEVBUF, M_NOWAIT | M_ZERO);
sl = sc->sc_cookie;
+ sc->chip_unmap = default_chip_unmap;
+
#define SII3112_RESET_BITS \
(SCS_CMD_PBM_RESET | SCS_CMD_ARB_RESET | \
SCS_CMD_FF1_RESET | SCS_CMD_FF0_RESET | \
@@ -8502,6 +8591,8 @@ phison_chip_map(struct pciide_softc *sc, struct pci_attach_args *pa)
bus_size_t cmdsize, ctlsize;
u_int32_t conf;
+ sc->chip_unmap = default_chip_unmap;
+
printf(": DMA");
pciide_mapreg_dma(sc, pa);
diff --git a/sys/dev/pci/pciidevar.h b/sys/dev/pci/pciidevar.h
index fb7d3591388..9de332aaa6f 100644
--- a/sys/dev/pci/pciidevar.h
+++ b/sys/dev/pci/pciidevar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pciidevar.h,v 1.18 2009/01/04 10:37:40 jsg Exp $ */
+/* $OpenBSD: pciidevar.h,v 1.19 2009/10/05 20:01:40 jsg Exp $ */
/* $NetBSD: pciidevar.h,v 1.6 2001/01/12 16:04:00 bouyer Exp $ */
/*
@@ -60,6 +60,7 @@ struct pciide_softc {
int sc_dma_ok; /* bus-master DMA info */
bus_space_tag_t sc_dma_iot;
bus_space_handle_t sc_dma_ioh;
+ bus_size_t sc_dma_iosz;
bus_dma_tag_t sc_dmat;
/*
@@ -71,6 +72,8 @@ struct pciide_softc {
/* Chip description */
const struct pciide_product_desc *sc_pp;
+ /* unmap/detach */
+ void (*chip_unmap)(struct pciide_softc *, int);
/* Chip revision */
int sc_rev;
/* common definitions */
@@ -157,6 +160,17 @@ void pciide_irqack(struct channel_softc *);
void pciide_print_modes(struct pciide_channel *);
void pciide_print_channels(int, pcireg_t);
+void default_chip_unmap(struct pciide_softc *, int);
+void pciide_unmapreg_dma(struct pciide_softc *);
+void pciide_chanfree(struct pciide_softc *, int);
+void pciide_unmap_chan(struct pciide_softc *, struct pciide_channel *, int);
+int pciide_unmapregs_compat(struct pciide_softc *,
+ struct pciide_channel *);
+int pciide_unmapregs_native(struct pciide_softc *,
+ struct pciide_channel *);
+int pciide_dma_table_free(struct pciide_softc *, int, int);
+void pciide_channel_dma_free(struct pciide_channel *);
+
/*
* Functions defined by machine-dependent code.
*/