summaryrefslogtreecommitdiff
path: root/xpp/xbus-core.h
diff options
context:
space:
mode:
Diffstat (limited to 'xpp/xbus-core.h')
-rw-r--r--xpp/xbus-core.h202
1 files changed, 194 insertions, 8 deletions
diff --git a/xpp/xbus-core.h b/xpp/xbus-core.h
index d1a3167..de6e859 100644
--- a/xpp/xbus-core.h
+++ b/xpp/xbus-core.h
@@ -22,20 +22,211 @@
#ifndef XBUS_CORE_H
#define XBUS_CORE_H
+#include <linux/wait.h>
+#include <linux/interrupt.h> /* for tasklets */
#include "xpd.h"
+#include "xframe_queue.h"
+#include "xbus-pcm.h"
#define MAX_BUSES 32
#define XFRAME_DATASIZE 512
+/* forward declarations */
+struct xbus_poller;
+#ifdef XPP_DEBUGFS
+struct debugfs_data;
+#endif
+
+#ifdef __KERNEL__
+
+struct xbus_ops {
+ int (*xframe_send_pcm)(xbus_t *xbus, xframe_t *xframe);
+ int (*xframe_send_cmd)(xbus_t *xbus, xframe_t *xframe);
+ xframe_t *(*alloc_xframe)(xbus_t *xbus, gfp_t gfp_flags);
+ void (*free_xframe)(xbus_t *xbus, xframe_t *xframe);
+};
+
+/*
+ * XBUS statistics counters
+ */
+enum {
+ XBUS_N_DESC_REQ,
+ XBUS_N_DEV_DESC_FULL,
+ XBUS_N_DEV_DESC_EMPTY,
+ XBUS_N_TX_XFRAME_PCM,
+ XBUS_N_RX_XFRAME_PCM,
+ XBUS_N_TX_PACK_PCM,
+ XBUS_N_RX_PACK_PCM,
+ XBUS_N_TX_BYTES,
+ XBUS_N_RX_BYTES,
+ XBUS_N_TX_PCM_FRAG,
+ XBUS_N_TX_CMD,
+};
+
+#define XBUS_COUNTER(xbus, counter) ((xbus)->counters[XBUS_N_ ## counter])
+
+#define C_(x) [ XBUS_N_ ## x ] = { #x }
+
+/* yucky, make an instance so we can size it... */
+static struct xbus_counters {
+ char *name;
+} xbus_counters[] = {
+ C_(DESC_REQ),
+ C_(DEV_DESC_FULL),
+ C_(DEV_DESC_EMPTY),
+ C_(TX_XFRAME_PCM),
+ C_(RX_XFRAME_PCM),
+ C_(TX_PACK_PCM),
+ C_(RX_PACK_PCM),
+ C_(TX_BYTES),
+ C_(RX_BYTES),
+ C_(TX_PCM_FRAG),
+ C_(TX_CMD),
+};
+
+#undef C_
+
+#define XBUS_COUNTER_MAX ARRAY_SIZE(xbus_counters)
+
+struct xbus_transport {
+ struct xbus_ops *ops;
+ void *priv;
+ ushort max_send_size;
+ bool transport_running; /* Hardware is functional */
+ atomic_t transport_refcount;
+ wait_queue_head_t transport_unused;
+ spinlock_t lock;
+};
+
+#define MAX_SEND_SIZE(xbus) ((xbus)->transport.max_send_size)
+#define TRANSPORT_RUNNING(xbus) ((xbus)->transport.transport_running)
+#define TRANSPORT_EXIST(xbus) ((xbus)->transport.ops != NULL)
+
+struct xbus_ops *transportops_get(xbus_t *xbus);
+void transportops_put(xbus_t *xbus);
+
+/*
+ * Allocate/Free an xframe from pools of empty xframes.
+ * Calls to {get,put}_xframe are wrapped in
+ * the macros bellow, so we take/return it
+ * to the correct pool.
+ */
+xframe_t *get_xframe(struct xframe_queue *q);
+void put_xframe(struct xframe_queue *q, xframe_t *xframe);
+
+#define ALLOC_SEND_XFRAME(xbus) get_xframe(&(xbus)->send_pool)
+#define ALLOC_RECV_XFRAME(xbus) get_xframe(&(xbus)->receive_pool)
+#define FREE_SEND_XFRAME(xbus, xframe) put_xframe(&(xbus)->send_pool, (xframe))
+#define FREE_RECV_XFRAME(xbus, xframe) put_xframe(&(xbus)->receive_pool, (xframe))
+
+xbus_t *get_xbus(uint num);
+void put_xbus(xbus_t *xbus);
+
+/*
+ * An xbus is a transport layer for Xorcom Protocol commands
+ */
+struct xbus {
+ char busname[XBUS_NAMELEN]; /* set by xbus_new() */
+
+ /* low-level bus drivers set these 2 fields */
+ char busdesc[XBUS_DESCLEN];
+ char label[LABEL_SIZE];
+ struct xbus_transport transport;
+
+ int num;
+ struct xpd *xpds[MAX_XPDS];
+
+ struct xframe_queue command_queue;
+ wait_queue_head_t command_queue_empty;
+
+ struct xframe_queue send_pool; /* empty xframes for send */
+ struct xframe_queue receive_pool; /* empty xframes for receive */
+
+ /* tasklet processing */
+ struct xframe_queue receive_queue;
+ struct tasklet_struct receive_tasklet;
+ int cpu_rcv_intr[NR_CPUS];
+ int cpu_rcv_tasklet[NR_CPUS];
+
+ bool self_ticking;
+ enum sync_mode sync_mode;
+ struct timer_list command_timer;
+ unsigned int xbus_frag_count;
+ struct xframe_queue pcm_tospan[2]; /* double buffer */
+ struct xpp_timing timing;
+ atomic_t pcm_rx_counter;
+ unsigned int global_counter;
+ long sync_offset_usec;
+
+ /* Device-Model */
+ struct device astribank;
+#define dev_to_xbus(dev) container_of(dev, struct xbus, astribank)
+
+ spinlock_t lock;
+ atomic_t xbus_ref_count; /* How many need this struct? */
+
+ /* PCM metrics */
+ struct timeval last_tx_sync;
+ struct timeval last_rx_sync;
+ unsigned long max_tx_sync;
+ unsigned long min_tx_sync;
+ unsigned long max_rx_sync;
+ unsigned long min_rx_sync;
+ unsigned long max_rx_process; /* packet processing time (usec) */
+
+ struct xbus_poller *poller;
+
+ /*
+ * Sync adjustment
+ */
+ int sync_adjustment;
+ int sync_adjustment_offset;
+ long pll_updated_at;
+
+ struct rw_semaphore in_use;
+#define XBUS_GET(xbus) down_read_trylock(&(xbus)->in_use)
+#define XBUS_PUT(xbus) up_read(&(xbus)->in_use)
+
+ int num_xpds;
+
+#ifdef XPP_DEBUGFS
+ struct dentry *debugfs_dir;
+ struct dentry *debugfs_file;
+ struct debugfs_data *debugfs_data;
+#endif
+#ifdef CONFIG_PROC_FS
+ struct proc_dir_entry *proc_xbus_dir;
+ struct proc_dir_entry *proc_xbus_summary;
+#ifdef PROTOCOL_DEBUG
+ struct proc_dir_entry *proc_xbus_command;
+#endif
+#endif
+
+ /* statistics */
+ int counters[XBUS_COUNTER_MAX];
+};
+#endif
+
+#define XFRAME_MAGIC 123456L
+
struct xframe {
+ unsigned long xframe_magic;
struct list_head frame_list;
atomic_t frame_len;
xbus_t *xbus;
struct timeval tv_created;
+ struct timeval tv_queued;
+ struct timeval tv_submitted;
struct timeval tv_received;
+ /* filled by transport layer */
+ size_t frame_maxlen;
byte *packets; /* max XFRAME_DATASIZE */
+ byte *first_free;
+ void *priv;
};
+void xframe_init(xbus_t *xbus, xframe_t *xframe, void *buf, size_t maxsize, void *priv);
+
#define XFRAME_LEN(frame) atomic_read(&(frame)->frame_len)
int xbus_core_init(void); /* Initializer */
@@ -47,10 +238,7 @@ int xbus_log(xbus_t *xbus, xpd_t *xpd, int direction, const void *buf, unsigned
#endif
/* Frame handling */
-xframe_t *xbus_frame_new(xbus_t *xbus, gfp_t flags);
-void xbus_frame_free(xbus_t *xbus, xframe_t *p);
void dump_xframe(const char msg[], const xbus_t *xbus, const xframe_t *xframe);
-int xframe_send(xbus_t *xbus, xframe_t *xframe);
int send_cmd_frame(xbus_t *xbus, xframe_t *xframe);
/*
@@ -68,17 +256,15 @@ xpacket_t *xframe_next_packet(xframe_t *xframe, int len);
#define XBUS_UNIT(idx) ((idx) / MAX_SUBUNIT)
#define XBUS_SUBUNIT(idx) ((idx) % MAX_SUBUNIT)
-xbus_t *xbus_of(int xbus_num);
xpd_t *xpd_of(const xbus_t *xbus, int xpd_num);
xpd_t *xpd_byaddr(const xbus_t *xbus, uint unit, uint subunit);
-xbus_t *xbus_new(xbus_ops_t *ops, size_t xframe_size);
+xbus_t *xbus_new(struct xbus_ops *ops, ushort max_send_size, void *priv);
void xbus_remove(xbus_t *xbus);
-void xbus_activate(xbus_t *xbus);
+int xbus_activate(xbus_t *xbus);
void xbus_disconnect(xbus_t *xbus);
+void xbus_receive_xframe(xbus_t *xbus, xframe_t *xframe);
void xbus_poller_notify(xbus_t *xbus, struct card_desc_struct *card_desc);
-void xbus_reset_counters(xbus_t *xbus);
-
int xbus_register_xpd(xbus_t *xbus, xpd_t *xpd);
int xbus_unregister_xpd(xbus_t *xbus, xpd_t *xpd);