summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Gray <jsg@cvs.openbsd.org>2008-04-08 12:20:32 +0000
committerJonathan Gray <jsg@cvs.openbsd.org>2008-04-08 12:20:32 +0000
commitccf2ce30e45cf5040831618d665bbd74527afa1c (patch)
treed75d96b5db29668c018e8c8852adab8e840549c9
parentf2dca634ba56d133ead0fd8a9d8cfa297d493af2 (diff)
Make ahci detachable. Not tested as the ppb on my shitty nvidia
board doesn't seem to properly propagate expresscard interrupts. Incoporating suggestions from dlg and kettenis, ok dlg.
-rw-r--r--sys/dev/pci/ahci.c65
1 files changed, 46 insertions, 19 deletions
diff --git a/sys/dev/pci/ahci.c b/sys/dev/pci/ahci.c
index 5138abaa268..c057ce481e2 100644
--- a/sys/dev/pci/ahci.c
+++ b/sys/dev/pci/ahci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ahci.c,v 1.136 2007/11/28 16:01:34 dlg Exp $ */
+/* $OpenBSD: ahci.c,v 1.137 2008/04/08 12:20:31 jsg Exp $ */
/*
* Copyright (c) 2006 David Gwynne <dlg@openbsd.org>
@@ -383,6 +383,7 @@ struct ahci_softc {
struct device sc_dev;
void *sc_ih;
+ pci_chipset_tag_t *sc_pc;
bus_space_tag_t sc_iot;
bus_space_handle_t sc_ioh;
@@ -433,13 +434,20 @@ static const struct ahci_device ahci_devices[] = {
int ahci_pci_match(struct device *, void *, void *);
void ahci_pci_attach(struct device *, struct device *,
void *);
+int ahci_pci_detach(struct device *, int);
struct cfattach ahci_pci_ca = {
- sizeof(struct ahci_softc), ahci_pci_match, ahci_pci_attach
+ sizeof(struct ahci_softc),
+ ahci_pci_match,
+ ahci_pci_attach,
+ ahci_pci_detach
};
struct cfattach ahci_jmb_ca = {
- sizeof(struct ahci_softc), ahci_pci_match, ahci_pci_attach
+ sizeof(struct ahci_softc),
+ ahci_pci_match,
+ ahci_pci_attach,
+ ahci_pci_detach
};
struct cfdriver ahci_cd = {
@@ -449,14 +457,10 @@ struct cfdriver ahci_cd = {
int ahci_map_regs(struct ahci_softc *,
struct pci_attach_args *);
-void ahci_unmap_regs(struct ahci_softc *,
- struct pci_attach_args *);
+void ahci_unmap_regs(struct ahci_softc *);
int ahci_map_intr(struct ahci_softc *,
struct pci_attach_args *, pci_intr_handle_t);
-#ifdef notyet
-void ahci_unmap_intr(struct ahci_softc *,
- struct pci_attach_args *);
-#endif
+void ahci_unmap_intr(struct ahci_softc *);
int ahci_init(struct ahci_softc *);
int ahci_port_alloc(struct ahci_softc *, u_int);
@@ -618,6 +622,8 @@ ahci_pci_attach(struct device *parent, struct device *self, void *aux)
u_int32_t cap, pi;
int i;
+ sc->sc_pc = pa->pa_pc;
+
ad = ahci_lookup_device(pa);
if (ad != NULL && ad->ad_attach != NULL) {
if (ad->ad_attach(sc, pa) != 0) {
@@ -742,17 +748,41 @@ noccc:
return;
freeports:
- for (i = 0; i < AHCI_MAX_PORTS; i++)
+ for (i = 0; i < AHCI_MAX_PORTS; i++) {
if (sc->sc_ports[i] != NULL)
ahci_port_free(sc, i);
+ }
unmap:
/* Disable controller */
ahci_write(sc, AHCI_REG_GHC, 0);
- ahci_unmap_regs(sc, pa);
+ ahci_unmap_regs(sc);
return;
}
int
+ahci_pci_detach(struct device *self, int flags)
+{
+ struct ahci_softc *sc = (struct ahci_softc *)self;
+ int rv, i;
+
+ if (sc->sc_atascsi != NULL) {
+ rv = atascsi_detach(sc->sc_atascsi, flags);
+ if (rv != 0)
+ return (rv);
+ }
+
+ for (i = 0; i < AHCI_MAX_PORTS; i++) {
+ if (sc->sc_ports[i] != NULL)
+ ahci_port_free(sc, i);
+ }
+
+ ahci_unmap_intr(sc);
+ ahci_unmap_regs(sc);
+
+ return (0);
+}
+
+int
ahci_map_regs(struct ahci_softc *sc, struct pci_attach_args *pa)
{
pcireg_t maptype;
@@ -768,7 +798,7 @@ ahci_map_regs(struct ahci_softc *sc, struct pci_attach_args *pa)
}
void
-ahci_unmap_regs(struct ahci_softc *sc, struct pci_attach_args *pa)
+ahci_unmap_regs(struct ahci_softc *sc)
{
bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
sc->sc_ios = 0;
@@ -778,7 +808,7 @@ int
ahci_map_intr(struct ahci_softc *sc, struct pci_attach_args *pa,
pci_intr_handle_t ih)
{
- sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_BIO,
+ sc->sc_ih = pci_intr_establish(sc->sc_pc, ih, IPL_BIO,
ahci_intr, sc, DEVNAME(sc));
if (sc->sc_ih == NULL) {
printf("%s: unable to map interrupt\n", DEVNAME(sc));
@@ -788,14 +818,11 @@ ahci_map_intr(struct ahci_softc *sc, struct pci_attach_args *pa,
return (0);
}
-#ifdef notyet
-/* one day we'll have hotplug pci */
void
-ahci_unmap_intr(struct ahci_softc *sc, struct pci_attach_args *pa)
+ahci_unmap_intr(struct ahci_softc *sc)
{
- pci_intr_disestablish(pa->pa_pc, sc->sc_ih);
+ pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
}
-#endif
int
ahci_init(struct ahci_softc *sc)
@@ -1604,7 +1631,7 @@ ahci_intr(void *arg)
/* Read global interrupt status */
is = ahci_read(sc, AHCI_REG_IS);
- if (is == 0)
+ if (is == 0 || is == 0xffffffff)
return (0);
ack = is;