📄 icn.c
字号:
/* $Id: icn.c,v 1.1.1.1 1999/11/15 13:42:15 vadim Exp $ * ISDN low-level module for the ICN active ISDN-Card. * * Copyright 1994-1998 by Fritz Elfert (fritz@isdn4linux.de) * * 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, 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. * * $Log: icn.c,v $ * Revision 1.1.1.1 1999/11/15 13:42:15 vadim * Initial import * * Revision 1.45.2.4 1998/11/05 22:13:02 fritz * Changed mail-address. * * Revision 1.45.2.3 1998/06/07 13:32:04 fritz * Minor bugfixes for broken Switches. * * Revision 1.45.2.2 1998/03/07 23:35:36 detabc * added the abc-extension to the linux isdn-kernel * for kernel-version 2.0.xx * DO NOT USE FOR HIGHER KERNELS-VERSIONS * all source-lines are switched with the define CONFIG_ISDN_WITH_ABC * (make config and answer ABC-Ext. Support (Compress,TCP-Keepalive ...) with yes * * you need also a modified isdnctrl-source the switch on the * features of the abc-extension * * please use carefully. more detail will be follow. * thanks * * Revision 1.45.2.1 1997/08/21 15:56:50 fritz * Synchronized 2.0.X branch with 2.0.31-pre7 * * Revision 1.45 1997/06/21 10:42:06 fritz * Added availability to select leased mode on only one channel. * * Revision 1.44 1997/03/30 16:51:26 calle * changed calls to copy_from_user/copy_to_user and removed verify_area * were possible. * * Revision 1.43 1997/03/21 18:27:04 fritz * Corrected parsing of incoming setup. * * Revision 1.42 1997/03/05 21:13:18 fritz * Bugfix: sndcount was not reset on hangup. * * Revision 1.41 1997/02/24 23:34:29 fritz * Bugfix in Layer1 error-recovery. * * Revision 1.40 1997/02/23 23:34:45 fritz * Minor bugfixes in debugging code. * * Revision 1.39 1997/02/23 16:21:56 fritz * Bugfix: Check for NULL pointer in icn_parse_status(). * * Revision 1.38 1997/02/11 18:29:31 fritz * Bugfix in D64S initialization. * * Revision 1.37 1997/02/10 22:43:20 fritz * Added plan and screen elements on ISDN_STAT_ICALL * * Revision 1.36 1997/02/10 21:31:20 fritz * Changed setup-interface (incoming and outgoing). * * Revision 1.35 1997/02/10 10:10:28 fritz * Changes for Kernel 2.1.X compatibility. * Enhanced initialization, can recover from * misconfiguration by other autoprobing drivers. * * Revision 1.34 1997/01/29 22:34:44 fritz * Cleanup, Corrected D64S setup of 2nd channel. * * Revision 1.33 1996/12/05 20:31:48 tsbogend * added handling of L2: DATA LINK LOST messages * * Revision 1.32 1996/11/14 23:49:18 fritz * Bugfix: copy_to_user/copy_from_user mismatch in debugging-ioctl. * * Revision 1.31 1996/11/13 02:36:25 fritz * Fixed a race condition in writecmd. * Some optimizations and cleanup. * * Revision 1.30 1996/10/22 23:14:09 fritz * Changes for compatibility to 2.0.X and 2.1.X kernels. * * Revision 1.29 1996/08/29 20:34:54 fritz * Bugfix in send queue management: * sndcount was not updated correctly. * Minor Bugfixes. * * Revision 1.28 1996/06/28 17:02:53 fritz * replaced memcpy_fromfs_toio. * * Revision 1.27 1996/06/25 18:38:59 fritz * Fixed function name in error message. * * Revision 1.26 1996/06/24 17:20:35 fritz * Bugfixes in pollbchan_send(): * - Using lock field of skbuff breaks networking. * - Added channel locking * - changed dequeuing scheme. * Eliminated misc. compiler warnings. * * Revision 1.25 1996/06/11 22:53:35 tsbogend * fixed problem with large array on stack * made the driver working on Linux/alpha * * Revision 1.24 1996/06/06 13:58:33 fritz * Changed code to be architecture independent * * Revision 1.23 1996/06/03 19:59:00 fritz * Fixed typos. * * Revision 1.22 1996/05/17 15:46:41 fritz * Removed own queue management. * Changed queue management to use sk_buffs. * * Revision 1.21 1996/05/02 04:01:20 fritz * Bugfix: * - icn_addcard() evaluated wrong driverId. * * Revision 1.20 1996/05/02 00:40:27 fritz * Major rewrite to support more than one card * with a single module. * Support for new firmware. * * Revision 1.19 1996/04/21 17:43:32 fritz * Changes for Support of new Firmware BRV3.02 * * Revision 1.18 1996/04/20 16:50:26 fritz * Fixed status-buffer overrun. * Misc. typos * * Revision 1.17 1996/02/11 02:39:04 fritz * Increased Buffer for status-messages. * Removed conditionals for HDLC-firmware. * * Revision 1.16 1996/01/22 05:01:55 fritz * Revert to GPL. * * Revision 1.15 1996/01/10 20:57:39 fritz * Bugfix: Loading firmware twice caused the device stop working. * * Revision 1.14 1995/12/18 18:23:37 fritz * Support for ICN-2B Cards. * Change for supporting user-settable service-octet. * * Revision 1.13 1995/10/29 21:41:07 fritz * Added support for DriverId's, added Jan's patches for Kernel versions. * * Revision 1.12 1995/04/29 13:07:35 fritz * Added support for new Euro-ISDN-firmware * * Revision 1.11 1995/04/23 13:40:45 fritz * Added support for SPV's. * Changed Dial-Command to support MSN's on DSS1-Lines. * * Revision 1.10 1995/03/25 23:23:24 fritz * Changed configurable Ports, to allow settings for DIP-Switch Cardversions. * * Revision 1.9 1995/03/25 23:17:30 fritz * Fixed race-condition in pollbchan_send * * Revision 1.8 1995/03/15 12:49:44 fritz * Added support for SPV's * Split pollbchan_work for calling send-routine directly * * Revision 1.7 1995/02/20 03:48:03 fritz * Added support of new request_region-function. * Minor bugfixes. * * Revision 1.6 1995/01/31 15:48:45 fritz * Added Cause-Messages to be signaled to upper layers. * Added Revision-Info on load. * * Revision 1.5 1995/01/29 23:34:59 fritz * Added stopdriver() and appropriate calls. * Changed printk-statements to support loglevels. * * Revision 1.4 1995/01/09 07:40:46 fritz * Added GPL-Notice * * Revision 1.3 1995/01/04 05:15:18 fritz * Added undocumented "bootload-finished"-command in download-code * to satisfy some brain-damaged icn card-versions. * * Revision 1.2 1995/01/02 02:14:45 fritz * Misc Bugfixes * * Revision 1.1 1994/12/14 17:56:06 fritz * Initial revision * */#include "icn.h"/* * Verbose bootcode- and protocol-downloading. */#undef BOOT_DEBUG/* * Verbose Shmem-Mapping. */#undef MAP_DEBUGstatic char*revision = "$Revision: 1.1.1.1 $";static int icn_addcard(int, char *, char *);/* * Free send-queue completely. * Parameter: * card = pointer to card struct * channel = channel number */static voidicn_free_queue(icn_card * card, int channel){ struct sk_buff_head *queue = &card->spqueue[channel]; struct sk_buff *skb; while ((skb = skb_dequeue(queue))) dev_kfree_skb(skb, FREE_WRITE); card->sndcount[channel] = 0;}/* Put a value into a shift-register, highest bit first. * Parameters: * port = port for output (bit 0 is significant) * val = value to be output * firstbit = Bit-Number of highest bit * bitcount = Number of bits to output */static inline voidicn_shiftout(unsigned short port, unsigned long val, int firstbit, int bitcount){ register u_char s; register u_char c; for (s = firstbit, c = bitcount; c > 0; s--, c--) OUTB_P((u_char) ((val >> s) & 1) ? 0xff : 0, port);}/* * disable a cards shared memory */static inline voidicn_disable_ram(icn_card * card){ OUTB_P(0, ICN_MAPRAM);}/* * enable a cards shared memory */static inline voidicn_enable_ram(icn_card * card){ OUTB_P(0xff, ICN_MAPRAM);}/* * Map a cards channel0 (Bank0/Bank8) or channel1 (Bank4/Bank12) */static inline voidicn_map_channel(icn_card * card, int channel){#ifdef MAP_DEBUG printk(KERN_DEBUG "icn_map_channel %d %d\n", dev.channel, channel);#endif if ((channel == dev.channel) && (card == dev.mcard)) return; if (dev.mcard) icn_disable_ram(dev.mcard); icn_shiftout(ICN_BANK, chan2bank[channel], 3, 4); /* Select Bank */ icn_enable_ram(card); dev.mcard = card; dev.channel = channel;#ifdef MAP_DEBUG printk(KERN_DEBUG "icn_map_channel done\n");#endif}/* * Lock a cards channel. * Return 0 if requested card/channel is unmapped (failure). * Return 1 on success. */static inline inticn_lock_channel(icn_card * card, int channel){ register int retval; ulong flags;#ifdef MAP_DEBUG printk(KERN_DEBUG "icn_lock_channel %d\n", channel);#endif save_flags(flags); cli(); if ((dev.channel == channel) && (card == dev.mcard)) { dev.chanlock++; retval = 1;#ifdef MAP_DEBUG printk(KERN_DEBUG "icn_lock_channel %d OK\n", channel);#endif } else { retval = 0;#ifdef MAP_DEBUG printk(KERN_DEBUG "icn_lock_channel %d FAILED, dc=%d\n", channel, dev.channel);#endif } restore_flags(flags); return retval;}/* * Release current card/channel lock */static inline voidicn_release_channel(void){ ulong flags;#ifdef MAP_DEBUG printk(KERN_DEBUG "icn_release_channel l=%d\n", dev.chanlock);#endif save_flags(flags); cli(); if (dev.chanlock > 0) dev.chanlock--; restore_flags(flags);}/* * Try to map and lock a cards channel. * Return 1 on success, 0 on failure. */static inline inticn_trymaplock_channel(icn_card * card, int channel){ ulong flags;#ifdef MAP_DEBUG printk(KERN_DEBUG "trymaplock c=%d dc=%d l=%d\n", channel, dev.channel, dev.chanlock);#endif save_flags(flags); cli(); if ((!dev.chanlock) || ((dev.channel == channel) && (dev.mcard == card))) { dev.chanlock++; icn_map_channel(card, channel); restore_flags(flags);#ifdef MAP_DEBUG printk(KERN_DEBUG "trymaplock %d OK\n", channel);#endif return 1; } restore_flags(flags);#ifdef MAP_DEBUG printk(KERN_DEBUG "trymaplock %d FAILED\n", channel);#endif return 0;}/* * Release current card/channel lock, * then map same or other channel without locking. */static inline voidicn_maprelease_channel(icn_card * card, int channel){ ulong flags;#ifdef MAP_DEBUG printk(KERN_DEBUG "map_release c=%d l=%d\n", channel, dev.chanlock);#endif save_flags(flags); cli(); if (dev.chanlock > 0) dev.chanlock--; if (!dev.chanlock) icn_map_channel(card, channel); restore_flags(flags);}/* Get Data from the B-Channel, assemble fragmented packets and put them * into receive-queue. Wake up any B-Channel-reading processes. * This routine is called via timer-callback from icn_pollbchan(). */static voidicn_pollbchan_receive(int channel, icn_card * card){ int mch = channel + ((card->secondhalf) ? 2 : 0); int eflag; int cnt; struct sk_buff *skb; if (icn_trymaplock_channel(card, mch)) { while (rbavl) { cnt = readb(&rbuf_l); if ((card->rcvidx[channel] + cnt) > 4000) { printk(KERN_WARNING "icn: (%s) bogus packet on ch%d, dropping.\n", CID, channel + 1); card->rcvidx[channel] = 0; eflag = 0; } else { memcpy_fromio(&card->rcvbuf[channel][card->rcvidx[channel]], &rbuf_d, cnt); card->rcvidx[channel] += cnt; eflag = readb(&rbuf_f); } rbnext; icn_maprelease_channel(card, mch & 2); if (!eflag) { if ((cnt = card->rcvidx[channel])) { if (!(skb = dev_alloc_skb(cnt))) { printk(KERN_WARNING "颿n: receive out of memory\n"); break; } memcpy(skb_put(skb, cnt), card->rcvbuf[channel], cnt); card->rcvidx[channel] = 0; card->interface.rcvcallb_skb(card->myid, channel, skb); } } if (!icn_trymaplock_channel(card, mch)) break; } icn_maprelease_channel(card, mch & 2); }}/* Send data-packet to B-Channel, split it up into fragments of * ICN_FRAGSIZE length. If last fragment is sent out, signal * success to upper layers via statcallb with ISDN_STAT_BSENT argument. * This routine is called via timer-callback from icn_pollbchan() or * directly from icn_sendbuf(). */static voidicn_pollbchan_send(int channel, icn_card * card){ int mch = channel + ((card->secondhalf) ? 2 : 0); int cnt; unsigned long flags; struct sk_buff *skb; isdn_ctrl cmd; if (!(card->sndcount[channel] || skb_queue_len(&card->spqueue[channel]))) return; if (icn_trymaplock_channel(card, mch)) { while (sbfree && (card->sndcount[channel] || skb_queue_len(&card->spqueue[channel]))) { save_flags(flags); cli();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -