aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/amr/amrvar.h
diff options
context:
space:
mode:
authorMike Smith <msmith@FreeBSD.org>2000-08-30 07:52:50 +0000
committerMike Smith <msmith@FreeBSD.org>2000-08-30 07:52:50 +0000
commit9f1776230d63537648a5174e3dac7a18c7ffdbca (patch)
tree3130d6b7c48e164dc29c8ce2a7de16a42cff3581 /sys/dev/amr/amrvar.h
parent429a82acc661b83cceaaae92f4ba169dfe5aaa04 (diff)
downloadsrc-9f1776230d63537648a5174e3dac7a18c7ffdbca.tar.gz
src-9f1776230d63537648a5174e3dac7a18c7ffdbca.zip
Major update to the AMI MegaRAID driver.
- New support for 40LD firmware found in Series 475 and 471 adapters. - Better support for 8LD firmware adapters - Ioctl passthrough interface for userland utilities. - Improved error handling and queueing. - Several bugfixes (including the 'still open' shutdown bug and closing some small race conditions). - Zone-style command allocator, reducing memory wasted under heavy load conditions. - CAM interface (disabled and not fully working) for SCSI passthrough access to non-disk devices Thanks to AMI for supplying a pile of new adapters and various other help in making this happen.
Notes
Notes: svn path=/head/; revision=65245
Diffstat (limited to 'sys/dev/amr/amrvar.h')
-rw-r--r--sys/dev/amr/amrvar.h292
1 files changed, 194 insertions, 98 deletions
diff --git a/sys/dev/amr/amrvar.h b/sys/dev/amr/amrvar.h
index 5edfb1fb93f0..159a4e8231ad 100644
--- a/sys/dev/amr/amrvar.h
+++ b/sys/dev/amr/amrvar.h
@@ -1,5 +1,6 @@
/*-
- * Copyright (c) 1999 Michael Smith
+ * Copyright (c) 1999,2000 Michael Smith
+ * Copyright (c) 2000 BSDi
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -26,24 +27,18 @@
* $FreeBSD$
*/
-/*
- * We could actually use all 17 segments, but using only 16 means that
- * each scatter/gather map is 128 bytes in size, and thus we don't have to worry about
- * maps crossing page boundaries.
- */
-#define AMR_NSEG 16
-
-#define AMR_CFG_BASE 0x10
-#define AMR_CFG_SIG 0xa0
-#define AMR_SIGNATURE 0x3344
-
-#define AMR_MAXCMD 255 /* ident = 0 not allowed */
-#define AMR_LIMITCMD 120 /* maximum count of outstanding commands */
-#define AMR_MAXLD 40
-
-#define AMR_BLKSIZE 512
+#if __FreeBSD_version >= 500005
+# include <sys/taskqueue.h>
+#endif
-struct amr_softc;
+#ifdef AMR_DEBUG
+# define debug(level, fmt, args...) do {if (level <= AMR_DEBUG) printf("%s: " fmt "\n", __FUNCTION__ , ##args);} while(0)
+# define debug_called(level) do {if (level <= AMR_DEBUG) printf("%s: called\n", __FUNCTION__);} while(0)
+#else
+# define debug(level, fmt, args...)
+# define debug_called(level)
+#endif
+#define xdebug(fmt, args...) printf("%s: " fmt "\n", __FUNCTION__ , ##args)
/*
* Per-logical-drive datastructure
@@ -63,6 +58,16 @@ struct amr_logdrive
device_t al_disk;
};
+/*
+ * Due to the difficulty of using the zone allocator to create a new
+ * zone from within a module, we use our own clustering to reduce
+ * memory wastage due to allocating lots of these small structures.
+ *
+ * 16k gives us a little under 200 command structures, which should
+ * normally be plenty. We will grab more if we need them.
+ */
+
+#define AMR_CMD_CLUSTERSIZE (16 * 1024)
/*
* Per-command control structure.
@@ -73,28 +78,45 @@ struct amr_command
struct amr_softc *ac_sc;
u_int8_t ac_slot;
- int ac_status;
-#define AMR_STATUS_BUSY 0xffff
-#define AMR_STATUS_WEDGED 0xdead
-#define AMR_STATUS_LATE 0xdeed
+ int ac_status; /* command completion status */
struct amr_mailbox ac_mailbox;
- u_int32_t ac_sgphys;
- int ac_nsgent;
int ac_flags;
#define AMR_CMD_DATAIN (1<<0)
#define AMR_CMD_DATAOUT (1<<1)
-#define AMR_CMD_PRIORITY (1<<2)
- time_t ac_stamp;
+#define AMR_CMD_CCB_DATAIN (1<<2)
+#define AMR_CMD_CCB_DATAOUT (1<<3)
+#define AMR_CMD_PRIORITY (1<<4)
+#define AMR_CMD_MAPPED (1<<5)
+#define AMR_CMD_SLEEP (1<<6)
+#define AMR_CMD_BUSY (1<<7)
+
+ struct bio *ac_bio;
void *ac_data;
size_t ac_length;
bus_dmamap_t ac_dmamap;
u_int32_t ac_dataphys;
+ void *ac_ccb_data;
+ size_t ac_ccb_length;
+ bus_dmamap_t ac_ccb_dmamap;
+ u_int32_t ac_ccb_dataphys;
+
void (* ac_complete)(struct amr_command *ac);
- void *ac_private;
};
+struct amr_command_cluster
+{
+ TAILQ_ENTRY(amr_command_cluster) acc_link;
+ struct amr_command acc_command[0];
+};
+
+#define AMR_CMD_CLUSTERCOUNT ((AMR_CMD_CLUSTERSIZE - sizeof(struct amr_command_cluster)) / \
+ sizeof(struct amr_command))
+
+/*
+ * Per-controller-instance data
+ */
struct amr_softc
{
/* bus attachments */
@@ -123,101 +145,74 @@ struct amr_softc
/* controller limits and features */
int amr_maxio; /* maximum number of I/O transactions */
int amr_maxdrives; /* max number of logical drives */
+ int amr_maxchan; /* count of SCSI channels */
/* connected logical drives */
struct amr_logdrive amr_drive[AMR_MAXLD];
- /* controller status */
+ /* controller state */
int amr_state;
#define AMR_STATE_OPEN (1<<0)
#define AMR_STATE_SUSPEND (1<<1)
#define AMR_STATE_INTEN (1<<2)
#define AMR_STATE_SHUTDOWN (1<<3)
- struct callout_handle amr_timeout; /* periodic status check */
/* per-controller queues */
- struct bio_queue_head amr_bioq; /* pending I/O */
- int amr_waitbufs;
+ struct bio_queue_head amr_bioq; /* pending I/O with no commands */
+ TAILQ_HEAD(,amr_command) amr_ready; /* commands ready to be submitted */
struct amr_command *amr_busycmd[AMR_MAXCMD];
- int amr_busycmdcount;
- TAILQ_HEAD(,amr_command) amr_work;
- int amr_workcount;
+ int amr_busyslots;
+ TAILQ_HEAD(,amr_command) amr_completed;
TAILQ_HEAD(,amr_command) amr_freecmds;
+ TAILQ_HEAD(,amr_command_cluster) amr_cmd_clusters;
+
+ /* CAM attachments for passthrough */
+ struct cam_sim *amr_cam_sim[AMR_MAX_CHANNELS];
+ TAILQ_HEAD(, ccb_hdr) amr_cam_ccbq;
- int amr_locks; /* reentrancy avoidance */
+ /* control device */
+ dev_t amr_dev_t;
/* controller type-specific support */
int amr_type;
-#define AMR_TYPE_STD 0
-#define AMR_TYPE_QUARTZ 1
- void (* amr_submit_command)(struct amr_softc *sc);
+#define AMR_TYPE_QUARTZ (1<<0)
+#define AMR_IS_QUARTZ(sc) ((sc)->amr_type & AMR_TYPE_QUARTZ)
+#define AMR_TYPE_40LD (1<<1)
+#define AMR_IS_40LD(sc) ((sc)->amr_type & AMR_TYPE_40LD)
+ int (* amr_submit_command)(struct amr_softc *sc);
int (* amr_get_work)(struct amr_softc *sc, struct amr_mailbox *mbsave);
- void (* amr_attach_mailbox)(struct amr_softc *sc);
+
+ /* misc glue */
+ struct intr_config_hook amr_ich; /* wait-for-interrupts probe hook */
+ struct callout_handle amr_timeout; /* periodic status check */
+#if __FreeBSD_version >= 500005
+ struct task amr_task_complete; /* deferred-completion task */
+#endif
};
/*
- * Simple (stupid) locks.
- *
- * Note that these are designed to avoid reentrancy, not concurrency, and will
- * need to be replaced with something better.
+ * Interface between bus connections and driver core.
*/
-#define AMR_LOCK_COMPLETING (1<<0)
-#define AMR_LOCK_STARTING (1<<1)
-
-static __inline int
-amr_lock_tas(struct amr_softc *sc, int lock)
-{
- if ((sc)->amr_locks & (lock))
- return(1);
- atomic_set_int(&sc->amr_locks, lock);
- return(0);
-}
+extern int amr_attach(struct amr_softc *sc);
+extern void amr_free(struct amr_softc *sc);
+extern int amr_flush(struct amr_softc *sc);
+extern int amr_done(struct amr_softc *sc);
+extern void amr_startio(struct amr_softc *sc);
-static __inline void
-amr_lock_clr(struct amr_softc *sc, int lock)
-{
- atomic_clear_int(&sc->amr_locks, lock);
-}
+extern devclass_t amr_devclass;
/*
- * I/O primitives
+ * Command buffer allocation.
*/
-/* Quartz */
-#define AMR_QPUT_IDB(sc, val) bus_space_write_4(sc->amr_btag, sc->amr_bhandle, AMR_QIDB, val)
-#define AMR_QGET_IDB(sc) bus_space_read_4 (sc->amr_btag, sc->amr_bhandle, AMR_QIDB)
-#define AMR_QPUT_ODB(sc, val) bus_space_write_4(sc->amr_btag, sc->amr_bhandle, AMR_QODB, val)
-#define AMR_QGET_ODB(sc) bus_space_read_4 (sc->amr_btag, sc->amr_bhandle, AMR_QODB)
-
-/* Standard */
-#define AMR_SPUT_ISTAT(sc, val) bus_space_write_1(sc->amr_btag, sc->amr_bhandle, AMR_SINTR, val)
-#define AMR_SGET_ISTAT(sc) bus_space_read_1 (sc->amr_btag, sc->amr_bhandle, AMR_SINTR)
-#define AMR_SACK_INTERRUPT(sc) bus_space_write_1(sc->amr_btag, sc->amr_bhandle, AMR_SCMD, AMR_SCMD_ACKINTR)
-#define AMR_SPOST_COMMAND(sc) bus_space_write_1(sc->amr_btag, sc->amr_bhandle, AMR_SCMD, AMR_SCMD_POST)
-#define AMR_SGET_MBSTAT(sc) bus_space_read_1 (sc->amr_btag, sc->amr_bhandle, AMR_SMBOX_BUSY)
-#define AMR_SENABLE_INTR(sc) \
- bus_space_write_1(sc->amr_btag, sc->amr_bhandle, AMR_STOGGLE, \
- bus_space_read_1(sc->amr_btag, sc->amr_bhandle, AMR_STOGGLE) | AMR_STOGL_IENABLE)
-#define AMR_SDISABLE_INTR(sc) \
- bus_space_write_1(sc->amr_btag, sc->amr_bhandle, AMR_STOGGLE, \
- bus_space_read_1(sc->amr_btag, sc->amr_bhandle, AMR_STOGGLE) & ~AMR_STOGL_IENABLE)
-#define AMR_SBYTE_SET(sc, reg, val) bus_space_write_1(sc->amr_btag, sc->amr_bhandle, reg, val)
+extern struct amr_command *amr_alloccmd(struct amr_softc *sc);
+extern void amr_releasecmd(struct amr_command *ac);
/*
- * Interface between bus connections and driver core.
+ * CAM interface
*/
-extern void amr_free(struct amr_softc *sc);
-extern int amr_attach(struct amr_softc *sc);
-extern void amr_startup(struct amr_softc *sc);
-extern void amr_intr(void *data);
-extern int amr_detach(device_t dev);
-extern int amr_shutdown(device_t dev);
-extern int amr_suspend(device_t dev);
-extern int amr_resume(device_t dev);
-extern d_open_t amr_open;
-extern d_close_t amr_close;
-extern d_ioctl_t amr_ioctl;
-
-extern devclass_t amr_devclass;
+extern int amr_cam_attach(struct amr_softc *sc);
+extern void amr_cam_detach(struct amr_softc *sc);
+extern int amr_cam_command(struct amr_softc *sc, struct amr_command **acp);
/*
* MegaRAID logical disk driver
@@ -233,15 +228,116 @@ struct amrd_softc
struct disklabel amrd_label;
int amrd_unit;
int amrd_flags;
-#define AMRD_OPEN (1<<0) /* drive is open (can't shut down) */
+#define AMRD_OPEN (1<<0) /* drive is open (can't detach) */
};
/*
* Interface between driver core and disk driver (should be using a bus?)
*/
-extern int amr_submit_buf(struct amr_softc *sc, struct bio *bp);
-extern int amr_submit_ioctl(struct amr_softc *sc, struct amr_logdrive *drive, u_long cmd,
- caddr_t addr, int32_t flag, struct proc *p);
+extern int amr_submit_bio(struct amr_softc *sc, struct bio *bio);
extern void amrd_intr(void *data);
-extern void amr_report(void);
+/********************************************************************************
+ * Enqueue/dequeue functions
+ */
+static __inline void
+amr_enqueue_bio(struct amr_softc *sc, struct bio *bio)
+{
+ int s;
+
+ s = splbio();
+ bioq_insert_tail(&sc->amr_bioq, bio);
+ splx(s);
+}
+
+static __inline struct bio *
+amr_dequeue_bio(struct amr_softc *sc)
+{
+ struct bio *bio;
+ int s;
+
+ s = splbio();
+ if ((bio = bioq_first(&sc->amr_bioq)) != NULL)
+ bioq_remove(&sc->amr_bioq, bio);
+ splx(s);
+ return(bio);
+}
+
+static __inline void
+amr_enqueue_ready(struct amr_command *ac)
+{
+ int s;
+
+ s = splbio();
+ TAILQ_INSERT_TAIL(&ac->ac_sc->amr_ready, ac, ac_link);
+ splx(s);
+}
+
+static __inline void
+amr_requeue_ready(struct amr_command *ac)
+{
+ int s;
+
+ s = splbio();
+ TAILQ_INSERT_HEAD(&ac->ac_sc->amr_ready, ac, ac_link);
+ splx(s);
+}
+
+static __inline struct amr_command *
+amr_dequeue_ready(struct amr_softc *sc)
+{
+ struct amr_command *ac;
+ int s;
+
+ s = splbio();
+ if ((ac = TAILQ_FIRST(&sc->amr_ready)) != NULL)
+ TAILQ_REMOVE(&sc->amr_ready, ac, ac_link);
+ splx(s);
+ return(ac);
+}
+
+static __inline void
+amr_enqueue_completed(struct amr_command *ac)
+{
+ int s;
+
+ s = splbio();
+ TAILQ_INSERT_TAIL(&ac->ac_sc->amr_completed, ac, ac_link);
+ splx(s);
+}
+
+static __inline struct amr_command *
+amr_dequeue_completed(struct amr_softc *sc)
+{
+ struct amr_command *ac;
+ int s;
+
+ s = splbio();
+ if ((ac = TAILQ_FIRST(&sc->amr_completed)) != NULL)
+ TAILQ_REMOVE(&sc->amr_completed, ac, ac_link);
+ splx(s);
+ return(ac);
+}
+
+static __inline void
+amr_enqueue_free(struct amr_command *ac)
+{
+ int s;
+
+ s = splbio();
+ TAILQ_INSERT_TAIL(&ac->ac_sc->amr_freecmds, ac, ac_link);
+ splx(s);
+}
+
+static __inline struct amr_command *
+amr_dequeue_free(struct amr_softc *sc)
+{
+ struct amr_command *ac;
+ int s;
+
+ s = splbio();
+ if ((ac = TAILQ_FIRST(&sc->amr_freecmds)) != NULL)
+ TAILQ_REMOVE(&sc->amr_freecmds, ac, ac_link);
+ splx(s);
+ return(ac);
+}