123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357 |
- /*
- * Written by Oron Peled <oron@actcom.co.il>
- * Copyright (C) 2004-2006, Xorcom
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
- #ifndef XBUS_CORE_H
- #define XBUS_CORE_H
- #include <linux/wait.h>
- #include <linux/interrupt.h> /* for tasklets */
- #include <linux/kref.h>
- #include "xpd.h"
- #include "xframe_queue.h"
- #include "xbus-pcm.h"
- #define MAX_BUSES 32
- #define XFRAME_DATASIZE 512
- /* forward declarations */
- struct xbus_workqueue;
- #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_UNITS,
- 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_RX_CMD,
- 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_(UNITS),
- 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_(RX_CMD),
- C_(TX_CMD),
- };
- #undef C_
- #define XBUS_COUNTER_MAX ARRAY_SIZE(xbus_counters)
- enum xbus_state {
- XBUS_STATE_START,
- XBUS_STATE_IDLE,
- XBUS_STATE_SENT_REQUEST,
- XBUS_STATE_RECVD_DESC,
- XBUS_STATE_READY,
- XBUS_STATE_DEACTIVATING,
- XBUS_STATE_DEACTIVATED,
- XBUS_STATE_FAIL,
- };
- const char *xbus_statename(enum xbus_state st);
- struct xbus_transport {
- struct xbus_ops *ops;
- void *priv;
- struct device *transport_device;
- ushort max_send_size;
- enum xbus_state xbus_state;
- unsigned long transport_flags;
- spinlock_t state_lock;
- atomic_t transport_refcount;
- wait_queue_head_t transport_unused;
- spinlock_t lock;
- };
- #define MAX_SEND_SIZE(xbus) ((xbus)->transport.max_send_size)
- #define XBUS_STATE(xbus) ((xbus)->transport.xbus_state)
- #define XBUS_IS(xbus, st) (XBUS_STATE(xbus) == XBUS_STATE_ ## st)
- #define TRANSPORT_EXIST(xbus) ((xbus)->transport.ops != NULL)
- #define XBUS_FLAG_CONNECTED 0
- #define XBUS_FLAGS(xbus, flg) test_bit(XBUS_FLAG_ ## flg, &((xbus)->transport.transport_flags))
- struct xbus_ops *transportops_get(xbus_t *xbus);
- void transportops_put(xbus_t *xbus);
- /*
- * Encapsulate all poll related data of a single xbus.
- */
- struct xbus_workqueue {
- struct workqueue_struct *wq;
- struct work_struct xpds_init_work;
- bool xpds_init_done;
- struct list_head card_list;
- int num_units;
- int num_units_initialized;
- wait_queue_head_t wait_for_xpd_initialization;
- #ifdef CONFIG_PROC_FS
- #ifdef OLD_PROC
- struct proc_dir_entry *proc_xbus_waitfor_xpds;
- #endif
- #endif
- spinlock_t worker_lock;
- struct semaphore running_initialization;
- };
- /*
- * 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 *xbus_num(uint num);
- xbus_t *get_xbus(const char *msg, uint num);
- void put_xbus(const char *msg, xbus_t *xbus);
- int refcount_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 connector[XBUS_DESCLEN];
- char label[LABEL_SIZE];
- byte revision; /* Protocol revision */
- struct xbus_transport transport;
- int num;
- struct xpd *xpds[MAX_XPDS];
- int command_tick_counter;
- int usec_nosend; /* Firmware flow control */
- 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;
- /* Managed by low-level drivers: */
- enum sync_mode sync_mode_default;
- struct timer_list command_timer;
- unsigned int xbus_frag_count;
- struct xframe_queue pcm_tospan;
- struct xpp_ticker ticker; /* for tick rate */
- struct xpp_drift drift; /* for tick offset */
- atomic_t pcm_rx_counter;
- unsigned int global_counter;
- /* Device-Model */
- struct device astribank;
- #define dev_to_xbus(dev) container_of(dev, struct xbus, astribank)
- struct kref kref;
- #define kref_to_xbus(k) container_of(k, struct xbus, kref)
- spinlock_t lock;
- /* 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) */
- #ifdef SAMPLE_TICKS
- #define SAMPLE_SIZE 1000
- int sample_ticks[SAMPLE_SIZE];
- bool sample_running;
- int sample_pos;
- #endif
- struct xbus_workqueue worker;
- /*
- * Sync adjustment
- */
- int sync_adjustment;
- int sync_adjustment_offset;
- long pll_updated_at;
- atomic_t 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;
- int usec_towait; /* prevent overflowing AB */
- 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 */
- void xbus_core_shutdown(void); /* Terminator */
- #ifdef XPP_DEBUGFS
- /* Debugfs handling */
- int xbus_log(xbus_t *xbus, xpd_t *xpd, int direction, const void *buf, unsigned long len);
- #endif
- /* Frame handling */
- void dump_xframe(const char msg[], const xbus_t *xbus, const xframe_t *xframe, int debug);
- int send_cmd_frame(xbus_t *xbus, xframe_t *xframe);
- /*
- * Return pointer to next packet slot in the frame
- * or NULL if the frame is full.
- */
- xpacket_t *xframe_next_packet(xframe_t *xframe, int len);
- /* XBUS handling */
- /*
- * Map: unit+subunit <--> index in xbus->xpds[]
- */
- #define XPD_IDX(unit,subunit) ((unit) * MAX_SUBUNIT + (subunit))
- #define XBUS_UNIT(idx) ((idx) / MAX_SUBUNIT)
- #define XBUS_SUBUNIT(idx) ((idx) % MAX_SUBUNIT)
- xpd_t *xpd_of(const xbus_t *xbus, int xpd_num);
- xpd_t *xpd_byaddr(const xbus_t *xbus, uint unit, uint subunit);
- int xbus_check_unique(xbus_t *xbus);
- bool xbus_setstate(xbus_t *xbus, enum xbus_state newstate);
- bool xbus_setflags(xbus_t *xbus, int flagbit, bool on);
- xbus_t *xbus_new(struct xbus_ops *ops, ushort max_send_size, struct device *transport_device, void *priv);
- void xbus_free(xbus_t *xbus);
- int xbus_connect(xbus_t *xbus);
- int xbus_activate(xbus_t *xbus);
- void xbus_deactivate(xbus_t *xbus);
- void xbus_disconnect(xbus_t *xbus);
- void xbus_receive_xframe(xbus_t *xbus, xframe_t *xframe);
- int xbus_process_worker(xbus_t *xbus);
- int waitfor_xpds(xbus_t *xbus, char *buf);
- int xbus_xpd_bind(xbus_t *xbus, xpd_t *xpd, int unit, int subunit);
- int xbus_xpd_unbind(xbus_t *xbus, xpd_t *xpd);
- /* sysfs */
- int xpd_device_register(xbus_t *xbus, xpd_t *xpd);
- void xpd_device_unregister(xpd_t *xpd);
- int xpp_driver_init(void);
- void xpp_driver_exit(void);
- int xbus_sysfs_transport_create(xbus_t *xbus);
- void xbus_sysfs_transport_remove(xbus_t *xbus);
- int xbus_sysfs_create(xbus_t *xbus);
- void xbus_sysfs_remove(xbus_t *xbus);
- #ifdef OLD_HOTPLUG_SUPPORT_269
- /* Copy from new kernels lib/kobject_uevent.c */
- enum kobject_action {
- KOBJ_ADD,
- KOBJ_REMOVE,
- KOBJ_CHANGE,
- KOBJ_MOUNT,
- KOBJ_UMOUNT,
- KOBJ_OFFLINE,
- KOBJ_ONLINE,
- };
- #endif
- void astribank_uevent_send(xbus_t *xbus, enum kobject_action act);
- #endif /* XBUS_CORE_H */
|