summaryrefslogtreecommitdiffstats
path: root/sys/dev/twe/twevar.h
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/twe/twevar.h')
-rw-r--r--sys/dev/twe/twevar.h219
1 files changed, 165 insertions, 54 deletions
diff --git a/sys/dev/twe/twevar.h b/sys/dev/twe/twevar.h
index 673a278..ea12062 100644
--- a/sys/dev/twe/twevar.h
+++ b/sys/dev/twe/twevar.h
@@ -28,8 +28,14 @@
*/
#ifdef TWE_DEBUG
-#define debug(level, fmt, args...) do { if (level <= TWE_DEBUG) printf("%s: " fmt "\n", __FUNCTION__ , ##args); } while(0)
-#define debug_called(level) do { if (level <= TWE_DEBUG) printf(__FUNCTION__ ": called\n"); } while(0)
+#define debug(level, fmt, args...) \
+ do { \
+ if (level <= TWE_DEBUG) printf("%s: " fmt "\n", __FUNCTION__ , ##args); \
+ } while(0)
+#define debug_called(level) \
+ do { \
+ if (level <= TWE_DEBUG) printf(__FUNCTION__ ": called\n"); \
+ } while(0)
#else
#define debug(level, fmt, args...)
#define debug_called(level)
@@ -47,16 +53,9 @@ struct twe_drive
int td_sectors;
int td_unit;
- /* unit state */
- int td_state;
-#define TWE_DRIVE_READY 0
-#define TWE_DRIVE_DEGRADED 1
-#define TWE_DRIVE_OFFLINE 2
- int td_raidlevel;
-#define TWE_DRIVE_RAID0 0
-#define TWE_DRIVE_RAID1 1
-
-#define TWE_DRIVE_UNKNOWN 0xff
+ /* unit state and type */
+ u_int8_t td_state;
+ u_int8_t td_type;
/* handle for attached driver */
device_t td_disk;
@@ -73,15 +72,11 @@ struct twe_request
{
/* controller command */
TWE_Command tr_command; /* command as submitted to controller */
- bus_dmamap_t tr_cmdmap; /* DMA map for command */
- u_int32_t tr_cmdphys; /* address of command in controller space */
/* command payload */
void *tr_data; /* data buffer */
void *tr_realdata; /* copy of real data buffer pointer for alignment fixup */
size_t tr_length;
- bus_dmamap_t tr_dmamap; /* DMA map for data */
- u_int32_t tr_dataphys; /* data buffer base address in controller space */
TAILQ_ENTRY(twe_request) tr_link; /* list linkage */
struct twe_softc *tr_sc; /* controller that owns us */
@@ -94,8 +89,11 @@ struct twe_request
#define TWE_CMD_DATAIN (1<<0)
#define TWE_CMD_DATAOUT (1<<1)
#define TWE_CMD_ALIGNBUF (1<<2) /* data in bio is misaligned, have to copy to/from private buffer */
+#define TWE_CMD_SLEEPER (1<<3) /* owner is sleeping on this command */
void (* tr_complete)(struct twe_request *tr); /* completion handler */
void *tr_private; /* submitter-private data or wait channel */
+
+ TWE_PLATFORM_REQUEST /* platform-specific request elements */
};
/*
@@ -103,28 +101,19 @@ struct twe_request
*/
struct twe_softc
{
- /* bus connections */
- device_t twe_dev;
- dev_t twe_dev_t;
- struct resource *twe_io; /* register interface window */
- bus_space_handle_t twe_bhandle; /* bus space handle */
- bus_space_tag_t twe_btag; /* bus space tag */
- bus_dma_tag_t twe_parent_dmat; /* parent DMA tag */
- bus_dma_tag_t twe_buffer_dmat; /* data buffer DMA tag */
- struct resource *twe_irq; /* interrupt */
- void *twe_intr; /* interrupt handle */
-
/* controller queues and arrays */
- TAILQ_HEAD(, twe_request) twe_freecmds; /* command structures available for reuse */
- TAILQ_HEAD(, twe_request) twe_work; /* active commands (busy or waiting for completion) */
- struct twe_request *twe_cmdlookup[TWE_Q_LENGTH]; /* busy commands indexed by request ID */
- int twe_busycmds; /* count of busy commands */
+ TAILQ_HEAD(, twe_request) twe_free; /* command structures available for reuse */
+ twe_bioq twe_bioq; /* outstanding I/O operations */
+ TAILQ_HEAD(, twe_request) twe_ready; /* requests ready for the controller */
+ TAILQ_HEAD(, twe_request) twe_busy; /* requests busy in the controller */
+ TAILQ_HEAD(, twe_request) twe_complete; /* active commands (busy or waiting for completion) */
+ struct twe_request *twe_lookup[TWE_Q_LENGTH]; /* commands indexed by request ID */
struct twe_drive twe_drive[TWE_MAX_UNITS]; /* attached drives */
- struct bio_queue_head twe_bioq; /* outstanding I/O operations */
- struct twe_request *twe_deferred; /* request that the controller wouldn't take */
+ /* asynchronous event handling */
u_int16_t twe_aen_queue[TWE_Q_LENGTH]; /* AENs queued for userland tool(s) */
int twe_aen_head, twe_aen_tail; /* ringbuffer pointers for AEN queue */
+ int twe_wait_aen; /* wait-for-aen notification */
/* controller status */
int twe_state;
@@ -132,32 +121,154 @@ struct twe_softc
#define TWE_STATE_SHUTDOWN (1<<1) /* controller is shut down */
#define TWE_STATE_OPEN (1<<2) /* control device is open */
#define TWE_STATE_SUSPEND (1<<3) /* controller is suspended */
+ int twe_host_id;
+#ifdef TWE_PERFORMANCE_MONITOR
+ struct twe_qstat twe_qstat[TWEQ_COUNT]; /* queue statistics */
+#endif
- /* delayed configuration hook */
- struct intr_config_hook twe_ich;
-
- /* wait-for-aen notification */
- int twe_wait_aen;
+ TWE_PLATFORM_SOFTC /* platform-specific softc elements */
};
/*
- * Virtual disk driver.
+ * Interface betwen driver core and platform-dependant code.
*/
-struct twed_softc
-{
- device_t twed_dev;
- dev_t twed_dev_t;
- struct twe_softc *twed_controller; /* parent device softc */
- struct twe_drive *twed_drive; /* drive data in parent softc */
- struct disk twed_disk; /* generic disk handle */
- struct devstat twed_stats; /* accounting */
- struct disklabel twed_label; /* synthetic label */
- int twed_flags;
-#define TWED_OPEN (1<<0) /* drive is open (can't shut down) */
-};
+extern int twe_setup(struct twe_softc *sc); /* do early driver/controller setup */
+extern void twe_init(struct twe_softc *sc); /* init controller */
+extern void twe_deinit(struct twe_softc *sc); /* stop controller */
+extern void twe_intr(struct twe_softc *sc); /* hardware interrupt signalled */
+extern int twe_submit_bio(struct twe_softc *sc,
+ twe_bio *bp); /* pass bio to core */
+extern int twe_ioctl(struct twe_softc *sc, int cmd,
+ void *addr); /* handle user request */
+extern void twe_describe_controller(struct twe_softc *sc); /* print controller info */
+extern void twe_print_controller(struct twe_softc *sc);
+extern void twe_enable_interrupts(struct twe_softc *sc); /* enable controller interrupts */
+extern void twe_disable_interrupts(struct twe_softc *sc); /* disable controller interrupts */
+
+extern void twe_attach_drive(struct twe_softc *sc,
+ struct twe_drive *dr); /* attach drive when found in twe_init */
+extern void twed_intr(twe_bio *bp); /* return bio from core */
+extern struct twe_request *twe_allocate_request(struct twe_softc *sc); /* allocate request structure */
+extern void twe_free_request(struct twe_request *tr); /* free request structure */
+extern void twe_map_request(struct twe_request *tr); /* make request visible to controller, do s/g */
+extern void twe_unmap_request(struct twe_request *tr); /* cleanup after transfer, unmap */
+
+/********************************************************************************
+ * Queue primitives
+ */
+#ifdef TWE_PERFORMANCE_MONITOR
+# define TWEQ_ADD(sc, qname) \
+ do { \
+ struct twe_qstat *qs = &(sc)->twe_qstat[qname]; \
+ \
+ qs->q_length++; \
+ if (qs->q_length > qs->q_max) \
+ qs->q_max = qs->q_length; \
+ } while(0)
+
+# define TWEQ_REMOVE(sc, qname) (sc)->twe_qstat[qname].q_length--
+# define TWEQ_INIT(sc, qname) \
+ do { \
+ sc->twe_qstat[qname].q_length = 0; \
+ sc->twe_qstat[qname].q_max = 0; \
+ } while(0)
+#else
+# define TWEQ_ADD(sc, qname)
+# define TWEQ_REMOVE(sc, qname)
+# define TWEQ_INIT(sc, qname)
+#endif
+
+
+#define TWEQ_REQUEST_QUEUE(name, index) \
+static __inline void \
+twe_initq_ ## name (struct twe_softc *sc) \
+{ \
+ TAILQ_INIT(&sc->twe_ ## name); \
+ TWEQ_INIT(sc, index); \
+} \
+static __inline void \
+twe_enqueue_ ## name (struct twe_request *tr) \
+{ \
+ int s; \
+ \
+ s = splbio(); \
+ TAILQ_INSERT_TAIL(&tr->tr_sc->twe_ ## name, tr, tr_link); \
+ TWEQ_ADD(tr->tr_sc, index); \
+ splx(s); \
+} \
+static __inline void \
+twe_requeue_ ## name (struct twe_request *tr) \
+{ \
+ int s; \
+ \
+ s = splbio(); \
+ TAILQ_INSERT_HEAD(&tr->tr_sc->twe_ ## name, tr, tr_link); \
+ TWEQ_ADD(tr->tr_sc, index); \
+ splx(s); \
+} \
+static __inline struct twe_request * \
+twe_dequeue_ ## name (struct twe_softc *sc) \
+{ \
+ struct twe_request *tr; \
+ int s; \
+ \
+ s = splbio(); \
+ if ((tr = TAILQ_FIRST(&sc->twe_ ## name)) != NULL) { \
+ TAILQ_REMOVE(&sc->twe_ ## name, tr, tr_link); \
+ TWEQ_REMOVE(sc, index); \
+ } \
+ splx(s); \
+ return(tr); \
+} \
+static __inline void \
+twe_remove_ ## name (struct twe_request *tr) \
+{ \
+ int s; \
+ \
+ s = splbio(); \
+ TAILQ_REMOVE(&tr->tr_sc->twe_ ## name, tr, tr_link); \
+ TWEQ_REMOVE(tr->tr_sc, index); \
+ splx(s); \
+}
+
+TWEQ_REQUEST_QUEUE(free, TWEQ_FREE)
+TWEQ_REQUEST_QUEUE(ready, TWEQ_READY)
+TWEQ_REQUEST_QUEUE(busy, TWEQ_BUSY)
+TWEQ_REQUEST_QUEUE(complete, TWEQ_COMPLETE)
+
/*
- * Interface betwen driver core and disk driver (should be using a bus?)
+ * outstanding bio queue
*/
-extern int twe_submit_buf(struct twe_softc *sc, struct bio *bp);
-extern void twed_intr(void *data);
+static __inline void
+twe_initq_bio(struct twe_softc *sc)
+{
+ TWE_BIO_QINIT(sc->twe_bioq);
+ TWEQ_INIT(sc, TWEQ_BIO);
+}
+
+static __inline void
+twe_enqueue_bio(struct twe_softc *sc, struct bio *bp)
+{
+ int s;
+
+ s = splbio();
+ TWE_BIO_QINSERT(sc->twe_bioq, bp);
+ TWEQ_ADD(sc, TWEQ_BIO);
+ splx(s);
+}
+
+static __inline struct bio *
+twe_dequeue_bio(struct twe_softc *sc)
+{
+ int s;
+ struct bio *bp;
+
+ s = splbio();
+ if ((bp = TWE_BIO_QFIRST(sc->twe_bioq)) != NULL) {
+ TWE_BIO_QREMOVE(sc->twe_bioq, bp);
+ TWEQ_REMOVE(sc, TWEQ_BIO);
+ }
+ splx(s);
+ return(bp);
+}
OpenPOWER on IntegriCloud