Port a major reworking of the way IPS driver commands are managed from
authorMatthew Dillon <dillon@dragonflybsd.org>
Tue, 9 Aug 2005 16:23:13 +0000 (16:23 +0000)
committerMatthew Dillon <dillon@dragonflybsd.org>
Tue, 9 Aug 2005 16:23:13 +0000 (16:23 +0000)
FreeBSD.

Submitted-by: YONETANI Tomokazu <qhwt+dfly@les.ath.cx>
Testing-by: =?ISO-8859-2?Q?Toma=BE_Bor=B9tnar?= <tomaz.borstnar@amis.net>
sys/dev/raid/ips/ips.c
sys/dev/raid/ips/ips.h
sys/dev/raid/ips/ips_commands.c
sys/dev/raid/ips/ips_disk.c
sys/dev/raid/ips/ips_ioctl.c
sys/dev/raid/ips/ips_pci.c

index b747908..4a75027 100644 (file)
@@ -25,7 +25,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/dev/ips/ips.c,v 1.12 2004/05/30 04:01:29 scottl Exp $
- * $DragonFly: src/sys/dev/raid/ips/ips.c,v 1.11 2005/06/07 00:51:13 y0netan1 Exp $
+ * $DragonFly: src/sys/dev/raid/ips/ips.c,v 1.12 2005/08/09 16:23:13 dillon Exp $
  */
 
 #include <dev/raid/ips/ips.h>
@@ -112,7 +112,7 @@ ips_cmd_dmaload(void *cmdptr, bus_dma_segment_t *segments, int segnum,
 }
 
 /* is locking needed? what locking guarentees are there on removal? */
-static __inline__ int
+static int
 ips_cmdqueue_free(ips_softc_t *sc)
 {
        int i, error = -1;
@@ -129,24 +129,34 @@ ips_cmdqueue_free(ips_softc_t *sc)
                        bus_dmamem_free(sc->command_dmatag,
                            command->command_buffer,
                            command->command_dmamap);
+                       if (command->data_dmamap != NULL)
+                               bus_dmamap_destroy(command->data_dmatag,
+                                   command->data_dmamap);
                }
                error = 0;
                sc->state |= IPS_OFFLINE;
        }
+       sc->staticcmd = NULL;
+       free(sc->commandarray, M_IPSBUF);
        crit_exit();
        return error;
 }
 
-/* places all ips command structs on the free command queue.  No locking as if someone else tries
- * to access this during init, we have bigger problems */
-static __inline__ int
+/*
+ * Places all ips command structs on the free command queue.
+ * The first slot is used exclusively for static commands
+ * No locking as if someone else tries to access this during init,
+ * we have bigger problems
+ */
+static int
 ips_cmdqueue_init(ips_softc_t *sc)
 {
        int i;
        ips_command_t *command;
 
+       sc->commandarray = malloc(sizeof(sc->commandarray[0]) * sc->max_cmds,
+           M_IPSBUF, M_INTWAIT | M_ZERO);
        SLIST_INIT(&sc->free_cmd_list);
-       STAILQ_INIT(&sc->cmd_wait_list);
        for (i = 0; i < sc->max_cmds; i++) {
                command = &sc->commandarray[i];
                command->id = i;
@@ -163,7 +173,16 @@ ips_cmdqueue_init(ips_softc_t *sc)
                            command->command_buffer, command->command_dmamap);
                        goto error;
                }
-               SLIST_INSERT_HEAD(&sc->free_cmd_list, command, next);
+
+               if (i == 0)
+                       sc->staticcmd = command;
+               else {
+                       command->data_dmatag = sc->sg_dmatag;
+                       if (bus_dmamap_create(command->data_dmatag, 0,
+                           &command->data_dmamap))
+                               goto error;
+                       SLIST_INSERT_HEAD(&sc->free_cmd_list, command, next);
+               }
        }
        sc->state &= ~IPS_OFFLINE;
        return 0;
@@ -172,67 +191,6 @@ error:
        return ENOMEM;
 }
 
-static int
-ips_add_waiting_command(ips_softc_t *sc, int (*callback)(ips_command_t *),
-    void *data)
-{
-       ips_command_t *command;
-       ips_wait_list_t *waiter;
-
-       waiter = malloc(sizeof(ips_wait_list_t), M_IPSBUF, M_INTWAIT);
-       crit_enter();
-       if (sc->state & IPS_OFFLINE) {
-               crit_exit();
-               free(waiter, M_IPSBUF);
-               return EIO;
-       }
-       command = SLIST_FIRST(&sc->free_cmd_list);
-       if (command && !(sc->state & IPS_TIMEOUT)) {
-               SLIST_REMOVE_HEAD(&sc->free_cmd_list, next);
-               sc->used_commands++;
-               crit_exit();
-               clear_ips_command(command);
-               bzero(command->command_buffer, IPS_COMMAND_LEN);
-               free(waiter, M_IPSBUF);
-               command->arg = data;
-               return callback(command);
-       }
-       DEVICE_PRINTF(1, sc->dev, "adding command to the wait queue\n");
-       waiter->callback = callback;
-       waiter->data = data;
-       STAILQ_INSERT_TAIL(&sc->cmd_wait_list, waiter, next);
-       crit_exit();
-       return 0;
-}
-
-static void
-ips_run_waiting_command(ips_softc_t *sc)
-{
-       ips_wait_list_t *waiter;
-       ips_command_t   *command;
-       int (*callback)(ips_command_t*);
-
-       crit_enter();
-       waiter = STAILQ_FIRST(&sc->cmd_wait_list);
-       command = SLIST_FIRST(&sc->free_cmd_list);
-       if (waiter == NULL || command == NULL) {
-               crit_exit();
-               return;
-       }
-       DEVICE_PRINTF(1, sc->dev, "removing command from wait queue\n");
-       SLIST_REMOVE_HEAD(&sc->free_cmd_list, next);
-       STAILQ_REMOVE_HEAD(&sc->cmd_wait_list, next);
-       sc->used_commands++;
-       crit_exit();
-       clear_ips_command(command);
-       bzero(command->command_buffer, IPS_COMMAND_LEN);
-       command->arg = waiter->data;
-       callback = waiter->callback;
-       free(waiter, M_IPSBUF);
-       callback(command);
-       return;
-}
-
 /*
  * returns a free command struct if one is available.
  * It also blanks out anything that may be a wild pointer/value.
@@ -240,30 +198,41 @@ ips_run_waiting_command(ips_softc_t *sc)
  * small so they are saved and kept dmamapped and loaded.
  */
 int
-ips_get_free_cmd(ips_softc_t *sc, int (*callback)(ips_command_t *), void *data,
-    unsigned long flags)
+ips_get_free_cmd(ips_softc_t *sc, ips_command_t **cmd, unsigned long flags)
 {
-       ips_command_t *command;
+       ips_command_t *command = NULL;
+       int error = 0;
 
        crit_enter();
        if (sc->state & IPS_OFFLINE) {
-               crit_exit();
-               return EIO;
+               error = EIO;
+               goto bail;
        }
-       command = SLIST_FIRST(&sc->free_cmd_list);
-       if (!command || (sc->state & IPS_TIMEOUT)) {
-               crit_exit();
-               if (flags & IPS_NOWAIT_FLAG)
-                       return EAGAIN;
-               return ips_add_waiting_command(sc, callback, data);
+       if ((flags & IPS_STATIC_FLAG) != 0) {
+               if (sc->state & IPS_STATIC_BUSY) {
+                       error = EAGAIN;
+                       goto bail;
+               }
+               command = sc->staticcmd;
+               sc->state |= IPS_STATIC_BUSY;
+       } else {
+               command = SLIST_FIRST(&sc->free_cmd_list);
+               if (!command || (sc->state & IPS_TIMEOUT)) {
+                       error = EBUSY;
+                       goto bail;
+               }
+               SLIST_REMOVE_HEAD(&sc->free_cmd_list, next);
+               sc->used_commands++;
        }
-       SLIST_REMOVE_HEAD(&sc->free_cmd_list, next);
-       sc->used_commands++;
+bail:
        crit_exit();
-       clear_ips_command(command);
+       if (error != 0)
+               return error;
+
+       bzero(&command->status, (char *)(command + 1) - (char *)(&command->status));
        bzero(command->command_buffer, IPS_COMMAND_LEN);
-       command->arg = data;
-       return callback(command);
+       *cmd = command;
+       return 0;
 }
 
 /* adds a command back to the free command queue */
@@ -271,12 +240,15 @@ void
 ips_insert_free_cmd(ips_softc_t *sc, ips_command_t *command)
 {
        crit_enter();
-       SLIST_INSERT_HEAD(&sc->free_cmd_list, command, next);
-       sc->used_commands--;
+       if (command == sc->staticcmd)
+               sc->state &= ~IPS_STATIC_BUSY;
+       else {
+               SLIST_INSERT_HEAD(&sc->free_cmd_list, command, next);
+               sc->used_commands--;
+       }
        crit_exit();
-       if (!(sc->state & IPS_TIMEOUT))
-               ips_run_waiting_command(sc);
 }
+
 static const char *
 ips_diskdev_statename(u_int8_t state)
 {
@@ -362,8 +334,8 @@ ips_timeout(void *arg)
        ips_softc_t *sc = arg;
        int i, state = 0;
 
+       lwkt_exlock(&sc->queue_lock, __func__);
        command = &sc->commandarray[0];
-       crit_enter();
        for (i = 0; i < sc->max_cmds; i++) {
                if (!command[i].timeout)
                        continue;
@@ -392,11 +364,10 @@ ips_timeout(void *arg)
                         */
                } else
                        sc->state &= ~IPS_TIMEOUT;
-               ips_run_waiting_command(sc);
        }
        if (sc->state != IPS_OFFLINE)
                callout_reset(&sc->timer, 10 * hz, ips_timeout, sc);
-       crit_exit();
+       lwkt_exunlock(&sc->queue_lock);
 }
 
 /* check card and initialize it */
@@ -579,21 +550,22 @@ ips_adapter_free(ips_softc_t *sc)
        return 0;
 }
 
-void
-ips_morpheus_intr(void *void_sc)
+static int
+ips_morpheus_check_intr(void *void_sc)
 {
        ips_softc_t *sc = (ips_softc_t *)void_sc;
        u_int32_t oisr, iisr;
        ips_cmd_status_t status;
        ips_command_t *command;
        int cmdnumber;
+       int found = 0;
 
        iisr =ips_read_4(sc, MORPHEUS_REG_IISR);
        oisr =ips_read_4(sc, MORPHEUS_REG_OISR);
        PRINTF(9, "interrupt registers in:%x out:%x\n", iisr, oisr);
        if (!(oisr & MORPHEUS_BIT_CMD_IRQ)) {
                DEVICE_PRINTF(2, sc->dev, "got a non-command irq\n");
-               return;
+               return(0);
        }
        while ((status.value = ips_read_4(sc, MORPHEUS_REG_OQPR))
               != 0xffffffff) {
@@ -603,8 +575,19 @@ ips_morpheus_intr(void *void_sc)
                command->timeout = 0;
                command->callback(command);
                DEVICE_PRINTF(9, sc->dev, "got command %d\n", cmdnumber);
+               found = 1;
        }
-       return;
+       return(found);
+}
+
+void
+ips_morpheus_intr(void *void_sc)
+{
+       ips_softc_t *sc = void_sc;
+
+       lwkt_exlock(&sc->queue_lock, __func__);
+       ips_morpheus_check_intr(sc);
+       lwkt_exunlock(&sc->queue_lock);
 }
 
 void
@@ -623,6 +606,18 @@ ips_issue_morpheus_cmd(ips_command_t *command)
        crit_exit();
 }
 
+void
+ips_morpheus_poll(ips_command_t *command)
+{
+       uint32_t ts;
+
+       ts = time_second + command->timeout;
+       while (command->timeout != 0 &&
+           ips_morpheus_check_intr(command->sc) == 0 &&
+           (ts > time_second))
+               DELAY(1000);
+ }
+
 static void
 ips_copperhead_queue_callback(void *queueptr, bus_dma_segment_t *segments,
                              int segnum, int error)
@@ -776,6 +771,7 @@ ips_copperhead_intr(void *void_sc)
        ips_cmd_status_t status;
        int cmdnumber;
 
+       lwkt_exlock(&sc->queue_lock, __func__);
        while (ips_read_1(sc, COPPER_REG_HISR) & COPPER_SCE_BIT) {
                status.value = ips_copperhead_cmd_status(sc);
                cmdnumber = status.fields.command_id;
@@ -784,6 +780,7 @@ ips_copperhead_intr(void *void_sc)
                sc->commandarray[cmdnumber].callback(&(sc->commandarray[cmdnumber]));
                PRINTF(9, "ips: got command %d\n", cmdnumber);
        }
+       lwkt_exunlock(&sc->queue_lock);
        return;
 }
 
@@ -814,3 +811,9 @@ ips_issue_copperhead_cmd(ips_command_t *command)
        ips_write_2(command->sc, COPPER_REG_CCCR, COPPER_CMD_START);
        crit_exit();
 }
+
+void
+ips_copperhead_poll(ips_command_t *command)
+{
+       printf("ips: cmd polling not implemented for copperhead devices\n");
+}
index dd1c930..81e9740 100644 (file)
@@ -26,7 +26,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/dev/ips/ips.h,v 1.10 2004/05/30 20:08:34 phk Exp $
- * $DragonFly: src/sys/dev/raid/ips/ips.h,v 1.6 2005/06/07 00:52:34 y0netan1 Exp $
+ * $DragonFly: src/sys/dev/raid/ips/ips.h,v 1.7 2005/08/09 16:23:13 dillon Exp $
  */
 
 
 #include <sys/bus.h>
 #include <sys/conf.h>
 #include <sys/types.h>
+#include <sys/thread.h>
+#include <sys/thread2.h>
 #include <sys/queue.h>
 #include <sys/buf.h>
+#include <sys/buf2.h>
 #include <sys/malloc.h>
 #include <sys/time.h>
 
@@ -70,12 +73,13 @@ MALLOC_DECLARE(M_IPSBUF);
 #define IPS_MAX_SG_LEN                 (sizeof(ips_sg_element_t) * IPS_MAX_SG_ELEMENTS)
 #define IPS_NVRAM_PAGE_SIZE            128
 /* various flags */
-#define IPS_NOWAIT_FLAG                        1
+#define IPS_STATIC_FLAG                        1
 
 /* states for the card to be in */
 #define IPS_DEV_OPEN                   0x01
 #define IPS_TIMEOUT                    0x02 /* command time out, need reset */
 #define IPS_OFFLINE                    0x04 /* can't reset card/card failure */
+#define IPS_STATIC_BUSY                        0x08 /* static command slot in use */
 
 /* max number of commands set to something low for now */
 #define IPS_MAX_CMD_NUM                        128
@@ -235,9 +239,6 @@ MALLOC_DECLARE(M_IPSBUF);
 
 #define ips_read_request(iobuf)                ((iobuf)->b_flags & B_READ)
 
-/* this is ugly.  It zeros the end elements in an ips_command_t struct starting with the status element */
-#define clear_ips_command(command)     bzero(&((command)->status), (unsigned long)(&(command)[1])-(unsigned long)&((command)->status))
-
 #define COMMAND_ERROR(status)          (((status)->fields.basic_status & 0x0f) >= IPS_MIN_ERROR)
 
 #ifndef IPS_DEBUG
@@ -413,13 +414,15 @@ typedef struct ips_command {
        bus_dmamap_t            command_dmamap;
        void                    *command_buffer;
        u_int32_t               command_phys_addr;      /*WARNING! must be changed if 64bit addressing ever used*/
-       ips_cmd_status_t        status;
-       SLIST_ENTRY(ips_command)        next;
        bus_dma_tag_t           data_dmatag;
        bus_dmamap_t            data_dmamap;
+       /* members below are zero'd when handed out */
+       ips_cmd_status_t        status;
+       SLIST_ENTRY(ips_command)        next;
        void                    *data_buffer;
        void                    *arg;
        void                    (*callback)(struct ips_command *command);
+       int                     completed;
 } ips_command_t;
 
 typedef struct ips_wait_list {
@@ -455,14 +458,18 @@ typedef struct ips_softc {
        u_int8_t                next_drive;
        u_int8_t                max_cmds;
        volatile u_int8_t       used_commands;
-       ips_command_t           commandarray[IPS_MAX_CMD_NUM];
+       ips_command_t           *commandarray;
+       ips_command_t           *staticcmd;
        SLIST_HEAD(command_list, ips_command) free_cmd_list;
-       STAILQ_HEAD(command_wait_list,ips_wait_list)  cmd_wait_list;
        int                     (*ips_adapter_reinit)(struct ips_softc *sc,
                                                       int force);
        void                    (*ips_adapter_intr)(void *sc);
        void                    (*ips_issue_cmd)(ips_command_t *command);
+       void                    (*ips_poll_cmd)(ips_command_t *command);
        ips_copper_queue_t      *copper_queue;
+
+       struct lwkt_rwlock      queue_lock;
+       struct buf_queue_head   queue;
 } ips_softc_t;
 
 /* function defines from ips_ioctl.c */
@@ -473,7 +480,7 @@ extern void ipsd_finish(struct bio *iobuf);
 
 /* function defines from ips_commands.c */
 extern int ips_flush_cache(ips_softc_t *sc);
-extern void ips_start_io_request(ips_softc_t *sc, struct bio *iobuf);
+extern void ips_start_io_request(ips_softc_t *sc);
 extern int ips_get_drive_info(ips_softc_t *sc);
 extern int ips_get_adapter_info(ips_softc_t *sc);
 extern int ips_ffdc_reset(ips_softc_t *sc);
@@ -481,17 +488,20 @@ extern int ips_update_nvram(ips_softc_t *sc);
 extern int ips_clear_adapter(ips_softc_t *sc);
 
 /* function defines from ips.c */
-extern int ips_get_free_cmd(ips_softc_t *sc, int (*callback)(ips_command_t *),
-                               void *data, unsigned long flags);
+extern int ips_get_free_cmd(ips_softc_t *sc, ips_command_t **command,
+                           unsigned long flags);
 extern void ips_insert_free_cmd(ips_softc_t *sc, ips_command_t *command);
 extern int ips_adapter_init(ips_softc_t *sc);
 extern int ips_morpheus_reinit(ips_softc_t *sc, int force);
 extern int ips_adapter_free(ips_softc_t *sc);
 extern void ips_morpheus_intr(void *sc);
 extern void ips_issue_morpheus_cmd(ips_command_t *command);
+extern void ips_morpheus_poll(ips_command_t *command);
 extern int ips_copperhead_reinit(ips_softc_t *sc, int force);
 extern void ips_copperhead_intr(void *sc);
 extern void ips_issue_copperhead_cmd(ips_command_t *command);
+extern void ips_copperhead_poll(ips_command_t *command);
+int ips_timed_wait(ips_command_t *, const char *, int);
 
 #define IPS_CDEV_MAJOR 175
 #define IPSD_CDEV_MAJOR 176
index 91f1c96..34b5d6f 100644 (file)
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/dev/ips/ips_commands.c,v 1.10 2004/05/30 04:01:29 scottl Exp $
- * $DragonFly: src/sys/dev/raid/ips/ips_commands.c,v 1.8 2004/12/10 04:09:46 y0netan1 Exp $
+ * $DragonFly: src/sys/dev/raid/ips/ips_commands.c,v 1.9 2005/08/09 16:23:13 dillon Exp $
  */
 
 #include <dev/raid/ips/ips.h>
 
+int
+ips_timed_wait(ips_command_t *command, const char *id, int timo)
+{
+       int error = 0;
+
+       while (command->completed == 0) {
+               crit_enter();
+               if (command->completed == 0)
+                       error = tsleep(&command->completed, 0, id, timo);
+               crit_exit();
+               if (error == EWOULDBLOCK) {
+                       error = ETIMEDOUT;
+                       break;
+               }
+       }
+       return(error);
+}
+
 /*
  * This is an interrupt callback.  It is called from
  * interrupt context when the adapter has completed the
- * command.  This very generic callback simply stores
- * the command's return value in command->arg and wake's
- * up anyone waiting on the command.
+ * command, and wakes up anyone waiting on the command.
  */
 static void
 ips_wakeup_callback(ips_command_t *command)
 {
-       ips_cmd_status_t *status;
-
-       status = command->arg;
-       status->value = command->status.value;
        bus_dmamap_sync(command->sc->command_dmatag, command->command_dmamap,
                        BUS_DMASYNC_POSTWRITE);
-       wakeup(status);
+       command->completed = 1;
+       wakeup(&command->completed);
 }
 
 /*
@@ -68,7 +81,6 @@ ips_io_request_finish(ips_command_t *command)
                                BUS_DMASYNC_POSTWRITE);
        }
        bus_dmamap_unload(command->data_dmatag, command->data_dmamap);
-       bus_dmamap_destroy(command->data_dmatag, command->data_dmamap);
        if (COMMAND_ERROR(&command->status)) {
                iobuf->bio_flags |=BIO_ERROR;
                iobuf->bio_error = EIO;
@@ -93,7 +105,6 @@ ips_io_request_callback(void *cmdptr, bus_dma_segment_t *segments, int segnum,
        if (error) {
                printf("ips: error = %d in ips_sg_request_callback\n", error);
                bus_dmamap_unload(command->data_dmatag, command->data_dmamap);
-               bus_dmamap_destroy(command->data_dmatag, command->data_dmamap);
                iobuf->bio_flags |= BIO_ERROR;
                iobuf->bio_error = ENOMEM;
                ips_insert_free_cmd(sc, command);
@@ -153,21 +164,10 @@ ips_io_request_callback(void *cmdptr, bus_dma_segment_t *segments, int segnum,
 }
 
 static int
-ips_send_io_request(ips_command_t *command)
+ips_send_io_request(ips_command_t *command, struct buf *iobuf)
 {
-       ips_softc_t *sc = command->sc;
-       struct bio *iobuf = command->arg;
-       command->data_dmatag = sc->sg_dmatag;
-
-       if (bus_dmamap_create(command->data_dmatag, 0, &command->data_dmamap)) {
-               device_printf(sc->dev, "dmamap failed\n");
-               iobuf->bio_flags |= BIO_ERROR;
-               iobuf->bio_error = ENOMEM;
-               ips_insert_free_cmd(sc, command);
-               ipsd_finish(iobuf);
-               return 0;
-       }
        command->callback = ips_io_request_finish;
+       command->arg = iobuf;
        PRINTF(10, "ips test: : bcount %ld\n", iobuf->bio_bcount);
        bus_dmamap_load(command->data_dmatag, command->data_dmamap,
                        iobuf->bio_data, iobuf->bio_bcount,
@@ -176,16 +176,18 @@ ips_send_io_request(ips_command_t *command)
 }
 
 void
-ips_start_io_request(ips_softc_t *sc, struct bio *iobuf)
+ips_start_io_request(ips_softc_t *sc)
 {
-       if (ips_get_free_cmd(sc, ips_send_io_request, iobuf, 0)) {
-               device_printf(sc->dev, "no mem for command slots!\n");
-               iobuf->bio_flags |= BIO_ERROR;
-               iobuf->bio_error = ENOMEM;
-               ipsd_finish(iobuf);
+       ips_command_t *command;
+       struct bio *iobuf;
+
+       iobuf = bufq_first(&sc->queue);
+       if (iobuf == NULL)
                return;
-       }
-       return;
+       if (ips_get_free_cmd(sc, &command, 0) != 0)
+               return;
+       bufq_remove(&sc->queue, iobuf);
+       ips_send_io_request(command, iobuf);
 }
 
 /*
@@ -203,8 +205,7 @@ ips_adapter_info_callback(void *cmdptr, bus_dma_segment_t *segments,int segnum,
        ips_adapter_info_cmd *command_struct;
        sc = command->sc;
        if (error) {
-               ips_cmd_status_t * status = command->arg;
-               status->value = IPS_ERROR_STATUS; /* a lovely error value */
+               command->status.value = IPS_ERROR_STATUS; /* a lovely error value */
                ips_insert_free_cmd(sc, command);
                printf("ips: error = %d in ips_get_adapter_info\n", error);
                return;
@@ -225,7 +226,6 @@ static int
 ips_send_adapter_info_cmd(ips_command_t *command)
 {
        ips_softc_t *sc = command->sc;
-       ips_cmd_status_t *status = command->arg;
        int error = 0;
 
        if (bus_dma_tag_create( /* parent    */ sc->adapter_dmatag,
@@ -253,8 +253,8 @@ ips_send_adapter_info_cmd(ips_command_t *command)
        bus_dmamap_load(command->data_dmatag, command->data_dmamap,
            command->data_buffer, IPS_ADAPTER_INFO_LEN,
            ips_adapter_info_callback, command, BUS_DMA_NOWAIT);
-       if ((status->value == IPS_ERROR_STATUS) ||
-           tsleep(status, 0, "ips", 30 * hz) == EWOULDBLOCK)
+       if ((command->status.value == IPS_ERROR_STATUS) ||
+           ips_timed_wait(command, "ips", 30 * hz) != 0)
                error = ETIMEDOUT;
        if (error == 0) {
                bus_dmamap_sync(command->data_dmatag, command->data_dmamap,
@@ -275,19 +275,16 @@ exit:
 int
 ips_get_adapter_info(ips_softc_t *sc)
 {
+       ips_command_t *command;
        int error = 0;
-       ips_cmd_status_t *status;
 
-       status = malloc(sizeof(ips_cmd_status_t), M_IPSBUF, M_INTWAIT | M_ZERO);
-       if (ips_get_free_cmd(sc, ips_send_adapter_info_cmd, status,
-           IPS_NOWAIT_FLAG) > 0) {
+       if (ips_get_free_cmd(sc, &command, IPS_STATIC_FLAG) != 0) {
                device_printf(sc->dev, "unable to get adapter configuration\n");
-               free(status, M_IPSBUF);
                return ENXIO;
        }
-       if (COMMAND_ERROR(status))
+       ips_send_adapter_info_cmd(command);
+       if (COMMAND_ERROR(&command->status))
                error = ENXIO;
-       free(status, M_IPSBUF);
        return error;
 }
 
@@ -307,9 +304,8 @@ ips_drive_info_callback(void *cmdptr, bus_dma_segment_t *segments, int segnum,
 
        sc = command->sc;
        if (error) {
-               ips_cmd_status_t *status = command->arg;
 
-               status->value = IPS_ERROR_STATUS;
+               command->status.value = IPS_ERROR_STATUS;
                ips_insert_free_cmd(sc, command);
                printf("ips: error = %d in ips_get_drive_info\n", error);
                return;
@@ -330,7 +326,6 @@ ips_send_drive_info_cmd(ips_command_t *command)
 {
        int error = 0;
        ips_softc_t *sc = command->sc;
-       ips_cmd_status_t *status = command->arg;
        ips_drive_info_t *driveinfo;
 
        if (bus_dma_tag_create( /* parent    */ sc->adapter_dmatag,
@@ -358,8 +353,8 @@ ips_send_drive_info_cmd(ips_command_t *command)
        bus_dmamap_load(command->data_dmatag, command->data_dmamap,
            command->data_buffer,IPS_DRIVE_INFO_LEN,
            ips_drive_info_callback, command, BUS_DMA_NOWAIT);
-       if ((status->value == IPS_ERROR_STATUS) ||
-           tsleep(status, 0, "ips", 10 * hz) == EWOULDBLOCK)
+       if ((command->status.value == IPS_ERROR_STATUS) ||
+           ips_timed_wait(command, "ips", 10 * hz) != 0)
                error = ETIMEDOUT;
 
        if (error == 0) {
@@ -378,24 +373,21 @@ exit:
        bus_dma_tag_destroy(command->data_dmatag);
        ips_insert_free_cmd(sc, command);
        return error;
-
 }
+
 int
 ips_get_drive_info(ips_softc_t *sc)
 {
        int error = 0;
-       ips_cmd_status_t *status;
+       ips_command_t *command;
 
-       status = malloc(sizeof(ips_cmd_status_t), M_IPSBUF, M_INTWAIT | M_ZERO);
-       if (ips_get_free_cmd(sc, ips_send_drive_info_cmd, status,
-           IPS_NOWAIT_FLAG) > 0) {
-               free(status, M_IPSBUF);
+       if (ips_get_free_cmd(sc, &command, IPS_STATIC_FLAG) != 0) {
                device_printf(sc->dev, "unable to get drive configuration\n");
                return ENXIO;
        }
-       if (COMMAND_ERROR(status))
+       ips_send_drive_info_cmd(command);
+       if (COMMAND_ERROR(&command->status))
                error = ENXIO;
-       free(status, M_IPSBUF);
        return error;
 }
 
@@ -407,7 +399,6 @@ static int
 ips_send_flush_cache_cmd(ips_command_t *command)
 {
        ips_softc_t *sc = command->sc;
-       ips_cmd_status_t *status = command->arg;
        ips_generic_cmd *command_struct;
 
        PRINTF(10,"ips test: got a command, building flush command\n");
@@ -418,8 +409,8 @@ ips_send_flush_cache_cmd(ips_command_t *command)
        bus_dmamap_sync(sc->command_dmatag, command->command_dmamap,
            BUS_DMASYNC_PREWRITE);
        sc->ips_issue_cmd(command);
-       if (status->value != IPS_ERROR_STATUS)
-               tsleep(status, 0, "flush2", 0);
+       if (command->status.value != IPS_ERROR_STATUS)
+               ips_timed_wait(command, "flush2", 0);
        ips_insert_free_cmd(sc, command);
        return 0;
 }
@@ -427,23 +418,19 @@ ips_send_flush_cache_cmd(ips_command_t *command)
 int
 ips_flush_cache(ips_softc_t *sc)
 {
-       ips_cmd_status_t *status;
+       ips_command_t *command;
 
-       status = malloc(sizeof(ips_cmd_status_t), M_IPSBUF, M_INTWAIT | M_ZERO);
        device_printf(sc->dev, "flushing cache\n");
-       if (ips_get_free_cmd(sc, ips_send_flush_cache_cmd, status,
-           IPS_NOWAIT_FLAG)) {
-               free(status, M_IPSBUF);
+       if (ips_get_free_cmd(sc, &command, IPS_STATIC_FLAG) != 0) {
                device_printf(sc->dev, "ERROR: unable to get a command! "
                    "can't flush cache!\n");
-               return 1;
+               return(1);
        }
-       if (COMMAND_ERROR(status)) {
-               free(status, M_IPSBUF);
+       ips_send_flush_cache_cmd(command);
+       if (COMMAND_ERROR(&command->status)) {
                device_printf(sc->dev, "ERROR: cache flush command failed!\n");
-               return 1;
+               return(1);
        }
-       free(status, M_IPSBUF);
        return 0;
 }
 
@@ -496,7 +483,6 @@ static int
 ips_send_ffdc_reset_cmd(ips_command_t *command)
 {
        ips_softc_t *sc = command->sc;
-       ips_cmd_status_t *status = command->arg;
        ips_adapter_ffdc_cmd *command_struct;
 
        PRINTF(10, "ips test: got a command, building ffdc reset command\n");
@@ -510,8 +496,8 @@ ips_send_ffdc_reset_cmd(ips_command_t *command)
        bus_dmamap_sync(sc->command_dmatag, command->command_dmamap,
            BUS_DMASYNC_PREWRITE);
        sc->ips_issue_cmd(command);
-       if (status->value != IPS_ERROR_STATUS)
-               tsleep(status, 0, "ffdc", 0);
+       if (command->status.value != IPS_ERROR_STATUS)
+               ips_timed_wait(command, "ffdc", 0);
        ips_insert_free_cmd(sc, command);
        return 0;
 }
@@ -519,22 +505,18 @@ ips_send_ffdc_reset_cmd(ips_command_t *command)
 int
 ips_ffdc_reset(ips_softc_t *sc)
 {
-       ips_cmd_status_t *status;
+       ips_command_t *command;
 
-       status = malloc(sizeof(ips_cmd_status_t), M_IPSBUF, M_INTWAIT | M_ZERO);
-       if (ips_get_free_cmd(sc, ips_send_ffdc_reset_cmd, status,
-           IPS_NOWAIT_FLAG)) {
-               free(status, M_IPSBUF);
+       if (ips_get_free_cmd(sc, &command, IPS_STATIC_FLAG) != 0) {
                device_printf(sc->dev, "ERROR: unable to get a command! "
                    "can't send ffdc reset!\n");
                return 1;
        }
-       if (COMMAND_ERROR(status)) {
-               free(status, M_IPSBUF);
+       ips_send_ffdc_reset_cmd(command);
+       if (COMMAND_ERROR(&command->status)) {
                device_printf(sc->dev, "ERROR: ffdc reset command failed!\n");
                return 1;
        }
-       free(status, M_IPSBUF);
        return 0;
 }
 
@@ -575,9 +557,7 @@ ips_read_nvram_callback(void *cmdptr, bus_dma_segment_t *segments, int segnum,
 
        sc = command->sc;
        if (error) {
-               ips_cmd_status_t *status = command->arg;
-
-               status->value = IPS_ERROR_STATUS;
+               command->status.value = IPS_ERROR_STATUS;
                ips_insert_free_cmd(sc, command);
                printf("ips: error = %d in ips_read_nvram_callback\n", error);
                return;
@@ -601,7 +581,6 @@ ips_read_nvram(ips_command_t *command)
 {
        int error = 0;
        ips_softc_t *sc = command->sc;
-       ips_cmd_status_t *status = command->arg;
 
        if (bus_dma_tag_create( /* parent    */ sc->adapter_dmatag,
                                /* alignemnt */ 1,
@@ -628,8 +607,8 @@ ips_read_nvram(ips_command_t *command)
        bus_dmamap_load(command->data_dmatag, command->data_dmamap,
            command->data_buffer, IPS_NVRAM_PAGE_SIZE, ips_read_nvram_callback,
            command, BUS_DMA_NOWAIT);
-       if ((status->value == IPS_ERROR_STATUS) ||
-           tsleep(status, 0, "ips", 0) == EWOULDBLOCK)
+       if ((command->status.value == IPS_ERROR_STATUS) ||
+           ips_timed_wait(command, "ips", 0) != 0)
                error = ETIMEDOUT;
        if (error == 0) {
                bus_dmamap_sync(command->data_dmatag, command->data_dmamap,
@@ -647,21 +626,18 @@ exit:
 int
 ips_update_nvram(ips_softc_t *sc)
 {
-       ips_cmd_status_t *status;
+       ips_command_t *command;
 
-       status = malloc(sizeof(ips_cmd_status_t), M_IPSBUF, M_INTWAIT | M_ZERO);
-       if (ips_get_free_cmd(sc, ips_read_nvram, status, IPS_NOWAIT_FLAG)) {
-               free(status, M_IPSBUF);
+       if (ips_get_free_cmd(sc, &command, IPS_STATIC_FLAG) != 0) {
                device_printf(sc->dev, "ERROR: unable to get a command! "
                    "can't update nvram\n");
                return 1;
        }
-       if (COMMAND_ERROR(status)) {
-               free(status, M_IPSBUF);
+       ips_read_nvram(command);
+       if (COMMAND_ERROR(&command->status)) {
                device_printf(sc->dev, "ERROR: nvram update command failed!\n");
                return 1;
        }
-       free(status, M_IPSBUF);
        return 0;
 }
 
@@ -669,7 +645,6 @@ static int
 ips_send_config_sync_cmd(ips_command_t *command)
 {
        ips_softc_t *sc = command->sc;
-       ips_cmd_status_t *status = command->arg;
        ips_generic_cmd *command_struct;
 
        PRINTF(10, "ips test: got a command, building flush command\n");
@@ -681,8 +656,8 @@ ips_send_config_sync_cmd(ips_command_t *command)
        bus_dmamap_sync(sc->command_dmatag, command->command_dmamap,
            BUS_DMASYNC_PREWRITE);
        sc->ips_issue_cmd(command);
-       if (status->value != IPS_ERROR_STATUS)
-               tsleep(status, 0, "ipssyn", 0);
+       if (command->status.value != IPS_ERROR_STATUS)
+               ips_timed_wait(command, "ipssyn", 0);
        ips_insert_free_cmd(sc, command);
        return 0;
 }
@@ -691,7 +666,6 @@ static int
 ips_send_error_table_cmd(ips_command_t *command)
 {
        ips_softc_t *sc = command->sc;
-       ips_cmd_status_t *status = command->arg;
        ips_generic_cmd *command_struct;
 
        PRINTF(10, "ips test: got a command, building errortable command\n");
@@ -703,8 +677,8 @@ ips_send_error_table_cmd(ips_command_t *command)
        bus_dmamap_sync(sc->command_dmatag, command->command_dmamap,
            BUS_DMASYNC_PREWRITE);
        sc->ips_issue_cmd(command);
-       if (status->value != IPS_ERROR_STATUS)
-               tsleep(status, 0, "ipsetc", 0);
+       if (command->status.value != IPS_ERROR_STATUS)
+               ips_timed_wait(command, "ipsetc", 0);
        ips_insert_free_cmd(sc, command);
        return 0;
 }
@@ -712,35 +686,29 @@ ips_send_error_table_cmd(ips_command_t *command)
 int
 ips_clear_adapter(ips_softc_t *sc)
 {
-       ips_cmd_status_t *status;
+       ips_command_t *command;
 
-       status = malloc(sizeof(ips_cmd_status_t), M_IPSBUF, M_INTWAIT | M_ZERO);
        device_printf(sc->dev, "syncing config\n");
-       if (ips_get_free_cmd(sc, ips_send_config_sync_cmd, status,
-           IPS_NOWAIT_FLAG)) {
-               free(status, M_IPSBUF);
+       if (ips_get_free_cmd(sc, &command, IPS_STATIC_FLAG) != 0) {
                device_printf(sc->dev, "ERROR: unable to get a command! "
                    "can't sync cache!\n");
                return 1;
        }
-       if (COMMAND_ERROR(status)) {
-               free(status, M_IPSBUF);
+       ips_send_config_sync_cmd(command);
+       if (COMMAND_ERROR(&command->status)) {
                device_printf(sc->dev, "ERROR: cache sync command failed!\n");
                return 1;
        }
        device_printf(sc->dev, "clearing error table\n");
-       if (ips_get_free_cmd(sc, ips_send_error_table_cmd, status,
-           IPS_NOWAIT_FLAG)) {
-               free(status, M_IPSBUF);
+       if (ips_get_free_cmd(sc, &command, IPS_STATIC_FLAG) != 0) {
                device_printf(sc->dev, "ERROR: unable to get a command! "
                    "can't sync cache!\n");
                return 1;
        }
-       if (COMMAND_ERROR(status)) {
+       ips_send_error_table_cmd(command);
+       if (COMMAND_ERROR(&command->status)) {
                device_printf(sc->dev, "ERROR: etable command failed!\n");
-               free(status, M_IPSBUF);
                return 1;
        }
-       free(status, M_IPSBUF);
        return 0;
 }
index 6cd8214..bff05af 100644 (file)
@@ -25,7 +25,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/dev/ips/ips_disk.c,v 1.4 2003/09/22 04:59:07 njl Exp $
- * $DragonFly: src/sys/dev/raid/ips/ips_disk.c,v 1.5 2004/10/06 02:12:31 y0netan1 Exp $
+ * $DragonFly: src/sys/dev/raid/ips/ips_disk.c,v 1.6 2005/08/09 16:23:13 dillon Exp $
  */
 
 #include <sys/devicestat.h>
 #include <dev/raid/ips/ips_disk.h>
 #include <sys/stat.h>
 
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <machine/md_var.h>
+
 static int ipsd_probe(device_t dev);
 static int ipsd_attach(device_t dev);
 static int ipsd_detach(device_t dev);
 
+static int ipsd_dump_helper(dev_t dev, u_int count, u_int blkno, u_int secsize);
+#if 0
+static int ipsd_dump(void *arg, void *virtual, vm_offset_t physical, off_t offset, size_t length);
+static void ipsd_dump_map_sg(void *arg, bus_dma_segment_t *segs, int nsegs,
+                            int error);
+static void ipsd_dump_block_complete(ips_command_t *command);
+#endif
+
 static disk_open_t ipsd_open;
 static disk_close_t ipsd_close;
 static disk_strategy_t ipsd_strategy;
@@ -52,6 +64,7 @@ static struct cdevsw ipsd_cdevsw = {
        .old_strategy   = ipsd_strategy,
        .old_read       = physread,
        .old_write      = physwrite,
+       .old_dump       = ipsd_dump_helper,
 };
 
 static device_method_t ipsd_methods[] = {
@@ -110,6 +123,7 @@ ipsd_finish(struct bio *iobuf)
                iobuf->bio_resid = 0;
        devstat_end_transaction_buf(&dsc->stats, iobuf);
        biodone(iobuf);
+       ips_start_io_request(dsc->sc);
 }
 
 
@@ -122,7 +136,10 @@ ipsd_strategy(struct bio *iobuf)
        DEVICE_PRINTF(8, dsc->dev, "in strategy\n");
        iobuf->bio_driver1 = (void *)(uintptr_t)dsc->sc->drives[dsc->disk_number].drivenum;
        devstat_start_transaction(&dsc->stats);
-       ips_start_io_request(dsc->sc, iobuf);
+       lwkt_exlock(&dsc->sc->queue_lock, __func__);
+       bufq_insert_tail(&dsc->sc->queue, iobuf);
+       ips_start_io_request(dsc->sc);
+       lwkt_exunlock(&dsc->sc->queue_lock);
 }
 
 static int
@@ -195,3 +212,162 @@ ipsd_detach(device_t dev)
        return 0;
 }
 
+static int
+ipsd_dump_helper(dev_t dev, u_int count, u_int blkno, u_int secsize)
+{
+       printf("dump support for IPS not yet working, will not dump\n");
+       return (ENODEV);
+
+#if 0
+       long blkcnt;
+       caddr_t va;
+       vm_offset_t addr, a;
+       int dumppages = MAXDUMPPGS;
+       int i;
+
+       addr = 0;
+       blkcnt = howmany(PAGE_SIZE, secsize);
+       while (count > 0) {
+               va = NULL;
+               if (count / blkcnt < dumppages)
+                       dumppages = count / blkcnt;
+               for (i = 0; i < dumppages; i++) {
+                       a = addr + (i * PAGE_SIZE);
+                       if (!is_physical_memory(a))
+                               a = 0;
+                       va = pmap_kenter_temporary(trunc_page(a), i);
+               }
+
+               ipsd_dump(dev, va, 0, blkno, PAGE_SIZE * dumppages);
+               if (dumpstatus(addr, (off_t)count * DEV_BSIZE) < 0)
+                       return (EINTR);
+               blkno += blkcnt * dumppages;
+               count -= blkcnt * dumppages;
+               addr += PAGE_SIZE * dumppages;
+       }
+       return (0);
+#endif
+}
+
+#if 0
+
+static int
+ipsd_dump(void *arg, void *virtual, vm_offset_t physical, off_t offset,
+          size_t length)
+{
+       dev_t dev = arg;
+       ips_softc_t *sc;
+       ips_command_t *command;
+       ips_io_cmd *command_struct;
+       ipsdisk_softc_t *dsc;
+       off_t off;
+       uint8_t *va;
+       int len;
+       int error = 0;
+
+       dsc = dev->si_drv1;
+       if (dsc == NULL)
+               return (EINVAL);
+       sc = dsc->sc;
+
+       if (ips_get_free_cmd(sc, &command, 0) != 0) {
+               printf("ipsd: failed to get cmd for dump\n");
+               return (ENOMEM);
+       }
+
+       command->data_dmatag = sc->sg_dmatag;
+       command->callback = ipsd_dump_block_complete;
+
+       command_struct = (ips_io_cmd *)command->command_buffer;
+       command_struct->id = command->id;
+       command_struct->drivenum = sc->drives[dsc->disk_number].drivenum;
+
+       off = offset;
+       va = virtual;
+
+       while (length > 0) {
+               len = length > IPS_MAX_IO_SIZE ? IPS_MAX_IO_SIZE : length;
+               command_struct->lba = off / IPS_BLKSIZE;
+               if (bus_dmamap_load(command->data_dmatag, command->data_dmamap,
+                   va, len, ipsd_dump_map_sg, command, 0) != 0) {
+                       error = EIO;
+                       break;
+               }
+               if (COMMAND_ERROR(&command->status)) {
+                       error = EIO;
+                       break;
+               }
+
+               length -= len;
+               off += len;
+               va += len;
+       }
+       ips_insert_free_cmd(command->sc, command);
+       return(error);
+}
+
+static void
+ipsd_dump_map_sg(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
+{
+       ips_softc_t *sc;
+       ips_command_t *command;
+       ips_sg_element_t *sg_list;
+       ips_io_cmd *command_struct;
+       int i, length;
+
+       command = (ips_command_t *)arg;
+       sc = command->sc;
+       length = 0;
+
+       if (error) {
+               printf("ipsd_dump_map_sg: error %d\n", error);
+               command->status.value = IPS_ERROR_STATUS;
+               return;
+       }
+
+       command_struct = (ips_io_cmd *)command->command_buffer;
+
+       if (nsegs != 1) {
+               command_struct->segnum = nsegs;
+               sg_list = (ips_sg_element_t *)((uint8_t *)
+                   command->command_buffer + IPS_COMMAND_LEN);
+               for (i = 0; i < nsegs; i++) {
+                       sg_list[i].addr = segs[i].ds_addr;
+                       sg_list[i].len = segs[i].ds_len;
+                       length += segs[i].ds_len;
+               }
+               command_struct->buffaddr =
+                   (uint32_t)command->command_phys_addr + IPS_COMMAND_LEN;
+               command_struct->command = IPS_SG_WRITE_CMD;
+       } else {
+               command_struct->buffaddr = segs[0].ds_addr;
+               length = segs[0].ds_len;
+               command_struct->segnum = 0;
+               command_struct->command = IPS_WRITE_CMD;
+       }
+
+       length = (length + IPS_BLKSIZE - 1) / IPS_BLKSIZE;
+       command_struct->length = length;
+       bus_dmamap_sync(sc->command_dmatag, command->command_dmamap,
+           BUS_DMASYNC_PREWRITE);
+       bus_dmamap_sync(command->data_dmatag, command->data_dmamap,
+           BUS_DMASYNC_PREWRITE);
+
+       sc->ips_issue_cmd(command);
+       sc->ips_poll_cmd(command);
+       return;
+}
+
+static void
+ipsd_dump_block_complete(ips_command_t *command)
+{
+       if (COMMAND_ERROR(&command->status)) {
+               printf("ipsd_dump completion error= 0x%x\n",
+                      command->status.value);
+       }
+       bus_dmamap_sync(command->data_dmatag, command->data_dmamap,
+           BUS_DMASYNC_POSTWRITE);
+       bus_dmamap_unload(command->data_dmatag, command->data_dmamap);
+}
+
+#endif
index 0187499..a7efa66 100644 (file)
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/dev/ips/ips_ioctl.c,v 1.5 2004/05/30 04:01:29 scottl Exp $
- * $DragonFly: src/sys/dev/raid/ips/ips_ioctl.c,v 1.4 2004/09/06 16:39:47 joerg Exp $
+ * $DragonFly: src/sys/dev/raid/ips/ips_ioctl.c,v 1.5 2005/08/09 16:23:13 dillon Exp $
  */
 
 #include <dev/raid/ips/ips.h>
 #include <dev/raid/ips/ips_ioctl.h>
+#include <sys/thread2.h>
 
 static void
 ips_ioctl_finish(ips_command_t *command)
@@ -98,6 +99,7 @@ static int
 ips_ioctl_cmd(ips_softc_t *sc, ips_ioctl_t *ioctl_cmd,
     ips_user_request *user_request)
 {
+       ips_command_t *command;
        int error = EINVAL;
 
        if (bus_dma_tag_create(
@@ -124,16 +126,22 @@ ips_ioctl_cmd(ips_softc_t *sc, ips_ioctl_t *ioctl_cmd,
            ioctl_cmd->datasize))
                goto exit;
        ioctl_cmd->status.value = 0xffffffff;
-       if ((error = ips_get_free_cmd(sc, ips_ioctl_start, ioctl_cmd, 0)) > 0) {
+       lwkt_exlock(&sc->queue_lock, __func__);
+       if ((error = ips_get_free_cmd(sc, &command, 0)) > 0) {
                error = ENOMEM;
+               lwkt_exunlock(&sc->queue_lock);
                goto exit;
        }
+       command->arg = ioctl_cmd;
+       ips_ioctl_start(command);
        while (ioctl_cmd->status.value == 0xffffffff)
                tsleep(ioctl_cmd, 0, "ips", hz / 10);
        if (COMMAND_ERROR(&ioctl_cmd->status))
                error = EIO;
        else
                error = 0;
+       lwkt_exunlock(&sc->queue_lock);
+
        if (copyout(ioctl_cmd->data_buffer, user_request->data_buffer,
            ioctl_cmd->datasize))
                error = EINVAL;
index 49fdce6..d644e7d 100644 (file)
@@ -26,7 +26,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/dev/ips/ips_pci.c,v 1.10 2004/03/19 17:36:47 scottl Exp $
- * $DragonFly: src/sys/dev/raid/ips/ips_pci.c,v 1.12 2005/05/24 20:59:04 dillon Exp $
+ * $DragonFly: src/sys/dev/raid/ips/ips_pci.c,v 1.13 2005/08/09 16:23:13 dillon Exp $
  */
 
 #include <dev/raid/ips/ips.h>
@@ -40,15 +40,17 @@ static struct ips_pci_product {
        int (*ips_adapter_reinit)(struct ips_softc *, int);
        void (*ips_adapter_intr)(void *);
        void (*ips_issue_cmd)(ips_command_t *);
+       void (*ips_poll_cmd)(ips_command_t *);
 } ips_pci_products[] = {
        { IPS_VENDOR_ID, IPS_MORPHEUS_DEVICE_ID, "IBM ServeRAID Adapter",
-         ips_morpheus_reinit, ips_morpheus_intr, ips_issue_morpheus_cmd },
+         ips_morpheus_reinit, ips_morpheus_intr, ips_issue_morpheus_cmd,
+         ips_morpheus_poll },
        { IPS_VENDOR_ID, IPS_COPPERHEAD_DEVICE_ID, "IBM ServeRAID Adapter",
-         ips_copperhead_reinit, ips_copperhead_intr,
-         ips_issue_copperhead_cmd },
+         ips_copperhead_reinit, ips_copperhead_intr, ips_issue_copperhead_cmd,
+         ips_copperhead_poll },
        { IPS_VENDOR_ID_ADAPTEC, IPS_MARCO_DEVICE_ID,
          "Adaptec ServeRAID Adapter", ips_morpheus_reinit, ips_morpheus_intr,
-         ips_issue_morpheus_cmd },
+         ips_issue_morpheus_cmd, ips_morpheus_poll },
        { 0, 0, NULL }
 };
 
@@ -66,6 +68,7 @@ ips_pci_probe(device_t dev)
                        sc->ips_adapter_reinit = pp->ips_adapter_reinit;
                        sc->ips_adapter_intr = pp->ips_adapter_intr;
                        sc->ips_issue_cmd = pp->ips_issue_cmd;
+                       sc->ips_poll_cmd = pp->ips_poll_cmd;
                        device_set_desc(dev, pp->desc);
                        return (0);
                }
@@ -151,6 +154,8 @@ ips_pci_attach(device_t dev)
        sc->ips_ich.ich_func = ips_intrhook;
        sc->ips_ich.ich_arg = sc;
        sc->ips_ich.ich_desc = "ips";
+       lwkt_rwlock_init(&sc->queue_lock);
+       bufq_init(&sc->queue);
        if (config_intrhook_establish(&sc->ips_ich) != 0) {
                printf("IPS can't establish configuration hook\n");
                goto error;