Change the kernel dev_t, representing a pointer to a specinfo structure,
[dragonfly.git] / sys / dev / raid / aac / aac.c
index 4bfacb1..82be80d 100644 (file)
@@ -27,7 +27,7 @@
  * SUCH DAMAGE.
  *
  *     $FreeBSD: src/sys/dev/aac/aac.c,v 1.9.2.14 2003/04/08 13:22:08 scottl Exp $
- *     $DragonFly: src/sys/dev/raid/aac/aac.c,v 1.16 2004/09/15 16:23:51 joerg Exp $
+ *     $DragonFly: src/sys/dev/raid/aac/aac.c,v 1.26 2006/09/10 01:26:35 dillon Exp $
  */
 
 /*
@@ -191,23 +191,12 @@ static int                aac_query_disk(struct aac_softc *sc, caddr_t uptr);
 
 #define AAC_CDEV_MAJOR 150
 
-static struct cdevsw aac_cdevsw = {
-       "aac",                  /* name */
-       AAC_CDEV_MAJOR,         /* major */
-       0,                      /* flags */
-       NULL,                   /* port */
-       NULL,                   /* clone */
-
-       aac_open,               /* open */
-       aac_close,              /* close */
-       noread,                 /* read */
-       nowrite,                /* write */
-       aac_ioctl,              /* ioctl */
-       aac_poll,               /* poll */
-       nommap,                 /* mmap */
-       nostrategy,             /* strategy */
-       nodump,                 /* dump */
-       nopsize                 /* psize */
+static struct dev_ops aac_ops = {
+       { "aac", AAC_CDEV_MAJOR, 0 },
+       .d_open =       aac_open,
+       .d_close =      aac_close,
+       .d_ioctl =      aac_ioctl,
+       .d_poll =       aac_poll,
 };
 
 DECLARE_DUMMY_MODULE(aac);
@@ -287,6 +276,7 @@ aac_attach(struct aac_softc *sc)
 
        sc->aac_ich.ich_func = aac_startup;
        sc->aac_ich.ich_arg = sc;
+       sc->aac_ich.ich_desc = "aac";
        if (config_intrhook_establish(&sc->aac_ich) != 0) {
                device_printf(sc->aac_dev,
                              "can't establish configuration hook\n");
@@ -297,8 +287,8 @@ aac_attach(struct aac_softc *sc)
         * Make the control device.
         */
        unit = device_get_unit(sc->aac_dev);
-       cdevsw_add(&aac_cdevsw, -1, unit);
-       sc->aac_dev_t = make_dev(&aac_cdevsw, unit, UID_ROOT, GID_WHEEL, 0644,
+       dev_ops_add(&aac_ops, -1, unit);
+       sc->aac_dev_t = make_dev(&aac_ops, unit, UID_ROOT, GID_WHEEL, 0644,
                                 "aac%d", unit);
 #if defined(__FreeBSD__) && __FreeBSD_version > 500005
        (void)make_dev_alias(sc->aac_dev_t, "afa%d", unit);
@@ -339,8 +329,8 @@ aac_startup(void *arg)
        struct aac_fib *fib;
        struct aac_mntinfo *mi;
        struct aac_mntinforesp *mir = NULL;
-       int i = 0;
-
+       int count = 0, i = 0;
+       
        debug_called(1);
 
        sc = (struct aac_softc *)arg;
@@ -360,14 +350,18 @@ aac_startup(void *arg)
                mi->MntCount = i;
                if (aac_sync_fib(sc, ContainerCommand, 0, fib,
                                 sizeof(struct aac_mntinfo))) {
-                       debug(2, "error probing container %d", i);
+                       device_printf(sc->aac_dev,
+                           "error probing container %d", i);
+
                        continue;
                }
 
                mir = (struct aac_mntinforesp *)&fib->data[0];
+               /* XXX Need to check if count changed */
+               count = mir->MntRespCount;
                aac_add_container(sc, mir, 0);
                i++;
-       } while ((i < mir->MntRespCount) && (i < AAC_MAX_CONTAINERS));
+       } while ((i < count) && (i < AAC_MAX_CONTAINERS));
 
        aac_release_sync_fib(sc);
 
@@ -472,7 +466,7 @@ aac_free(struct aac_softc *sc)
                bus_release_resource(sc->aac_dev, SYS_RES_MEMORY,
                                     sc->aac_regs_rid, sc->aac_regs_resource);
        }
-       cdevsw_remove(&aac_cdevsw, -1, device_get_unit(sc->aac_dev));
+       dev_ops_remove(&aac_ops, -1, device_get_unit(sc->aac_dev));
 }
 
 /*
@@ -530,13 +524,12 @@ aac_shutdown(device_t dev)
        struct aac_softc *sc;
        struct aac_fib *fib;
        struct aac_close_command *cc;
-       int s;
 
        debug_called(1);
 
        sc = device_get_softc(dev);
 
-       s = splbio();
+       crit_enter();
 
        sc->aac_state |= AAC_STATE_SUSPEND;
 
@@ -574,7 +567,7 @@ aac_shutdown(device_t dev)
 
        AAC_MASK_INTERRUPTS(sc);
 
-       splx(s);
+       crit_exit();
        return(0);
 }
 
@@ -585,18 +578,17 @@ int
 aac_suspend(device_t dev)
 {
        struct aac_softc *sc;
-       int s;
 
        debug_called(1);
 
        sc = device_get_softc(dev);
 
-       s = splbio();
+       crit_enter();
 
        sc->aac_state |= AAC_STATE_SUSPEND;
        
        AAC_MASK_INTERRUPTS(sc);
-       splx(s);
+       crit_exit();
        return(0);
 }
 
@@ -878,18 +870,17 @@ aac_complete(void *context, int pending)
  * Handle a bio submitted from a disk device.
  */
 void
-aac_submit_bio(struct bio *bp)
+aac_submit_bio(struct aac_disk *ad, struct bio *bio)
 {
-       struct aac_disk *ad;
        struct aac_softc *sc;
 
        debug_called(2);
 
-       ad = (struct aac_disk *)bp->bio_dev->si_drv1;
+       bio->bio_driver_info = ad;
        sc = ad->ad_controller;
 
        /* queue the BIO and try to get some work done */
-       aac_enqueue_bio(sc, bp);
+       aac_enqueue_bio(sc, bio);
        aac_startio(sc);
 }
 
@@ -904,22 +895,24 @@ aac_bio_command(struct aac_softc *sc, struct aac_command **cmp)
        struct aac_blockread *br;
        struct aac_blockwrite *bw;
        struct aac_disk *ad;
-       struct bio *bp;
+       struct bio *bio;
+       struct buf *bp;
 
        debug_called(2);
 
        /* get the resources we will need */
        cm = NULL;
-       if ((bp = aac_dequeue_bio(sc)) == NULL)
+       if ((bio = aac_dequeue_bio(sc)) == NULL)
                goto fail;
        if (aac_alloc_command(sc, &cm)) /* get a command */
                goto fail;
 
        /* fill out the command */
-       cm->cm_data = (void *)bp->bio_data;
-       cm->cm_datalen = bp->bio_bcount;
+       bp = bio->bio_buf;
+       cm->cm_data = (void *)bp->b_data;
+       cm->cm_datalen = bp->b_bcount;
        cm->cm_complete = aac_bio_complete;
-       cm->cm_private = bp;
+       cm->cm_private = bio;
        cm->cm_timestamp = time_second;
        cm->cm_queue = AAC_ADAP_NORM_CMD_QUEUE;
 
@@ -938,13 +931,13 @@ aac_bio_command(struct aac_softc *sc, struct aac_command **cmp)
        fib->Header.Size = sizeof(struct aac_fib_header);
 
        /* build the read/write request */
-       ad = (struct aac_disk *)bp->bio_dev->si_drv1;
-       if (BIO_IS_READ(bp)) {
+       ad = (struct aac_disk *)bio->bio_driver_info;
+       if (bp->b_cmd == BUF_CMD_READ) {
                br = (struct aac_blockread *)&fib->data[0];
                br->Command = VM_CtBlockRead;
                br->ContainerId = ad->ad_container->co_mntobj.ObjectId;
-               br->BlockNumber = bp->bio_pblkno;
-               br->ByteCount = bp->bio_bcount;
+               br->BlockNumber = bio->bio_offset / AAC_BLOCK_SIZE;
+               br->ByteCount = bp->b_bcount;
                fib->Header.Size += sizeof(struct aac_blockread);
                cm->cm_sgtable = &br->SgMap;
                cm->cm_flags |= AAC_CMD_DATAIN;
@@ -952,8 +945,8 @@ aac_bio_command(struct aac_softc *sc, struct aac_command **cmp)
                bw = (struct aac_blockwrite *)&fib->data[0];
                bw->Command = VM_CtBlockWrite;
                bw->ContainerId = ad->ad_container->co_mntobj.ObjectId;
-               bw->BlockNumber = bp->bio_pblkno;
-               bw->ByteCount = bp->bio_bcount;
+               bw->BlockNumber = bio->bio_offset / AAC_BLOCK_SIZE;
+               bw->ByteCount = bp->b_bcount;
                bw->Stable = CUNSTABLE; /* XXX what's appropriate here? */
                fib->Header.Size += sizeof(struct aac_blockwrite);
                cm->cm_flags |= AAC_CMD_DATAOUT;
@@ -964,8 +957,8 @@ aac_bio_command(struct aac_softc *sc, struct aac_command **cmp)
        return(0);
 
 fail:
-       if (bp != NULL)
-               aac_enqueue_bio(sc, bp);
+       if (bio != NULL)
+               aac_enqueue_bio(sc, bio);
        if (cm != NULL)
                aac_release_command(cm);
        return(ENOMEM);
@@ -979,12 +972,15 @@ aac_bio_complete(struct aac_command *cm)
 {
        struct aac_blockread_response *brr;
        struct aac_blockwrite_response *bwr;
-       struct bio *bp;
+       struct bio *bio;
+       struct buf *bp;
+       const char *code;
        AAC_FSAStatus status;
 
        /* fetch relevant status and then release the command */
-       bp = (struct bio *)cm->cm_private;
-       if (BIO_IS_READ(bp)) {
+       bio = (struct bio *)cm->cm_private;
+       bp = bio->bio_buf;
+       if (bp->b_cmd == BUF_CMD_READ) {
                brr = (struct aac_blockread_response *)&cm->cm_fib->data[0];
                status = brr->Status;
        } else {
@@ -995,15 +991,15 @@ aac_bio_complete(struct aac_command *cm)
 
        /* fix up the bio based on status */
        if (status == ST_OK) {
-               bp->bio_resid = 0;
+               bp->b_resid = 0;
+               code = 0;
        } else {
-               bp->bio_error = EIO;
-               bp->bio_flags |= BIO_ERROR;
+               bp->b_error = EIO;
+               bp->b_flags |= B_ERROR;
                /* pass an error string out to the disk layer */
-               bp->bio_driver1 = aac_describe_code(aac_command_status_table,
-                                                   status);
+               code = aac_describe_code(aac_command_status_table, status);
        }
-       aac_biodone(bp);
+       aac_biodone(bio, code);
 }
 
 /*
@@ -1117,7 +1113,7 @@ aac_dump_complete(struct aac_softc *sc)
 static int
 aac_wait_command(struct aac_command *cm, int timeout)
 {
-       int s, error = 0;
+       int error = 0;
 
        debug_called(2);
 
@@ -1125,11 +1121,11 @@ aac_wait_command(struct aac_command *cm, int timeout)
        cm->cm_queue = AAC_ADAP_NORM_CMD_QUEUE;
        aac_enqueue_ready(cm);
        aac_startio(cm->cm_sc);
-       s = splbio();
+       crit_enter();
        while (!(cm->cm_flags & AAC_CMD_COMPLETED) && (error != EWOULDBLOCK)) {
                error = tsleep(cm, 0, "aacwait", 0);
        }
-       splx(s);
+       crit_exit();
        return(error);
 }
 
@@ -1481,7 +1477,7 @@ aac_init(struct aac_softc *sc)
                               sizeof(struct aac_fib),  /* maxsegsize */
                               BUS_DMA_ALLOCNOW,        /* flags */
                               &sc->aac_fib_dmat)) {
-               device_printf(sc->aac_dev, "can't allocate FIB DMA tag\n");;
+               device_printf(sc->aac_dev, "can't allocate FIB DMA tag\n");
                goto out;
        }
  
@@ -1795,7 +1791,7 @@ static int
 aac_enqueue_fib(struct aac_softc *sc, int queue, struct aac_command *cm)
 {
        u_int32_t pi, ci;
-       int s, error;
+       int error;
        u_int32_t fib_size;
        u_int32_t fib_addr;
 
@@ -1804,7 +1800,7 @@ aac_enqueue_fib(struct aac_softc *sc, int queue, struct aac_command *cm)
        fib_size = cm->cm_fib->Header.Size; 
        fib_addr = cm->cm_fib->Header.ReceiverFibAddress;
 
-       s = splbio();
+       crit_enter();
 
        /* get the producer/consumer indices */
        pi = sc->aac_queues->qt_qindex[queue][AAC_PRODUCER_INDEX];
@@ -1819,6 +1815,13 @@ aac_enqueue_fib(struct aac_softc *sc, int queue, struct aac_command *cm)
                error = EBUSY;
                goto out;
        }
+       /*
+        * To avoid a race with its completion interrupt, place this command on
+        * the busy queue prior to advertising it to the controller.
+        */
+       aac_enqueue_busy(cm);
+
+
 
        /* populate queue entry */
        (sc->aac_qentries[queue] + pi)->aq_fib_size = fib_size;
@@ -1827,12 +1830,6 @@ aac_enqueue_fib(struct aac_softc *sc, int queue, struct aac_command *cm)
        /* update producer index */
        sc->aac_queues->qt_qindex[queue][AAC_PRODUCER_INDEX] = pi + 1;
 
-       /*
-        * To avoid a race with its completion interrupt, place this command on
-        * the busy queue prior to advertising it to the controller.
-        */
-       aac_enqueue_busy(cm);
-
        /* notify the adapter if we know how */
        if (aac_qinfo[queue].notify != 0)
                AAC_QNOTIFY(sc, aac_qinfo[queue].notify);
@@ -1840,7 +1837,7 @@ aac_enqueue_fib(struct aac_softc *sc, int queue, struct aac_command *cm)
        error = 0;
 
 out:
-       splx(s);
+       crit_exit();
        return(error);
 }
 
@@ -1853,12 +1850,12 @@ aac_dequeue_fib(struct aac_softc *sc, int queue, u_int32_t *fib_size,
                struct aac_fib **fib_addr)
 {
        u_int32_t pi, ci;
-       int s, error;
+       int error;
        int notify;
 
        debug_called(3);
 
-       s = splbio();
+       crit_enter();
 
        /* get the producer/consumer indices */
        pi = sc->aac_queues->qt_qindex[queue][AAC_PRODUCER_INDEX];
@@ -1869,7 +1866,11 @@ aac_dequeue_fib(struct aac_softc *sc, int queue, u_int32_t *fib_size,
                error = ENOENT;
                goto out;
        }
-       
+
+       /* wrap the pi so the following test works */
+       if (pi >= aac_qinfo[queue].size)
+               pi = 0;
+
        notify = 0;
        if (ci == pi + 1)
                notify++;
@@ -1901,7 +1902,7 @@ aac_dequeue_fib(struct aac_softc *sc, int queue, u_int32_t *fib_size,
        error = 0;
 
 out:
-       splx(s);
+       crit_exit();
        return(error);
 }
 
@@ -1912,7 +1913,7 @@ static int
 aac_enqueue_response(struct aac_softc *sc, int queue, struct aac_fib *fib)
 {
        u_int32_t pi, ci;
-       int s, error;
+       int error;
        u_int32_t fib_size;
        u_int32_t fib_addr;
 
@@ -1923,7 +1924,7 @@ aac_enqueue_response(struct aac_softc *sc, int queue, struct aac_fib *fib)
        fib_addr = fib->Header.SenderFibAddress;
        fib->Header.ReceiverFibAddress = fib_addr;
 
-       s = splbio();
+       crit_enter();
 
        /* get the producer/consumer indices */
        pi = sc->aac_queues->qt_qindex[queue][AAC_PRODUCER_INDEX];
@@ -1953,7 +1954,7 @@ aac_enqueue_response(struct aac_softc *sc, int queue, struct aac_fib *fib)
        error = 0;
 
 out:
-       splx(s);
+       crit_exit();
        return(error);
 }
 
@@ -1965,10 +1966,9 @@ static void
 aac_timeout(void *xsc)
 {
        struct aac_softc *sc = xsc;
-       int s;
        struct aac_command *cm;
        time_t deadline;
-
+       int timedout, code;
 #if 0
        /* simulate an interrupt to handle possibly-missed interrupts */
        /*
@@ -1977,9 +1977,9 @@ aac_timeout(void *xsc)
         * threads in the interrupt handler at the same time!  If calling
         * is deamed neccesary in the future, proper mutexes must be used.
         */
-       s = splbio();
+       crit_enter();
        aac_intr(sc);
-       splx(s);
+       crit_exit();
 
        /* kick the I/O queue to restart it in the case of deadlock */
        aac_startio(sc);
@@ -1989,8 +1989,9 @@ aac_timeout(void *xsc)
         * traverse the busy command list, bitch about late commands once
         * only.
         */
+       timedout = 0;
        deadline = time_second - AAC_CMD_TIMEOUT;
-       s = splbio();
+       crit_enter();
        TAILQ_FOREACH(cm, &sc->aac_busy, cm_link) {
                if ((cm->cm_timestamp  < deadline)
                        /* && !(cm->cm_flags & AAC_CMD_TIMEDOUT) */) {
@@ -1999,9 +2000,18 @@ aac_timeout(void *xsc)
                                      "COMMAND %p TIMEOUT AFTER %d SECONDS\n",
                                      cm, (int)(time_second-cm->cm_timestamp));
                        AAC_PRINT_FIB(sc, cm->cm_fib);
+                       timedout++;
                }
        }
-       splx(s);
+       if (timedout) {
+               code = AAC_GET_FWSTATUS(sc);
+               if (code != AAC_UP_AND_RUNNING) {
+                       device_printf(sc->aac_dev, "WARNING! Controller is no "
+                                     "longer running! code= 0x%x\n", code);
+
+               }
+       }
+       crit_exit();
 
        /* reset the timer for next time */
        callout_reset(&sc->aac_watchdog, AAC_PERIODIC_INTERVAL * hz,
@@ -2329,8 +2339,9 @@ aac_describe_code(struct aac_code_lookup *table, u_int32_t code)
  */
 
 static int
-aac_open(dev_t dev, int flags, int fmt, d_thread_t *td)
+aac_open(struct dev_open_args *ap)
 {
+       cdev_t dev = ap->a_head.a_dev;
        struct aac_softc *sc;
 
        debug_called(2);
@@ -2347,8 +2358,9 @@ aac_open(dev_t dev, int flags, int fmt, d_thread_t *td)
 }
 
 static int
-aac_close(dev_t dev, int flags, int fmt, d_thread_t *td)
+aac_close(struct dev_close_args *ap)
 {
+       cdev_t dev = ap->a_head.a_dev;
        struct aac_softc *sc;
 
        debug_called(2);
@@ -2362,15 +2374,17 @@ aac_close(dev_t dev, int flags, int fmt, d_thread_t *td)
 }
 
 static int
-aac_ioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, d_thread_t *td)
+aac_ioctl(struct dev_ioctl_args *ap)
 {
+       cdev_t dev = ap->a_head.a_dev;
+       caddr_t arg = ap->a_data;
        struct aac_softc *sc = dev->si_drv1;
        int error = 0;
        int i;
 
        debug_called(2);
 
-       if (cmd == AACIO_STATS) {
+       if (ap->a_cmd == AACIO_STATS) {
                union aac_statrequest *as = (union aac_statrequest *)arg;
 
                switch (as->as_item) {
@@ -2391,7 +2405,7 @@ aac_ioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, d_thread_t *td)
 
        arg = *(caddr_t *)arg;
 
-       switch (cmd) {
+       switch (ap->a_cmd) {
        /* AACIO_STATS already handled above */
        case FSACTL_SENDFIB:
                debug(1, "FSACTL_SENDFIB");
@@ -2443,7 +2457,7 @@ aac_ioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, d_thread_t *td)
                error = 0;
                break;
        default:
-               debug(1, "unsupported cmd 0x%lx\n", cmd);
+               debug(1, "unsupported cmd 0x%lx\n", ap->a_cmd);
                error = EINVAL;
                break;
        }
@@ -2451,8 +2465,9 @@ aac_ioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, d_thread_t *td)
 }
 
 static int
-aac_poll(dev_t dev, int poll_events, d_thread_t *td)
+aac_poll(struct dev_poll_args *ap)
 {
+       cdev_t dev = ap->a_head.a_dev;
        struct aac_softc *sc;
        int revents;
 
@@ -2460,18 +2475,18 @@ aac_poll(dev_t dev, int poll_events, d_thread_t *td)
        revents = 0;
 
        AAC_LOCK_ACQUIRE(&sc->aac_aifq_lock);
-       if ((poll_events & (POLLRDNORM | POLLIN)) != 0) {
+       if ((ap->a_events & (POLLRDNORM | POLLIN)) != 0) {
                if (sc->aac_aifq_tail != sc->aac_aifq_head)
-                       revents |= poll_events & (POLLIN | POLLRDNORM);
+                       revents |= ap->a_events & (POLLIN | POLLRDNORM);
        }
        AAC_LOCK_RELEASE(&sc->aac_aifq_lock);
 
        if (revents == 0) {
-               if (poll_events & (POLLIN | POLLRDNORM))
-                       selrecord(td, &sc->rcv_select);
+               if (ap->a_events & (POLLIN | POLLRDNORM))
+                       selrecord(curthread, &sc->rcv_select);
        }
-
-       return (revents);
+       ap->a_events = revents;
+       return (0);
 }
 
 /*
@@ -2551,7 +2566,7 @@ aac_handle_aif(struct aac_softc *sc, struct aac_fib *fib)
        struct aac_mntinforesp *mir = NULL;
        u_int16_t rsize;
        int next, found;
-       int added = 0, i = 0;
+       int count = 0, added = 0, i = 0;
 
        debug_called(2);
 
@@ -2586,11 +2601,15 @@ aac_handle_aif(struct aac_softc *sc, struct aac_fib *fib)
                                rsize = sizeof(mir);
                                if (aac_sync_fib(sc, ContainerCommand, 0, fib,
                                                 sizeof(struct aac_mntinfo))) {
-                                       debug(2, "Error probing container %d\n",
-                                             i);
+                                       device_printf(sc->aac_dev,
+                                           "Error probing container %d\n", i);
+
                                        continue;
                                }
                                mir = (struct aac_mntinforesp *)&fib->data[0];
+                               /* XXX Need to check if count changed */
+                               count = mir->MntRespCount;
+
                                /*
                                 * Check the container against our list.
                                 * co->co_found was already set to 0 in a
@@ -2625,8 +2644,7 @@ aac_handle_aif(struct aac_softc *sc, struct aac_fib *fib)
                                        added = 1;
                                }
                                i++;
-                       } while ((i < mir->MntRespCount) &&
-                                (i < AAC_MAX_CONTAINERS));
+                       } while ((i < count) && (i < AAC_MAX_CONTAINERS));
                        aac_release_sync_fib(sc);
 
                        /*
@@ -2736,7 +2754,7 @@ static int
 aac_getnext_aif(struct aac_softc *sc, caddr_t arg)
 {
        struct get_adapter_fib_ioctl agf;
-       int error, s;
+       int error;
 
        debug_called(2);
 
@@ -2749,7 +2767,7 @@ aac_getnext_aif(struct aac_softc *sc, caddr_t arg)
                        error = EFAULT;
                } else {
        
-                       s = splbio();
+                       crit_enter();
                        error = aac_return_aif(sc, agf.AifFib);
        
                        if ((error == EAGAIN) && (agf.Wait)) {
@@ -2763,7 +2781,7 @@ aac_getnext_aif(struct aac_softc *sc, caddr_t arg)
                                }
                                sc->aac_state &= ~AAC_STATE_AIF_SLEEPER;
                        }
-               splx(s);
+                       crit_exit();
                }
        }
        return(error);