Author: mjacob
Date: Sat Aug  4 00:00:30 2012
New Revision: 239023
URL: http://svn.freebsd.org/changeset/base/239023

Log:
  Add detach logic to SBus variant.
  
  Obtained from:        Marius
  MFC after:    1 month

Modified:
  head/sys/dev/isp/isp_sbus.c

Modified: head/sys/dev/isp/isp_sbus.c
==============================================================================
--- head/sys/dev/isp/isp_sbus.c Fri Aug  3 20:30:40 2012        (r239022)
+++ head/sys/dev/isp/isp_sbus.c Sat Aug  4 00:00:30 2012        (r239023)
@@ -78,19 +78,22 @@ static struct ispmdvec mdvec = {
 
 static int isp_sbus_probe (device_t);
 static int isp_sbus_attach (device_t);
+static int isp_sbus_detach (device_t);
 
 
 #define        ISP_SBD(isp)    ((struct isp_sbussoftc *)isp)->sbus_dev
 struct isp_sbussoftc {
        ispsoftc_t                      sbus_isp;
        device_t                        sbus_dev;
-       struct resource *               sbus_reg;
+       struct resource *               regs;
+       void *                          irq;
+       int                             iqd;
+       int                             rgd;
        void *                          ih;
        int16_t                         sbus_poff[_NREG_BLKS];
        sdparam                         sbus_param;
        struct isp_spi                  sbus_spi;
        struct ispmdvec                 sbus_mdvec;
-       struct resource *               sbus_ires;
 };
 
 
@@ -98,6 +101,7 @@ static device_method_t isp_sbus_methods[
        /* Device interface */
        DEVMETHOD(device_probe,         isp_sbus_probe),
        DEVMETHOD(device_attach,        isp_sbus_attach),
+       DEVMETHOD(device_detach,        isp_sbus_detach),
        { 0, 0 }
 };
 
@@ -136,13 +140,21 @@ isp_sbus_probe(device_t dev)
 static int
 isp_sbus_attach(device_t dev)
 {
-       struct resource *regs;
-       int tval, iqd, isp_debug, role, rid, ispburst, default_id;
+       int tval, isp_debug, role, ispburst, default_id;
        struct isp_sbussoftc *sbs;
        ispsoftc_t *isp = NULL;
        int locksetup = 0;
        int ints_setup = 0;
 
+       sbs = device_get_softc(dev);
+       if (sbs == NULL) {
+               device_printf(dev, "cannot get softc\n");
+               return (ENOMEM);
+       }
+
+       sbs->sbus_dev = dev;
+       sbs->sbus_mdvec = mdvec;
+
        /*
         * Figure out if we're supposed to skip this one.
         * If we are, we actually go to ISP_ROLE_NONE.
@@ -165,23 +177,15 @@ isp_sbus_attach(device_t dev)
                role = ISP_DEFAULT_ROLES;
        }
 
-       sbs = malloc(sizeof (*sbs), M_DEVBUF, M_NOWAIT | M_ZERO);
-       if (sbs == NULL) {
-               device_printf(dev, "cannot allocate softc\n");
-               return (ENOMEM);
-       }
+       sbs->irq = sbs->regs = NULL;
+       sbs->rgd = sbs->iqd = 0;
 
-       regs = NULL;
-       iqd = 0;
-       rid = 0;
-       regs = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
-       if (regs == 0) {
+       sbs->regs = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sbs->rgd,
+           RF_ACTIVE);
+       if (sbs->regs == NULL) {
                device_printf(dev, "unable to map registers\n");
                goto bad;
        }
-       sbs->sbus_dev = dev;
-       sbs->sbus_reg = regs;
-       sbs->sbus_mdvec = mdvec;
 
        sbs->sbus_poff[BIU_BLOCK >> _BLK_REG_SHFT] = BIU_REGS_OFF;
        sbs->sbus_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = SBUS_MBOX_REGS_OFF;
@@ -189,8 +193,8 @@ isp_sbus_attach(device_t dev)
        sbs->sbus_poff[RISC_BLOCK >> _BLK_REG_SHFT] = SBUS_RISC_REGS_OFF;
        sbs->sbus_poff[DMA_BLOCK >> _BLK_REG_SHFT] = DMA_REGS_OFF;
        isp = &sbs->sbus_isp;
-       isp->isp_bus_tag = rman_get_bustag(regs);
-       isp->isp_bus_handle = rman_get_bushandle(regs);
+       isp->isp_bus_tag = rman_get_bustag(sbs->regs);
+       isp->isp_bus_handle = rman_get_bushandle(sbs->regs);
        isp->isp_mdvec = &sbs->sbus_mdvec;
        isp->isp_bustype = ISP_BT_SBUS;
        isp->isp_type = ISP_HA_SCSI_UNKNOWN;
@@ -244,7 +248,6 @@ isp_sbus_attach(device_t dev)
                SDPARAM(isp, 0)->isp_ptisp = 1;
        }
 
-
        isp->isp_osinfo.fw = firmware_get("isp_1000");
        if (isp->isp_osinfo.fw) {
                union {
@@ -280,16 +283,15 @@ isp_sbus_attach(device_t dev)
        mtx_init(&isp->isp_osinfo.lock, "isp", NULL, MTX_DEF);
        locksetup++;
 
-       iqd = 0;
-       sbs->sbus_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &iqd,
+       sbs->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sbs->iqd,
            RF_ACTIVE | RF_SHAREABLE);
-       if (sbs->sbus_ires == NULL) {
+       if (sbs->irq == NULL) {
                device_printf(dev, "could not allocate interrupt\n");
                goto bad;
        }
 
-       if (isp_setup_intr(dev, sbs->sbus_ires, ISP_IFLAGS, NULL,
-           isp_platform_intr, isp, &sbs->ih)) {
+       if (isp_setup_intr(dev, sbs->irq, ISP_IFLAGS, NULL, isp_platform_intr,
+           isp, &sbs->ih)) {
                device_printf(dev, "could not setup interrupt\n");
                goto bad;
        }
@@ -333,25 +335,49 @@ isp_sbus_attach(device_t dev)
 bad:
 
        if (sbs && ints_setup) {
-               (void) bus_teardown_intr(dev, sbs->sbus_ires, sbs->ih);
+               (void) bus_teardown_intr(dev, sbs->irq, sbs->ih);
        }
 
-       if (sbs && sbs->sbus_ires) {
-               bus_release_resource(dev, SYS_RES_IRQ, iqd, sbs->sbus_ires);
+       if (sbs && sbs->irq) {
+               bus_release_resource(dev, SYS_RES_IRQ, sbs->iqd, sbs->irq);
        }
 
        if (locksetup && isp) {
                mtx_destroy(&isp->isp_osinfo.lock);
        }
 
-       if (regs) {
-               (void) bus_release_resource(dev, SYS_RES_MEMORY, 0, regs);
+       if (sbs->regs) {
+               (void) bus_release_resource(dev, SYS_RES_MEMORY, sbs->rgd,
+                   sbs->regs);
        }
+       return (ENXIO);
+}
 
-       if (sbs) {
-               free(sbs, M_DEVBUF);
+static int
+isp_sbus_detach(device_t dev)
+{
+       struct isp_sbussoftc *sbs;
+       ispsoftc_t *isp;
+       int status;
+
+       sbs = device_get_softc(dev);
+       if (sbs == NULL) {
+               return (ENXIO);
        }
-       return (ENXIO);
+       isp = (ispsoftc_t *) sbs;
+       status = isp_detach(isp);
+       if (status)
+               return (status);
+       ISP_LOCK(isp);
+       isp_uninit(isp);
+       if (sbs->ih) {
+               (void) bus_teardown_intr(dev, sbs->irq, sbs->ih);
+       }
+       ISP_UNLOCK(isp);
+       mtx_destroy(&isp->isp_osinfo.lock);
+       (void) bus_release_resource(dev, SYS_RES_IRQ, sbs->iqd, sbs->irq);
+       (void) bus_release_resource(dev, SYS_RES_MEMORY, sbs->rgd, sbs->regs);
+       return (0);
 }
 
 #define        IspVirt2Off(a, x)       \
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to