1/* $Id: isdn_net.h,v 1.1.1.1 2007/08/03 18:52:36 Exp $ 2 * 3 * header for Linux ISDN subsystem, network related functions (linklevel). 4 * 5 * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de) 6 * Copyright 1995,96 by Thinking Objects Software GmbH Wuerzburg 7 * Copyright 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de) 8 * 9 * This software may be used and distributed according to the terms 10 * of the GNU General Public License, incorporated herein by reference. 11 * 12 */ 13 14 /* Definitions for hupflags: */ 15#define ISDN_WAITCHARGE 1 /* did not get a charge info yet */ 16#define ISDN_HAVECHARGE 2 /* We know a charge info */ 17#define ISDN_CHARGEHUP 4 /* We want to use the charge mechanism */ 18#define ISDN_INHUP 8 /* Even if incoming, close after huptimeout */ 19#define ISDN_MANCHARGE 16 /* Charge Interval manually set */ 20 21/* 22 * Definitions for Cisco-HDLC header. 23 */ 24 25#define CISCO_ADDR_UNICAST 0x0f 26#define CISCO_ADDR_BROADCAST 0x8f 27#define CISCO_CTRL 0x00 28#define CISCO_TYPE_CDP 0x2000 29#define CISCO_TYPE_SLARP 0x8035 30#define CISCO_SLARP_REQUEST 0 31#define CISCO_SLARP_REPLY 1 32#define CISCO_SLARP_KEEPALIVE 2 33 34extern char *isdn_net_new(char *, struct net_device *); 35extern char *isdn_net_newslave(char *); 36extern int isdn_net_rm(char *); 37extern int isdn_net_rmall(void); 38extern int isdn_net_stat_callback(int, isdn_ctrl *); 39extern int isdn_net_setcfg(isdn_net_ioctl_cfg *); 40extern int isdn_net_getcfg(isdn_net_ioctl_cfg *); 41extern int isdn_net_addphone(isdn_net_ioctl_phone *); 42extern int isdn_net_getphones(isdn_net_ioctl_phone *, char __user *); 43extern int isdn_net_getpeer(isdn_net_ioctl_phone *, isdn_net_ioctl_phone __user *); 44extern int isdn_net_delphone(isdn_net_ioctl_phone *); 45extern int isdn_net_find_icall(int, int, int, setup_parm *); 46extern void isdn_net_hangup(struct net_device *); 47extern void isdn_net_dial(void); 48extern void isdn_net_autohup(void); 49extern int isdn_net_force_hangup(char *); 50extern int isdn_net_force_dial(char *); 51extern isdn_net_dev *isdn_net_findif(char *); 52extern int isdn_net_rcv_skb(int, struct sk_buff *); 53extern int isdn_net_dial_req(isdn_net_local *); 54extern void isdn_net_writebuf_skb(isdn_net_local *lp, struct sk_buff *skb); 55extern void isdn_net_write_super(isdn_net_local *lp, struct sk_buff *skb); 56 57#define ISDN_NET_MAX_QUEUE_LENGTH 2 58 59/* 60 * is this particular channel busy? 61 */ 62static __inline__ int isdn_net_lp_busy(isdn_net_local *lp) 63{ 64 if (atomic_read(&lp->frame_cnt) < ISDN_NET_MAX_QUEUE_LENGTH) 65 return 0; 66 else 67 return 1; 68} 69 70/* 71 * For the given net device, this will get a non-busy channel out of the 72 * corresponding bundle. The returned channel is locked. 73 */ 74static __inline__ isdn_net_local * isdn_net_get_locked_lp(isdn_net_dev *nd) 75{ 76 unsigned long flags; 77 isdn_net_local *lp; 78 79 spin_lock_irqsave(&nd->queue_lock, flags); 80 lp = nd->queue; /* get lp on top of queue */ 81 spin_lock(&nd->queue->xmit_lock); 82 while (isdn_net_lp_busy(nd->queue)) { 83 spin_unlock(&nd->queue->xmit_lock); 84 nd->queue = nd->queue->next; 85 if (nd->queue == lp) { /* not found -- should never happen */ 86 lp = NULL; 87 goto errout; 88 } 89 spin_lock(&nd->queue->xmit_lock); 90 } 91 lp = nd->queue; 92 nd->queue = nd->queue->next; 93 local_bh_disable(); 94errout: 95 spin_unlock_irqrestore(&nd->queue_lock, flags); 96 return lp; 97} 98 99/* 100 * add a channel to a bundle 101 */ 102static __inline__ void isdn_net_add_to_bundle(isdn_net_dev *nd, isdn_net_local *nlp) 103{ 104 isdn_net_local *lp; 105 unsigned long flags; 106 107 spin_lock_irqsave(&nd->queue_lock, flags); 108 109 lp = nd->queue; 110// printk(KERN_DEBUG "%s: lp:%s(%p) nlp:%s(%p) last(%p)\n", 111// __FUNCTION__, lp->name, lp, nlp->name, nlp, lp->last); 112 nlp->last = lp->last; 113 lp->last->next = nlp; 114 lp->last = nlp; 115 nlp->next = lp; 116 nd->queue = nlp; 117 118 spin_unlock_irqrestore(&nd->queue_lock, flags); 119} 120/* 121 * remove a channel from the bundle it belongs to 122 */ 123static __inline__ void isdn_net_rm_from_bundle(isdn_net_local *lp) 124{ 125 isdn_net_local *master_lp = lp; 126 unsigned long flags; 127 128 if (lp->master) 129 master_lp = (isdn_net_local *) lp->master->priv; 130 131// printk(KERN_DEBUG "%s: lp:%s(%p) mlp:%s(%p) last(%p) next(%p) mndq(%p)\n", 132// __FUNCTION__, lp->name, lp, master_lp->name, master_lp, lp->last, lp->next, master_lp->netdev->queue); 133 spin_lock_irqsave(&master_lp->netdev->queue_lock, flags); 134 lp->last->next = lp->next; 135 lp->next->last = lp->last; 136 if (master_lp->netdev->queue == lp) { 137 master_lp->netdev->queue = lp->next; 138 if (lp->next == lp) { /* last in queue */ 139 master_lp->netdev->queue = master_lp->netdev->local; 140 } 141 } 142 lp->next = lp->last = lp; /* (re)set own pointers */ 143// printk(KERN_DEBUG "%s: mndq(%p)\n", 144// __FUNCTION__, master_lp->netdev->queue); 145 spin_unlock_irqrestore(&master_lp->netdev->queue_lock, flags); 146} 147 148static inline int 149put_u8(unsigned char *p, u8 x) 150{ 151 *p = x; 152 return 1; 153} 154 155static inline int 156put_u16(unsigned char *p, u16 x) 157{ 158 *((u16 *)p) = htons(x); 159 return 2; 160} 161 162static inline int 163put_u32(unsigned char *p, u32 x) 164{ 165 *((u32 *)p) = htonl(x); 166 return 4; 167} 168 169static inline int 170get_u8(unsigned char *p, u8 *x) 171{ 172 *x = *p; 173 return 1; 174} 175 176static inline int 177get_u16(unsigned char *p, u16 *x) 178{ 179 *x = ntohs(*((u16 *)p)); 180 return 2; 181} 182 183static inline int 184get_u32(unsigned char *p, u32 *x) 185{ 186 *x = ntohl(*((u32 *)p)); 187 return 4; 188} 189