summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authordyoung <dyoung@NetBSD.org>2009-07-16 01:01:46 +0000
committerdyoung <dyoung@NetBSD.org>2009-07-16 01:01:46 +0000
commit78500bdfd5135ebd1c1bb068b241d92d5d2e3d49 (patch)
tree11fff5f41bef343f2140be3e479590fa6070cae1 /sys/dev
parent569aa0de8b282a491d8d02eb4e74247bdb5df174 (diff)
Add a rudimentary detachment hook for mfi(4).
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ic/mfi.c85
-rw-r--r--sys/dev/ic/mfivar.h7
-rw-r--r--sys/dev/pci/mfi_pci.c44
3 files changed, 122 insertions, 14 deletions
diff --git a/sys/dev/ic/mfi.c b/sys/dev/ic/mfi.c
index aacc91fe758..b4607bd82a2 100644
--- a/sys/dev/ic/mfi.c
+++ b/sys/dev/ic/mfi.c
@@ -1,4 +1,4 @@
-/* $NetBSD: mfi.c,v 1.23 2009/05/12 14:25:17 cegger Exp $ */
+/* $NetBSD: mfi.c,v 1.24 2009/07/16 01:01:47 dyoung Exp $ */
/* $OpenBSD: mfi.c,v 1.66 2006/11/28 23:59:45 dlg Exp $ */
/*
* Copyright (c) 2006 Marco Peereboom <marco@peereboom.us>
@@ -17,7 +17,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mfi.c,v 1.23 2009/05/12 14:25:17 cegger Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mfi.c,v 1.24 2009/07/16 01:01:47 dyoung Exp $");
#include "bio.h"
@@ -104,17 +104,20 @@ static int mfi_ioctl_setstate(struct mfi_softc *,
struct bioc_setstate *);
static int mfi_bio_hs(struct mfi_softc *, int, int, void *);
static int mfi_create_sensors(struct mfi_softc *);
+static int mfi_destroy_sensors(struct mfi_softc *);
static void mfi_sensor_refresh(struct sysmon_envsys *,
envsys_data_t *);
#endif /* NBIO > 0 */
static uint32_t mfi_xscale_fw_state(struct mfi_softc *sc);
static void mfi_xscale_intr_ena(struct mfi_softc *sc);
+static void mfi_xscale_intr_dis(struct mfi_softc *sc);
static int mfi_xscale_intr(struct mfi_softc *sc);
static void mfi_xscale_post(struct mfi_softc *sc, struct mfi_ccb *ccb);
static const struct mfi_iop_ops mfi_iop_xscale = {
mfi_xscale_fw_state,
+ mfi_xscale_intr_dis,
mfi_xscale_intr_ena,
mfi_xscale_intr,
mfi_xscale_post
@@ -122,11 +125,13 @@ static const struct mfi_iop_ops mfi_iop_xscale = {
static uint32_t mfi_ppc_fw_state(struct mfi_softc *sc);
static void mfi_ppc_intr_ena(struct mfi_softc *sc);
+static void mfi_ppc_intr_dis(struct mfi_softc *sc);
static int mfi_ppc_intr(struct mfi_softc *sc);
static void mfi_ppc_post(struct mfi_softc *sc, struct mfi_ccb *ccb);
static const struct mfi_iop_ops mfi_iop_ppc = {
mfi_ppc_fw_state,
+ mfi_ppc_intr_dis,
mfi_ppc_intr_ena,
mfi_ppc_intr,
mfi_ppc_post
@@ -134,6 +139,7 @@ static const struct mfi_iop_ops mfi_iop_ppc = {
#define mfi_fw_state(_s) ((_s)->sc_iop->mio_fw_state(_s))
#define mfi_intr_enable(_s) ((_s)->sc_iop->mio_intr_ena(_s))
+#define mfi_intr_disable(_s) ((_s)->sc_iop->mio_intr_dis(_s))
#define mfi_my_intr(_s) ((_s)->sc_iop->mio_intr(_s))
#define mfi_post(_s, _c) ((_s)->sc_iop->mio_post((_s), (_c)))
@@ -180,6 +186,28 @@ mfi_put_ccb(struct mfi_ccb *ccb)
}
static int
+mfi_destroy_ccb(struct mfi_softc *sc)
+{
+ struct mfi_ccb *ccb;
+ uint32_t i;
+
+ DNPRINTF(MFI_D_CCB, "%s: mfi_init_ccb\n", DEVNAME(sc));
+
+
+ for (i = 0; (ccb = mfi_get_ccb(sc)) != NULL; i++) {
+ /* create a dma map for transfer */
+ bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap);
+ }
+
+ if (i < sc->sc_max_cmds)
+ return EBUSY;
+
+ free(sc->sc_ccb, M_DEVBUF);
+
+ return 0;
+}
+
+static int
mfi_init_ccb(struct mfi_softc *sc)
{
struct mfi_ccb *ccb;
@@ -601,6 +629,37 @@ mfiminphys(struct buf *bp)
}
int
+mfi_detach(struct mfi_softc *sc, int flags)
+{
+ int error;
+
+ DNPRINTF(MFI_D_MISC, "%s: mfi_detach\n", DEVNAME(sc));
+
+#if NBIO > 0
+ mfi_destroy_sensors(sc);
+ bio_unregister(&sc->sc_dev);
+#endif /* NBIO > 0 */
+
+ mfi_intr_disable(sc);
+
+ if ((error = config_detach_children(&sc->sc_dev, flags)) != 0)
+ return error;
+
+ /* TBD: shutdown firmware */
+
+ if ((error = mfi_destroy_ccb(sc)) != 0)
+ return error;
+
+ mfi_freemem(sc, sc->sc_sense);
+
+ mfi_freemem(sc, sc->sc_frames);
+
+ mfi_freemem(sc, sc->sc_pcq);
+
+ return 0;
+}
+
+int
mfi_attach(struct mfi_softc *sc, enum mfi_iop iop)
{
struct scsipi_adapter *adapt = &sc->sc_adapt;
@@ -1879,6 +1938,14 @@ freeme:
}
static int
+mfi_destroy_sensors(struct mfi_softc *sc)
+{
+ sysmon_envsys_unregister(sc->sc_sme);
+ free(sc->sc_sensor, M_DEVBUF);
+ return 0;
+}
+
+static int
mfi_create_sensors(struct mfi_softc *sc)
{
int i;
@@ -1976,6 +2043,12 @@ mfi_xscale_fw_state(struct mfi_softc *sc)
}
static void
+mfi_xscale_intr_dis(struct mfi_softc *sc)
+{
+ mfi_write(sc, MFI_OMSK, 0);
+}
+
+static void
mfi_xscale_intr_ena(struct mfi_softc *sc)
{
mfi_write(sc, MFI_OMSK, MFI_ENABLE_INTR);
@@ -2016,6 +2089,14 @@ mfi_ppc_fw_state(struct mfi_softc *sc)
}
static void
+mfi_ppc_intr_dis(struct mfi_softc *sc)
+{
+ /* Taking a wild guess --dyoung */
+ mfi_write(sc, MFI_OMSK, ~(uint32_t)0x0);
+ mfi_write(sc, MFI_ODC, 0xffffffff);
+}
+
+static void
mfi_ppc_intr_ena(struct mfi_softc *sc)
{
mfi_write(sc, MFI_ODC, 0xffffffff);
diff --git a/sys/dev/ic/mfivar.h b/sys/dev/ic/mfivar.h
index 19112d56df8..83efcc711d0 100644
--- a/sys/dev/ic/mfivar.h
+++ b/sys/dev/ic/mfivar.h
@@ -1,4 +1,4 @@
-/* $NetBSD: mfivar.h,v 1.10 2008/06/24 10:09:24 gmcgarry Exp $ */
+/* $NetBSD: mfivar.h,v 1.11 2009/07/16 01:01:47 dyoung Exp $ */
/* $OpenBSD: mfivar.h,v 1.28 2006/08/31 18:18:46 marco Exp $ */
/*
* Copyright (c) 2006 Marco Peereboom <marco@peereboom.us>
@@ -103,6 +103,7 @@ enum mfi_iop {
struct mfi_iop_ops {
uint32_t (*mio_fw_state)(struct mfi_softc *);
+ void (*mio_intr_dis)(struct mfi_softc *);
void (*mio_intr_ena)(struct mfi_softc *);
int (*mio_intr)(struct mfi_softc *);
void (*mio_post)(struct mfi_softc *, struct mfi_ccb *);
@@ -122,6 +123,7 @@ struct mfi_softc {
bus_space_tag_t sc_iot;
bus_space_handle_t sc_ioh;
bus_dma_tag_t sc_dmat;
+ bus_size_t sc_size;
/* save some useful information for logical drives that is missing
* in sc_ld_list
@@ -161,5 +163,6 @@ struct mfi_softc {
};
-int mfi_attach(struct mfi_softc *sc, enum mfi_iop);
+int mfi_attach(struct mfi_softc *, enum mfi_iop);
+int mfi_detach(struct mfi_softc *, int);
int mfi_intr(void *);
diff --git a/sys/dev/pci/mfi_pci.c b/sys/dev/pci/mfi_pci.c
index dcb88d4d14b..692417cc360 100644
--- a/sys/dev/pci/mfi_pci.c
+++ b/sys/dev/pci/mfi_pci.c
@@ -1,4 +1,4 @@
-/* $NetBSD: mfi_pci.c,v 1.8 2009/05/12 08:23:01 cegger Exp $ */
+/* $NetBSD: mfi_pci.c,v 1.9 2009/07/16 01:01:46 dyoung Exp $ */
/* $OpenBSD: mfi_pci.c,v 1.11 2006/08/06 04:40:08 brad Exp $ */
/*
* Copyright (c) 2006 Marco Peereboom <marco@peereboom.us>
@@ -17,7 +17,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mfi_pci.c,v 1.8 2009/05/12 08:23:01 cegger Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mfi_pci.c,v 1.9 2009/07/16 01:01:46 dyoung Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -40,12 +40,18 @@ __KERNEL_RCSID(0, "$NetBSD: mfi_pci.c,v 1.8 2009/05/12 08:23:01 cegger Exp $");
#define MFI_BAR 0x10
#define MFI_PCI_MEMSIZE 0x2000 /* 8k */
+struct mfi_pci_softc {
+ struct mfi_softc psc_sc;
+ pci_chipset_tag_t psc_pc;
+};
+
const struct mfi_pci_device *mfi_pci_find_device(struct pci_attach_args *);
int mfi_pci_match(device_t, cfdata_t, void *);
void mfi_pci_attach(device_t, device_t, void *);
+int mfi_pci_detach(device_t, int);
-CFATTACH_DECL(mfi_pci, sizeof(struct mfi_softc),
- mfi_pci_match, mfi_pci_attach, NULL, NULL);
+CFATTACH_DECL(mfi_pci, sizeof(struct mfi_pci_softc),
+ mfi_pci_match, mfi_pci_attach, mfi_pci_detach, NULL);
struct mfi_pci_subtype {
pcireg_t st_vendor;
@@ -117,24 +123,42 @@ mfi_pci_match(device_t parent, cfdata_t match, void *aux)
return (mfi_pci_find_device(aux) != NULL) ? 1 : 0;
}
+int
+mfi_pci_detach(device_t self, int flags)
+{
+ struct mfi_pci_softc *psc = device_private(self);
+ struct mfi_softc *sc = &psc->psc_sc;
+ int error;
+
+ if ((error = mfi_detach(sc, flags)) != 0)
+ return error;
+
+ /* xxx */
+ pci_intr_disestablish(psc->psc_pc, sc->sc_ih);
+ bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_size);
+ return 0;
+}
+
void
mfi_pci_attach(device_t parent, device_t self, void *aux)
{
- struct mfi_softc *sc = device_private(self);
+ struct mfi_pci_softc *psc = device_private(self);
+ struct mfi_softc *sc = &psc->psc_sc;
struct pci_attach_args *pa = aux;
const struct mfi_pci_device *mpd;
const struct mfi_pci_subtype *st;
const char *intrstr;
pci_intr_handle_t ih;
- bus_size_t size;
pcireg_t csr;
const char *subtype = NULL;
uint32_t subsysid;
+ psc->psc_pc = pa->pa_pc;
+
csr = pci_mapreg_type(pa->pa_pc, pa->pa_tag, MFI_BAR);
csr |= PCI_MAPREG_MEM_TYPE_32BIT;
if (pci_mapreg_map(pa, MFI_BAR, csr, 0,
- &sc->sc_iot, &sc->sc_ioh, NULL, &size)) {
+ &sc->sc_iot, &sc->sc_ioh, NULL, &sc->sc_size)) {
aprint_error(": can't map controller pci space\n");
return;
}
@@ -143,7 +167,7 @@ mfi_pci_attach(device_t parent, device_t self, void *aux)
if (pci_intr_map(pa, &ih)) {
aprint_error(": can't map interrupt\n");
- bus_space_unmap(sc->sc_iot, sc->sc_ioh, size);
+ bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_size);
return;
}
intrstr = pci_intr_string(pa->pa_pc, ih);
@@ -153,7 +177,7 @@ mfi_pci_attach(device_t parent, device_t self, void *aux)
if (intrstr)
aprint_error(" at %s", intrstr);
aprint_error("\n");
- bus_space_unmap(sc->sc_iot, sc->sc_ioh, size);
+ bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_size);
return;
}
@@ -180,6 +204,6 @@ mfi_pci_attach(device_t parent, device_t self, void *aux)
aprint_error("%s: can't attach", DEVNAME(sc));
pci_intr_disestablish(pa->pa_pc, sc->sc_ih);
sc->sc_ih = NULL;
- bus_space_unmap(sc->sc_iot, sc->sc_ioh, size);
+ bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_size);
}
}