u-isdn/streams/stream.h

614 lines
20 KiB
C

#if !defined(_LINUX_STREAMS_H)
#define _LINUX_STREAMS_H
#include <linux/config.h>
#include <linux/types.h>
#include <linux/syscompat.h>
#include <linux/stropts.h>
#ifdef __KERNEL__
#include <linux/fs.h>
#include <linux/major.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
#if 0 /* not yet */
#include <linux/skbuff.h>
#define SK_STREAM
#endif
#define MAX_STRDEV MAX_CHRDEV /* don't change */
#define MAX_STRMOD MAX_CHRDEV /* change if necessary */
#else
#define MAX_STRMOD 32
#endif
#undef STREAMS_TTY /* Not yet */
#ifdef linux
#define ERR_DECL
#define ERR_RETURN(x) return (x)
#else
#define OPENFAIL (-1) /* compatibility */
#endif
#ifdef CONFIG_DEBUG_STREAMS
#define DEB_PMAGIC 0x13572469
#define DEB_DMAGIC 0x14582368
#endif
#define STREAM_MAGIC 0x53AA
#ifdef SK_STREAM
#define DATA_BLOCK(m) ((m)->b_skb)
#define DATA_START(m) ((m)->b_skb->head)
#define DATA_END(m) ((m)->b_skb->tail)
#define DATA_REFS(m) ((m)->b_skb->users)
#define DATA_TYPE(m) ((m)->b_skb->pkt_type)
#else
#define DATA_BLOCK(m) ((m)->b_datap)
#define DATA_START(m) ((m)->b_datap->db_base)
#define DATA_END(m) ((m)->b_datap->db_lim)
#define DATA_REFS(m) ((m)->b_datap->db_ref)
#define DATA_TYPE(m) ((m)->b_datap->db_type)
#endif
/*
* Grumble. Some Streams subsystems use signed characters, some unsigned.
*/
typedef unsigned char streamchar;
/*
* The following data structures are culled from various header files.
*/
/*
* Q_Flag bits
*/
#define QENAB 01 /* Queue is scheduled */
#define QWANTR 02 /* Someone wants to read */
#define QWANTW 04 /* Someone wants to write */
#define QFULL 010 /* Queue is full */
#define QREADR 020 /* This is the reader Queue */
#define QNOENB 040 /* Don't enable queue in putq */
#define QRETRY 0100 /* Timer to re-qenable() a queue if we're
temporarily out of resources */
/*
* module information
*/
struct module_info {
short mi_idnum; /* module id number */
char *mi_idname; /* module name */
char dummy1; /* Compatibility with old drivers */
char dummy2;
short mi_hiwat; /* hi-water mark */
short mi_lowat; /* lo-water mark */
};
/*
* flag bits
*/
#define SF_HANGUP 01 /* Hangup */
#define SF_MSGDISCARD 02 /* Read messages: discard rest */
#define SF_MSGKEEP 04 /* Read messages: keep rest */
#define SF_WAITOPEN 010 /* Wait for open to complete */
#define SF_WAITCLOSE 020 /* Wait for open to complete */
#define SF_PRIORITY 040 /* Reading a priority message */
#define SF_CTTY 0100 /* Create a controlling TTY on open? */
#define SF_IOCTL 0200 /* Waiting for ioctl to finish */
#define SF_PARTIALREAD 0400 /* partially read message in front */
#ifndef SK_STREAM
/*
* Data block descriptor
*/
typedef struct datab {
streamchar *db_base;
streamchar *db_lim;
uchar_t db_ref;
uchar_t db_type;
#ifdef CONFIG_DEBUG_STREAMS
long deb_magic;
#endif
} dblk_t;
#endif
/*
* Message block descriptor
*/
typedef struct msgb {
struct msgb *b_next;
struct msgb *b_prev;
struct msgb *b_cont;
#ifdef SK_STREAM
struct sk_buff *b_skb;
#else
struct datab *b_datap;
#endif
#ifdef CONFIG_DEBUG_STREAMS
long deb_magic;
struct queue *deb_queue;
const char *deb_file;
unsigned int deb_line;
#endif
streamchar *b_rptr;
streamchar *b_wptr;
} mblk_t;
/*
* stream information
*/
struct streamtab {
struct qinit *st_rdinit;
struct qinit *st_wrinit;
void *dummy1;
void *dummy2;
};
/*
* stream header -- interface to the system. This is Linux specific.
*/
struct stream_header {
int magic;
struct stream_header *prev;
struct stream_header *next;
struct queue *write_queue; /* write queue */
struct msgb *iocblk; /* data block for ioctl */
struct inode *inode; /* One of the inodes this was opened with */
#if 0
struct streamtab *strtab; /* driver's data -- needed for muxing */
#endif
struct wait_queue *waiting; /* Waiting for open/close to complete */
struct wait_queue *reading; /* Waiting for data in RD queue */
struct wait_queue *writing; /* Waiting for room in WR queue */
struct wait_queue *ioctling; /* Waiting for IOCTL to finish */
struct tty_struct *tty; /* terminal data */
struct fasync_struct *fasync; /* async calls */
mblk_t *write_buf;
long ioctl_id; /* ioctl id */
int error; /* hangup or error to set u.u_error */
ushort_t push_count; /* # modules */
ushort_t count; /* # times this has been opened */
ushort_t flag; /* state/flags */
ushort_t write_offset; /* write offset for downstream data */
ushort_t ref; /* reference count */
uchar_t wait; /* time to timeout */
};
/*
* data queue
*/
typedef struct queue {
struct qinit *q_qinfo; /* queue limits and procedures */
struct msgb *q_first; /* first data block */
struct msgb *q_last; /* last data block */
struct queue *q_next; /* next stream to send data to */
struct queue *q_link; /* next scheduled stream */
caddr_t q_ptr; /* private data structure for driver/module */
#ifdef NEW_TIMEOUT
long q_retry; /* redo a service proc when temp-out-of-space */
#endif
short q_count; /* number of queued bytes */
ushort_t q_flag; /* queue state */
short q_hiwat; /* queue high water mark */
short q_lowat; /* queue low water mark */
} queue_t;
/*
* queue information
*/
typedef int (qf_open)(queue_t *,dev_t,int,int);
typedef void (qf_close)(queue_t *,int);
typedef void (qf_put)(queue_t *,mblk_t *);
typedef void (qf_srv)(queue_t *);
struct qinit {
qf_put *qi_putp;
qf_srv *qi_srvp;
qf_open *qi_qopen;
qf_close *qi_qclose;
void *dummy1; /* (*qadmin)() */
struct module_info *qi_minfo; /* module information */
void *dummy2;
};
/****************
* Message types.
*/
/*
* Regular priority, data
*/
#define M_DATA 00 /* regular data */
#define M_PROTO 01 /* protocol control */
#define M_SPROTO 02 /* strippable protocol control */
/*
* , control
*/
#define M_BREAK 010 /* line break */
#define M_SIG 013 /* generate signal */
#define M_DELAY 014 /* real-time xmit delay (1 param) */
#define M_CTL 015 /* device-specific control message */
#define M_IOCTL 016 /* ioctl; set/get params */
#define M_SETOPTS 020 /* set various stream head options */
#define M_ADMIN 030 /* administration (out of stream) */
/*
* Expedited messages
*/
#define M_EXPROTO 0100 /* expedited protocol control */
#define M_EXDATA 0101 /* expedited data */
#define M_EXSPROTO 0102 /* strippable expedited protocol control */
#define M_EXSIG 0103 /* generate process signal */
/*
* Priority messages: no flow control
*/
#define M_PCPROTO 0200 /* priority protocol control */
#define M_IOCACK 0201 /* acknowledge ioctl */
#define M_IOCNAK 0202 /* negative ioctl acknowledge */
#define M_PCSIG 0203 /* generate process signal */
#define M_FLUSH 0206 /* flush your queues */
#define M_STOP 0207 /* stop transmission immediately */
#define M_START 0210 /* restart transmission after stop */
#define M_HANGUP 0211 /* line disconnect */
#define M_ERROR 0212 /* fatal error used to set u.u_error */
/*
* Misc message type defines
*/
#define QNORM 0 /* normal messages */
#define QEXP 0100 /* expedited messages */
#define QPCTL 0200 /* priority cntrl messages */
/*
* IOCTL structure - this structure is the format of the M_IOCTL message type.
*/
struct iocblk {
int ioc_cmd; /* ioctl command type */
ushort_t ioc_uid; /* effective uid of user */
ushort_t ioc_gid; /* effective gid of user */
int ioc_id; /* ioctl id */
int ioc_count; /* count of bytes in data field */
int ioc_error; /* error code */
int ioc_rval; /* return value */
};
/*
* Options structure for M_SETOPTS message. This is sent upstream
* by driver to set stream head options.
*/
struct stroptions {
short so_flags; /* options to set */
short so_readopt; /* read option */
short so_wroff; /* write offset */
short so_hiwat; /* read queue high water mark */
short so_lowat; /* read queue low water mark */
};
/* flags for stream options set message */
#define SO_ALL 077 /* set all options */
#define SO_READOPT 01 /* set read opttion */
#define SO_WROFF 02 /* set write offset */
#define SO_HIWAT 020 /* set high water mark */
#define SO_LOWAT 040 /* set low water mark */
/********************************************************************************/
/* Miscellaneous parameters and flags */
/********************************************************************************/
/*
* Default timeout in seconds for ioctls and close
*/
#define STRTIMOUT 15
/*
* Stream head default high/low water marks
*/
#define STRHIGH 512
#define STRLOW 256
/* Compatibility... */
#define INFPSZ -1
/*
* Flags for flushq()
*/
#define FLUSHALL 1 /* flush all messages */
#define FLUSHDATA 0 /* don't flush control messages */
/*
* maximum ioctl data block size
*/
#define MAXIOCBSZ 1024
#if 0
/*
* Copy modes for tty and I_STR ioctls
*/
#define U_TO_K 01 /* User to Kernel */
#define K_TO_K 02 /* Kernel to Kernel */
#endif
/*
* Values for dev in open to indicate module open, clone open;
* return value for failure.
*/
#define DEVOPEN 0 /* open as a device */
#define MODOPEN 1 /* open as a module */
#define CLONEOPEN 2 /* open for clone, pick own minor device */
#if 0
#define FWDPUSH 3 /* forwarder push */
#define FWDPOP 4 /* forwarder pop */
#define FWDMNAME 5 /* forwarder I_MNAME */
#define FWDFIND 6 /* forwarder I_FIND */
#define FWDLOOK 7 /* forwarder I_LOOK */
/*
* Forwarder module ID range (do not use for non-forwarder modules)
*/
#define FORWARDERMIN 5000
#define FORWARDERMAX 5299
#endif
/*
* Block allocation priorities. Currently ignored.
*/
#define BPRI_LO 1
#define BPRI_MED 2
#define BPRI_HI 3
/*
* Turn off interrupt and Streams processing
*/
#ifdef CONFIG_DEBUG_STREAMS
#define splstr() deb_splstr(__FILE__,__LINE__)
extern int deb_splstr(const char *,unsigned int);
#else
#define splstr() spl((1<<STREAMS_BH)|(1<<IRQ_BH))
#endif
/*
* noenable - prevent queue from running.
* enableok - Let queue be runnable again.
* canenable - check if queue is runnable. DO NOT call qenable() unless canenable is true.
*/
#define noenable(p_queue) (p_queue)->q_flag |= QNOENB
#define enableok(p_queue) (p_queue)->q_flag &= ~QNOENB
#define canenable(p_queue) !((p_queue)->q_flag & QNOENB)
/*
* Getting related queues. RDQ and WRQ are safe versions of RD and WR.
*/
#define OTHERQ(p_queue) ((p_queue)->q_flag&QREADR? (p_queue)+1: (p_queue)-1)
#define RDQ(p_queue) ((p_queue)->q_flag&QREADR? (p_queue): (p_queue)-1)
#define WRQ(p_queue) ((p_queue)->q_flag&QREADR? (p_queue)+1: (p_queue))
#define WR(p_queue) ((p_queue)+1)
#define RD(p_queue) ((p_queue)-1)
/*
* Message priority.
*/
#define queclass(p_msg) (DATA_TYPE(p_msg) & (QPCTL | QEXP))
/*
* Free a queue (pair). WARNING: Call flushq() on both queues before doing this!
*/
/*
* The usual, except this is ANSI and we might be debugging.
*/
#ifdef CONFIG_DEBUG_STREAMS
#ifdef linux
#define STREAM_INVAL 0x0400 /* Linux */
#else
#define STREAM_INVAL 0x12345687
#endif
/* add invalid addresses appropriate for other kernels */
extern mblk_t *deb_rmvb(const char *, unsigned int, mblk_t *, mblk_t *);
#define rmvb(a,b) deb_rmvb(__FILE__,__LINE__,a,b)
extern mblk_t *deb_allocb(const char *, unsigned int, ushort,ushort);
#define allocb(a,b) deb_allocb(__FILE__,__LINE__,a,b)
extern int deb_testb(const char *, unsigned int, ushort,ushort);
#define testb(a,b) deb_testb(__FILE__,__LINE__,a,b)
extern void deb_freeb(const char *, unsigned int, mblk_t *);
#define freeb(a) deb_freeb(__FILE__,__LINE__,a)
extern void deb_freemsg(const char *, unsigned int, mblk_t *);
#define freemsg(a) deb_freemsg(__FILE__,__LINE__,a)
extern mblk_t *deb_dupb(const char *, unsigned int, mblk_t *);
#define dupb(a) deb_dupb(__FILE__,__LINE__,a)
extern mblk_t *deb_dupmsg(const char *, unsigned int, mblk_t *);
#define dupmsg(a) deb_dupmsg(__FILE__,__LINE__,a)
extern mblk_t *deb_copyb(const char *, unsigned int, mblk_t *);
#define copyb(a) deb_copyb(__FILE__,__LINE__,a)
extern mblk_t *deb_copymsg(const char *, unsigned int, mblk_t *);
#define copymsg(a) deb_copymsg(__FILE__,__LINE__,a)
extern mblk_t *deb_copybufb(const char *, unsigned int, mblk_t *);
#define copybufb(a) deb_copybufb(__FILE__,__LINE__,a)
extern mblk_t *deb_copybufmsg(const char *, unsigned int, mblk_t *);
#define copybufmsg(a) deb_copybufmsg(__FILE__,__LINE__,a)
extern int deb_pullupmsg(const char *, unsigned int, mblk_t *, short);
#define pullupmsg(a,b) deb_pullupmsg(__FILE__,__LINE__,a,b)
extern int deb_adjmsg(const char *, unsigned int, mblk_t *, short);
#define adjmsg(a,b) deb_adjmsg(__FILE__,__LINE__,a,b)
extern int deb_msgdsize(const char *, unsigned int, mblk_t *);
#define msgdsize(a) deb_msgdsize(__FILE__,__LINE__,a)
extern int deb_xmsgsize(const char *, unsigned int, mblk_t *);
#define xmsgsize(a) deb_xmsgsize(__FILE__,__LINE__,a)
extern mblk_t *deb_getq(const char *, unsigned int, queue_t *);
#define getq(a) deb_getq(__FILE__,__LINE__,a)
extern void deb_rmvq(const char *, unsigned int, queue_t *, mblk_t *);
#define rmvq(a,b) deb_rmvq(__FILE__,__LINE__,a,b)
extern void deb_flushq(const char *, unsigned int, queue_t *, int);
#define flushq(a,b) deb_flushq(__FILE__,__LINE__,a,b)
extern void deb_putq(const char *, unsigned int, queue_t *, mblk_t *);
static inline void putq(queue_t *q, mblk_t *p) { deb_putq("PUTQ",0,q,p); }
#define putq(a,b) deb_putq(__FILE__,__LINE__,a,b)
extern void deb_putbq(const char *, unsigned int, queue_t *, mblk_t *);
#define putbq(a,b) deb_putbq(__FILE__,__LINE__,a,b)
extern void deb_insq(const char *, unsigned int, queue_t *, mblk_t *, mblk_t *);
#define insq(a,b,c) deb_insq(__FILE__,__LINE__,a,b,c)
extern void deb_appq(const char *, unsigned int, queue_t *, mblk_t *, mblk_t *);
#define appq(a,b,c) deb_appq(__FILE__,__LINE__,a,b,c)
extern int deb_putctl(const char *, unsigned int, queue_t *, uchar_t);
#define putctl(a,b) deb_putctl(__FILE__,__LINE__,a,b)
extern int deb_putctlerr(const char *, unsigned int, queue_t *, int);
#define putctlerr(a,b) deb_putctlerr(__FILE__,__LINE__,a,b)
extern int deb_putctl1(const char *, unsigned int, queue_t *, uchar_t, streamchar);
#define putctl1(a,b,c) deb_putctl1(__FILE__,__LINE__,a,b,c)
extern int deb_canput(const char *, unsigned int, queue_t *);
#define canput(a) deb_canput(__FILE__,__LINE__,a)
extern queue_t *deb_backq(const char *, unsigned int, queue_t *);
#define backq(a) deb_backq(__FILE__,__LINE__,a)
extern queue_t *deb_allocq(const char *, unsigned int);
#define allocq() deb_allocq(__FILE__,__LINE__)
extern void deb_freeq(const char *, unsigned int, queue_t *q);
#define freeq(a) deb_freeq(__FILE__,__LINE__,a)
extern void deb_qreply(const char *, unsigned int, queue_t *p_queue, mblk_t *p_msg);
#define qreply(a,b) deb_qreply(__FILE__,__LINE__,a,b)
extern void deb_qenable(const char *, unsigned int, queue_t *p_queue);
#define qenable(a) deb_qenable(__FILE__,__LINE__,a)
extern void deb_runqueues(const char *, unsigned int);
#define runqueues() deb_runqueues(__FILE__,__LINE__)
extern int deb_qattach (const char *, unsigned int, struct streamtab *qinfo, queue_t * qp, dev_t dev, int flag);
#define qattach(a,b,c,d) deb_qattach(__FILE__,__LINE__,a,b,c,d)
extern void deb_qdetach (const char *, unsigned int, queue_t * qp, int clmode, int flag);
#define qdetach(a,b,c) deb_qdetach(__FILE__,__LINE__,a,b,c)
extern int deb_findmod(const char *, unsigned int, const char *);
#define findmod(a) deb_findmod(__FILE__,__LINE__,a)
extern int deb_qsize(const char *, unsigned int, queue_t *);
#define qsize(a) deb_qsize(__FILE__,__LINE__,a)
extern void deb_setq (const char *, unsigned int, queue_t *, struct qinit *, struct qinit *);
#define setq(a,b,c) deb_setq(__FILE__,__LINE__,a,b,c)
extern void deb_get_post (const char *, unsigned int, queue_t *);
#define get_post(a) deb_get_post(__FILE__,__LINE__,a)
#else /* !DEBUG */
extern mblk_t *rmvb(mblk_t *, mblk_t *); /* Remove a message block (2nd arg) from the message. */
extern mblk_t *allocb(ushort,ushort); /* Allocate a message */
extern int testb(ushort,ushort); /* Check if a message can be allocated */
extern void freeb(mblk_t *); /* Free a message block */
extern void freemsg(mblk_t *); /* Free a message list */
extern mblk_t *dupb(mblk_t *); /* Duplicate a message block */
extern mblk_t *dupmsg(mblk_t *); /* Duplicate a message */
extern mblk_t *copyb(mblk_t *); /* Copy a message block */
extern mblk_t *copymsg(mblk_t *); /* Copy a message */
extern mblk_t *copybufb(mblk_t *); /* Copy a message block */
extern mblk_t *copybufmsg(mblk_t *); /* Copy a message */
extern int pullupmsg(mblk_t *, short); /* Pull up the first N bytes */
extern int adjmsg(mblk_t *, short); /* Trim first/last(N<0) bytes */
extern int msgdsize(mblk_t *); /* # data bytes */
extern int xmsgsize(mblk_t *); /* # bytes of first msg block type */
extern mblk_t *getq(queue_t *); /* Remove first msg from queue */
extern void rmvq(queue_t *, mblk_t *); /* Remove this msg from queue */
extern void flushq(queue_t *, int); /* Flush messages */
extern void putq(queue_t *, mblk_t *); /* Append message to queue */
extern void putbq(queue_t *, mblk_t *); /* Put message back onto queue */
extern void insq(queue_t *, mblk_t *, mblk_t *);/* Insert message(3) before message(2) or at end */
extern void appq(queue_t *, mblk_t *, mblk_t *);/* Insert message(3) after message(2) or at start */
extern int putctl(queue_t *, uchar_t); /* Zero-byte ctl msg */
extern int putctlerr(queue_t *, int); /* Error msg */
extern int putctl1(queue_t *, uchar_t, streamchar);/* One-byte ctl msg */
extern int canput(queue_t *); /* Room in queue? */
extern queue_t *backq(queue_t *); /* Get the queue pointing to me */
extern queue_t *allocq(void); /* Allocate queues */
extern void freeq(queue_t *q); /* Free a queue pair */
extern void qreply(queue_t *p_queue, mblk_t *p_msg);/* Send a message back */
extern void qenable(queue_t *p_queue); /* Schedule a service procedure */
extern void runqueues(void); /* Schedule queues */
extern int qattach (struct streamtab *qinfo, queue_t * qp, dev_t dev, int flag);
extern void qdetach (queue_t * qp, int clmode, int flag);
extern int findmod(const char *); /* Find module name in fmodsw[] */
extern int qsize(queue_t *); /* Count messages on a queue */
extern void setq (queue_t *, struct qinit *, struct qinit *);/* set queue procs and params */
extern void get_post (queue_t *); /* postprocess after dequeuing a packet */
#endif
extern void qretry(queue_t *); /* reruns a queue */
extern void do_qretry(queue_t *); /* timeout proc for qretry */
extern int getclass(ushort); /* Message class of given size. Unimplemented; returns 1. */
extern int register_strdev (unsigned int major, struct streamtab *strtab, int nminor);
extern int unregister_strdev (unsigned int major, struct streamtab *strtab, int nminor);
extern int register_strmod (struct streamtab *strtab);
extern int unregister_strmod (struct streamtab *strtab);
#ifndef FMNAMESZ
#define FMNAMESZ 16
#endif
struct fmodsw {
char f_name[FMNAMESZ+1];
struct streamtab *f_str;
};
extern struct fmodsw fmod_sw[MAX_STRMOD];
extern int fmodcnt;
#ifdef __KERNEL__
extern struct file_operations streams_fops;
extern struct streamtab *fstr_sw[MAX_STRDEV];
#endif
extern int strmsgsz; /* maximum stream message size */
extern int nstrpush; /* maximum # of pushed modules */
extern volatile queue_t *sched_first, *sched_last;
#ifdef CONFIG_DEBUG_STREAMS
extern void putnext(queue_t *p_queue, mblk_t *p_msg);
extern void linkb(mblk_t *p_msg1, mblk_t *p_msg2);
extern mblk_t *unlinkb(mblk_t *p_msg);
#else
static inline void putnext(queue_t *p_queue, mblk_t *p_msg)
{
(*p_queue->q_next->q_qinfo->qi_putp)(p_queue->q_next, p_msg);
}
static inline void linkb(mblk_t *p_msg1, mblk_t *p_msg2)
{
if(p_msg1 == NULL || p_msg2 == NULL)
return;
while(p_msg1->b_cont != NULL)
p_msg1 = p_msg1->b_cont;
p_msg1->b_cont = p_msg2;
}
static inline mblk_t *unlinkb(mblk_t *p_msg)
{
mblk_t *p_nextmsg;
if(p_msg == NULL)
return NULL;
p_nextmsg = p_msg->b_cont;
p_msg->b_cont = NULL;
return p_nextmsg;
}
#endif /* DEBUG */
#endif /* __sys_stream_h */