/* $Id$ * * Basic declarations, defines and prototypes * * This file is (c) under GNU PUBLIC LICENSE * */ #ifndef _mISDN_HELPER_H #define _mISDN_HELPER_H #include #ifdef MISDN_MEMDEBUG #include "memdbg.h" #endif /* shortcut to report errors locations, sometime also used for debugging !FIXME! */ #define int_error() \ printk(KERN_ERR "mISDN: INTERNAL ERROR in %s:%d\n", \ __FILE__, __LINE__) /* shortcut to report errors locations with an additional message text */ #define int_errtxt(fmt, arg...) \ printk(KERN_ERR "mISDN: INTERNAL ERROR in %s:%d " fmt "\n", \ __FILE__, __LINE__, ## arg) /* cleanup SKB queues, return count of dropped packets */ static inline int discard_queue(struct sk_buff_head *q) { struct sk_buff *skb; int ret=0; while ((skb = skb_dequeue(q))) { dev_kfree_skb(skb); ret++; } return(ret); } /* allocate a SKB for DATA packets in the mISDN stack with enough headroom * the MEMDEBUG version is for debugging memory leaks in the mISDN stack */ #ifdef MISDN_MEMDEBUG #define alloc_stack_skb(s, r) __mid_alloc_stack_skb(s, r, __FILE__, __LINE__) static inline struct sk_buff * __mid_alloc_stack_skb(u_int size, u_int reserve, char *fn, int line) { struct sk_buff *skb; if (!(skb = __mid_alloc_skb(size + reserve, GFP_ATOMIC, fn, line))) #else static inline struct sk_buff * alloc_stack_skb(u_int size, u_int reserve) { struct sk_buff *skb; if (!(skb = alloc_skb(size + reserve, GFP_ATOMIC))) #endif printk(KERN_WARNING "%s(%d,%d): no skb size\n", __FUNCTION__, size, reserve); else skb_reserve(skb, reserve); return(skb); } /* * mISDN_set_dchannel_pid(mISDN_pid_t *pid, int protocol, int layermask) * * set default values for the D-channel protocol ID struct * * layermask - bitmask which layers should be set (default 0,1,2,3,4) * protocol - bitmask for special L2/L3 option (from protocol module parameter of L0 modules) */ extern void mISDN_set_dchannel_pid(mISDN_pid_t *, int, int); /* * int mISDN_get_lowlayer(int layermask) * * get the lowest layer number of a layermask * e.g layermask=0x0c returns 2 */ extern int mISDN_get_lowlayer(int); /* * int mISDN_get_up_layer(int layermask) * * get the next higher layer number, which is not part of the given layermask */ extern int mISDN_get_up_layer(int); /* * int mISDN_get_down_layer(int layermask) * * get the next lower layer number, which is not part of the given layermask */ extern int mISDN_get_down_layer(int); /* * int mISDN_layermask2layer(int layermask) * * translate bit position in layermask into the layernumber * only valid if only one bit in the mask was set */ extern int mISDN_layermask2layer(int); /* * int mISDN_get_protocol(mISDNstack_t *st, int layer) * * get the protocol value of layer in stack */ extern int mISDN_get_protocol(mISDNstack_t *, int); /* * int mISDN_HasProtocol(mISDNobject_t *obj, u_int protocol) * * test if given object can handle protocol * * return 0 if yes * */ extern int mISDN_HasProtocol(mISDNobject_t *, u_int); /* * int mISDN_SetHandledPID(mISDNobject_t *obj, mISDN_pid_t *pid) * * returns the layermask of the supported protocols of object * from the protocol ID struct */ extern int mISDN_SetHandledPID(mISDNobject_t *, mISDN_pid_t *); /* * mISDN_RemoveUsedPID(mISDN_pid_t *pid, mISDN_pid_t *used) * * remove the protocol values from struct which are also in the * struct */ extern void mISDN_RemoveUsedPID(mISDN_pid_t *, mISDN_pid_t *); /* * mISDN_init_instance(mISDNinstance_t *inst, mISDNobject_t *obj, void *data) * * initialisize the mISDNinstance_t struct */ extern void mISDN_init_instance(mISDNinstance_t *, mISDNobject_t *, void *, if_func_t *); /* returns the member count of a list */ static inline int count_list_member(struct list_head *head) { int cnt = 0; struct list_head *m; list_for_each(m, head) cnt++; return(cnt); } /* same as mISDN_HasProtocol, but for a pointer */ static inline int mISDN_HasProtocolP(mISDNobject_t *obj, int *PP) { if (!PP) { int_error(); return(-EINVAL); } return(mISDN_HasProtocol(obj, *PP)); } /* set primitiv and dinfo field of a internal (SKB) mISDN message */ static inline void mISDN_sethead(u_int prim, int dinfo, struct sk_buff *skb) { mISDN_head_t *hh = mISDN_HEAD_P(skb); hh->prim = prim; hh->dinfo = dinfo; } static inline int mISDN_send_message(void) {return 0;}; static inline int mISDN_send_data(void) {return 0;}; static inline int mISDN_sendup(void) {return 0;}; static inline int mISDN_sendup_newhead(void) {return 0;}; static inline int mISDN_senddown(void) {return 0;}; static inline int mISDN_senddown_newhead(void) {return 0;}; #define mISDN_queue_up(i, a, s) mISDN_queue_message(i, a | FLG_MSG_UP, s) #define mISDN_queue_down(i, a, s) mISDN_queue_message(i, a | FLG_MSG_DOWN, s) static inline int mISDN_queueup_newhead(mISDNinstance_t *inst, u_int aflag, u_int prim, int dinfo, struct sk_buff *skb) { mISDN_head_t *hh = mISDN_HEAD_P(skb); hh->prim = prim; hh->dinfo = dinfo; return(mISDN_queue_up(inst, aflag, skb)); } static inline int mISDN_queuedown_newhead(mISDNinstance_t *inst, u_int aflag, u_int prim, int dinfo, struct sk_buff *skb) { mISDN_head_t *hh = mISDN_HEAD_P(skb); hh->prim = prim; hh->dinfo = dinfo; return(mISDN_queue_down(inst, aflag, skb)); } /* allocate a mISDN message SKB with enough headroom and set the header fields * the MEMDEBUG version is for debugging memory leaks in the mISDN stack */ #ifdef MISDN_MEMDEBUG #define create_link_skb(p, d, l, dp, r) __mid_create_link_skb(p, d, l, dp, r, __FILE__, __LINE__) static inline struct sk_buff * __mid_create_link_skb(u_int prim, int dinfo, u_int len, void *dp, u_int reserve, char *fn, int line) { struct sk_buff *skb; mISDN_head_t *hh; if (!(skb = __mid_alloc_skb(len + reserve, GFP_ATOMIC, fn, line))) { #else static inline struct sk_buff * create_link_skb(u_int prim, int dinfo, u_int len, void *dp, u_int reserve) { struct sk_buff *skb; mISDN_head_t *hh; if (!(skb = alloc_skb(len + reserve, GFP_ATOMIC))) { #endif printk(KERN_WARNING "%s: no skb size %d+%d\n", __FUNCTION__, len, reserve); return(NULL); } else skb_reserve(skb, reserve); if (len) memcpy(skb_put(skb, len), dp, len); hh = mISDN_HEAD_P(skb); hh->prim = prim; hh->dinfo = dinfo; hh->len = len; return(skb); } /* allocate a SKB for a mISDN message with enough headroom * fill mesage data into this SKB and send it trough the interface * the MEMDEBUG version is for debugging memory leaks in the mISDN stack */ #ifdef MISDN_MEMDEBUG #define mISDN_queue_data(i, a, p, d, l, dp, r) __mid_queue_data(i, a, p, d, l, dp, r, __FILE__, __LINE__) static inline int __mid_queue_data(mISDNinstance_t *inst, u_int aflag, u_int prim, int dinfo, u_int len, void *dp, u_int reserve, char *fn, int line) { struct sk_buff *skb; int err; if (!(skb = __mid_create_link_skb(prim, dinfo, len, dp, reserve, fn, line))) #else static inline int mISDN_queue_data(mISDNinstance_t *inst, u_int aflag, u_int prim, int dinfo, u_int len, void *dp, u_int reserve) { struct sk_buff *skb; int err; if (!(skb = create_link_skb(prim, dinfo, len, dp, reserve))) #endif return(-ENOMEM); err = mISDN_queue_message(inst, aflag, skb); if (err) kfree_skb(skb); return(err); } /* L3 data struct helper functions */ extern signed int mISDN_l3_ie2pos(u_char); extern unsigned char mISDN_l3_pos2ie(int); extern void mISDN_initQ931_info(Q931_info_t *); #ifdef MISDN_MEMDEBUG #define mISDN_alloc_l3msg(a, b) __mid_alloc_l3msg(a, b, __FILE__, __LINE__) extern struct sk_buff *__mid_alloc_l3msg(int, u_char, char *, int); #else extern struct sk_buff *mISDN_alloc_l3msg(int, u_char); #endif extern void mISDN_AddvarIE(struct sk_buff *, u_char *); extern void mISDN_AddIE(struct sk_buff *, u_char, u_char *); extern void mISDN_LogL3Msg(struct sk_buff *); /* manager default handler helper macros */ #define PRIM_NOT_HANDLED(p) case p: break #define MGR_HASPROTOCOL_HANDLER(p,a,o) \ if ((MGR_HASPROTOCOL | REQUEST) == p) {\ if (a) {\ int prot = *((int *)a);\ return(mISDN_HasProtocol(o, prot));\ } else \ return(-EINVAL);\ } #endif /* _mISDN_HELPER_H */