]> git.neil.brown.name Git - history.git/commitdiff
Linux 2.2.3pre3 2.2.3pre3
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:18:20 +0000 (15:18 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:18:20 +0000 (15:18 -0500)
There's a new pre-patch for 2.2.3, one that I was already going to make
the final 2.2.3, but I decided that I'm chicken after all, and that I
might as well let some people check that it's sane.
This pre-2.2.3 does:

 - Fix some silly NFS problems. Some of them can be quite bad: lost error
   notification of asynchronous writes, which can result in horrible
   problems (including lost email etc). Most people wouldn't ever notice,
   so don't panic, but forgetting about the error notification certainly
   counts as a brown paper bag.
 - Alpha should compile and work again
 - Various driver updates. This is actually the bulk of the patch, with
   IRDA updates, some scsi, video and sound driver updates etc.
 - The "mmap forgets about the file that was mapped" bug that has been
   discussed here. Only affected certain drivers.
 - shaper atomicity fixes
 - various minor TCP fixes
 - buffer growth fix and recursive IO memory reclaim fix from Andrea
 - network filter compiles ;)
 - unix gc fixes

Tell me if you see problems, because I'm going to release it as 2.2.3
unless people tell me otherwise..

                Linus

167 files changed:
CREDITS
Documentation/Configure.help
Documentation/sound/CMI8330 [new file with mode: 0644]
Documentation/sound/VIBRA16 [new file with mode: 0644]
MAINTAINERS
arch/i386/defconfig
arch/i386/kernel/bios32.c
drivers/char/Config.in
drivers/char/Makefile
drivers/char/dtlk.c [new file with mode: 0644]
drivers/char/ftape/zftape/zftape-init.c
drivers/char/mem.c
drivers/char/misc.c
drivers/char/radio-aimslab.c
drivers/char/radio-aztech.c
drivers/net/Makefile
drivers/net/cosa.c
drivers/net/cosa.h
drivers/net/irda/Config.in
drivers/net/irda/Makefile
drivers/net/irda/actisys.c
drivers/net/irda/esi.c
drivers/net/irda/girbil.c [new file with mode: 0644]
drivers/net/irda/irport.c
drivers/net/irda/irtty.c
drivers/net/irda/pc87108.c
drivers/net/irda/tekram.c
drivers/net/irda/uircc.c
drivers/net/irda/w83977af_ir.c
drivers/net/ne.c
drivers/net/plip.c
drivers/net/sk_g16.c
drivers/pci/pci.c
drivers/sbus/char/flash.c
drivers/sbus/char/vfc_dev.c
drivers/scsi/ChangeLog.ncr53c8xx
drivers/scsi/README.ncr53c8xx
drivers/scsi/README.st
drivers/scsi/ncr53c8xx.c
drivers/scsi/ncr53c8xx.h
drivers/scsi/st.c
drivers/sound/Config.in
drivers/sound/ad1848.c
drivers/sound/ad1848_mixer.h
drivers/sound/es1370.c
drivers/sound/es1371.c
drivers/sound/lowlevel/awe_compat.h
drivers/sound/lowlevel/awe_wave.c
drivers/sound/mad16.c
drivers/sound/sb.h
drivers/sound/sb_card.c
drivers/sound/sb_common.c
drivers/sound/sb_mixer.c
drivers/sound/sequencer.c
drivers/sound/sonicvibes.c
drivers/sound/sound_core.c
drivers/sound/soundcard.c
drivers/sound/trix.c
drivers/video/atyfb.c
drivers/video/fbmem.c
drivers/video/igafb.c
drivers/video/sbusfb.c
fs/Config.in
fs/affs/inode.c
fs/affs/super.c
fs/dquot.c
fs/fat/mmap.c
fs/isofs/file.c
fs/ncpfs/mmap.c
fs/smbfs/cache.c
include/linux/awe_voice.h
include/linux/dtlk.h [new file with mode: 0644]
include/linux/miscdevice.h
include/linux/pci.h
include/net/br.h
include/net/irda/dongle.h
include/net/irda/ircomm_common.h
include/net/irda/irda.h
include/net/irda/irda_device.h
include/net/irda/iriap.h
include/net/irda/irias_object.h
include/net/irda/irlan_cli.h [deleted file]
include/net/irda/irlan_client.h [new file with mode: 0644]
include/net/irda/irlan_common.h
include/net/irda/irlan_eth.h
include/net/irda/irlan_event.h
include/net/irda/irlan_filter.h [new file with mode: 0644]
include/net/irda/irlan_provider.h [new file with mode: 0644]
include/net/irda/irlan_srv.h [deleted file]
include/net/irda/irlap.h
include/net/irda/irlap_event.h
include/net/irda/irlmp.h
include/net/irda/irlmp_event.h
include/net/irda/irlmp_frame.h
include/net/irda/irlpt_cli.h
include/net/irda/irlpt_cli_fsm.h
include/net/irda/irlpt_common.h
include/net/irda/irlpt_server.h
include/net/irda/irlpt_server_fsm.h
include/net/irda/irmod.h
include/net/irda/irobex.h
include/net/irda/irttp.h
include/net/irda/irtty.h
include/net/irda/pc87108.h
include/net/irda/timer.h
include/net/irda/wrapper.h
mm/filemap.c
mm/mmap.c
mm/swapfile.c
net/Makefile
net/ax25/af_ax25.c
net/bridge/br.c
net/bridge/br_tree.c
net/core/scm.c
net/core/skbuff.c
net/core/sock.c
net/econet/econet.c
net/ipv4/Config.in
net/ipv4/arp.c
net/ipv4/icmp.c
net/ipv4/tcp.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_output.c
net/ipv6/tcp_ipv6.c
net/irda/Makefile
net/irda/af_irda.c
net/irda/ircomm/attach.c
net/irda/ircomm/ircomm_common.c
net/irda/irda_device.c
net/irda/iriap.c
net/irda/iriap_event.c
net/irda/irlan/Config.in
net/irda/irlan/Makefile
net/irda/irlan/irlan_cli.c [deleted file]
net/irda/irlan/irlan_cli_event.c [deleted file]
net/irda/irlan/irlan_client.c [new file with mode: 0644]
net/irda/irlan/irlan_client_event.c [new file with mode: 0644]
net/irda/irlan/irlan_common.c
net/irda/irlan/irlan_eth.c
net/irda/irlan/irlan_event.c
net/irda/irlan/irlan_filter.c [new file with mode: 0644]
net/irda/irlan/irlan_provider.c [new file with mode: 0644]
net/irda/irlan/irlan_provider_event.c [new file with mode: 0644]
net/irda/irlan/irlan_srv.c [deleted file]
net/irda/irlan/irlan_srv_event.c [deleted file]
net/irda/irlap.c
net/irda/irlap_comp.c
net/irda/irlap_event.c
net/irda/irlap_frame.c
net/irda/irlmp.c
net/irda/irlmp_event.c
net/irda/irlmp_frame.c
net/irda/irlpt/irlpt_cli.c
net/irda/irlpt/irlpt_cli_fsm.c
net/irda/irlpt/irlpt_common.c
net/irda/irlpt/irlpt_srvr.c
net/irda/irlpt/irlpt_srvr_fsm.c
net/irda/irmod.c
net/irda/irobex/irobex.c
net/irda/irproc.c
net/irda/irqueue.c
net/irda/irsysctl.c
net/irda/irttp.c
net/irda/qos.c
net/irda/timer.c
net/irda/wrapper.c

diff --git a/CREDITS b/CREDITS
index 3984ee2778bdfbf45333fff91a411483094c4402..f98666c4378a2fdc0f99d7942b3182bfa891aef4 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -1061,6 +1061,14 @@ S: Markham, Ontario
 S: L3R 8B2
 S: Canada
 
+N: Russell Kroll
+E: rkroll@exploits.org
+W: http://www.exploits.org/
+D: V4L Aztech radio card driver, mods to Aimslab driver
+S: Post Office Box 49458
+S: Colorado Springs, Colorado 80949-9458
+S: USA
+
 N: Gero Kuhlmann
 E: gero@gkminix.han.de
 D: mounting root via NFS
@@ -2004,6 +2012,14 @@ S: Chudenicka 8
 S: 10200 Prague 10, Hostivar
 S: Czech Republic
 
+N: James R. Van Zandt
+E: jrv@vanzandt.mv.com
+P: 1024/E298966D F0 37 4F FD E5 7E C5 E6  F1 A0 1E 22 6F 46 DA 0C
+D: Author and maintainer of the Double Talk speech synthesizer driver
+S: 27 Spencer Drive
+S: Nashua, New Hampshire 03062
+S: USA
+
 N: Andrew Veliath
 E: andrewtv@usa.net
 D: Turtle Beach MultiSound sound driver
index 5368897871ece051b6fe1726e2bcd3e42b6c6509..cf504364cb614cbdad4ab4e9c5cb98a0b66badec 100644 (file)
@@ -8466,6 +8466,15 @@ CONFIG_SUN_ZS
   This driver does not exist at this point, so you might as well 
   say N.
 
+Double Talk PC internal speech card support
+CONFIG_DTLK
+  This driver is for the DoubleTalk PC, a speech synthesizer
+  manufactured by RC Systems (http://www.rcsys.com/).  It is also
+  called the `internal DoubleTalk'.  If you want to compile this as a
+  module ( = code which can be inserted in and removed from the
+  running kernel whenever you want), say M here and read
+  Documentation/modules.txt. The module will be called dtlk.o.
+
 Advanced Power Management
 CONFIG_APM
   APM is a BIOS specification for saving power using several different
diff --git a/Documentation/sound/CMI8330 b/Documentation/sound/CMI8330
new file mode 100644 (file)
index 0000000..43b1c5a
--- /dev/null
@@ -0,0 +1,86 @@
+How to enable CMI 8330 soundchip on Linux
+------------------------------------------
+Stefan Laudat <Stefan.Laudat@asit.ro>
+
+Hello folks, 
+       
+       The CMI8330 soundchip is a very small chip found on many recent 
+       motherboards. In order to use it you just have to use a proper 
+        isapnp.conf and a little bit of patience. 
+       
+       Of course you will have to compile kernel sound support as module, 
+        as shown below:
+
+CONFIG_SOUND=m
+CONFIG_SOUND_OSS=m
+CONFIG_SOUND_SB=m
+CONFIG_SOUND_ADLIB=m
+CONFIG_SOUND_MPU401=m
+# Just for fun :)
+CONFIG_SOUND_MSS=m
+
+       The /etc/isapnp.conf file will be:
+
+<snip below>
+
+(READPORT 0x0203)
+(ISOLATE PRESERVE)
+(IDENTIFY *)
+(VERBOSITY 2)
+(CONFLICT (IO FATAL)(IRQ FATAL)(DMA FATAL)(MEM FATAL)) # or WARNING
+(VERIFYLD N)
+# WSS 
+
+(CONFIGURE CMI0001/16777472 (LD 0
+(IO 0 (SIZE 8) (BASE 0x0530))
+(IO 1 (SIZE 8) (BASE 0x0388))
+(INT 0 (IRQ 5 (MODE +E)))
+(DMA 0 (CHANNEL 0))
+(NAME "CMI0001/16777472[0]{CMI8330/C3D Audio Adapter}")
+(ACT Y)
+))
+
+# Control device ? 
+
+(CONFIGURE CMI0001/16777472 (LD 1
+(IO 0 (SIZE 2) (BASE 0x0330))
+(INT 0 (IRQ 11 (MODE +E)))
+(NAME "CMI0001/16777472[1]{CMI8330/C3D Audio Adapter}")
+(ACT Y)
+))
+
+# Joystick
+
+(CONFIGURE CMI0001/16777472 (LD 2
+(IO 0 (SIZE 8) (BASE 0x0200))
+(NAME "CMI0001/16777472[2]{CMI8330/C3D Audio Adapter}")
+(ACT Y)
+))
+
+#  SB... 
+(CONFIGURE CMI0001/16777472 (LD 3
+(IO 0 (SIZE 16) (BASE 0x0220))
+(INT 0 (IRQ 7 (MODE +E)))
+(DMA 0 (CHANNEL 1))
+(DMA 1 (CHANNEL 5))
+(NAME "CMI0001/16777472[3]{CMI8330/C3D Audio Adapter}")
+(ACT Y)
+))
+
+
+(WAITFORKEY)
+
+<end of snip>
+
+       The module sequence is trivial:
+
+/sbin/modprobe sound
+# You need to load the ad1848 module first. That matters, otherwise the 
+# chip falls into soundblaster compatibility and you won't get it back out
+/sbin/insmod ad1848 io=0x530 dma=0 irq=5 soundpro=1
+/sbin/insmod uart401
+/sbin/insmod sb io=0x220 irq=5 dma=1 dma16=-1
+/sbin/insmod mpu401 io=0x330
+/sbin/insmod opl3 io=0x388
+
+       The soundchip is now fully initialized. Enjoy it.
diff --git a/Documentation/sound/VIBRA16 b/Documentation/sound/VIBRA16
new file mode 100644 (file)
index 0000000..0a0aff9
--- /dev/null
@@ -0,0 +1,80 @@
+Sound Blaster 16X Vibra addendum
+--------------------------------
+by Marius Ilioaea <mariusi@protv.ro>
+   Stefan Laudat  <stefan@asit.ro>
+
+Sat Mar 6 23:55:27 EET 1999
+
+                       Hello again,
+       
+       Playing with a SB Vibra 16x soundcard we found it very difficult
+to setup because the kernel reported a lot of DMA errors and wouldn't
+simply play any sound.
+       A good starting point is that the vibra16x chip full-duplex facility
+is neither still exploited by the sb driver found in the linux kernel 
+(tried it with a 2.2.2-ac7), nor in the commercial OSS package (it reports
+it as half-duplex soundcard). Oh, I almost forgot, the RedHat sndconfig
+failed detecting it ;)
+       So, the big problem still remains, because the sb module wants a
+8-bit and a 16-bit dma, which we could not allocate for vibra... it supports
+only two 8-bit dma channels, the second one will be passed to the module
+as a 16 bit channel, the kernel will yield about that but everything will
+be okay, trust us. 
+       The only inconvenient you may find is that you will have
+some sound playing jitters if you have HDD dma support enabled - but this
+will happen with almost all soundcards...
+
+       A fully working isapnp.conf is just here:
+
+<snip here>
+
+(READPORT 0x0203)
+(ISOLATE PRESERVE)
+(IDENTIFY *)
+(VERBOSITY 2)
+(CONFLICT (IO FATAL)(IRQ FATAL)(DMA FATAL)(MEM FATAL)) # or WARNING
+# SB 16 and OPL3 devices
+(CONFIGURE CTL00f0/-1 (LD 0
+(INT 0 (IRQ 5 (MODE +E)))
+(DMA 0 (CHANNEL 1))
+(DMA 1 (CHANNEL 3))
+(IO 0 (SIZE 16) (BASE 0x0220))
+(IO 2 (SIZE 4) (BASE 0x0388))
+(NAME "CTL00f0/-1[0]{Audio               }")
+(ACT Y)
+))
+
+# Joystick device - only if you need it :-/
+
+(CONFIGURE CTL00f0/-1 (LD 1
+(IO 0 (SIZE 1) (BASE 0x0200))
+(NAME "CTL00f0/-1[1]{Game                }")
+(ACT Y)
+))
+(WAITFORKEY)
+
+<end of snipping>
+
+       So, after a good kernel modules compilation and a 'depmod -a kernel_ver'
+you may want to:
+
+modprobe sb io=0x220 irq=5 dma=1 dma16=3
+
+       Or, take the hard way:
+
+insmod souncore
+insmod sound
+insmod uart401
+insmod sb io=0x220 irq=5 dma=1 dma16=3
+# do you need MIDI?
+insmod opl3=0x388
+
+       Just in case, the kernel sound support should be:
+
+CONFIG_SOUND=m
+CONFIG_SOUND_OSS=m
+CONFIG_SOUND_SB=m
+       
+       Enjoy your new noisy Linux box! ;)
+       
+
index 137de4bcd958e2c54e58e5c2ff6849480cadf5ae..b743736c09a12f28a427d1dbd732a9afb296e80b 100644 (file)
@@ -246,6 +246,12 @@ M: mvw@planets.elm.net
 L:     linux-kernel@vger.rutgers.edu
 S:     Maintained
 
+DOUBLETALK DRIVER
+P:     James R. Van Zandt
+M:     jrv@vanzandt.mv.com
+L:     blinux-list@redhat.com
+S:     Maintained
+
 EATA-DMA SCSI DRIVER
 P:     Michael Neuffer
 M:     mike@i-Connect.Net
index 696de8ddcb84909c9c94d0d82cc18c4b699ed762..6ecccdf8cbf7cd1661aa4fac5387f2f06b8de772 100644 (file)
@@ -120,7 +120,6 @@ CONFIG_INET=y
 # (it is safe to leave these untouched)
 #
 # CONFIG_INET_RARP is not set
-CONFIG_IP_NOSR=y
 CONFIG_SKB_LARGE=y
 
 #
@@ -283,6 +282,7 @@ CONFIG_82C710_MOUSE=y
 # Joystick support
 #
 # CONFIG_JOYSTICK is not set
+# CONFIG_DTLK is not set
 
 #
 # Ftape, the floppy tape device driver
index e7383e55b213143c7dcfa822764df63c03078e2d..9bf2fdce2ba6aceaa0a2815aeb96384daaf38a79 100644 (file)
@@ -14,7 +14,7 @@
  *     Hannover, Germany
  *     hm@ix.de
  *
- * Copyright 1997, 1998 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ * Copyright 1997--1999 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
  *
  * For more information, please consult the following manuals (look at
  * http://www.pcisig.com/ for how to get them):
  *     a large gallery of common hardware bug workarounds (watch the comments)
  *     -- the PCI specs themselves are sane, but most implementors should be
  *     hit hard with \hammer scaled \magstep5. [mj]
+ *
+ * Jan 23, 1999 : More improvements to peer host bridge logic. i450NX fixup. [mj]
+ *
+ * Feb 8,  1999 : Added UM8886BF I/O address fixup. [mj]
  */
 
 #include <linux/config.h>
@@ -171,6 +175,7 @@ PCI_STUB(write, dword, u32)
 #define PCI_NO_SORT 0x100
 #define PCI_BIOS_SORT 0x200
 #define PCI_NO_CHECKS 0x400
+#define PCI_NO_PEER_FIXUP 0x800
 
 static unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2;
 
@@ -521,6 +526,8 @@ static struct {
        unsigned short segment;
 } pci_indirect = { 0, __KERNEL_CS };
 
+static int pci_bios_present;
+
 __initfunc(static int check_pcibios(void))
 {
        u32 signature, eax, ebx, ecx;
@@ -803,7 +810,7 @@ __initfunc(static struct pci_access *pci_find_bios(void))
  * which used BIOS ordering, we are bound to do this...
  */
 
-__initfunc(void pcibios_sort(void))
+static void __init pcibios_sort(void)
 {
        struct pci_dev *dev = pci_devices;
        struct pci_dev **last = &pci_devices;
@@ -856,7 +863,7 @@ __initfunc(void pcibios_sort(void))
 
 static int pci_last_io_addr __initdata = 0x5800;
 
-__initfunc(void pcibios_fixup_io_addr(struct pci_dev *dev, int idx))
+static void __init pcibios_fixup_io_addr(struct pci_dev *dev, int idx)
 {
        unsigned short cmd;
        unsigned int reg = PCI_BASE_ADDRESS_0 + 4*idx;
@@ -868,13 +875,16 @@ __initfunc(void pcibios_fixup_io_addr(struct pci_dev *dev, int idx))
                printk("PCI: Unassigned I/O space for %02x:%02x\n", bus, devfn);
                return;
        }
-       if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && idx < 4) {
+       if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && idx < 4 ||
+           (dev->class >> 8) == PCI_CLASS_DISPLAY_VGA) {
                /*
                 * In case the BIOS didn't assign an address 0--3 to an IDE
                 * controller, we don't try to fix it as it means "use default
                 * addresses" at least with several broken chips and the IDE
                 * driver needs the original settings to recognize which devices
                 * correspond to the primary controller.
+                *
+                * We don't assign VGA I/O ranges as well.
                 */
                return;
        }
@@ -914,7 +924,7 @@ __initfunc(void pcibios_fixup_io_addr(struct pci_dev *dev, int idx))
  * expected to be unique) and remove the ghost devices.
  */
 
-__initfunc(void pcibios_fixup_ghosts(struct pci_bus *b))
+static void __init pcibios_fixup_ghosts(struct pci_bus *b)
 {
        struct pci_dev *d, *e, **z;
        int mirror = PCI_DEVFN(16,0);
@@ -954,12 +964,17 @@ __initfunc(void pcibios_fixup_ghosts(struct pci_bus *b))
  * the reality doesn't pass this test and the bus number is usually
  * set by BIOS to the first free value.
  */
-__initfunc(void pcibios_fixup_peer_bridges(void))
+static void __init pcibios_fixup_peer_bridges(void)
 {
        struct pci_bus *b = &pci_root;
        int i, n, cnt=-1;
        struct pci_dev *d;
 
+#ifdef CONFIG_VISWS
+       pci_scan_peer_bridge(1);
+       return;
+#endif
+
 #ifdef CONFIG_PCI_DIRECT
        /*
         * Don't search for peer host bridges if we use config type 2
@@ -969,6 +984,7 @@ __initfunc(void pcibios_fixup_peer_bridges(void))
        if (access_pci == &pci_direct_conf2)
                return;
 #endif
+
        for(d=b->devices; d; d=d->sibling)
                if ((d->class >> 8) == PCI_CLASS_BRIDGE_HOST)
                        cnt++;
@@ -979,6 +995,20 @@ __initfunc(void pcibios_fixup_peer_bridges(void))
                for(i=0; i<256; i += 8)
                        if (!pcibios_read_config_word(n, i, PCI_VENDOR_ID, &l) &&
                            l != 0x0000 && l != 0xffff) {
+#ifdef CONFIG_PCI_BIOS
+                               if (pci_bios_present) {
+                                       int succ, idx = 0;
+                                       u8 bios_bus, bios_dfn;
+                                       u16 d;
+                                       pcibios_read_config_word(n, i, PCI_DEVICE_ID, &d);
+                                       DBG("BIOS test for %02x:%02x (%04x:%04x)\n", n, i, l, d);
+                                       while ((succ = pci_bios_find_device(l, d, idx, &bios_bus, &bios_dfn)) &&
+                                              (bios_bus != n || bios_dfn != i))
+                                               idx++;
+                                       if (!succ)
+                                               break;
+                               }
+#endif
                                DBG("Found device at %02x:%02x\n", n, i);
                                found++;
                                if (!pcibios_read_config_word(n, i, PCI_CLASS_DEVICE, &l) &&
@@ -989,25 +1019,83 @@ __initfunc(void pcibios_fixup_peer_bridges(void))
                        break;
                if (found) {
                        printk("PCI: Discovered primary peer bus %02x\n", n);
-                       b = kmalloc(sizeof(*b), GFP_KERNEL);
-                       memset(b, 0, sizeof(*b));
-                       b->next = pci_root.next;
-                       pci_root.next = b;
-                       b->number = b->secondary = n;
-                       b->subordinate = 0xff;
-                       b->subordinate = pci_scan_bus(b);
+                       b = pci_scan_peer_bridge(n);
                        n = b->subordinate;
                }
                n++;
        }
 }
 
+/*
+ * Exceptions for specific devices. Usually work-arounds for fatal design flaws.
+ */
+
+static void __init pci_fixup_i450nx(struct pci_dev *d)
+{
+       /*
+        * i450NX -- Find and scan all secondary buses on all PXB's.
+        */
+       int pxb, reg;
+       u8 busno, suba, subb;
+       reg = 0xd0;
+       for(pxb=0; pxb<2; pxb++) {
+               pci_read_config_byte(d, reg++, &busno);
+               pci_read_config_byte(d, reg++, &suba);
+               pci_read_config_byte(d, reg++, &subb);
+               DBG("i450NX PXB %d: %02x/%02x/%02x\n", pxb, busno, suba, subb);
+               if (busno)
+                       pci_scan_peer_bridge(busno);    /* Bus A */
+               if (suba < subb)
+                       pci_scan_peer_bridge(suba+1);   /* Bus B */
+       }
+       pci_probe |= PCI_NO_PEER_FIXUP;
+}
+
+static void __init pci_fixup_umc_ide(struct pci_dev *d)
+{
+       /*
+        * UM8886BF IDE controller sets region type bits incorrectly,
+        * therefore they look like memory despite of them being I/O.
+        */
+       int i;
+
+       for(i=0; i<4; i++)
+               d->base_address[i] |= PCI_BASE_ADDRESS_SPACE_IO;
+}
+
+struct dev_ex {
+       u16 vendor, device;
+       void (*handler)(struct pci_dev *);
+       char *comment;
+};
+
+static struct dev_ex __initdata dev_ex_table[] = {
+ { PCI_VENDOR_ID_INTEL,                PCI_DEVICE_ID_INTEL_82451NX,    pci_fixup_i450nx,       "Scanning peer host bridges" },
+ { PCI_VENDOR_ID_UMC,          PCI_DEVICE_ID_UMC_UM8886BF,     pci_fixup_umc_ide,      "Working around UM8886BF bugs" }
+};
+
+static void __init pcibios_scan_buglist(struct pci_bus *b)
+{
+       struct pci_dev *d;
+       int i;
+
+       for(d=b->devices; d; d=d->sibling)
+               for(i=0; i<sizeof(dev_ex_table)/sizeof(dev_ex_table[0]); i++) {
+                       struct dev_ex *e = &dev_ex_table[i];
+                       if (e->vendor == d->vendor && e->device == d->device) {
+                               printk("PCI: %02x:%02x [%04x/%04x]: %s\n",
+                                       b->number, d->devfn, d->vendor, d->device, e->comment);
+                               e->handler(d);
+                       }
+               }
+}
+
 /*
  * Fix base addresses, I/O and memory enables and IRQ's (mostly work-arounds
  * for buggy PCI BIOS'es :-[).
  */
 
-__initfunc(void pcibios_fixup_devices(void))
+static void __init pcibios_fixup_devices(void)
 {
        struct pci_dev *dev;
        int i, has_io, has_mem;
@@ -1099,7 +1187,8 @@ __initfunc(void pcibios_fixup_devices(void))
 
 __initfunc(void pcibios_fixup(void))
 {
-       pcibios_fixup_peer_bridges();
+       if (!(pci_probe & PCI_NO_PEER_FIXUP))
+               pcibios_fixup_peer_bridges();
        pcibios_fixup_devices();
 
 #ifdef CONFIG_PCI_BIOS
@@ -1111,6 +1200,7 @@ __initfunc(void pcibios_fixup(void))
 __initfunc(void pcibios_fixup_bus(struct pci_bus *b))
 {
        pcibios_fixup_ghosts(b);
+       pcibios_scan_buglist(b);
 }
 
 /*
@@ -1126,8 +1216,10 @@ __initfunc(void pcibios_init(void))
        struct pci_access *dir = NULL;
 
 #ifdef CONFIG_PCI_BIOS
-       if ((pci_probe & PCI_PROBE_BIOS) && ((bios = pci_find_bios())))
+       if ((pci_probe & PCI_PROBE_BIOS) && ((bios = pci_find_bios()))) {
                pci_probe |= PCI_BIOS_SORT;
+               pci_bios_present = 1;
+       }
 #endif
 #ifdef CONFIG_PCI_DIRECT
        if (pci_probe & (PCI_PROBE_CONF1 | PCI_PROBE_CONF2))
@@ -1139,10 +1231,6 @@ __initfunc(void pcibios_init(void))
                access_pci = bios;
 }
 
-#if !defined(CONFIG_PCI_BIOS) && !defined(CONFIG_PCI_DIRECT)
-#error PCI configured with neither PCI BIOS or PCI direct access support.
-#endif
-
 __initfunc(char *pcibios_setup(char *str))
 {
        if (!strcmp(str, "off")) {
@@ -1178,5 +1266,9 @@ __initfunc(char *pcibios_setup(char *str))
                return NULL;
        }
 #endif
+       else if (!strcmp(str, "nopeer")) {
+               pci_probe |= PCI_NO_PEER_FIXUP;
+               return NULL;
+       }
        return str;
 }
index c0760b8877df4d210354069fb61f142e8eeea5fb..f5facd8dd6614244f62cde45ff4a34823f638adb 100644 (file)
@@ -166,6 +166,8 @@ if [ "$CONFIG_JOYSTICK" != "n" ]; then
 fi
 endmenu
 
+tristate 'Double Talk PC internal speech card support' CONFIG_DTLK
+
 mainmenu_option next_comment
 comment 'Ftape, the floppy tape device driver'
 tristate 'Ftape (QIC-80/Travan) support' CONFIG_FTAPE
index 6a627847b29ada8479a5d156992b661c4dcaf0a7..78fb870a761bcd1dee71fe65281841f592d3f2d0 100644 (file)
@@ -176,6 +176,14 @@ else
   endif
 endif
 
+ifeq ($(CONFIG_DTLK),y)
+L_OBJS += dtlk.o
+else
+  ifeq ($(CONFIG_DTLK),m)
+  M_OBJS += dtlk.o
+  endif
+endif
+
 ifeq ($(CONFIG_MS_BUSMOUSE),y)
 L_OBJS += msbusmouse.o
 else
diff --git a/drivers/char/dtlk.c b/drivers/char/dtlk.c
new file mode 100644 (file)
index 0000000..0b928dc
--- /dev/null
@@ -0,0 +1,722 @@
+/*                                              -*- linux-c -*-
+ * dtlk.c - DoubleTalk PC driver for Linux kernel 2.0.29
+ * 
+ * $Id: dtlk.c,v 1.19 1999/02/28 12:13:13 jrv Exp jrv $
+ *
+ * Original author: Chris Pallotta <chris@allmedia.com>
+ * Current maintainer: Jim Van Zandt <jrv@vanzandt.mv.com>
+ */
+
+/* This driver is for the DoubleTalk PC, a speech synthesizer
+   manufactured by RC Systems (http://www.rcsys.com/).  It was written
+   based on documentation in their User's Manual file and Developer's
+   Tools disk.
+
+   The DoubleTalk PC contains four voice synthesizers: text-to-speech
+   (TTS), linear predictive coding (LPC), PCM/ADPCM, and CVSD.  It
+   also has a tone generator.  Output data for LPC are written to the
+   LPC port, and output data for the other modes are written to the
+   TTS port.
+
+   Two kinds of data can be read from the DoubleTalk: status
+   information (in response to the "\001?" interrogation command) is
+   read from the TTS port, and index markers (which mark the progress
+   of the speech) are read from the LPC port.  Not all models of the
+   DoubleTalk PC implement index markers.  Both the TTS and LPC ports
+   can also display status flags.
+
+   The DoubleTalk PC generates no interrupts.
+
+   These characteristics are mapped into the Unix stream I/O model as
+   follows:
+
+   "write" sends bytes to the TTS port.  It is the responsibility of
+   the user program to switch modes among TTS, PCM/ADPCM, and CVSD.
+   This driver was written for use with the text-to-speech
+   synthesizer.  If LPC output is needed some day, other minor device
+   numbers can be used to select among output modes.
+
+   "read" gets index markers from the LPC port.  If the device does
+   not implement index markers, the read will fail with error EINVAL.
+
+   Status information is available using the DTLK_INTERROGATE ioctl.
+
+ */
+
+#ifdef MODVERSIONS
+#include <linux/modversions.h>
+#endif
+
+#ifdef MODULE
+#include <linux/module.h>
+#include <linux/version.h>
+#else
+#define MOD_INC_USE_COUNT
+#define MOD_DEC_USE_COUNT
+#endif
+
+#define KERNEL
+#include <linux/config.h>
+
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/mm.h>          /* for verify_area */
+#include <linux/errno.h>       /* for -EBUSY */
+#include <linux/ioport.h>      /* for check_region, request_region */
+#include <linux/delay.h>       /* for loops_per_sec */
+#include <asm/segment.h>       /* for put_user_byte */
+#include <asm/io.h>            /* for inb_p, outb_p, inb, outb, etc. */
+#include <asm/uaccess.h>       /* for get_user, etc. */
+#include <linux/wait.h>                /* for wait_queue */
+#include <linux/init.h>                /* for __init */
+#include <linux/poll.h>                /* for POLLIN, etc. */
+#include <linux/dtlk.h>                /* local header file for DoubleTalk values */
+
+#ifdef TRACING
+#define TRACE_TEXT(str) printk(str);
+#define TRACE_RET printk(")")
+#else                          /* !TRACING */
+#define TRACE_TEXT(str) ((void) 0)
+#define TRACE_RET ((void) 0)
+#endif                         /* TRACING */
+
+
+static int dtlk_major;
+static int dtlk_port_lpc;
+static int dtlk_port_tts;
+static int dtlk_busy;
+static int dtlk_timer_active;
+static int dtlk_has_indexing;
+static unsigned int dtlk_portlist[] =
+{0x25e, 0x29e, 0x2de, 0x31e, 0x35e, 0x39e, 0};
+static struct wait_queue *dtlk_process_list = NULL;
+static struct timer_list dtlk_timer;
+
+/* prototypes for file_operations struct */
+static ssize_t dtlk_read(struct file *, char *,
+                        size_t nbytes, loff_t * ppos);
+static ssize_t dtlk_write(struct file *, const char *,
+                         size_t nbytes, loff_t * ppos);
+static unsigned int dtlk_poll(struct file *, poll_table *);
+static int dtlk_open(struct inode *, struct file *);
+static int dtlk_release(struct inode *, struct file *);
+static int dtlk_ioctl(struct inode *inode, struct file *file,
+                     unsigned int cmd, unsigned long arg);
+
+static struct file_operations dtlk_fops =
+{
+       NULL,                   /* lseek */
+       dtlk_read,
+       dtlk_write,
+       NULL,                   /* readdir */
+       dtlk_poll,
+       dtlk_ioctl,
+       NULL,                   /* mmap */
+       dtlk_open,
+       NULL,                   /* flush */
+       dtlk_release,
+       NULL,                   /* fsync */
+       NULL,                   /* fasync */
+       NULL,                   /* check_media_change */
+       NULL,                   /* revalidate */
+       NULL                    /* lock */
+};
+
+/* local prototypes */
+static void dtlk_delay(int ms);
+static int dtlk_dev_probe(void);
+static struct dtlk_settings *dtlk_interrogate(void);
+static int dtlk_readable(void);
+static char dtlk_read_lpc(void);
+static char dtlk_read_tts(void);
+static void dtlk_stop_timer(void);
+static int dtlk_writeable(void);
+static char dtlk_write_bytes(const char *buf, int n);
+static char dtlk_write_tts(char);
+/*
+   static void dtlk_handle_error(char, char, unsigned int);
+   static char dtlk_write_byte(unsigned int, const char*);
+ */
+static void dtlk_timer_tick(unsigned long data);
+
+static ssize_t dtlk_read(struct file *file, char *buf,
+                        size_t count, loff_t * ppos)
+{
+       unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
+       char ch;
+       int retval, i = 0, retries;
+
+       /* Can't seek (pread) on the DoubleTalk.  */
+       if (ppos != &file->f_pos)
+               return -ESPIPE;
+
+       TRACE_TEXT("(dtlk_read");
+       /*  printk("DoubleTalk PC - dtlk_read()\n"); */
+
+       if (minor != DTLK_MINOR || !dtlk_has_indexing)
+               return -EINVAL;
+
+       for (retries = 0; retries < loops_per_sec / 10; retries++) {
+               while (i < count && dtlk_readable()) {
+                       ch = dtlk_read_lpc();
+                       /*        printk("dtlk_read() reads 0x%02x\n", ch); */
+                       if ((retval = put_user(ch, buf++)))
+                               return retval;
+                       i++;
+               }
+               if (i)
+                       return i;
+               if (file->f_flags & O_NONBLOCK)
+                       break;
+               dtlk_delay(10);
+       }
+       if (retries == loops_per_sec)
+               printk(KERN_ERR "dtlk_read times out\n");
+       TRACE_RET;
+       return -EAGAIN;
+}
+
+static ssize_t dtlk_write(struct file *file, const char *buf,
+                         size_t count, loff_t * ppos)
+{
+       int i = 0, retries = 0, err, ch;
+
+       TRACE_TEXT("(dtlk_write");
+#ifdef TRACING
+       printk(" \"");
+       {
+               int i, ch;
+               for (i = 0; i < count; i++) {
+                       err = get_user(ch, buf + i);
+                       if (' ' <= ch && ch <= '~')
+                               printk("%c", ch);
+                       else
+                               printk("\\%03o", ch);
+               }
+               printk("\"");
+       }
+#endif
+
+       /* Can't seek (pwrite) on the DoubleTalk.  */
+       if (ppos != &file->f_pos)
+               return -ESPIPE;
+
+       if (MINOR(file->f_dentry->d_inode->i_rdev) != DTLK_MINOR)
+               return -EINVAL;
+
+       while (1) {
+               while (i < count && (err = get_user(ch, buf)) == 0 &&
+                      (ch == DTLK_CLEAR || dtlk_writeable())) {
+                       dtlk_write_tts(ch);
+                       buf++;
+                       i++;
+                       if (i % 5 == 0)
+                               /* We yield our time until scheduled
+                                  again.  This reduces the transfer
+                                  rate to 500 bytes/sec, but that's
+                                  still enough to keep up with the
+                                  speech synthesizer. */
+                               dtlk_delay(1);
+                       else {
+                               /* the RDY bit goes zero 2-3 usec
+                                  after writing, and goes 1 again
+                                  180-190 usec later.  Here, we wait
+                                  up to 250 usec for the RDY bit to
+                                  go nonzero. */
+                               for (retries = 0;
+                                    retries < loops_per_sec / 4000;
+                                    retries++)
+                                       if (inb_p(dtlk_port_tts) &
+                                           TTS_WRITABLE)
+                                               break;
+                       }
+                       retries = 0;
+               }
+               if (i == count)
+                       return i;
+               if (file->f_flags & O_NONBLOCK)
+                       break;
+
+               dtlk_delay(1);
+
+               if (++retries > 10 * HZ) { /* wait no more than 10 sec
+                                             from last write */
+                       printk("dtlk: write timeout.  "
+                              "inb_p(dtlk_port_tts) = 0x%02x\n",
+                              inb_p(dtlk_port_tts));
+                       TRACE_RET;
+                       return -EBUSY;
+               }
+       }
+       TRACE_RET;
+       return -EAGAIN;
+}
+
+static unsigned int dtlk_poll(struct file *file, poll_table * wait)
+{
+       int mask = 0;
+       TRACE_TEXT(" dtlk_poll");
+       /*
+          static long int j;
+          printk(".");
+          printk("<%ld>", jiffies-j);
+          j=jiffies;
+        */
+       poll_wait(file, &dtlk_process_list, wait);
+
+       if (dtlk_has_indexing && dtlk_readable()) {
+               dtlk_stop_timer();
+               mask = POLLIN | POLLRDNORM;
+       }
+       if (dtlk_writeable()) {
+               dtlk_stop_timer();
+               mask |= POLLOUT | POLLWRNORM;
+       }
+       /* there are no exception conditions */
+
+       if (mask == 0 && !dtlk_timer_active) {
+               /* not ready just yet.  There won't be any interrupts,
+                  so we set a timer instead. */
+               dtlk_timer_active = 1;
+               dtlk_timer.expires = jiffies + HZ / 100;
+               add_timer(&dtlk_timer);
+       }
+       return 0;
+}
+
+static void dtlk_stop_timer()
+{
+       if (dtlk_timer_active) {
+               dtlk_timer_active = 0;
+               del_timer(&dtlk_timer);
+       }
+}
+
+static void dtlk_timer_tick(unsigned long data)
+{
+
+       wake_up_interruptible(&dtlk_process_list);
+
+       if (dtlk_timer_active) {
+               del_timer(&dtlk_timer);
+               dtlk_timer.expires = jiffies + HZ / 100;
+               add_timer(&dtlk_timer);
+       }
+}
+
+static int dtlk_ioctl(struct inode *inode,
+                     struct file *file,
+                     unsigned int cmd,
+                     unsigned long arg)
+{
+       struct dtlk_settings *sp;
+       int err;
+       char portval;
+       TRACE_TEXT(" dtlk_ioctl");
+
+       switch (cmd) {
+
+       case DTLK_INTERROGATE:
+               sp = dtlk_interrogate();
+               err = copy_to_user((char *) arg, (char *) sp,
+                                  sizeof(struct dtlk_settings));
+               if (err)
+                       return -EINVAL;
+               return 0;
+
+       case DTLK_STATUS:
+               portval = inb_p(dtlk_port_tts);
+               return put_user(portval, (char *) arg);
+
+       default:
+               return -EINVAL;
+       }
+}
+
+static int dtlk_open(struct inode *inode, struct file *file)
+{
+       MOD_INC_USE_COUNT;
+       TRACE_TEXT("(dtlk_open");
+
+       switch (MINOR(inode->i_rdev)) {
+       case DTLK_MINOR:
+               if (dtlk_busy)
+                       return -EBUSY;
+               return 0;
+
+       default:
+               return -ENXIO;
+       }
+}
+
+static int dtlk_release(struct inode *inode, struct file *file)
+{
+       MOD_DEC_USE_COUNT;
+       TRACE_TEXT("(dtlk_release");
+
+       switch (MINOR(inode->i_rdev)) {
+       case DTLK_MINOR:
+               break;
+
+       default:
+               break;
+       }
+       TRACE_RET;
+
+       dtlk_stop_timer();
+
+       return 0;
+}
+
+int __init dtlk_init(void)
+{
+       dtlk_port_lpc = 0;
+       dtlk_port_tts = 0;
+       dtlk_busy = 0;
+       dtlk_timer_active = 0;
+       dtlk_major = register_chrdev(0, "dtlk", &dtlk_fops);
+       if (dtlk_major == 0) {
+               printk(KERN_ERR "DoubleTalk PC - cannot register device\n");
+               return 0;
+       }
+       if (dtlk_dev_probe() == 0)
+               printk(", MAJOR %d\n", dtlk_major);
+
+       init_timer(&dtlk_timer);
+       dtlk_timer.function = dtlk_timer_tick;
+       dtlk_process_list = NULL;
+
+       return 0;
+}
+
+#ifdef MODULE
+int init_module(void)
+{
+       return dtlk_init();
+}
+
+void cleanup_module(void)
+{
+       dtlk_write_bytes("goodbye", 8);
+       current->state = TASK_INTERRUPTIBLE;
+       schedule_timeout(5 * HZ / 10);          /* nap 0.50 sec but
+                                                  could be awakened
+                                                  earlier by
+                                                  signals... */
+
+       dtlk_write_tts(DTLK_CLEAR);
+       unregister_chrdev(dtlk_major, "dtlk");
+       release_region(dtlk_port_lpc, DTLK_IO_EXTENT);
+}
+
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+/* sleep for ms milliseconds */
+static void dtlk_delay(int ms)
+{
+       current->state = TASK_INTERRUPTIBLE;
+       schedule_timeout((ms * HZ + 1000 - HZ) / 1000);
+       current->state = TASK_RUNNING;
+}
+
+static int dtlk_readable(void)
+{
+       TRACE_TEXT(" dtlk_readable");
+       return inb_p(dtlk_port_lpc) != 0x7f;
+}
+
+static int dtlk_writeable(void)
+{
+       /* TRACE_TEXT(" dtlk_writeable"); */
+#ifdef TRACING
+       printk(" dtlk_writeable(%02x)", inb_p(dtlk_port_tts));
+#endif
+       return inb_p(dtlk_port_tts) & TTS_WRITABLE;
+}
+
+static int __init dtlk_dev_probe(void)
+{
+       unsigned int testval = 0;
+       int i = 0;
+       struct dtlk_settings *sp;
+
+       if (dtlk_port_lpc | dtlk_port_tts)
+               return -EBUSY;
+
+       for (i = 0; dtlk_portlist[i]; i++) {
+#if 0
+               printk("DoubleTalk PC - Port %03x = %04x\n",
+                      dtlk_portlist[i], (testval = inw_p(dtlk_portlist[i])));
+#endif
+
+               if (check_region(dtlk_portlist[i], DTLK_IO_EXTENT))
+                       continue;
+               testval = inw_p(dtlk_portlist[i]);
+               if ((testval &= 0xfbff) == 0x107f) {
+                       request_region(dtlk_portlist[i], DTLK_IO_EXTENT, 
+                                      "dtlk");
+                       dtlk_port_lpc = dtlk_portlist[i];
+                       dtlk_port_tts = dtlk_port_lpc + 1;
+
+                       sp = dtlk_interrogate();
+                       printk("DoubleTalk PC at %03x-%03x, "
+                              "ROM version %s, serial number %u",
+                              dtlk_portlist[i], dtlk_portlist[i] +
+                              DTLK_IO_EXTENT - 1,
+                              sp->rom_version, sp->serial_number);
+
+                        /* put LPC port into known state, so
+                          dtlk_readable() gives valid result */
+                       outb_p(0xff, dtlk_port_lpc); 
+
+                        /* INIT string and index marker */
+                       dtlk_write_bytes("\036\1@\0\0012I\r", 8);
+                       /* posting an index takes 18 msec.  Here, we
+                          wait up to 100 msec to see whether it
+                          appears. */
+                       dtlk_delay(100);
+                       dtlk_has_indexing = dtlk_readable();
+
+#ifdef INSCOPE
+                       {
+/* This macro records ten samples read from the LPC port, for later display */
+#define LOOK                                   \
+for (i = 0; i < 10; i++)                       \
+  {                                            \
+    buffer[b++] = inb_p(dtlk_port_lpc);                \
+    __delay(loops_per_sec/1000000);             \
+  }
+                               char buffer[1000];
+                               int b = 0, i, j;
+
+                               LOOK
+                                   outb_p(0xff, dtlk_port_lpc);
+                               buffer[b++] = 0;
+                               LOOK
+                                   dtlk_write_bytes("\0012I\r", 4);
+                               buffer[b++] = 0;
+                               __delay(50 * loops_per_sec / 1000);
+                               outb_p(0xff, dtlk_port_lpc);
+                               buffer[b++] = 0;
+                               LOOK
+
+                                   printk("\n");
+                               for (j = 0; j < b; j++)
+                                       printk(" %02x", buffer[j]);
+                               printk("\n");
+                       }
+#endif                         /* INSCOPE */
+
+#ifdef OUTSCOPE
+                       {
+/* This macro records ten samples read from the TTS port, for later display */
+#define LOOK                                   \
+for (i = 0; i < 10; i++)                       \
+  {                                            \
+    buffer[b++] = inb_p(dtlk_port_tts);                \
+    __delay(loops_per_sec/1000000);  /* 1 us */ \
+  }
+                               char buffer[1000];
+                               int b = 0, i, j;
+
+                               __delay(loops_per_sec / 100);   /* 10 ms */
+                               LOOK
+                                   outb_p(0x03, dtlk_port_tts);
+                               buffer[b++] = 0;
+                               LOOK
+                                   LOOK
+
+                                   printk("\n");
+                               for (j = 0; j < b; j++)
+                                       printk(" %02x", buffer[j]);
+                               printk("\n");
+                       }
+#endif                         /* OUTSCOPE */
+
+                       dtlk_write_bytes("Double Talk found", 18);
+
+                       return 0;
+               }
+       }
+
+       printk(KERN_INFO "\nDoubleTalk PC - not found\n");
+       return -ENODEV;
+}
+
+/*
+   static void dtlk_handle_error(char op, char rc, unsigned int minor)
+   {
+   printk(KERN_INFO"\nDoubleTalk PC - MINOR: %d, OPCODE: %d, ERROR: %d\n", 
+   minor, op, rc);
+   return;
+   }
+ */
+
+/* interrogate the DoubleTalk PC and return its settings */
+static struct dtlk_settings *dtlk_interrogate(void)
+{
+       unsigned char *t;
+       static char buf[sizeof(struct dtlk_settings) + 1];
+       int total, i;
+       static struct dtlk_settings status;
+       TRACE_TEXT("(dtlk_interrogate");
+       dtlk_write_bytes("\030\001?", 3);
+       for (total = 0, i = 0; i < 50; i++) {
+               buf[total] = dtlk_read_tts();
+               if (total > 2 && buf[total] == 0x7f)
+                       break;
+               if (total < sizeof(struct dtlk_settings))
+                        total++;
+       }
+       /*
+          if (i==50) printk("interrogate() read overrun\n");
+          for (i=0; i<sizeof(buf); i++)
+          printk(" %02x", buf[i]);
+          printk("\n");
+        */
+       t = buf;
+       status.serial_number = t[0] + t[1] * 256; /* serial number is
+                                                    little endian */
+       t += 2;
+
+       i = 0;
+       while (*t != '\r') {
+               status.rom_version[i] = *t;
+               if (i < sizeof(status.rom_version) - 1)
+                       i++;
+               t++;
+       }
+       status.rom_version[i] = 0;
+       t++;
+
+       status.mode = *t++;
+       status.punc_level = *t++;
+       status.formant_freq = *t++;
+       status.pitch = *t++;
+       status.speed = *t++;
+       status.volume = *t++;
+       status.tone = *t++;
+       status.expression = *t++;
+       status.ext_dict_loaded = *t++;
+       status.ext_dict_status = *t++;
+       status.free_ram = *t++;
+       status.articulation = *t++;
+       status.reverb = *t++;
+       status.eob = *t++;
+       status.has_indexing = dtlk_has_indexing;
+       TRACE_RET;
+       return &status;
+}
+
+static char dtlk_read_tts(void)
+{
+       int portval, retries = 0;
+       char ch;
+       TRACE_TEXT("(dtlk_read_tts");
+
+       /* verify DT is ready, read char, wait for ACK */
+       do {
+               portval = inb_p(dtlk_port_tts);
+       } while ((portval & TTS_READABLE) == 0 && retries++ < DTLK_MAX_RETRIES);
+       if (retries == DTLK_MAX_RETRIES)
+               printk(KERN_ERR "dtlk_read_tts() timeout\n");
+
+       ch = inb_p(dtlk_port_tts);      /* input from TTS port */
+       ch &= 0x7f;
+       outb_p(ch, dtlk_port_tts);
+
+       retries = 0;
+       do {
+               portval = inb_p(dtlk_port_tts);
+       } while ((portval & TTS_READABLE) != 0 && retries++ < DTLK_MAX_RETRIES);
+       if (retries == DTLK_MAX_RETRIES)
+               printk(KERN_ERR "dtlk_read_tts() timeout\n");
+
+       TRACE_RET;
+       return ch;
+}
+
+static char dtlk_read_lpc(void)
+{
+       int retries = 0;
+       char ch;
+       TRACE_TEXT("(dtlk_read_lpc");
+
+       /* no need to test -- this is only called when the port is readable */
+
+       ch = inb_p(dtlk_port_lpc);      /* input from LPC port */
+
+       outb_p(0xff, dtlk_port_lpc);
+
+       /* acknowledging a read takes 3-4
+          usec.  Here, we wait up to 20 usec
+          for the acknowledgement */
+       retries = (loops_per_sec * 20) / 1000000;
+       while (inb_p(dtlk_port_lpc) != 0x7f && --retries > 0);
+       if (retries == 0)
+               printk(KERN_ERR "dtlk_read_lpc() timeout\n");
+
+       TRACE_RET;
+       return ch;
+}
+
+#ifdef NEVER
+static char dtlk_write_byte(unsigned int minor, const char *buf)
+{
+       char ch;
+       int err;
+       /* TRACE_TEXT("(dtlk_write_byte"); */
+       err = get_user(ch, buf);
+       /* printk("  dtlk_write_byte(%d, 0x%02x)", minor, (int)ch); */
+
+       ch = dtlk_write_tts(ch);
+       /* 
+          TRACE_RET; */
+       return ch;
+}
+#endif                         /* NEVER */
+
+/* write n bytes to tts port */
+static char dtlk_write_bytes(const char *buf, int n)
+{
+       char val = 0;
+       /*  printk("dtlk_write_bytes(\"%-*s\", %d)\n", n, buf, n); */
+       TRACE_TEXT("(dtlk_write_bytes");
+       while (n-- > 0)
+               val = dtlk_write_tts(*buf++);
+       TRACE_RET;
+       return val;
+}
+
+static char dtlk_write_tts(char ch)
+{
+       int retries = 0;
+#ifdef TRACING
+       printk("  dtlk_write_tts(");
+       if (' ' <= ch && ch <= '~')
+               printk("'%c'", ch);
+       else
+               printk("0x%02x", ch);
+#endif
+       if (ch != DTLK_CLEAR)   /* no flow control for CLEAR command */
+               while ((inb_p(dtlk_port_tts) & TTS_WRITABLE) == 0 &&
+                      retries++ < DTLK_MAX_RETRIES)    /* DT ready? */
+                       ;
+       if (retries == DTLK_MAX_RETRIES)
+               printk(KERN_ERR "dtlk_write_tts() timeout\n");
+
+       outb_p(ch, dtlk_port_tts);      /* output to TTS port */
+       /* the RDY bit goes zero 2-3 usec after writing, and goes
+          1 again 180-190 usec later.  Here, we wait up to 10
+          usec for the RDY bit to go zero. */
+       for (retries = 0; retries < loops_per_sec / 100000; retries++)
+               if ((inb_p(dtlk_port_tts) & TTS_WRITABLE) == 0)
+                       break;
+
+#ifdef TRACING
+       printk(")\n");
+#endif
+       return 0;
+}
index 1b50349391ec22585e893a72dc4ef0b76e4b5d77..10ac9929223a1bca0c7f41987e0afbd0875b0ec0 100644 (file)
@@ -280,8 +280,6 @@ static int zft_mmap(struct inode *ino,
                static struct vm_operations_struct dummy = { NULL, };
                vma->vm_ops = &dummy;
 #endif
-               vma->vm_file = filep;
-               filep->f_count++;
        }
        current->blocked = old_sigmask; /* restore mask */
        TRACE_EXIT result;
index 6eaa07d23e714e9daacb5a1edd929490771eccd4..588856d3c4e9cefe4fcdf487563563d3306f3c1d 100644 (file)
@@ -178,8 +178,6 @@ static int mmap_mem(struct file * file, struct vm_area_struct * vma)
        if (remap_page_range(vma->vm_start, offset, vma->vm_end-vma->vm_start,
                             vma->vm_page_prot))
                return -EAGAIN;
-       vma->vm_file = file;
-       file->f_count++;
        return 0;
 }
 
index 563d16050ad003955e738de6cfaf4defcc567663..04409a84ee103cfb90af58167d9bb7cf9a760bc8 100644 (file)
@@ -231,6 +231,9 @@ int __init misc_init(void)
 #ifdef CONFIG_SOFT_WATCHDOG
        watchdog_init();
 #endif
+#ifdef CONFIG_DTLK
+       dtlk_init();
+#endif
 #ifdef CONFIG_APM
        apm_bios_init();
 #endif
index 4ebbe24755808e3a6cb05419026321be77254d56..f0a9a1c1734ec9e588a2d009ff4101f075967bd5 100644 (file)
@@ -3,6 +3,11 @@
  * Coverted to new API by Alan Cox <Alan.Cox@linux.org>
  * Various bugfixes and enhancements by Russell Kroll <rkroll@exploits.org>
  *
+ * History:
+ * 1999-02-24  Russell Kroll <rkroll@exploits.org>
+ *             Fine tuning/VIDEO_TUNER_LOW
+ *             Frequency range expanded to start at 87 MHz
+ *
  * TODO: Allow for more than one of these foolish entities :-)
  *
  * Notes on the hardware (reverse engineered from other peoples'
@@ -156,14 +161,11 @@ static int rt_setfreq(struct rt_device *dev, unsigned long freq)
 
        /* adapted from radio-aztech.c */
 
-       /* We want to compute x * 100 / 16 without overflow 
-        * So we compute x*6 + (x/100)*25 to give x*6.25
-        */
-        
-       freq = freq * 6 + freq/4;       /* massage the data a little    */
-       freq += 1070;                   /* IF = 10.7 MHz                */
-       freq /= 5;                      /* ref = 25 kHz                 */
+       /* now uses VIDEO_TUNER_LOW for fine tuning */
 
+       freq += 171200;                 /* Add 10.7 MHz IF              */
+       freq /= 800;                    /* Convert to 50 kHz units      */
+        
        send_0_byte (io, dev);          /*  0: LSB of frequency         */
 
        for (i = 0; i < 13; i++)        /*   : frequency bits (1-13)    */
@@ -200,16 +202,6 @@ int rt_getsigstr(struct rt_device *dev)
        return 1;               /* signal present               */
 }
 
-int rt_chkstereo(struct rt_device *dev)
-{
-       outb(0xd8, io);
-       sleep_delay(100000);
-       if (inb(io) & 0x0fd)
-               return VIDEO_SOUND_STEREO;      /* stereo detected */
-       else 
-               return VIDEO_SOUND_MONO;        /* mono */
-}
-
 static int rt_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
 {
        struct rt_device *rt=dev->priv;
@@ -239,9 +231,9 @@ static int rt_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
                                return -EFAULT;
                        if(v.tuner)     /* Only 1 tuner */ 
                                return -EINVAL;
-                       v.rangelow=(88*16);
-                       v.rangehigh=(108*16);
-                       v.flags=0;
+                       v.rangelow=(87*16000);
+                       v.rangehigh=(108*16000);
+                       v.flags=VIDEO_TUNER_LOW;
                        v.mode=VIDEO_MODE_AUTO;
                        v.signal=0xFFFF*rt_getsigstr(rt);
                        if(copy_to_user(arg,&v, sizeof(v)))
@@ -273,7 +265,6 @@ static int rt_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
                        memset(&v,0, sizeof(v));
                        v.flags|=VIDEO_AUDIO_MUTABLE|VIDEO_AUDIO_VOLUME;
                        v.volume=rt->curvol * 6554;
-                       v.mode=rt_chkstereo(rt);
                        v.step=6554;
                        strcpy(v.name, "Radio");
                        if(copy_to_user(arg,&v, sizeof(v)))
index 39d56a86fcf465f660af25a748af22ab92443941..f9f1d94c82a8a8adf04fef84e402e7a281a56466 100644 (file)
@@ -1,9 +1,7 @@
-/* aztech.c - Aztech radio card driver for Linux 2.1 by Russell Kroll
+/* radio-aztech.c - Aztech radio card driver for Linux 2.2 
  *
- * Heavily modified to support the new 2.1 radio card interfaces by
- * Russell Kroll (rkroll@exploits.org)
- *
- * Based on code by
+ * Adapted to support the Video for Linux API by 
+ * Russell Kroll <rkroll@exploits.org>.  Based on original tuner code by:
  *
  * Quay Ly
  * Donald Song
  * The basis for this code may be found at http://bigbang.vtc.vsc.edu/fmradio/
  * along with more information on the card itself.
  *
+ * History:
+ * 1999-02-24  Russell Kroll <rkroll@exploits.org>
+ *             Fine tuning/VIDEO_TUNER_LOW
+ *             Range expanded to 87-108 MHz (from 87.9-107.8)
+ *
  * Notable changes from the original source:
  * - includes stripped down to the essentials
  * - for loops used as delays replaced with udelay()
@@ -113,11 +116,8 @@ static int az_setfreq(struct az_device *dev, unsigned long frequency)
 {
        int  i;
 
-       /*  6.25 *  */
-       frequency = frequency*6 + frequency/4;  /* massage data a bit */
-  
-       frequency += 1070;              /* tuning needs 24 data bits  */
-       frequency /= 5;
+       frequency += 171200;            /* Add 10.7 MHz IF              */
+       frequency /= 800;               /* Convert to 50 kHz units      */
                                        
        send_0_byte (dev);              /*  0: LSB of frequency       */
 
@@ -179,9 +179,9 @@ static int az_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
                                return -EFAULT;
                        if(v.tuner)     /* Only 1 tuner */ 
                                return -EINVAL;
-                       v.rangelow=(879*16)/10;
-                       v.rangehigh=(1078*16)/10;
-                       v.flags=0;
+                       v.rangelow=(87*16000);
+                       v.rangehigh=(108*16000);
+                       v.flags=VIDEO_TUNER_LOW;
                        v.mode=VIDEO_MODE_AUTO;
                        v.signal=0xFFFF*az_getsigstr(az);
                        if(az_getstereo(az))
@@ -292,7 +292,7 @@ __initfunc(int aztech_init(struct video_init *v))
                return -EINVAL;
                
        request_region(io, 2, "aztech");
-       printk(KERN_INFO "Aztech radio card driver v0.40/19980422 rkroll@exploits.org\n");
+       printk(KERN_INFO "Aztech radio card driver v1.00/19990224 rkroll@exploits.org\n");
        /* mute card - prevents noisy bootups */
        outb (0, io);
        return 0;
index 8786bf6483c6087f424a2fd71c4197b1e4af9f54..4eb7d49c51aca64f92fdf89fc0b9f85c5ce75adc 100644 (file)
@@ -1046,6 +1046,7 @@ endif
 
 ifeq ($(CONFIG_IRDA),y)
 SUB_DIRS += irda
+MOD_IN_SUB_DIRS += irda
 else
   ifeq ($(CONFIG_IRDA),m)
   MOD_SUB_DIRS += irda
index 5c76aa0d414aa5604b4fb077d522532538ffc74a..69f8bb0d840648612dc581a300d49e6a5bb89836 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: cosa.c,v 1.11 1998/12/24 23:44:23 kas Exp $ */
+/* $Id: cosa.c,v 1.21 1999/02/06 19:49:18 kas Exp $ */
 
 /*
  *  Copyright (C) 1995-1997  Jan "Yenya" Kasprzak <kas@fi.muni.cz>
@@ -27,7 +27,7 @@
  * Masaryk University (http://www.ics.muni.cz/). The hardware is
  * developed by Jiri Novotny <novotny@ics.muni.cz>. More information
  * and the photo of both cards is available at
- * http://www.kozakmartin.cz/cosa.html. The card documentation, firmwares
+ * http://www.pavoucek.cz/cosa.html. The card documentation, firmwares
  * and other goods can be downloaded from ftp://ftp.ics.muni.cz/pub/cosa/.
  * For Linux-specific utilities, see below in the "Software info" section.
  * If you want to order the card, contact Jiri Novotny.
@@ -141,11 +141,13 @@ struct cosa_data {
        unsigned int datareg, statusreg;        /* I/O ports */
        unsigned short irq, dma;        /* IRQ and DMA number */
        unsigned short startaddr;       /* Firmware start address */
+       unsigned short busmaster;       /* Use busmastering? */
        int nchannels;                  /* # of channels on this card */
        int driver_status;              /* For communicating with firware */
        int firmware_status;            /* Downloaded, reseted, etc. */
        int rxbitmap, txbitmap;         /* Bitmap of channels who are willing to send/receive data */
        int rxtx;                       /* RX or TX in progress? */
+       int enabled;
        int usage;                              /* usage count */
        int txchan, txsize, rxsize;
        struct channel_data *rxchan;
@@ -331,9 +333,8 @@ static int cosa_reset_and_read_id(struct cosa_data *cosa, char *id);
 static int get_wait_data(struct cosa_data *cosa);
 static int put_wait_data(struct cosa_data *cosa, int data);
 static int puthexnumber(struct cosa_data *cosa, int number);
-static void put_driver_status_common(struct cosa_data *cosa, int nolock);
-#define put_driver_status(x) put_driver_status_common((x), 0)
-#define put_driver_status_nolock(x) put_driver_status_common((x), 1)
+static void put_driver_status(struct cosa_data *cosa);
+static void put_driver_status_nolock(struct cosa_data *cosa);
 
 /* Interrupt handling */
 static void cosa_interrupt(int irq, void *cosa, struct pt_regs *regs);
@@ -357,7 +358,7 @@ __initfunc(static int cosa_init(void))
 #endif
 {
        int i;
-       printk(KERN_INFO "cosa v1.03 (c) 1997-8 Jan Kasprzak <kas@fi.muni.cz>\n");
+       printk(KERN_INFO "cosa v1.04 (c) 1997-8 Jan Kasprzak <kas@fi.muni.cz>\n");
 #ifdef __SMP__
        printk(KERN_INFO "cosa: SMP found. Please mail any success/failure reports to the author.\n");
 #endif
@@ -630,9 +631,14 @@ static int cosa_sppp_tx(struct sk_buff *skb, struct device *dev)
        if (dev->tbusy) { 
                if (time_before(jiffies, dev->trans_start+2*HZ))
                        return 1;       /* Two seconds timeout */
+               if (test_bit(RXBIT, &chan->cosa->rxtx)) {
+                       chan->stats.rx_errors++;
+                       chan->stats.rx_missed_errors++;
+               } else {
+                       chan->stats.tx_errors++;
+                       chan->stats.tx_aborted_errors++;
+               }
                cosa_kick(chan->cosa);
-               chan->stats.tx_errors++;
-               chan->stats.tx_aborted_errors++;
                if (chan->tx_skb) {
                        dev_kfree_skb(chan->tx_skb);
                        chan->tx_skb = 0;
@@ -659,6 +665,14 @@ static int cosa_sppp_close(struct device *d)
        d->tbusy = 1;
        cosa_disable_rx(chan);
        spin_lock_irqsave(&chan->cosa->lock, flags);
+       if (chan->rx_skb) {
+               kfree_skb(chan->rx_skb);
+               chan->rx_skb = 0;
+       }
+       if (chan->tx_skb) {
+               kfree_skb(chan->tx_skb);
+               chan->tx_skb = 0;
+       }
        chan->usage=0;
        chan->cosa->usage--;
        MOD_DEC_USE_COUNT;
@@ -1128,6 +1142,17 @@ static int cosa_ioctl_common(struct cosa_data *cosa,
                return nr_cards;
        case COSAIONRCHANS:
                return cosa->nchannels;
+       case COSAIOBMSET:
+               if (!suser())
+                       return -EACCES;
+               if (is_8bit(cosa))
+                       return -EINVAL;
+               if (arg != COSA_BM_OFF && arg != COSA_BM_ON)
+                       return -EINVAL;
+               cosa->busmaster = arg;
+               return 0;
+       case COSAIOBMGET:
+               return cosa->busmaster;
        }
        return -ENOIOCTLCMD;
 }
@@ -1208,37 +1233,67 @@ static int cosa_start_tx(struct channel_data *chan, char *buf, int len)
        return 0;
 }
 
-static void put_driver_status_common(struct cosa_data *cosa, int nolock)
+static void put_driver_status(struct cosa_data *cosa)
 {
        unsigned flags=0;
        int status;
 
-       if (!nolock)
-               spin_lock_irqsave(&cosa->lock, flags);
+       spin_lock_irqsave(&cosa->lock, flags);
 
        status = (cosa->rxbitmap ? DRIVER_RX_READY : 0)
                | (cosa->txbitmap ? DRIVER_TX_READY : 0)
                | (cosa->txbitmap? ~(cosa->txbitmap<<DRIVER_TXMAP_SHIFT)
                        &DRIVER_TXMAP_MASK : 0);
-       if (!cosa->rxtx || nolock) {
-#ifdef DEBUG_IO
-               debug_data_cmd(cosa, status);
-#endif
-               cosa_putdata8(cosa, status);
+       if (!cosa->rxtx) {
                if (cosa->rxbitmap|cosa->txbitmap) {
-                       cosa_putstatus(cosa, SR_RX_INT_ENA);
+                       if (!cosa->enabled) {
+                               cosa_putstatus(cosa, SR_RX_INT_ENA);
 #ifdef DEBUG_IO
-                       debug_status_out(cosa, SR_RX_INT_ENA);
+                               debug_status_out(cosa, SR_RX_INT_ENA);
 #endif
-               } else {
+                               cosa->enabled = 1;
+                       }
+               } else if (cosa->enabled) {
+                       cosa->enabled = 0;
                        cosa_putstatus(cosa, 0);
 #ifdef DEBUG_IO
                        debug_status_out(cosa, 0);
 #endif
                }
+               cosa_putdata8(cosa, status);
+#ifdef DEBUG_IO
+               debug_data_cmd(cosa, status);
+#endif
        }
-       if (!nolock)
-               spin_unlock_irqrestore(&cosa->lock, flags);
+       spin_unlock_irqrestore(&cosa->lock, flags);
+}
+
+static void put_driver_status_nolock(struct cosa_data *cosa)
+{
+       int status;
+
+       status = (cosa->rxbitmap ? DRIVER_RX_READY : 0)
+               | (cosa->txbitmap ? DRIVER_TX_READY : 0)
+               | (cosa->txbitmap? ~(cosa->txbitmap<<DRIVER_TXMAP_SHIFT)
+                       &DRIVER_TXMAP_MASK : 0);
+
+       if (cosa->rxbitmap|cosa->txbitmap) {
+               cosa_putstatus(cosa, SR_RX_INT_ENA);
+#ifdef DEBUG_IO
+               debug_status_out(cosa, SR_RX_INT_ENA);
+#endif
+               cosa->enabled = 1;
+       } else {
+               cosa_putstatus(cosa, 0);
+#ifdef DEBUG_IO
+               debug_status_out(cosa, 0);
+#endif
+               cosa->enabled = 0;
+       }
+       cosa_putdata8(cosa, status);
+#ifdef DEBUG_IO
+       debug_data_cmd(cosa, status);
+#endif
 }
 
 /*
@@ -1249,9 +1304,14 @@ static void put_driver_status_common(struct cosa_data *cosa, int nolock)
 static void cosa_kick(struct cosa_data *cosa)
 {
        unsigned flags, flags1;
+       char *s = "Unknown";
 
-       printk(KERN_INFO "%s: DMA timeout - restarting.\n", cosa->name);
+       if (test_bit(RXBIT, &cosa->rxtx))
+               s = "RX";
+       if (test_bit(TXBIT, &cosa->rxtx))
+               s = "TX";
 
+       printk(KERN_INFO "%s: %s DMA timeout - restarting.\n", cosa->name, s); 
        spin_lock_irqsave(&cosa->lock, flags);
        cosa->rxtx = 0;
 
@@ -1261,6 +1321,13 @@ static void cosa_kick(struct cosa_data *cosa)
        release_dma_lock(flags1);
 
        /* FIXME: Anything else? */
+       udelay(100);
+       cosa_putstatus(cosa, 0);
+       udelay(100);
+       (void) cosa_getdata8(cosa);
+       udelay(100);
+       cosa_putdata8(cosa, 0);
+       udelay(100);
        put_driver_status_nolock(cosa);
        spin_unlock_irqrestore(&cosa->lock, flags);
 }
@@ -1556,6 +1623,10 @@ static int puthexnumber(struct cosa_data *cosa, int number)
  * COSA status byte. I have moved the rx/tx/eot interrupt handling into
  * separate functions to make it more readable. These functions are inline,
  * so there should be no overhead of function call.
+ * 
+ * In the COSA bus-master mode, we need to tell the card the address of a
+ * buffer. Unfortunately, COSA may be too slow for us, so we must busy-wait.
+ * It's time to use the bottom half :-(
  */
 
 /*
@@ -1606,13 +1677,13 @@ static inline void tx_interrupt(struct cosa_data *cosa, int status)
 
        if (is_8bit(cosa)) {
                if (!test_bit(IRQBIT, &cosa->rxtx)) {
+                       cosa_putstatus(cosa, SR_TX_INT_ENA);
                        cosa_putdata8(cosa, ((cosa->txchan << 5) & 0xe0)|
                                ((cosa->txsize >> 8) & 0x1f));
-                       cosa_putstatus(cosa, SR_TX_INT_ENA);
 #ifdef DEBUG_IO
+                       debug_status_out(cosa, SR_TX_INT_ENA);
                        debug_data_out(cosa, ((cosa->txchan << 5) & 0xe0)|
                                 ((cosa->txsize >> 8) & 0x1f));
-                       debug_status_out(cosa, SR_TX_INT_ENA);
                        debug_data_in(cosa, cosa_getdata8(cosa));
 #else
                        cosa_getdata8(cosa);
@@ -1630,27 +1701,57 @@ static inline void tx_interrupt(struct cosa_data *cosa, int status)
 #endif
                }
        } else {
+               cosa_putstatus(cosa, SR_TX_INT_ENA);
                cosa_putdata16(cosa, ((cosa->txchan<<13) & 0xe000)
                        | (cosa->txsize & 0x1fff));
-               cosa_getdata16(cosa);
 #ifdef DEBUG_IO
-               debug_status_out(cosa, ((cosa->txchan<<13) & 0xe000)
+               debug_status_out(cosa, SR_TX_INT_ENA);
+               debug_data_out(cosa, ((cosa->txchan<<13) & 0xe000)
                         | (cosa->txsize & 0x1fff));
-               debug_data_in(cosa, cosa_getdata16(cosa));
+               debug_data_in(cosa, cosa_getdata8(cosa));
+               debug_status_out(cosa, 0);
 #else
-               cosa_getdata16(cosa);
+               cosa_getdata8(cosa);
 #endif
+               cosa_putstatus(cosa, 0);
        }
 
-       /* start the DMA */
-       flags1 = claim_dma_lock();
-       disable_dma(cosa->dma);
-       clear_dma_ff(cosa->dma);
-       set_dma_mode(cosa->dma, DMA_MODE_WRITE);
-       set_dma_addr(cosa->dma, virt_to_bus(cosa->txbuf));
-       set_dma_count(cosa->dma, cosa->txsize);
-       enable_dma(cosa->dma);
-       release_dma_lock(flags1);
+       if (cosa->busmaster) {
+               unsigned long addr = virt_to_bus(cosa->txbuf);
+               int count=0;
+               printk(KERN_INFO "busmaster IRQ\n");
+               while (!(cosa_getstatus(cosa)&SR_TX_RDY)) {
+                       count++;
+                       udelay(10);
+                       if (count > 1000) break;
+               }
+               printk(KERN_INFO "status %x\n", cosa_getstatus(cosa));
+               printk(KERN_INFO "ready after %d loops\n", count);
+               cosa_putdata16(cosa, (addr >> 16)&0xffff);
+
+               count = 0;
+               while (!(cosa_getstatus(cosa)&SR_TX_RDY)) {
+                       count++;
+                       if (count > 1000) break;
+                       udelay(10);
+               }
+               printk(KERN_INFO "ready after %d loops\n", count);
+               cosa_putdata16(cosa, addr &0xffff);
+               flags1 = claim_dma_lock();
+               set_dma_mode(cosa->dma, DMA_MODE_CASCADE);
+               enable_dma(cosa->dma);
+               release_dma_lock(flags1);
+       } else {
+               /* start the DMA */
+               flags1 = claim_dma_lock();
+               disable_dma(cosa->dma);
+               clear_dma_ff(cosa->dma);
+               set_dma_mode(cosa->dma, DMA_MODE_WRITE);
+               set_dma_addr(cosa->dma, virt_to_bus(cosa->txbuf));
+               set_dma_count(cosa->dma, cosa->txsize);
+               enable_dma(cosa->dma);
+               release_dma_lock(flags1);
+       }
        cosa_putstatus(cosa, SR_TX_DMA_ENA|SR_USR_INT_ENA);
 #ifdef DEBUG_IO
        debug_status_out(cosa, SR_TX_DMA_ENA|SR_USR_INT_ENA);
@@ -1671,21 +1772,16 @@ static inline void rx_interrupt(struct cosa_data *cosa, int status)
        if (is_8bit(cosa)) {
                if (!test_bit(IRQBIT, &cosa->rxtx)) {
                        set_bit(IRQBIT, &cosa->rxtx);
-                       cosa_putstatus(cosa, 0);
                        cosa->rxsize = cosa_getdata8(cosa) <<8;
 #ifdef DEBUG_IO
-                       debug_status_out(cosa, 0);
                        debug_data_in(cosa, cosa->rxsize >> 8);
 #endif
-                       put_driver_status_nolock(cosa);
                        spin_unlock_irqrestore(&cosa->lock, flags);
                        return;
                } else {
                        clear_bit(IRQBIT, &cosa->rxtx);
-                       cosa_putstatus(cosa, 0);
                        cosa->rxsize |= cosa_getdata8(cosa) & 0xff;
 #ifdef DEBUG_IO
-                       debug_status_out(cosa, 0);
                        debug_data_in(cosa, cosa->rxsize & 0xff);
 #endif
 #if 0
@@ -1695,12 +1791,8 @@ static inline void rx_interrupt(struct cosa_data *cosa, int status)
                }
        } else {
                cosa->rxsize = cosa_getdata16(cosa);
-               cosa_putstatus(cosa, 0);
-               cosa_putdata8(cosa, DRIVER_RX_READY);
 #ifdef DEBUG_IO
                debug_data_in(cosa, cosa->rxsize);
-               debug_status_out(cosa, 0);
-               debug_cmd_out(cosa, DRIVER_RX_READY);
 #endif
 #if 0
                printk(KERN_INFO "cosa%d: receive rxsize = (0x%04x).\n",
@@ -1725,10 +1817,7 @@ static inline void rx_interrupt(struct cosa_data *cosa, int status)
 reject:                /* Reject the packet */
                printk(KERN_INFO "cosa%d: rejecting packet on channel %d\n",
                        cosa->num, cosa->rxchan->num);
-               /* FIXME: This works for COSA only (not SRP) */
-               cosa->rxtx = 0;
-               put_driver_status(cosa);
-               return;
+               cosa->rxbuf = cosa->bouncebuf;
        }
 
        /* start the DMA */
@@ -1746,8 +1835,12 @@ reject:          /* Reject the packet */
        release_dma_lock(flags);
        spin_lock_irqsave(&cosa->lock, flags);
        cosa_putstatus(cosa, SR_RX_DMA_ENA|SR_USR_INT_ENA);
+       if (!is_8bit(cosa) && (status & SR_TX_RDY))
+               cosa_putdata8(cosa, DRIVER_RX_READY);
 #ifdef DEBUG_IO
        debug_status_out(cosa, SR_RX_DMA_ENA|SR_USR_INT_ENA);
+       if (!is_8bit(cosa) && (status & SR_TX_RDY))
+               debug_data_cmd(cosa, DRIVER_RX_READY);
 #endif
        spin_unlock_irqrestore(&cosa->lock, flags);
 }
@@ -1756,11 +1849,12 @@ static void inline eot_interrupt(struct cosa_data *cosa, int status)
 {
        unsigned long flags, flags1;
        spin_lock_irqsave(&cosa->lock, flags);
+       flags1 = claim_dma_lock();
+       disable_dma(cosa->dma);
+       clear_dma_ff(cosa->dma);
+       release_dma_lock(flags1);
        if (test_bit(TXBIT, &cosa->rxtx)) {
                struct channel_data *chan = cosa->chan+cosa->txchan;
-#ifdef DEBUG_IRQS
-               printk(KERN_INFO "cosa%d: end of transfer.\n", cosa->num);
-#endif
                if (chan->tx_done)
                        if (chan->tx_done(chan, cosa->txsize))
                                clear_bit(chan->num, &cosa->txbitmap);
@@ -1775,6 +1869,9 @@ static void inline eot_interrupt(struct cosa_data *cosa, int status)
                printk("\n");
        }
 #endif
+               /* Packet for unknown channel? */
+               if (cosa->rxbuf == cosa->bouncebuf)
+                       goto out;
                if (!cosa_dma_able(cosa->rxchan, cosa->rxbuf, cosa->rxsize))
                        memcpy(cosa->rxbuf, cosa->bouncebuf, cosa->rxsize);
                if (cosa->rxchan->rx_done)
@@ -1786,12 +1883,11 @@ static void inline eot_interrupt(struct cosa_data *cosa, int status)
        }
        /*
         * Clear the RXBIT, TXBIT and IRQBIT (the latest should be
-        * cleared anyway).
+        * cleared anyway). We should do it as soon as possible
+        * so that we can tell the COSA we are done and to give it a time
+        * for recovery.
         */
-       flags1 = claim_dma_lock();
-       disable_dma(cosa->dma);
-       clear_dma_ff(cosa->dma);
-       release_dma_lock(flags1);
+out:
        cosa->rxtx = 0;
        put_driver_status_nolock(cosa);
        spin_unlock_irqrestore(&cosa->lock, flags);
@@ -1799,7 +1895,7 @@ static void inline eot_interrupt(struct cosa_data *cosa, int status)
 
 static void cosa_interrupt(int irq, void *cosa_, struct pt_regs *regs)
 {
-       int status;
+       unsigned status;
        int count = 0;
        struct cosa_data *cosa = cosa_;
 again:
index 09f2e243d2848c5b72794bd0e01d3be1463dbf77..7b5a39018e869b44c606d3c6027f97119561d1fd 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: cosa.h,v 1.5 1998/12/24 12:40:18 kas Exp $ */
+/* $Id: cosa.h,v 1.6 1999/01/06 14:02:44 kas Exp $ */
 
 /*
  *  Copyright (C) 1995-1997  Jan "Yenya" Kasprzak <kas@fi.muni.cz>
@@ -99,4 +99,13 @@ struct cosa_download {
 /* Get the number of channels on this card */
 #define COSAIONRCHANS  _IO('C',0xf8)
 
+/* Set the driver for the bus-master operations */
+#define COSAIOBMSET    _IOW('C', 0xf9, sizeof(unsigned short))
+
+#define COSA_BM_OFF    0       /* Bus-mastering off - use ISA DMA (default) */
+#define COSA_BM_ON     1       /* Bus-mastering on - faster but untested */
+
+/* Gets the busmaster status */
+#define COSAIOBMGET    _IO('C', 0xfa)
+
 #endif /* !COSA_H__ */
index c40b6f5c801bd6a82c379c4a1671f6f821b0f221..64f6c327e911199898977ef186b39307afdd744e 100644 (file)
@@ -9,6 +9,7 @@ if [ "$CONFIG_IRTTY_SIR" != "n" ]; then
     dep_tristate '   ESI JetEye PC dongle' CONFIG_ESI_DONGLE $CONFIG_IRTTY_SIR
     dep_tristate '   ACTiSYS IR-220L and IR220L+ dongle' CONFIG_ACTISYS_DONGLE $CONFIG_IRTTY_SIR
     dep_tristate '   Tekram IrMate 210B dongle' CONFIG_TEKRAM_DONGLE $CONFIG_IRTTY_SIR
+    dep_tristate '   Greenwich GIrBIL dongle' CONFIG_GIRBIL_DONGLE $CONFIG_IRTTY_SIR
   fi
 fi
 dep_tristate '  NSC PC87108' CONFIG_NSC_FIR  $CONFIG_IRDA
index 05880d5e1f167454f0df7eb06f70859f9f70a6e9..6a15710043124655b5513a6753ef4aface948dba 100644 (file)
@@ -68,6 +68,14 @@ else
   endif
 endif
 
+ifeq ($(CONFIG_GIRBIL_DONGLE),y)
+L_OBJS += girbil.o
+else
+  ifeq ($(CONFIG_GIRBIL_DONGLE),m)
+  M_OBJS += girbil.o
+  endif
+endif
+
 include $(TOPDIR)/Rules.make
 
 clean:
index 97fb5fa2791940aad72e232f999d73fc2f60f152..513b9ba30bd676593413e6b2cd98a8ee2e764f61 100644 (file)
@@ -1,13 +1,13 @@
 /*********************************************************************
  *                
  * Filename:      actisys.c
- * Version:       0.4
+ * Version:       0.5
  * Description:   Implementation for the ACTiSYS IR-220L and IR-220L+ 
  *                dongles
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Wed Oct 21 20:02:35 1998
- * Modified at:   Mon Jan 18 11:30:25 1999
+ * Modified at:   Tue Feb  9 15:38:16 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
@@ -70,9 +70,10 @@ void actisys_cleanup(void)
 
 static void actisys_open( struct irda_device *idev, int type)
 {
-       strcat( idev->name, " <-> actisys");
+       strcat(idev->description, " <-> actisys");
 
         idev->io.dongle_id = type;
+       idev->flags |= IFF_DONGLE;
 
        MOD_INC_USE_COUNT;
 }
@@ -85,24 +86,20 @@ static void actisys_close( struct irda_device *dev)
 /*
  * Function actisys_change_speed (tty, baud)
  *
- *    Change speed of the ACTiSYS IR-220L and IR-220L+ type IrDA dongles.  
- *    To cycle through the available baud rates, pulse RTS low for a few ms.
- *    To be compatible with the new IR-220L+, we have to reset the dongle 
- *    first since its not possible cycle around anymore and still be 
- *    compatible with both dongles :-(
+ *    Change speed of the ACTiSYS IR-220L and IR-220L+ type IrDA dongles.
+ *    To cycle through the available baud rates, pulse RTS low for a few
+ *    ms.  
  */
 static void actisys_change_speed( struct irda_device *idev, int baudrate)
 {
         struct irtty_cb *self;
         struct tty_struct *tty;
-        int arg;
         struct termios old_termios;
        int cflag;
         int current_baudrate;
         int index = 0;
-       mm_segment_t fs;
        
-       DEBUG( 0, __FUNCTION__ "()\n");
+       DEBUG( 4, __FUNCTION__ "()\n");
 
        ASSERT( idev != NULL, return;);
        ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
@@ -115,10 +112,10 @@ static void actisys_change_speed( struct irda_device *idev, int baudrate)
        current_baudrate = idev->qos.baud_rate.value;
 
        /* Find the correct baudrate index for the currently used baudrate */
-       while ( current_baudrate != baud_rates[index])
+       while (current_baudrate != baud_rates[index])
                index++;
 
-        DEBUG( 0, __FUNCTION__ "(), index=%d\n", index);
+        DEBUG( 4, __FUNCTION__ "(), index=%d\n", index);
 
        if ( !self->tty)
                return;
@@ -127,38 +124,18 @@ static void actisys_change_speed( struct irda_device *idev, int baudrate)
 
        /* Cycle through avaiable baudrates until we reach the correct one */
         while ( current_baudrate != baudrate) {        
-                DEBUG( 0, __FUNCTION__ "(), current baudrate = %d\n",
+                DEBUG( 4, __FUNCTION__ "(), current baudrate = %d\n",
                        baud_rates[index]);
-               DEBUG( 0, __FUNCTION__ "(), Clearing RTS\n");
                
                /* Set DTR, clear RTS */
-               arg = TIOCM_DTR|TIOCM_OUT2;
-               
-               fs = get_fs();
-               set_fs( get_ds());
-               
-               if ( tty->driver.ioctl( tty, NULL, TIOCMSET, 
-                                       (unsigned long) &arg)) { 
-                       DEBUG( 0, __FUNCTION__ 
-                              "Error clearing RTS!\n");
-               }
-               set_fs(fs);
+               irtty_set_dtr_rts(tty, TRUE, FALSE);
                
                /* Wait at a few ms */
                current->state = TASK_INTERRUPTIBLE;
                schedule_timeout(2);
 
                /* Set DTR, Set RTS */
-                arg = TIOCM_DTR | TIOCM_RTS |TIOCM_OUT2;
-
-               fs = get_fs();
-               set_fs( get_ds());
-               
-               if ( tty->driver.ioctl( tty, NULL, TIOCMSET, 
-                                       (unsigned long) &arg)) { 
-                       DEBUG( 0, __FUNCTION__  "Error setting RTS!\n");
-               }
-               set_fs(fs);
+               irtty_set_dtr_rts(tty, TRUE, TRUE);
                
                /* Wait at a few ms again */
                current->state = TASK_INTERRUPTIBLE;
@@ -172,8 +149,8 @@ static void actisys_change_speed( struct irda_device *idev, int baudrate)
 
                 current_baudrate = baud_rates[index];
         }
-       DEBUG( 0, __FUNCTION__ "(), current baudrate = %d\n", 
-                  baud_rates[index]);
+       DEBUG(4, __FUNCTION__ "(), current baudrate = %d\n", 
+             baud_rates[index]);
 
        /* Now change the speed of the serial port */
        old_termios = *(tty->termios);
@@ -200,9 +177,8 @@ static void actisys_change_speed( struct irda_device *idev, int baudrate)
                break;
        }
 
+       /* Change speed of serial port */
        tty->termios->c_cflag = cflag;
-
-       DEBUG( 0, __FUNCTION__ "(), Setting the speed of the serial port\n");
        tty->driver.set_termios( tty, &old_termios);
 }
 
@@ -219,10 +195,6 @@ static void actisys_reset( struct irda_device *idev, int unused)
 {
        struct irtty_cb *self;
         struct tty_struct *tty;
-        int arg = 0;
-       mm_segment_t fs;
-
-       DEBUG( 4, __FUNCTION__ "()\n");
 
        ASSERT( idev != NULL, return;);
        ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
@@ -236,36 +208,16 @@ static void actisys_reset( struct irda_device *idev, int unused)
        if ( !tty)
                return;
 
-       DEBUG( 0, __FUNCTION__ "(), Clearing DTR\n");
-       arg = TIOCM_RTS | TIOCM_OUT2;
-
-       fs = get_fs();
-       set_fs( get_ds());
-       
-       if ( tty->driver.ioctl( tty, NULL, TIOCMSET, 
-                               (unsigned long) &arg)) 
-       { 
-               DEBUG( 0, __FUNCTION__"(), ioctl error!\n");
-       }
-       set_fs(fs);
+       /* Clear DTR */
+       irtty_set_dtr_rts(tty, FALSE, TRUE);
 
        /* Sleep 10-20 ms*/
        current->state = TASK_INTERRUPTIBLE;
        schedule_timeout(2);
        
-       DEBUG( 0, __FUNCTION__ "(), Setting DTR\n");
-       arg = TIOCM_RTS | TIOCM_DTR | TIOCM_OUT2;
-       
-       fs = get_fs();
-       set_fs( get_ds());
+       /* Go back to normal mode */
+       irtty_set_dtr_rts(tty, TRUE, TRUE);
        
-       if ( tty->driver.ioctl( tty, NULL, TIOCMSET, 
-                               (unsigned long) &arg)) 
-       { 
-               DEBUG( 0, __FUNCTION__"(), ioctl error!\n");
-       }
-       set_fs(fs);
-
        idev->qos.baud_rate.value = 9600;
 }
 
@@ -287,6 +239,9 @@ static void actisys_init_qos( struct irda_device *idev, struct qos_info *qos)
 }
 
 #ifdef MODULE
+
+MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
+MODULE_DESCRIPTION("ACTiSYS IR-220L and IR-220L+ dongle driver");      
                
 /*
  * Function init_module (void)
index a93e167aacbbbce4144175e57a2351a45656850c..8bdf796ef730ff9162400599ef13cb34196550cb 100644 (file)
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      esi.c
- * Version:       1.1
- * Description:   Driver for the Extended Systems JetEye PC
+ * Version:       1.2
+ * Description:   Driver for the Extended Systems JetEye PC dongle
  * Status:        Experimental.
  * Author:        Thomas Davis, <ratbert@radiks.net>
  * Created at:    Sat Feb 21 18:54:38 1998
- * Modified at:   Mon Jan 18 11:30:32 1999
+ * Modified at:   Tue Feb  9 15:36:47 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Sources:      esi.c
  *
@@ -71,6 +71,7 @@ static void esi_open( struct irda_device *idev, int type)
        strcat( idev->description, " <-> esi");
 
        idev->io.dongle_id = type;
+       idev->flags |= IFF_DONGLE;
 
        MOD_INC_USE_COUNT;
 }
@@ -90,10 +91,9 @@ static void esi_change_speed( struct irda_device *idev, int baud)
 {
        struct irtty_cb *self;
        struct tty_struct *tty;
-       int arg = TIOCM_OUT2;
+       int dtr, rts;
         struct termios old_termios;
        int cflag;
-       mm_segment_t fs;
        
        ASSERT( idev != NULL, return;);
        ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
@@ -116,37 +116,25 @@ static void esi_change_speed( struct irda_device *idev, int baud)
        switch (baud) {
        case 19200:
                cflag |= B19200;
-               arg |= TIOCM_DTR;
+               dtr = TRUE;
+               rts = FALSE;
                break;
        case 115200:
                cflag |= B115200;
-               arg |= TIOCM_RTS | TIOCM_DTR;
+               dtr = rts = TRUE;
                break;
        case 9600:
        default:
                cflag |= B9600;
-               arg |= TIOCM_RTS;
+               dtr = FALSE;
+               rts = TRUE;
                break;
        }
-               
+       /* Change speed of serial driver */
        tty->termios->c_cflag = cflag;
        tty->driver.set_termios( tty, &old_termios);
 
-       /*
-        *  The ioctl function, or actually set_modem_info in serial.c
-        *  expects a pointer to the argument in user space. To hack us
-        *  around this we use the set_fs function to fool the routines 
-        *  that check if they are called from user space. We also need 
-        *  to send a pointer to the argument so get_user() gets happy. 
-        *  DB.
-        */
-       fs = get_fs();
-       set_fs( get_ds());
-
-       if ( tty->driver.ioctl( tty, NULL, TIOCMSET, (unsigned long) &arg)) { 
-               DEBUG( 0, __FUNCTION__ "(), error setting ESI speed!\n");
-       }
-       set_fs(fs);
+       irtty_set_dtr_rts(tty, dtr, rts);
 }
 
 static void esi_reset( struct irda_device *idev, int unused)
diff --git a/drivers/net/irda/girbil.c b/drivers/net/irda/girbil.c
new file mode 100644 (file)
index 0000000..f74186b
--- /dev/null
@@ -0,0 +1,276 @@
+/*********************************************************************
+ *                
+ * Filename:      girbil.c
+ * Version:       1.0
+ * Description:   Implementation for the Greenwich GIrBIL dongle
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Sat Feb  6 21:02:33 1999
+ * Modified at:   Tue Feb  9 15:36:36 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1999 Dag Brattli, 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.
+ *  
+ *     Neither Dag Brattli nor University of Tromsø admit liability nor
+ *     provide warranty for any of this software. This material is 
+ *     provided "AS-IS" and at no charge.
+ *     
+ ********************************************************************/
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/tty.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+
+#include <asm/ioctls.h>
+#include <asm/segment.h>
+#include <asm/uaccess.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irmod.h>
+#include <net/irda/irda_device.h>
+#include <net/irda/irtty.h>
+#include <net/irda/dongle.h>
+
+static void girbil_reset(struct irda_device *dev, int unused);
+static void girbil_open(struct irda_device *dev, int type);
+static void girbil_close(struct irda_device *dev);
+static void girbil_change_speed(struct irda_device *dev, int baud);
+static void girbil_init_qos(struct irda_device *idev, struct qos_info *qos);
+
+/* Control register 1 */
+#define GIRBIL_TXEN    0x01 /* Enable transmitter */
+#define GIRBIL_RXEN    0x02 /* Enable receiver */
+#define GIRBIL_ECAN    0x04 /* Cancel self emmited data */
+#define GIRBIL_ECHO    0x08 /* Echo control characters */
+
+/* LED Current Register (0x2) */
+#define GIRBIL_HIGH    0x20
+#define GIRBIL_MEDIUM  0x21
+#define GIRBIL_LOW     0x22
+
+/* Baud register (0x3) */
+#define GIRBIL_2400    0x30
+#define GIRBIL_4800    0x31    
+#define GIRBIL_9600    0x32
+#define GIRBIL_19200   0x33
+#define GIRBIL_38400   0x34    
+#define GIRBIL_57600   0x35    
+#define GIRBIL_115200  0x36
+
+/* Mode register (0x4) */
+#define GIRBIL_IRDA    0x40
+#define GIRBIL_ASK     0x41
+
+/* Control register 2 (0x5) */
+#define GIRBIL_LOAD    0x51 /* Load the new baud rate value */
+
+static struct dongle dongle = {
+       GIRBIL_DONGLE,
+       girbil_open,
+       girbil_close,
+       girbil_reset,
+       girbil_change_speed,
+       girbil_init_qos,
+};
+
+__initfunc(void girbil_init(void))
+{
+       irtty_register_dongle(&dongle);
+}
+
+void girbil_cleanup(void)
+{
+       irtty_unregister_dongle(&dongle);
+}
+
+static void girbil_open(struct irda_device *idev, int type)
+{
+       strcat( idev->description, " <-> girbil");
+
+       idev->io.dongle_id = type;
+       idev->flags |= IFF_DONGLE;
+       
+       MOD_INC_USE_COUNT;
+}
+
+static void girbil_close(struct irda_device *dev)
+{
+       MOD_DEC_USE_COUNT;
+}
+
+/*
+ * Function girbil_change_speed (dev, speed)
+ *
+ *    Set the speed for the Girbil type dongle. Warning, this 
+ *    function must be called with a process context!
+ *
+ */
+static void girbil_change_speed(struct irda_device *idev, int speed)
+{
+       struct irtty_cb *self;
+       struct tty_struct *tty;
+       struct termios old_termios;
+       int cflag;
+       __u8 control[2];
+       
+       ASSERT(idev != NULL, return;);
+       ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
+       
+       self = (struct irtty_cb *) idev->priv;
+       
+       ASSERT(self != NULL, return;); 
+       ASSERT(self->magic == IRTTY_MAGIC, return;);
+       
+       if (!self->tty)
+               return;
+
+       tty = self->tty;
+       
+       old_termios = *(tty->termios);
+       cflag = tty->termios->c_cflag;
+
+       cflag &= ~CBAUD;
+
+       switch (speed) {
+       case 9600:
+       default:
+               cflag |= B9600;
+               control[0] = GIRBIL_9600;
+               break;
+       case 19200:
+               cflag |= B19200;
+               control[0] = GIRBIL_19200;
+               break;
+       case 34800:
+               cflag |= B38400;
+               control[0] = GIRBIL_38400;
+               break;
+       case 57600:
+               cflag |= B57600;
+               control[0] = GIRBIL_57600;
+               break;
+       case 115200:
+               cflag |= B115200;
+               control[0] = GIRBIL_115200;
+               break;
+       }
+       control[1] = GIRBIL_LOAD;
+
+       /* Set DTR and Clear RTS to enter command mode */
+       irtty_set_dtr_rts(tty, FALSE, TRUE);
+
+       /* Write control bytes */
+       if (tty->driver.write)
+               tty->driver.write(self->tty, 0, control, 2);
+
+       current->state = TASK_INTERRUPTIBLE;
+       schedule_timeout(2);
+       
+       /* Go back to normal mode */
+       irtty_set_dtr_rts(tty, TRUE, TRUE);
+
+       /* Now change the speed of the serial port */
+       tty->termios->c_cflag = cflag;
+       tty->driver.set_termios(tty, &old_termios);     
+}
+
+/*
+ * Function girbil_reset (driver)
+ *
+ *      This function resets the girbil dongle. Warning, this function 
+ *      must be called with a process context!! 
+ *
+ *      Algorithm:
+ *       0. set RTS, and wait at least 5 ms 
+ *        1. clear RTS 
+ */
+void girbil_reset(struct irda_device *idev, int unused)
+{
+       struct irtty_cb *self;
+       struct tty_struct *tty;
+       __u8 control = GIRBIL_TXEN | GIRBIL_RXEN /* | GIRBIL_ECAN */;
+
+       ASSERT(idev != NULL, return;);
+       ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
+       
+       self = (struct irtty_cb *) idev->priv;
+       
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == IRTTY_MAGIC, return;);
+
+       tty = self->tty;
+       if (!tty)
+               return;
+
+       /* Reset dongle */
+       irtty_set_dtr_rts(tty, TRUE, FALSE);
+
+       /* Sleep at least 5 ms */
+       current->state = TASK_INTERRUPTIBLE;
+       schedule_timeout(2);
+       
+       /* Set DTR and clear RTS to enter command mode */
+       irtty_set_dtr_rts(tty, FALSE, TRUE);
+
+       current->state = TASK_INTERRUPTIBLE;
+       schedule_timeout(2);
+
+       /* Write control byte */
+       if (tty->driver.write)
+               tty->driver.write(self->tty, 0, &control, 1);
+
+       current->state = TASK_INTERRUPTIBLE;
+       schedule_timeout(2);
+
+       /* Go back to normal mode */
+       irtty_set_dtr_rts(tty, TRUE, TRUE);
+}
+
+/*
+ * Function girbil_init_qos (qos)
+ *
+ *    Initialize QoS capabilities
+ *
+ */
+static void girbil_init_qos(struct irda_device *idev, struct qos_info *qos)
+{
+       qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
+       qos->min_turn_time.bits &= 0xfe; /* All except 0 ms */
+}
+
+#ifdef MODULE
+
+MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
+MODULE_DESCRIPTION("Greenwich GIrBIL dongle driver");
+       
+/*
+ * Function init_module (void)
+ *
+ *    Initialize Girbil module
+ *
+ */
+int init_module(void)
+{
+       girbil_init();
+       return(0);
+}
+
+/*
+ * Function cleanup_module (void)
+ *
+ *    Cleanup Girbil module
+ *
+ */
+void cleanup_module(void)
+{
+        girbil_cleanup();
+}
+
+#endif /* MODULE */
index ae8bcb27ba7c2ebdea9651efc70e76e9c740dd6f..616a8d3d9500b75a19f47d225008f1352e30e7eb 100644 (file)
@@ -96,7 +96,7 @@ __initfunc(int irport_init(void))
 #ifdef MODULE
 static void irport_cleanup(void)
 {
-       int i;
+/*     int i; */
 
         DEBUG( 4, __FUNCTION__ "()\n");
 
@@ -303,7 +303,6 @@ static int irport_write( int iobase, int fifo_size, __u8 *buf, int len)
 int irport_hard_xmit( struct sk_buff *skb, struct device *dev)
 {
        struct irda_device *idev;
-       int xbofs;
        int actual;
 
        DEBUG( 4, __FUNCTION__ "()\n");
index 09853b5b69747b2d0c1a08e5fe20931b885fd0d5..f4c39035ffb76a089b448e846afd2482f42427eb 100644 (file)
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      irtty.c
- * Version:       1.0
+ * Version:       1.1
  * Description:   IrDA line discipline implementation
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Dec  9 21:18:38 1997
- * Modified at:   Mon Jan 18 15:32:03 1999
+ * Modified at:   Tue Feb  9 13:08:25 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Sources:       slip.c by Laurence Culhane,   <loz@holmes.demon.co.uk>
  *                          Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
@@ -206,6 +206,7 @@ static int irtty_open( struct tty_struct *tty)
        self->idev.qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
                IR_115200;
        self->idev.qos.min_turn_time.bits = 0x03;
+       self->idev.flags = IFF_SIR | IFF_PIO;
        irda_qos_bits_to_value( &self->idev.qos);
 
        /* Specify which buffer allocation policy we need */
@@ -272,8 +273,6 @@ static void irtty_close( struct tty_struct *tty)
                kfree( self);
 
        MOD_DEC_USE_COUNT;
-
-       DEBUG( 4, "IrTTY: close() -->\n");
 }
 
 /* 
@@ -289,6 +288,8 @@ static void irtty_change_speed( struct irda_device *idev, int baud)
        struct irtty_cb *self;
        int cflag;
 
+       DEBUG(4,__FUNCTION__ "(), <%ld>\n", jiffies); 
+
        ASSERT( idev != NULL, return;);
        ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
 
@@ -360,10 +361,15 @@ static void irtty_init_dongle( struct irtty_cb *self, int type)
                DEBUG( 0, __FUNCTION__ "(), Tekram dongle!\n");
                request_module( "tekram");
                break;
-       case ACTISYS_DONGLE:
+       case ACTISYS_DONGLE:     /* FALLTHROUGH */
+       case ACTISYS_PLUS_DONGLE:
                DEBUG( 0, __FUNCTION__ "(), ACTiSYS dongle!\n");
                request_module( "actisys");
                break;
+       case GIRBIL_DONGLE:
+               DEBUG( 0, __FUNCTION__ "(), GIrBIL dongle!\n");
+               request_module( "girbil");
+               break;
        default:
                DEBUG( 0, __FUNCTION__ "(), Unknown dongle type!\n");
                return;
@@ -373,8 +379,7 @@ static void irtty_init_dongle( struct irtty_cb *self, int type)
 
        node = hashbin_find( dongles, type, NULL);
        if ( !node) {
-               DEBUG( 0, __FUNCTION__ 
-                      "(), Unable to find requested dongle\n");
+               DEBUG(0, __FUNCTION__ "(), Unable to find requested dongle\n");
                return;
        }
        self->dongle_q = node;
@@ -401,8 +406,7 @@ static void irtty_init_dongle( struct irtty_cb *self, int type)
  *     The Swiss army knife of system calls :-)
  *
  */
-static int irtty_ioctl( struct tty_struct *tty, void *file, int cmd, 
-                       void *arg) 
+static int irtty_ioctl(struct tty_struct *tty, void *file, int cmd, void *arg)
 {
        struct irtty_cb *self;
        int err = 0;
@@ -444,8 +448,8 @@ static int irtty_ioctl( struct tty_struct *tty, void *file, int cmd,
  *    been received, which can now be decapsulated and delivered for
  *    further processing 
  */
-static void irtty_receive_buf( struct tty_struct *tty, const unsigned 
-                              char *cp, char *fp, int count) 
+static void irtty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
+                             char *fp, int count) 
 {
        struct irtty_cb *self = (struct irtty_cb *) tty->disc_data;
 
@@ -464,11 +468,8 @@ static void irtty_receive_buf( struct tty_struct *tty, const unsigned
                        cp++;
                        continue;
                }
-               /*
-                *  Unwrap and destuff one byte
-                */
+               /* Unwrap and destuff one byte */
                async_unwrap_char( &self->idev, *cp++);
-               /* self->rx_over_errors++; */
        }
 }
 
@@ -478,7 +479,7 @@ static void irtty_receive_buf( struct tty_struct *tty, const unsigned
  *    Transmit skb
  *
  */
-static int irtty_hard_xmit( struct sk_buff *skb, struct device *dev)
+static int irtty_hard_xmit(struct sk_buff *skb, struct device *dev)
 {
        struct irtty_cb *self;
        struct irda_device *idev;
@@ -487,43 +488,40 @@ static int irtty_hard_xmit( struct sk_buff *skb, struct device *dev)
        ASSERT( dev != NULL, return 0;);
        ASSERT( skb != NULL, return 0;);
 
-       if ( dev->tbusy) {
-               DEBUG( 4, __FUNCTION__ "(), tbusy==TRUE\n");
-               
-               return -EBUSY;
-       }
-
        idev = (struct irda_device *) dev->priv;
 
-       ASSERT( idev != NULL, return 0;);
-       ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+       ASSERT(idev != NULL, return 0;);
+       ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;);
        
        self = (struct irtty_cb *) idev->priv;
 
-       ASSERT( self != NULL, return 0;);
-       ASSERT( self->magic == IRTTY_MAGIC, return 0;);
+       ASSERT(self != NULL, return 0;);
+       ASSERT(self->magic == IRTTY_MAGIC, return 0;);
 
        /* Lock transmit buffer */
-       if ( irda_lock( (void *) &dev->tbusy) == FALSE)
-               return 0;
+       if (irda_lock((void *) &dev->tbusy) == FALSE)
+               return -EBUSY;
 
         /*  
         *  Transfer skb to tx_buff while wrapping, stuffing and making CRC 
         */
-        idev->tx_buff.len = async_wrap_skb( skb, idev->tx_buff.data, 
-                                           idev->tx_buff.truesize); 
+        idev->tx_buff.len = async_wrap_skb(skb, idev->tx_buff.data, 
+                                          idev->tx_buff.truesize); 
 
        self->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
 
        dev->trans_start = jiffies;
 
        if ( self->tty->driver.write)
-               actual = self->tty->driver.write( self->tty, 0, 
-                                                 idev->tx_buff.data, 
-                                                 idev->tx_buff.len);
+               actual = self->tty->driver.write(self->tty, 0, 
+                                                idev->tx_buff.data, 
+                                                idev->tx_buff.len);
 
        idev->tx_buff.offset = actual;
        idev->tx_buff.head = idev->tx_buff.data + actual;
+
+       idev->stats.tx_packets++;
+       idev->stats.tx_bytes += idev->tx_buff.len;
 #if 0
        /* 
         *  Did we transmit the whole frame? Commented out for now since
@@ -535,8 +533,7 @@ static int irtty_hard_xmit( struct sk_buff *skb, struct device *dev)
                irda_unlock( &self->tbusy);
        }
 #endif
-
-       dev_kfree_skb( skb);
+       dev_kfree_skb(skb);
 
        return 0;
 }
@@ -587,8 +584,6 @@ static void irtty_write_wakeup( struct tty_struct *tty)
                tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
 
                idev->netdev.tbusy = 0; /* Unlock */
-               idev->stats.tx_packets++;
-               idev->stats.tx_bytes += idev->tx_buff.len;
 
                /* Tell network layer that we want more frames */
                mark_bh( NET_BH);
@@ -602,8 +597,6 @@ static void irtty_write_wakeup( struct tty_struct *tty)
        actual = tty->driver.write( tty, 0, idev->tx_buff.head, count);
        idev->tx_buff.offset += actual;
        idev->tx_buff.head += actual;
-
-       DEBUG( 4, "actual=%d, sent %d\n", actual, count);
 }
 
 /*
@@ -648,8 +641,7 @@ int irtty_register_dongle( struct dongle *dongle)
         }
        
        /* Make new IrDA dongle */
-        new = (struct dongle_q *) kmalloc (sizeof (struct dongle_q), 
-                                             GFP_KERNEL);
+        new = (struct dongle_q *)kmalloc(sizeof(struct dongle_q), GFP_KERNEL);
         if (new == NULL) {
                 return 1;
                
@@ -675,6 +667,35 @@ void irtty_unregister_dongle( struct dongle *dongle)
        kfree( node);
 }
 
+
+void irtty_set_dtr_rts(struct tty_struct *tty, int dtr, int rts)
+{
+       mm_segment_t fs;
+       int arg = TIOCM_OUT2;
+
+       if (rts)
+               arg |= TIOCM_RTS;
+       if (dtr)
+               arg |= TIOCM_DTR;
+
+       /*
+        *  The ioctl() function, or actually set_modem_info() in serial.c
+        *  expects a pointer to the argument in user space. To hack us
+        *  around this, we use the set_fs() function to fool the routines 
+        *  that check if they are called from user space. We also need 
+        *  to send a pointer to the argument so get_user() gets happy. DB.
+        */
+
+       fs = get_fs();
+       set_fs(get_ds());
+       
+       if (tty->driver.ioctl(tty, NULL, TIOCMSET, (unsigned long) &arg)) { 
+               DEBUG(0, __FUNCTION__ "(), error!\n");
+       }
+       set_fs(fs);
+}
+
+
 static int irtty_net_init( struct device *dev)
 {
        /* Set up to be a normal IrDA network device driver */
@@ -715,6 +736,9 @@ static int irtty_net_close(struct device *dev)
 
 #ifdef MODULE
 
+MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
+MODULE_DESCRIPTION("IrDA TTY device driver");
+
 /*
  * Function init_module (void)
  *
index faf9eea3376d51c21ddae046a37ad349c3da734e..ea35883a55630f905803ea0f813b78986fd84ce4 100644 (file)
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Nov  7 21:43:15 1998
- * Modified at:   Mon Dec 28 08:46:16 1998
+ * Modified at:   Tue Feb  9 13:29:40 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>
@@ -50,7 +50,6 @@
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <linux/malloc.h>
-#include <linux/delay.h>
 #include <linux/init.h>
 
 #include <asm/io.h>
@@ -100,7 +99,9 @@ static char *dongle_types[] = {
 /* Some prototypes */
 static int  pc87108_open( int i, unsigned int iobase, unsigned int board_addr, 
                          unsigned int irq, unsigned int dma);
+#ifdef MODULE
 static int  pc87108_close( struct irda_device *idev);
+#endif /* MODULE */
 static int  pc87108_probe( int iobase, int board_addr, int irq, int dma);
 static void pc87108_pio_receive( struct irda_device *idev);
 static int  pc87108_dma_receive( struct irda_device *idev); 
@@ -221,6 +222,8 @@ static int pc87108_open( int i, unsigned int iobase, unsigned int board_addr,
        idev->qos.min_turn_time.bits = 0x07;
        irda_qos_bits_to_value( &idev->qos);
        
+       idev->flags = IFF_FIR|IFF_MIR|IFF_SIR|IFF_DMA|IFF_PIO|IFF_DONGLE;
+
        /* Specify which buffer allocation policy we need */
        idev->rx_buff.flags = GFP_KERNEL | GFP_DMA;
        idev->tx_buff.flags = GFP_KERNEL | GFP_DMA;
@@ -250,6 +253,7 @@ static int pc87108_open( int i, unsigned int iobase, unsigned int board_addr,
        return 0;
 }
 
+#ifdef MODULE
 /*
  * Function pc87108_close (idev)
  *
@@ -276,6 +280,7 @@ static int pc87108_close( struct irda_device *idev)
 
        return 0;
 }
+#endif /* MODULE */
 
 /*
  * Function pc87108_probe (iobase, board_addr, irq, dma)
@@ -720,12 +725,6 @@ static int pc87108_hard_xmit( struct sk_buff *skb, struct device *dev)
        iobase = idev->io.iobase;
 
        DEBUG(4, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, (int) skb->len);
-
-       if ( dev->tbusy) {
-               DEBUG( 4, __FUNCTION__ "(), tbusy==TRUE\n");
-                       
-               return -EBUSY;
-       }
        
        /* Lock transmit buffer */
        if ( irda_lock( (void *) &dev->tbusy) == FALSE)
index bdada4afab5e7603aed4846dd8167d1e38847a6b..40a1e46bf2b8e17723c11af1fea0040c6281497a 100644 (file)
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      tekram.c
- * Version:       0.4
+ * Version:       0.5
  * Description:   Implementation of the Tekram IrMate IR-210B dongle
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Wed Oct 21 20:02:35 1998
- * Modified at:   Mon Jan 18 11:30:38 1999
+ * Modified at:   Tue Feb  9 15:36:55 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
@@ -63,9 +63,12 @@ void tekram_cleanup(void)
        irtty_unregister_dongle( &dongle);
 }
 
-static void tekram_open( struct irda_device *dev, int type)
+static void tekram_open( struct irda_device *idev, int type)
 {
-       strcat( dev->name, " <-> tekram");
+       strcat(idev->description, " <-> tekram");
+
+       idev->io.dongle_id = type;
+       idev->flags |= IFF_DONGLE;
        
        MOD_INC_USE_COUNT;
 }
@@ -96,11 +99,8 @@ static void tekram_change_speed( struct irda_device *dev, int baud)
        struct irtty_cb *self;
        struct tty_struct *tty;
        struct termios old_termios;
-       int arg = 0;
        int cflag;
        __u8 byte;
-       int actual;
-       mm_segment_t fs;
        
        DEBUG( 4, __FUNCTION__ "()\n");
 
@@ -147,44 +147,22 @@ static void tekram_change_speed( struct irda_device *dev, int baud)
        }
 
        /* Set DTR, Clear RTS */
-       DEBUG( 0, __FUNCTION__ "(), Setting DTR, Clearing RTS\n");
-       arg = TIOCM_DTR | TIOCM_OUT2;
-       
-       fs = get_fs();
-       set_fs( get_ds());
-       
-       if ( tty->driver.ioctl( tty, NULL, TIOCMSET, 
-                                (unsigned long) &arg)) { 
-               DEBUG( 0, "error setting Tekram speed!\n");
-       }
-       set_fs(fs);
+       irtty_set_dtr_rts(tty, TRUE, FALSE);
        
        /* Wait at least 7us */
        udelay( 7);
 
-       DEBUG( 0, __FUNCTION__ "(), Writing control byte\n");
        /* Write control byte */
        if ( tty->driver.write)
-               actual = tty->driver.write( self->tty, 0, &byte, 1);
+               tty->driver.write( self->tty, 0, &byte, 1);
        
        /* Wait at least 100 ms */
        current->state = TASK_INTERRUPTIBLE;
        schedule_timeout( 10);
         
        /* Set DTR, Set RTS */
-       DEBUG( 0, __FUNCTION__ "(), Setting DTR, Setting RTS\n");
-       arg = TIOCM_DTR | TIOCM_RTS | TIOCM_OUT2;
-       
-       fs = get_fs();
-       set_fs( get_ds());
-       
-       if ( tty->driver.ioctl( tty, NULL, TIOCMSET, 
-                               (unsigned long) &arg)) { 
-               DEBUG( 0, "error setting Tekram speed!\n");
-       }
-       set_fs(fs);
+       irtty_set_dtr_rts(tty, TRUE, TRUE);
 
-       DEBUG( 0, __FUNCTION__ "(), Setting new speed on serial port\n");
        /* Now change the speed of the serial port */
        tty->termios->c_cflag = cflag;
        tty->driver.set_termios( tty, &old_termios);    
@@ -208,8 +186,6 @@ void tekram_reset( struct irda_device *dev, int unused)
 {
        struct irtty_cb *self;
        struct tty_struct *tty;
-       int arg = 0;
-       mm_segment_t fs;
 
        DEBUG( 4, __FUNCTION__ "()\n");
 
@@ -225,51 +201,22 @@ void tekram_reset( struct irda_device *dev, int unused)
        if ( !tty)
                return;
 
-       DEBUG( 0, __FUNCTION__ "(), Power off dongle\n");
-       arg = TIOCM_RTS | TIOCM_DTR | TIOCM_OUT2;
-       
-       fs = get_fs();
-       set_fs( get_ds());
-       
-       if ( tty->driver.ioctl( tty, NULL, TIOCMSET, 
-                               (unsigned long) &arg)) 
-       { 
-               DEBUG(0, "error setting ESI speed!\n");
-       }
-       set_fs(fs);
+       /* Power off dongle */
+       irtty_set_dtr_rts(tty, FALSE, FALSE);
 
        /* Sleep 50 ms */
        current->state = TASK_INTERRUPTIBLE;
        schedule_timeout(5);
-       
-       DEBUG( 0, __FUNCTION__ "(), Set DTR, clear RTS\n");
-       /* Set DTR, clear RTS */
-       arg = TIOCM_DTR | TIOCM_OUT2;
-       
-       fs = get_fs();
-       set_fs( get_ds());
-       
-       if ( tty->driver.ioctl( tty, NULL, TIOCMSET, 
-                               (unsigned long) &arg)) { 
-               DEBUG( 0, "Error setting Tekram speed!\n");
-       }
-       set_fs(fs);
+
+       /* Clear DTR, Set RTS */
+       irtty_set_dtr_rts(tty, FALSE, TRUE); 
 
        /* Should sleep 1 ms, but 10-20 should not do any harm */
        current->state = TASK_INTERRUPTIBLE;
        schedule_timeout(2);
 
-       DEBUG( 0, __FUNCTION__ "(), STATE3\n");
-       /* Clear DTR, clear RTS */
-       arg = TIOCM_OUT2;
-
-       fs = get_fs();
-       set_fs( get_ds());
-       
-       if ( tty->driver.ioctl( tty, NULL, TIOCMSET, (unsigned long) &arg)) { 
-               DEBUG( 0, "error setting Tekram speed!\n");
-       }
-       set_fs(fs);
+       /* Set DTR, Set RTS */
+       irtty_set_dtr_rts(tty, TRUE, TRUE);
        
        /* Finished! */
 }
@@ -287,6 +234,9 @@ static void tekram_init_qos( struct irda_device *idev, struct qos_info *qos)
 }
 
 #ifdef MODULE
+
+MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
+MODULE_DESCRIPTION("Tekram IrMate IR-210B dongle driver");
                
 /*
  * Function init_module (void)
@@ -311,4 +261,4 @@ void cleanup_module(void)
         tekram_cleanup();
 }
 
-#endif
+#endif /* MODULE */
index 05da78a001ffd2947b43a9363481cb0e58724ab2..e182049eabc825df0d702dae40ec590e284ab88a 100644 (file)
@@ -7,7 +7,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Dec 26 10:59:03 1998
- * Modified at:   Tue Jan 19 23:54:04 1999
+ * Modified at:   Tue Feb  9 13:30:41 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
@@ -196,6 +196,8 @@ static int uircc_open( int i, unsigned int iobase, unsigned int iobase2,
 
        idev->qos.min_turn_time.bits = 0x07;
        irda_qos_bits_to_value( &idev->qos);
+
+       idev->flags = IFF_FIR|IFF_SIR|IFF_DMA|IFF_PIO;
        
        /* Specify which buffer allocation policy we need */
        idev->rx_buff.flags = GFP_KERNEL | GFP_DMA;
@@ -271,9 +273,11 @@ static int uircc_close( struct irda_device *idev)
 static int uircc_probe( int iobase, int iobase2, int irq, int dma) 
 {
        int version;
+#if 0
        int probe_irq=0;
        unsigned long mask;
        int i;
+#endif
        
        DEBUG( 0, __FUNCTION__ "()\n");
 
@@ -442,20 +446,12 @@ static int uircc_hard_xmit( struct sk_buff *skb, struct device *dev)
        DEBUG(0, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, (int) skb->len);
 
        /* Use irport for SIR speeds */
-       if ( idev->io.baudrate <= 115200) {
-               return irport_hard_xmit( skb, dev);
-       }
-
-       if ( dev->tbusy) {
-               __u8 sr3;
-
-               DEBUG( 4, __FUNCTION__ "(), tbusy==TRUE\n");
-                       
-               return -EBUSY;
+       if (idev->io.baudrate <= 115200) {
+               return irport_hard_xmit(skb, dev);
        }
        
        /* Lock transmit buffer */
-       if ( irda_lock( (void *) &dev->tbusy) == FALSE)
+       if (irda_lock((void *) &dev->tbusy) == FALSE)
                return -EBUSY;
 
        memcpy( idev->tx_buff.data, skb->data, skb->len);
index 5a7995ef7ead306e8d4ad9b085923cc0cfca7713..7e634e0fe41d1a317a634200f0b00a0339f6b886 100644 (file)
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Paul VanderSpek
  * Created at:    Wed Nov  4 11:46:16 1998
- * Modified at:   Mon Dec 14 21:51:53 1998
+ * Modified at:   Tue Feb  9 13:30:35 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Corel Computer Corp.
@@ -204,6 +204,8 @@ int w83977af_open( int i, unsigned int iobase, unsigned int irq,
        /* The HP HDLS-1100 needs 1 ms according to the specs */
        idev->qos.min_turn_time.bits = 0x03; /* 1ms and more */
        irda_qos_bits_to_value( &idev->qos);
+       
+       idev->flags = IFF_FIR|IFF_MIR|IFF_SIR|IFF_DMA|IFF_PIO;
 
        /* Specify which buffer allocation policy we need */
        idev->rx_buff.flags = GFP_KERNEL | GFP_DMA;
@@ -468,12 +470,6 @@ int w83977af_hard_xmit( struct sk_buff *skb, struct device *dev)
        iobase = idev->io.iobase;
 
        DEBUG(4, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, (int) skb->len);
-
-       if ( dev->tbusy) {
-               DEBUG( 4, __FUNCTION__ "(), tbusy==TRUE\n");
-
-               return -EBUSY;
-       }
        
        /* Lock transmit buffer */
        if ( irda_lock( (void *) &dev->tbusy) == FALSE)
index 36b9123e8aa24dc83a7eab3f0f11f67136d7b29c..9bbf753c5ae9d09ecc1ee0947ec2040d1501f2b5 100644 (file)
@@ -105,6 +105,7 @@ bad_clone_list[] __initdata = {
     {"ET-100","ET-200", {0x00, 0x45, 0x54}}, /* YANG and YA clone */
     {"COMPEX","COMPEX16",{0x00,0x80,0x48}}, /* Broken ISA Compex cards */
     {"E-LAN100", "E-LAN200", {0x00, 0x00, 0x5d}}, /* Broken ne1000 clones */
+    {"PCM-4823", "PCM-4823", {0x00, 0xc0, 0x6c}}, /* Broken Advantech MoBo */    
     {0,}
 };
 #endif
index c41da18669e49958766ffbed84a736dc14021416..4bf73f81e225f7084e6d0cad0182e5f71edf947c 100644 (file)
@@ -1217,7 +1217,7 @@ static int inline
 plip_searchfor(int list[], int a)
 {
        int i;
-       for (i = 0; i < 3 && list[i] != -1; i++) {
+       for (i = 0; i < PLIP_MAX && list[i] != -1; i++) {
                if (list[i] == a) return 1;
        }
        return 0;
@@ -1240,7 +1240,7 @@ plip_init(void))
        /* If the user feeds parameters, use them */
        while (pb) {
                if ((parport[0] == -1 && (!timid || !pb->devices)) || 
-                   plip_searchfor(parport, i)) {
+                   plip_searchfor(parport, pb->number)) {
                        if (i == PLIP_MAX) {
                                printk(KERN_ERR "plip: too many devices\n");
                                break;
index ac6736cabfb44451111489a38c1f7292c94e4b95..244df754479c659acbdb6c276e2dc3bf8b61d74f 100644 (file)
@@ -733,7 +733,7 @@ __initfunc(int SK_probe(struct device *dev, short ioaddr))
     SK_print_pos(dev, "POS registers after ROM, RAM config");
 #endif
 
-    board = (SK_RAM *) rom_addr; 
+    board = (SK_RAM *) bus_to_virt(rom_addr);
 
     /* Read in station address */
     for (i = 0, j = 0; i < ETH_ALEN; i++, j+=2)
index 599253933317f92bf5afeb2e8a17e123159933d1..4e1e3465d3306cbb90c12c0c3ab4dd354f43cfda 100644 (file)
@@ -1,12 +1,12 @@
 /*
- *     $Id: pci.c,v 1.90 1998/09/05 12:39:39 mj Exp $
+ *     $Id: pci.c,v 1.91 1999/01/21 13:34:01 davem Exp $
  *
  *     PCI Bus Services, see include/linux/pci.h for further explanation.
  *
  *     Copyright 1993 -- 1997 Drew Eckhardt, Frederic Potter,
  *     David Mosberger-Tang
  *
- *     Copyright 1997 -- 1998 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ *     Copyright 1997 -- 1999 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
  */
 
 #include <linux/config.h>
@@ -28,9 +28,6 @@
 #endif
 
 struct pci_bus pci_root;
-#ifdef CONFIG_VISWS
-struct pci_bus pci_other;
-#endif
 struct pci_dev *pci_devices = NULL;
 static struct pci_dev **pci_last_dev_p = &pci_devices;
 static int pci_reverse __initdata = 0;
@@ -371,6 +368,18 @@ __initfunc(unsigned int pci_scan_bus(struct pci_bus *bus))
        return max;
 }
 
+struct pci_bus * __init pci_scan_peer_bridge(int bus)
+{
+       struct pci_bus *b;
+
+       b = kmalloc(sizeof(*b), GFP_KERNEL);
+       memset(b, 0, sizeof(*b));
+       b->next = pci_root.next;
+       pci_root.next = b;
+       b->number = b->secondary = bus;
+       b->subordinate = pci_scan_bus(b);
+       return b;
+}
 
 __initfunc(void pci_init(void))
 {
@@ -385,11 +394,6 @@ __initfunc(void pci_init(void))
 
        memset(&pci_root, 0, sizeof(pci_root));
        pci_root.subordinate = pci_scan_bus(&pci_root);
-#ifdef CONFIG_VISWS
-       pci_other.number = 1; /* XXX unless bridge(s) on pci_root */
-       pci_other.subordinate = pci_scan_bus(&pci_other);
-       pci_root.next = &pci_other;
-#endif
 
        /* give BIOS a chance to apply platform specific fixes: */
        pcibios_fixup();
@@ -403,7 +407,6 @@ __initfunc(void pci_init(void))
 #endif
 }
 
-
 __initfunc(void pci_setup (char *str, int *ints))
 {
        while (str) {
index cea0c5131aac7bc012fd45485c6e78ff933bf902..2160b75a4a1b4643eadc1e322e9ac31f1862b9ca 100644 (file)
@@ -72,8 +72,6 @@ flash_mmap(struct file *file, struct vm_area_struct *vma)
        if (remap_page_range(vma->vm_start, addr, size, vma->vm_page_prot))
                return -EAGAIN;
                
-       vma->vm_file = file;
-       file->f_count++;
        return 0;
 }
 
index 48661f34b0af27f1fd902cc66797eebf4a89e7b9..9ebc20c7189842f02ecf3882a4f6905e2e20ca93 100644 (file)
@@ -582,8 +582,6 @@ static int vfc_mmap(struct inode *inode, struct file *file,
        if(ret)
                return -EAGAIN;
 
-       vma->vm_file = file;
-       file->f_count++;
        return 0;
 }
 
index 0f9c85de5bc510d914f010b03e76f257ac6c2afa..2ecad6f2b39b78c6ac7e41b3ad64ec3839126b3c 100644 (file)
@@ -1,4 +1,26 @@
-Sat Jan 16  17:30 1998 Gerard Roudier (groudier@club-internet.fr)
+Sat Mar 6  11:00 1999 Gerard Roudier (groudier@club-internet.fr)
+       * revision 3.1h
+       - Fix some oooold bug that hangs the bus if a device rejects a 
+         negotiation. Btw, the corresponding stuff also needed some cleanup 
+         and thus the change is a bit larger than it could have been.
+       - Still some typo that made compilation fail for 64 bit (trivial fix).
+
+Sun Feb  14:00 1999 Gerard Roudier (groudier@club-internet.fr)
+       * revision 3.1g
+       - Deal correctly with 64 bit PCI address registers on Linux 2.2.
+         Pointed out by Leonard Zubkoff.
+       - Allow to tune request_irq() flags from the boot command line using 
+         ncr53c8xx=irqm:??, as follows:
+         a) If bit 0x10 is set in irqm, SA_SHIRQ flag is not used.
+         b) If bit 0x20 is set in irqm, SA_INTERRUPT flag is not used.
+         By default the driver uses both SA_SHIRQ and SA_INTERRUPT.
+         Option 'ncr53c8xx=irqm:0x20' may be used when an IRQ is shared by 
+         a 53C8XX adapter and a network board.
+       - Tiny mispelling fixed (ABORT instead of ABRT). Was fortunately 
+         harmless.
+       - Negotiate SYNC data transfers with CCS devices.
+
+Sat Jan 16  17:30 1999 Gerard Roudier (groudier@club-internet.fr)
        * revision 3.1f
        - Some PCI fix-ups not needed any more for PPC (from Cort).
        - Cache line size set to 16 DWORDS for Sparc   (from DSM).
index 47bbe19ba6bfe202c3e6eecea7811774b96e7292..38babc5f1099ddabd16664ec6fa4546b8e52a40a 100644 (file)
@@ -4,7 +4,7 @@ Written by Gerard Roudier <groudier@club-internet.fr>
 21 Rue Carnot
 95170 DEUIL LA BARRE - FRANCE
 
-22 November 1998
+14 February 1999
 ===============================================================================
 
 1.  Introduction
@@ -39,6 +39,7 @@ Written by Gerard Roudier <groudier@club-internet.fr>
       14.2 Device names change when another controller is added
       14.3 Using only 8 bit devices with a WIDE SCSI controller.
       14.4 Possible data corruption during a Memory Write and Invalidate
+      14.5 IRQ sharing problems
 15. SCSI problem troubleshooting
 16. Synchonous transfer negotiation tables
       16.1 Synchronous timings for 53C875 and 53C860 Ultra-SCSI controllers
@@ -669,6 +670,10 @@ IRQ mode
     irqm:0     always open drain
     irqm:1     same as initial settings (assumed BIOS settings)
     irqm:2     always totem pole
+    irqm:0x10  driver will not use SA_SHIRQ flag when requesting irq
+    irqm:0x20  driver will not use SA_INTERRUPT flag when requesting irq
+
+    (Bits 0x10 and 0x20 can be combined with hardware irq mode option)
 
 Reverse probe
     revprob:n   probe chip ids from the PCI configuration in this order:
@@ -1027,7 +1032,25 @@ they only refer to system buffers that are well aligned. So, a work around
 may only be needed under Linux when a scatter/gather list is not used and 
 when the SCSI DATA IN phase is reentered after a phase mismatch.
 
+14.5 IRQ sharing problems
+
+When an IRQ is shared by devices that are handled by different drivers, it 
+may happen that one driver complains about the request of the IRQ having 
+failed. This may be due to one driver having requested the IRQ using the 
+SA_INTERRUPT flag but some other having requested the same IRQ without this 
+flag, or to one driver not having requested the IRQ with the SA_SHIRQ flag.
+
+By default, the ncr53c8xx driver requests IRQs with both the SA_INTERRUPT 
+and the SA_SHIRQ flag, but you can disable use of SA_INTERRUPT flags from 
+the boot command line by using the following option:
+
+                      ncr53c8xx=irqm:0x20
+
+If this does not fix the problem, then you may want to check how all other 
+drivers are requesting the IRQ and report the problem. Note that if at least 
+a single driver does not request the IRQ with the SA_SHIRQ flag (share IRQ), 
+then the request of the IRQ obviously will not succeed for all the drivers.
+
 15. SCSI problem troubleshooting
 
 Most SCSI problems are due to a non conformant SCSI bus or to buggy
index c50bd279394527eb2cf2d57362d3e4564985c0bc..da8099937ccf7b167d734c42434216dd23b4a18a 100644 (file)
@@ -2,7 +2,7 @@ This file contains brief information about the SCSI tape driver.
 The driver is currently maintained by Kai M{kisara (email
 Kai.Makisara@metla.fi)
 
-Last modified: Sun Sep  6 10:03:47 1998 by makisara@home
+Last modified: Sun Jan 17 10:57:41 1999 by makisara@home
 
 
 BASICS
@@ -60,11 +60,20 @@ scans its database, and sets up the modes using the ioctls. Another
 alternative is to make a small script that uses mt to set the defaults
 tailored to the system.
 
-
 The driver supports fixed and variable block size (within buffer
 limits). Both the auto-rewind (minor equals device number) and
 non-rewind devices (minor is 128 + device number) are implemented.
 
+In variable block mode, the byte count in write() determines the size
+of the physical block on tape. When reading, the drive reads the next
+tape block and returns to the user the data if the read() byte count
+is at least the block size. Otherwise the data is truncated.
+
+In fixed block mode, the data transfer between the drive and the
+driver is in multiples of the block size. The write() byte count must
+be a multiple of the block size. This is not required when reading but
+may be advisable for portability.
+
 Support is provided for changing the tape partition and partitioning
 of the tape with one or two partitions. By default support for
 partitioned tape is disabled for each driver and it can be enabled
index d6cbbcded52bb7d463d99988f49819f6324b82e1..ccd54869fd3f3d39c69186f0fa1bdade14debfe1 100644 (file)
@@ -73,7 +73,7 @@
 */
 
 /*
-**     January 16 1998, version 3.1f
+**     March 6 1999, version 3.1h
 **
 **     Supported SCSI-II features:
 **         Synchronous negotiation
@@ -2081,6 +2081,7 @@ struct scripth {
        ncrcmd  msg_ext_3       [ 10];
        ncrcmd  msg_sdtr        [ 14];
        ncrcmd  send_sdtr       [  7];
+       ncrcmd  nego_bad_phase  [  4];
        ncrcmd  msg_out_abort   [ 10];
        ncrcmd  hdata_in        [MAX_SCATTERH * 4];
        ncrcmd  hdata_in2       [  2];
@@ -3185,16 +3186,15 @@ static  struct scripth scripth0 __initdata = {
        /*
        **      If a negotiation was in progress,
        **      negotiation failed.
+       **      Otherwise, let the C code print 
+       **      some message.
        */
        SCR_FROM_REG (HS_REG),
                0,
-       SCR_INT ^ IFTRUE (DATA (HS_NEGOTIATE)),
-               SIR_NEGO_FAILED,
-       /*
-       **      else make host log this message
-       */
        SCR_INT ^ IFFALSE (DATA (HS_NEGOTIATE)),
                SIR_REJECT_RECEIVED,
+       SCR_INT ^ IFTRUE (DATA (HS_NEGOTIATE)),
+               SIR_NEGO_FAILED,
        SCR_JUMP,
                PADDR (clrack),
 
@@ -3304,10 +3304,9 @@ static   struct scripth scripth0 __initdata = {
                0,
        SCR_CLR (SCR_ACK),
                0,
+       SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_OUT)),
+               PADDRH (nego_bad_phase),
 
-/* CHECK THE SOURCE FOR 'send_wdtr' IF YOU INTEND TO CHANGE SOMETHING HERE */
-       SCR_INT ^ IFFALSE (WHEN (SCR_MSG_OUT)),
-               SIR_NEGO_PROTO,
 }/*-------------------------< SEND_WDTR >----------------*/,{
        /*
        **      Send the M_X_WIDE_REQ
@@ -3360,10 +3359,9 @@ static   struct scripth scripth0 __initdata = {
                0,
        SCR_CLR (SCR_ACK),
                0,
+       SCR_JUMP ^ IFFALSE (WHEN (SCR_MSG_OUT)),
+               PADDRH (nego_bad_phase),
 
-/* CHECK THE SOURCE FOR 'send_sdtr' IF YOU INTEND TO CHANGE SOMETHING HERE */
-       SCR_INT ^ IFFALSE (WHEN (SCR_MSG_OUT)),
-               SIR_NEGO_PROTO,
 }/*-------------------------< SEND_SDTR >-------------*/,{
        /*
        **      Send the M_X_SYNC_REQ
@@ -3376,6 +3374,12 @@ static   struct scripth scripth0 __initdata = {
        SCR_JUMP,
                PADDR (msg_out_done),
 
+}/*-------------------------< NEGO_BAD_PHASE >------------*/,{
+       SCR_INT,
+               SIR_NEGO_PROTO,
+       SCR_JUMP,
+               PADDR (dispatch),
+
 }/*-------------------------< MSG_OUT_ABORT >-------------*/,{
        /*
        **      After ABORT message,
@@ -4274,7 +4278,7 @@ static int ncr_prepare_setting(ncb_p np, ncr_nvram *nvram)
        /*
        **      Set irq mode.
        */
-       switch(driver_setup.irqm) {
+       switch(driver_setup.irqm & 3) {
        case 2:
                np->rv_dcntl    |= IRQM;
                break;
@@ -4665,21 +4669,11 @@ printk(KERN_INFO "ncr53c%s-%d: rev=0x%02x, base=0x%lx, io_port=0x%lx, irq=%d\n",
        /*
        **      Install the interrupt handler.
        */
-#ifdef SCSI_NCR_SHARE_IRQ
-#define        NCR_SA_INTERRUPT_FLAGS (SA_INTERRUPT | SA_SHIRQ)
-       if (bootverbose > 1)
-#ifdef __sparc__
-               printk(KERN_INFO "%s: requesting shared irq %s (dev_id=0x%lx)\n",
-                       ncr_name(np), __irq_itoa(device->slot.irq), (u_long) np);
-#else
-               printk(KERN_INFO "%s: requesting shared irq %d (dev_id=0x%lx)\n",
-                       ncr_name(np), device->slot.irq, (u_long) np);
-#endif
-#else
-#define        NCR_SA_INTERRUPT_FLAGS SA_INTERRUPT
-#endif
+
        if (request_irq(device->slot.irq, ncr53c8xx_intr,
-                       NCR_SA_INTERRUPT_FLAGS, "ncr53c8xx", np)) {
+                       ((driver_setup.irqm & 0x10) ? 0 : SA_SHIRQ) |
+                       ((driver_setup.irqm & 0x20) ? 0 : SA_INTERRUPT),
+                       "ncr53c8xx", np)) {
 #ifdef __sparc__
                printk(KERN_ERR "%s: request irq %s failure\n",
                        ncr_name(np), __irq_itoa(device->slot.irq));
@@ -4689,6 +4683,7 @@ printk(KERN_INFO "ncr53c%s-%d: rev=0x%02x, base=0x%lx, io_port=0x%lx, irq=%d\n",
 #endif
                goto attach_error;
        }
+
        np->irq = device->slot.irq;
 
        /*
@@ -4956,9 +4951,8 @@ int ncr_queue_command (ncb_p np, Scsi_Cmnd *cmd)
                                nego = NS_SYNC;
                        } else {
                                tp->period  =0xffff;
-                               tp->sval = 0xe0;
                                PRINT_TARGET(np, cmd->target);
-                               printk ("SYNC transfers not supported.\n");
+                               printk ("device did not report SYNC.\n");
                        };
                };
 
@@ -5824,7 +5818,7 @@ void ncr_complete (ncb_p np, ccb_p cp)
                **      announced capabilities (we need the 1rst 7 bytes).
                */
                if (cmd->cmnd[0] == 0x12 && !(cmd->cmnd[1] & 0x3) &&
-                   cmd->cmnd[4] >= 7) {
+                   cmd->cmnd[4] >= 7 && !cmd->use_sg) {
                        ncr_setup_lcb (np, cmd->target, cmd->lun,
                                       (char *) cmd->request_buffer);
                }
@@ -7051,7 +7045,7 @@ void ncr_exception (ncb_p np)
        OUTONB (nc_ctest3, CLF);
 
        if ((sist & (SGE)) ||
-               (dstat & (MDPE|BF|ABORT|IID))) {
+               (dstat & (MDPE|BF|ABRT|IID))) {
                ncr_start_reset(np);
                return;
        };
@@ -7528,7 +7522,7 @@ unexpected_phase:
                }
                else if (dsp == NCB_SCRIPTH_PHYS (np, send_wdtr) ||
                         dsp == NCB_SCRIPTH_PHYS (np, send_sdtr)) {
-                       nxtdsp = dsp - 8; /* Should raise SIR_NEGO_PROTO */
+                       nxtdsp = NCB_SCRIPTH_PHYS (np, nego_bad_phase);
                }
                break;
 #if 0
@@ -7882,9 +7876,7 @@ void ncr_int_sir (ncb_p np)
                np->msgin [0] = M_NOOP;
                np->msgout[0] = M_NOOP;
                cp->nego_status = 0;
-               OUTL (nc_dsp, NCB_SCRIPT_PHYS (np, dispatch));
-               return;
-/*             break;  */
+               break;
 
        case SIR_NEGO_SYNC:
                /*
@@ -8657,10 +8649,15 @@ static lcb_p ncr_setup_lcb (ncb_p np, u_char tn, u_char ln, u_char *inq_data)
        **      Evaluate trustable target/unit capabilities.
        **      We only believe device version >= SCSI-2 that 
        **      use appropriate response data format (2).
+       **      But it seems that some CCS devices also 
+       **      support SYNC and I donnot want to frustrate 
+       **      anybody. ;-)
        */
        inq_byte7 = 0;
-       if ((inq_data[2] & 0x7) >= 2 && (inq_data[3] & 0xf) == 2)
+       if      ((inq_data[2] & 0x7) >= 2 && (inq_data[3] & 0xf) == 2)
                inq_byte7 = inq_data[7];
+       else if ((inq_data[2] & 0x7) == 1 && (inq_data[3] & 0xf) == 1)
+               inq_byte7 = INQ7_SYNC;
 
        /*
        **      Throw away announced LUN capabilities if we are told 
@@ -9585,6 +9582,50 @@ if (ncr53c8xx)
        return attach_count;
 }
 
+/*
+**   Generically read a base address from the PCI configuration space.
+**   Return the offset immediately after the base address that has 
+**   been read. Btw, we blindly assume that the high 32 bits of 64 bit 
+**   base addresses are set to zero on 32 bit architectures.
+**
+*/
+#if LINUX_VERSION_CODE <= LinuxVersionCode(2,1,92)
+__initfunc(
+static int 
+pci_read_base_address(u_char bus, u_char device_fn, int offset, u_long *base)
+)
+{
+       u_int32 tmp;
+
+       pcibios_read_config_dword(bus, device_fn, offset, &tmp);
+       *base = tmp;
+       offset += sizeof(u_int32);
+       if ((tmp & 0x7) == 0x4) {
+#if BITS_PER_LONG > 32
+               pcibios_read_config_dword(bus, device_fn, offset, &tmp);
+               *base |= (((u_long)tmp) << 32);
+#endif
+               offset += sizeof(u_int32);
+       }
+       return offset;
+}
+#else  /* LINUX_VERSION_CODE > LinuxVersionCode(2,1,92) */
+__initfunc(
+static int 
+pci_get_base_address(struct pci_dev *pdev, int index, u_long *base)
+)
+{
+       *base = pdev->base_address[index++];
+       if ((*base & 0x7) == 0x4) {
+#if BITS_PER_LONG > 32
+               *base |= (((u_long)pdev->base_address[index]) << 32);
+#endif
+               ++index;
+       }
+       return index;
+}
+#endif
+
 /*
 **   Read and check the PCI configuration for any detected NCR 
 **   boards and save data for attaching after all boards have 
@@ -9601,61 +9642,46 @@ static int ncr53c8xx_pci_init(Scsi_Host_Template *tpnt,
        uchar revision;
 #if LINUX_VERSION_CODE > LinuxVersionCode(2,1,92)
        struct pci_dev *pdev;
-       ulong base, base_2, io_port; 
        uint irq;
 #else
        uchar irq;
-       uint base, base_2, io_port; 
 #endif
+       ulong base, base_2, io_port; 
        int i;
-
 #ifdef SCSI_NCR_NVRAM_SUPPORT
        ncr_nvram *nvram = device->nvram;
 #endif
        ncr_chip *chip;
 
        /*
-        * Read info from the PCI config space.
-        * pcibios_read_config_xxx() functions are assumed to be used for 
-        * successfully detected PCI devices.
-        * Expecting error conditions from them is just paranoia,
-        * thus void cast.
-        */
-       (void) pcibios_read_config_word(bus, device_fn,
-                                       PCI_VENDOR_ID, &vendor_id);
-       (void) pcibios_read_config_word(bus, device_fn,
-                                       PCI_DEVICE_ID, &device_id);
-       (void) pcibios_read_config_word(bus, device_fn,
-                                       PCI_COMMAND, &command);
+       **    Read info from the PCI config space.
+       **    pcibios_read_config_xxx() functions are assumed to be used for 
+       **    successfully detected PCI devices.
+       */
 #if LINUX_VERSION_CODE > LinuxVersionCode(2,1,92)
        pdev = pci_find_slot(bus, device_fn);
-       io_port = pdev->base_address[0];
-       base = pdev->base_address[1];
-       base_2 = pdev->base_address[2];
+       vendor_id = pdev->vendor;
+       device_id = pdev->device;
        irq = pdev->irq;
-       if ((base & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64)
-               base_2 = pdev->base_address[3];
+       i =     0;
+       i =     pci_get_base_address(pdev, i, &io_port);
+       i =     pci_get_base_address(pdev, i, &base);
+       (void)  pci_get_base_address(pdev, i, &base_2);
 #else
-       (void) pcibios_read_config_dword(bus, device_fn,
-                                       PCI_BASE_ADDRESS_0, &io_port);  
-       (void) pcibios_read_config_dword(bus, device_fn,
-                                       PCI_BASE_ADDRESS_1, &base);
-       (void) pcibios_read_config_dword(bus, device_fn,
-                                       PCI_BASE_ADDRESS_2, &base_2);
-
-       /* Handle 64bit base addresses for 53C896. */
-       if ((base & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64)
-               (void) pcibios_read_config_dword(bus, device_fn,
-                                                PCI_BASE_ADDRESS_3, &base_2);
-       (void) pcibios_read_config_byte(bus, device_fn,
-                                       PCI_INTERRUPT_LINE, &irq);
-#endif
-       (void) pcibios_read_config_byte(bus, device_fn,
-                                       PCI_CLASS_REVISION,&revision);  
-       (void) pcibios_read_config_byte(bus, device_fn,
-                                       PCI_CACHE_LINE_SIZE, &cache_line_size);
-       (void) pcibios_read_config_byte(bus, device_fn,
-                                       PCI_LATENCY_TIMER, &latency_timer);
+       pcibios_read_config_word(bus, device_fn, PCI_VENDOR_ID, &vendor_id);
+       pcibios_read_config_word(bus, device_fn, PCI_DEVICE_ID, &device_id);
+       pcibios_read_config_byte(bus, device_fn, PCI_INTERRUPT_LINE, &irq);
+       i =     PCI_BASE_ADDRESS_0;
+       i =     pci_read_base_address(bus, device_fn, i, &io_port);
+       i =     pci_read_base_address(bus, device_fn, i, &base);
+       (void)  pci_read_base_address(bus, device_fn, i, &base_2);
+#endif
+       pcibios_read_config_word(bus, device_fn, PCI_COMMAND, &command);
+       pcibios_read_config_byte(bus, device_fn, PCI_CLASS_REVISION, &revision);
+       pcibios_read_config_byte(bus, device_fn, PCI_CACHE_LINE_SIZE,
+                                &cache_line_size);
+       pcibios_read_config_byte(bus, device_fn, PCI_LATENCY_TIMER,
+                                &latency_timer);
 
        /*
         *      Check if the chip is supported
index b9a3b1156f9a59b2b7530fc58942f22b429abe75..6ba860aa34c1d812b038ee8d266253e9cae55f2f 100644 (file)
@@ -45,7 +45,7 @@
 /*
 **     Name and revision of the driver
 */
-#define SCSI_NCR_DRIVER_NAME           "ncr53c8xx - revision 3.1f"
+#define SCSI_NCR_DRIVER_NAME           "ncr53c8xx - revision 3.1h"
 
 /*
 **     Check supported Linux versions
@@ -69,7 +69,6 @@
 **     These options are not tunable from 'make config'
 */
 #define        SCSI_NCR_PROC_INFO_SUPPORT
-#define SCSI_NCR_SHARE_IRQ
 
 /*
 **     If you want a driver as small as possible, donnot define the 
index 8ffabde7ecc2e294f312ac467cabeb2aa9c8a7f8..c53e2e7908a2514dfd6bf39166d80edbb1aa7649 100644 (file)
@@ -8,10 +8,10 @@
   order) Klaus Ehrenfried, Wolfgang Denk, Steve Hirsch, Andreas Koppenh"ofer,
   Michael Leodolter, Eyal Lebedinsky, J"org Weule, and Eric Youngdale.
 
-  Copyright 1992 - 1998 Kai Makisara
+  Copyright 1992 - 1999 Kai Makisara
                 email Kai.Makisara@metla.fi
 
-  Last modified: Thu Dec  3 20:27:46 1998 by makisara@home
+  Last modified: Sun Mar  7 09:03:17 1999 by makisara@home
   Some small formal changes - aeb, 950809
 */
 
@@ -1094,8 +1094,11 @@ st_write(struct file * filp, const char * buf, size_t count, loff_t *ppos)
 #endif
 
     /* Write must be integral number of blocks */
-    if (STp->block_size != 0 && (count % STp->block_size) != 0)
+    if (STp->block_size != 0 && (count % STp->block_size) != 0) {
+       printk(KERN_WARNING "st%d: Write not multiple of tape block size.\n",
+              dev);
        return (-EIO);
+    }
 
     if (STp->can_partitions &&
        (retval = update_partition(inode)) < 0)
index 435c2168a67156ddbeff96c60dc81239a7689b67..634bb1820162de0e4c7d3dc340ad5ad1a64974c8 100644 (file)
@@ -12,7 +12,7 @@
 dep_tristate 'Ensoniq AudioPCI (ES1370)' CONFIG_SOUND_ES1370 $CONFIG_SOUND
 if [ "$CONFIG_SOUND_ES1370" = "y" ]; then
    bool 'Joystick support at boot time' CONFIG_SOUND_ES1370_JOYPORT_BOOT
-fi  
+fi
 dep_tristate 'Creative Ensoniq AudioPCI 97 (ES1371)' CONFIG_SOUND_ES1371 $CONFIG_SOUND
 if [ "$CONFIG_SOUND_ES1371" = "y" ]; then
    bool 'Joystick support at boot time' CONFIG_SOUND_ES1371_JOYPORT_BOOT
@@ -75,6 +75,10 @@ fi
 dep_tristate 'OSS sound modules' CONFIG_SOUND_OSS $CONFIG_SOUND
 
 if [ "$CONFIG_SOUND_OSS" = "y" -o "$CONFIG_SOUND_OSS" = "m" ]; then
+  if [ "$CONFIG_SOUND_OSS" = "y" ]; then
+    bool 'Persistent DMA buffers' CONFIG_SOUND_DMAP
+  fi
+
   dep_tristate 'ProAudioSpectrum 16 support' CONFIG_SOUND_PAS $CONFIG_SOUND_OSS
   if [ "$CONFIG_SOUND_PAS" = "y" ]; then
       int 'PAS16 IRQ 3, 4, 5, 7, 9, 10, 11, 12, 14 or 15' CONFIG_PAS_IRQ 10
@@ -138,6 +142,7 @@ if [ "$CONFIG_SOUND_OSS" = "y" -o "$CONFIG_SOUND_OSS" = "m" ]; then
   
   dep_tristate 'Microsoft Sound System support' CONFIG_SOUND_MSS $CONFIG_SOUND_OSS
   if [ "$CONFIG_SOUND_MSS" = "y" ]; then
+      bool 'Enable support for the SoundPro mixer' CONFIG_SOUND_SPRO
       hex 'MSS/WSS I/O base 530, 604, E80 or F40' CONFIG_MSS_BASE 530
       int 'MSS/WSS IRQ 7, 9, 10 or 11' CONFIG_MSS_IRQ 11
       int 'MSS/WSS DMA 0, 1 or 3' CONFIG_MSS_DMA 3
index 709d7f2edf4ee258f4531cf30cc989bb35997d1f..c80c9517c2696089cf77e0d872be402b1abb273f 100644 (file)
@@ -100,6 +100,11 @@ ad1848_port_info;
 
 static int nr_ad1848_devs = 0;
 int deskpro_xl = 0;
+#ifdef CONFIG_SOUND_SPRO
+int soundpro = 1;
+#else
+int soundpro = 0;
+#endif
 
 static volatile char irq2dev[17] = {
        -1, -1, -1, -1, -1, -1, -1, -1,
@@ -312,22 +317,21 @@ static int ad1848_set_recmask(ad1848_info * devc, int mask)
                if (mask & (1 << i))
                        n++;
 
-       if (n == 0)
-               mask = SOUND_MASK_MIC;
-       else if (n != 1)        /* Too many devices selected */
-       {
-                 mask &= ~devc->recmask;       /* Filter out active settings */
+       if (!soundpro) {
+               if (n == 0)
+                       mask = SOUND_MASK_MIC;
+               else if (n != 1) {      /* Too many devices selected */
+                       mask &= ~devc->recmask; /* Filter out active settings */
 
-               n = 0;
-               for (i = 0; i < 32; i++)        /* Count selected device bits */
-                       if (mask & (1 << i))
-                               n++;
+                       n = 0;
+                       for (i = 0; i < 32; i++)        /* Count selected device bits */
+                               if (mask & (1 << i))
+                                       n++;
 
-               if (n != 1)
-                       mask = SOUND_MASK_MIC;
-       }
-       switch (mask)
-       {
+                       if (n != 1)
+                               mask = SOUND_MASK_MIC;
+               }
+               switch (mask) {
                case SOUND_MASK_MIC:
                        recdev = 2;
                        break;
@@ -349,11 +353,38 @@ static int ad1848_set_recmask(ad1848_info * devc, int mask)
                default:
                        mask = SOUND_MASK_MIC;
                        recdev = 2;
-       }
+               }
+
+               recdev <<= 6;
+               ad_write(devc, 0, (ad_read(devc, 0) & 0x3f) | recdev);
+               ad_write(devc, 1, (ad_read(devc, 1) & 0x3f) | recdev);
+       } else { /* soundpro */
+               unsigned char val;
+               int set_rec_bit;
+               int j;
 
-       recdev <<= 6;
-       ad_write(devc, 0, (ad_read(devc, 0) & 0x3f) | recdev);
-       ad_write(devc, 1, (ad_read(devc, 1) & 0x3f) | recdev);
+               for (i = 0; i < 32; i++) {      /* For each bit */
+                       if ((devc->supported_rec_devices & (1 << i)) == 0)
+                               continue;       /* Device not supported */
+
+                       for (j = LEFT_CHN; j <= RIGHT_CHN; j++) {
+                               if (devc->mix_devices[i][j].nbits == 0) /* Inexistent channel */
+                                       continue;
+
+                               /*
+                                * This is tricky:
+                                * set_rec_bit becomes 1 if the corresponding bit in mask is set
+                                * then it gets flipped if the polarity is inverse
+                                */
+                               set_rec_bit = ((mask & (1 << i)) != 0) ^ devc->mix_devices[i][j].recpol;
+
+                               val = ad_read(devc, devc->mix_devices[i][j].recreg);
+                               val &= ~(1 << devc->mix_devices[i][j].recpos);
+                               val |= (set_rec_bit << devc->mix_devices[i][j].recpos);
+                               ad_write(devc, devc->mix_devices[i][j].recreg, val);
+                       }
+               }
+       }
 
        /* Rename the mixer bits back if necessary */
        for (i = 0; i < 32; i++)
@@ -371,7 +402,8 @@ static int ad1848_set_recmask(ad1848_info * devc, int mask)
        return mask;
 }
 
-static void change_bits(ad1848_info * devc, unsigned char *regval, int dev, int chn, int newval)
+static void change_bits(ad1848_info * devc, unsigned char *regval,
+                       unsigned char *muteval, int dev, int chn, int newval)
 {
        unsigned char mask;
        int shift;
@@ -379,7 +411,7 @@ static void change_bits(ad1848_info * devc, unsigned char *regval, int dev, int
        int mutemask;
        int set_mute_bit;
 
-       set_mute_bit = (newval == 0);
+       set_mute_bit = (newval == 0) ^ devc->mix_devices[dev][chn].mutepol;
 
        if (devc->mix_devices[dev][chn].polarity == 1)  /* Reverse */
                newval = 100 - newval;
@@ -399,8 +431,11 @@ static void change_bits(ad1848_info * devc, unsigned char *regval, int dev, int
        }
 
        newval = (int) ((newval * mask) + 50) / 100;    /* Scale it */
-       *regval &= (~(mask << shift)) & (mutemask);     /* Clear bits */
-       *regval |= ((newval & mask) << shift) | mute;   /* Set new value */
+       *regval &= ~(mask << shift);                    /* Clear bits */
+       *regval |= (newval & mask) << shift;            /* Set new value */
+
+       *muteval &= mutemask;
+       *muteval |= mute;
 }
 
 static int ad1848_mixer_get(ad1848_info * devc, int dev)
@@ -413,15 +448,36 @@ static int ad1848_mixer_get(ad1848_info * devc, int dev)
        return devc->levels[dev];
 }
 
+static void ad1848_mixer_set_channel(ad1848_info *devc, int dev, int value, int channel)
+{
+       int regoffs, muteregoffs;
+       unsigned char val, muteval;
+
+       regoffs = devc->mix_devices[dev][channel].regno;
+       muteregoffs = devc->mix_devices[dev][channel].mutereg;
+       val = ad_read(devc, regoffs);
+
+       if (muteregoffs != regoffs) {
+               muteval = ad_read(devc, muteregoffs);
+               change_bits(devc, &val, &muteval, dev, channel, value);
+       }
+       else
+               change_bits(devc, &val, &val, dev, channel, value);
+
+       ad_write(devc, regoffs, val);
+       devc->saved_regs[regoffs] = val;
+       if (muteregoffs != regoffs) {
+               ad_write(devc, muteregoffs, muteval);
+               devc->saved_regs[muteregoffs] = muteval;
+       }
+}
+
 static int ad1848_mixer_set(ad1848_info * devc, int dev, int value)
 {
        int left = value & 0x000000ff;
        int right = (value & 0x0000ff00) >> 8;
        int retvol;
 
-       int regoffs;
-       unsigned char val;
-
        if (dev > 31)
                return -EINVAL;
 
@@ -430,6 +486,9 @@ static int ad1848_mixer_set(ad1848_info * devc, int dev, int value)
 
        dev = devc->mixer_reroute[dev];
 
+       if (devc->mix_devices[dev][LEFT_CHN].nbits == 0)
+               return -EINVAL;
+
        if (left > 100)
                left = 100;
        if (right > 100)
@@ -444,34 +503,21 @@ static int ad1848_mixer_set(ad1848_info * devc, int dev, int value)
        left = mix_cvt[left];
        right = mix_cvt[right];
 
-       if (devc->mix_devices[dev][LEFT_CHN].nbits == 0)
-               return -EINVAL;
-
        devc->levels[dev] = retvol;
 
        /*
         * Set the left channel
         */
-
-       regoffs = devc->mix_devices[dev][LEFT_CHN].regno;
-       val = ad_read(devc, regoffs);
-       change_bits(devc, &val, dev, LEFT_CHN, left);
-       ad_write(devc, regoffs, val);
-       devc->saved_regs[regoffs] = val;
+       ad1848_mixer_set_channel(devc, dev, left, LEFT_CHN);
 
        /*
         * Set the right channel
         */
-
        if (devc->mix_devices[dev][RIGHT_CHN].nbits == 0)
-               return retvol;  /* Was just a mono channel */
-
-       regoffs = devc->mix_devices[dev][RIGHT_CHN].regno;
-       val = ad_read(devc, regoffs);
-       change_bits(devc, &val, dev, RIGHT_CHN, right);
-       ad_write(devc, regoffs, val);
-       devc->saved_regs[regoffs] = val;
+               goto out;
+       ad1848_mixer_set_channel(devc, dev, right, RIGHT_CHN);
 
+ out:
        return retvol;
 }
 
@@ -487,6 +533,8 @@ static void ad1848_mixer_reset(ad1848_info * devc)
        for (i = 0; i < 32; i++)
                devc->mixer_reroute[i] = i;
 
+       devc->supported_rec_devices = MODE1_REC_DEVICES;
+
        switch (devc->model)
        {
                case MD_4231:
@@ -509,11 +557,18 @@ static void ad1848_mixer_reset(ad1848_info * devc)
                        devc->supported_devices = MODE3_MIXER_DEVICES;
                        break;
 
+               case MD_1848:
+                       if (soundpro) {
+                               devc->supported_devices = SPRO_MIXER_DEVICES;
+                               devc->supported_rec_devices = SPRO_REC_DEVICES;
+                               devc->mix_devices = &(spro_mix_devices[0]);
+                               break;
+                       }
+
                default:
                        devc->supported_devices = MODE1_MIXER_DEVICES;
        }
 
-       devc->supported_rec_devices = MODE1_REC_DEVICES;
        devc->orig_devices = devc->supported_devices;
        devc->orig_rec_devices = devc->supported_rec_devices;
 
@@ -528,10 +583,20 @@ static void ad1848_mixer_reset(ad1848_info * devc)
        ad1848_set_recmask(devc, SOUND_MASK_MIC);
        
        devc->mixer_output_port = devc->levels[31] | AUDIO_HEADPHONE | AUDIO_LINE_OUT;
-       if (devc->mixer_output_port & AUDIO_SPEAKER)
-               ad_write(devc, 26, ad_read(devc, 26) & ~0x40);  /* Unmute mono out */
-       else
-               ad_write(devc, 26, ad_read(devc, 26) | 0x40);   /* Mute mono out */
+
+       if (!soundpro) {
+               if (devc->mixer_output_port & AUDIO_SPEAKER)
+                       ad_write(devc, 26, ad_read(devc, 26) & ~0x40);  /* Unmute mono out */
+               else
+                       ad_write(devc, 26, ad_read(devc, 26) | 0x40);   /* Mute mono out */
+       } else {
+               /*
+                * From the "wouldn't it be nice if the mixer API had (better)
+                * support for custom stuff" category
+                */
+               /* Enable surround mode and SB16 mixer */
+               ad_write(devc, 16, 0x60);
+       }
 }
 
 static int ad1848_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg)
@@ -1357,6 +1422,8 @@ static void ad1848_init_hw(ad1848_info * devc)
        {
                  devc->audio_flags &= ~DMA_DUPLEX;
                  ad_write(devc, 9, ad_read(devc, 9) | 0x04);   /* Single DMA mode */
+                 if (soundpro)
+                         ad_write(devc, 12, ad_read(devc, 12) | 0x40); /* Mode2 = enabled */
        }
 
        outb((0), io_Status(devc));     /* Clear pending interrupts */
@@ -1706,7 +1773,27 @@ int ad1848_detect(int io_base, int *ad_flags, int *osp)
 
                        DDB(printk("ad1848_detect() - step K\n"));
                }
+       } else if (tmp1 == 0x0a) {
+               /*
+                * Is it perhaps a SoundPro CMI8330?
+                * If so, then we should be able to change indirect registers
+                * greater than I15 after activating MODE2, even though reading
+                * back I12 does not show it.
+                */
+
+               /*
+                * Let's try comparing register values
+                */
+               for (i = 0; i < 16; i++) {
+                       if ((tmp1 = ad_read(devc, i)) != (tmp2 = ad_read(devc, i + 16))) {
+                               DDB(printk("ad1848 detect step H(%d/%x/%x) - SoundPro chip?\n", i, tmp1, tmp2));
+                               soundpro = 1;
+                               devc->chip_name = "SoundPro CMI 8330";
+                               break;
+                       }
+               }
        }
+
        DDB(printk("ad1848_detect() - step L\n"));
        if (ad_flags)
        {
@@ -2302,7 +2389,8 @@ int probe_ms_sound(struct address_info *hw_config)
            (hw_config->irq != 7)  &&
            (hw_config->irq != 9)  &&
            (hw_config->irq != 10) &&
-           (hw_config->irq != 11))
+           (hw_config->irq != 11) &&
+           (hw_config->irq != 12))
        {
                printk(KERN_ERR "MSS: Bad IRQ %d\n", hw_config->irq);
                return 0;
@@ -2555,6 +2643,7 @@ MODULE_PARM(dma, "i");                    /* First DMA channel */
 MODULE_PARM(dma2, "i");                        /* Second DMA channel */
 MODULE_PARM(type, "i");                        /* Card type */
 MODULE_PARM(deskpro_xl, "i");          /* Special magic for Deskpro XL boxen */
+MODULE_PARM(soundpro, "i");            /* More special magic for SoundPro chips */
 
 int io = -1;
 int irq = -1;
index 5768420a9746f550fdd5a7c7c92a8c6f36911416..fdd06e49978cc8c4299bcf32cfe81c15fc5b39a4 100644 (file)
  * solution).
  */
 #define MODE1_REC_DEVICES              (SOUND_MASK_LINE3 | SOUND_MASK_MIC | \
-                                        SOUND_MASK_LINE1|SOUND_MASK_IMIX)
+                                        SOUND_MASK_LINE1 | SOUND_MASK_IMIX)
+
+#define SPRO_REC_DEVICES               (SOUND_MASK_LINE | SOUND_MASK_MIC | \
+                                        SOUND_MASK_CD | SOUND_MASK_LINE1)
 
 #define MODE1_MIXER_DEVICES            (SOUND_MASK_LINE1 | SOUND_MASK_MIC | \
                                         SOUND_MASK_LINE2 | \
                                 SOUND_MASK_LINE3 | \
                                 SOUND_MASK_IGAIN | SOUND_MASK_PCM)
 
+#define SPRO_MIXER_DEVICES     (SOUND_MASK_VOLUME | SOUND_MASK_PCM | \
+                                SOUND_MASK_LINE | SOUND_MASK_SYNTH | \
+                                SOUND_MASK_CD | SOUND_MASK_MIC | \
+                                SOUND_MASK_SPEAKER | SOUND_MASK_LINE1 | \
+                                SOUND_MASK_OGAIN)
+
 struct mixer_def {
-       unsigned int regno: 5;
-       unsigned int polarity:1;        /* 0=normal, 1=reversed */
-       unsigned int bitpos:3;
-       unsigned int nbits:3;
-       unsigned int mutepos:4;
+       unsigned int regno:5;           /* register number for volume */
+       unsigned int polarity:1;        /* volume polarity: 0=normal, 1=reversed */
+       unsigned int bitpos:3;          /* position of bits in register for volume */
+       unsigned int nbits:3;           /* number of bits in register for volume */
+       unsigned int mutereg:5;         /* register number for mute bit */
+       unsigned int mutepol:1;         /* mute polarity: 0=normal, 1=reversed */
+       unsigned int mutepos:4;         /* position of mute bit in register */
+       unsigned int recreg:5;          /* register number for recording bit */
+       unsigned int recpol:1;          /* recording polarity: 0=normal, 1=reversed */
+       unsigned int recpos:4;          /* position of recording bit in register */
 };
 
 static char mix_cvt[101] = {
-       0, 0,3,7,10,13,16,19,21,23,26,28,30,32,34,35,37,39,40,42,
+        0, 0, 3, 7,10,13,16,19,21,23,26,28,30,32,34,35,37,39,40,42,
        43,45,46,47,49,50,51,52,53,55,56,57,58,59,60,61,62,63,64,65,
        65,66,67,68,69,70,70,71,72,73,73,74,75,75,76,77,77,78,79,79,
        80,81,81,82,82,83,84,84,85,85,86,86,87,87,88,88,89,89,90,90,
@@ -77,7 +91,17 @@ typedef mixer_ent mixer_ents[2];
  */
 
 #define MIX_ENT(name, reg_l, pola_l, pos_l, len_l, reg_r, pola_r, pos_r, len_r, mute_bit)      \
-       {{reg_l, pola_l, pos_l, len_l, mute_bit}, {reg_r, pola_r, pos_r, len_r, mute_bit}}
+       [name] = {{reg_l, pola_l, pos_l, len_l, reg_l, 0, mute_bit, 0, 0, 8},                   \
+                 {reg_r, pola_r, pos_r, len_r, reg_r, 0, mute_bit, 0, 0, 8}}
+
+#define MIX_ENT2(name, reg_l, pola_l, pos_l, len_l, mute_reg_l, mute_pola_l, mute_pos_l, \
+                   rec_reg_l, rec_pola_l, rec_pos_l,                                    \
+                reg_r, pola_r, pos_r, len_r, mute_reg_r, mute_pola_r, mute_pos_r,       \
+                   rec_reg_r, rec_pola_r, rec_pos_r)                                    \
+       [name] = {{reg_l, pola_l, pos_l, len_l, mute_reg_l, mute_pola_l, mute_pos_l,     \
+                   rec_reg_l, rec_pola_l, rec_pos_l},                                   \
+                 {reg_r, pola_r, pos_r, len_r, mute_reg_r, mute_pola_r, mute_pos_r,     \
+                   rec_reg_r, rec_pola_r, rec_pos_r}}
 
 static mixer_ents ad1848_mix_devices[32] = {
 MIX_ENT(SOUND_MIXER_VOLUME,    27, 1, 0, 4,    29, 1, 0, 4,  8),
@@ -144,6 +168,30 @@ MIX_ENT(SOUND_MIXER_LINE2,  4, 1, 1, 4,     5, 1, 1, 4,  7),
 MIX_ENT(SOUND_MIXER_LINE3,     18, 1, 1, 4,    19, 1, 1, 4,  7)
 };
 
+static mixer_ents spro_mix_devices[32] = {
+MIX_ENT (SOUND_MIXER_VOLUME,   19, 0, 4, 4,                     19, 0, 0, 4,  8),
+MIX_ENT (SOUND_MIXER_BASS,      0, 0, 0, 0,                      0, 0, 0, 0,  8),
+MIX_ENT (SOUND_MIXER_TREBLE,    0, 0, 0, 0,                      0, 0, 0, 0,  8),
+MIX_ENT2(SOUND_MIXER_SYNTH,     4, 1, 1, 4, 23, 0, 3,  0, 0, 8,
+                                5, 1, 1, 4, 23, 0, 3, 0, 0, 8),
+MIX_ENT (SOUND_MIXER_PCM,       6, 1, 1, 4,                      7, 1, 1, 4,  8),
+MIX_ENT (SOUND_MIXER_SPEAKER,  18, 0, 3, 2,                      0, 0, 0, 0,  8),
+MIX_ENT2(SOUND_MIXER_LINE,     20, 0, 4, 4, 17, 1, 4, 16, 0, 2,
+                               20, 0, 0, 4, 17, 1, 3, 16, 0, 1),
+MIX_ENT2(SOUND_MIXER_MIC,      18, 0, 0, 3, 17, 1, 0, 16, 0, 0,
+                                0, 0, 0, 0,  0, 0, 0,  0, 0, 0),
+MIX_ENT2(SOUND_MIXER_CD,       21, 0, 4, 4, 17, 1, 2, 16, 0, 4,
+                               21, 0, 0, 4, 17, 1, 1, 16, 0, 3),
+MIX_ENT (SOUND_MIXER_IMIX,      0, 0, 0, 0,                      0, 0, 0, 0,  8),
+MIX_ENT (SOUND_MIXER_ALTPCM,    0, 0, 0, 0,                      0, 0, 0, 0,  8),
+MIX_ENT (SOUND_MIXER_RECLEV,    0, 0, 0, 0,                      0, 0, 0, 0,  8),
+MIX_ENT (SOUND_MIXER_IGAIN,     0, 0, 0, 0,                      0, 0, 0, 0,  8),
+MIX_ENT (SOUND_MIXER_OGAIN,    17, 1, 6, 1,                      0, 0, 0, 0,  8),
+/* This is external wavetable */
+MIX_ENT2(SOUND_MIXER_LINE1,    22, 0, 4, 4, 23, 1, 1, 23, 0, 4,
+                               22, 0, 0, 4, 23, 1, 0, 23, 0, 5),
+};
+
 static int default_mixer_levels[32] =
 {
   0x3232,                      /* Master Volume */
index 37d1fc38fb1ec4f17d5ae8aea82679144fec545e..dd73886db389af10dbc6257acbe2cb9d64744f85 100644 (file)
@@ -1228,8 +1228,6 @@ static int es1370_mmap(struct file *file, struct vm_area_struct *vma)
        if (remap_page_range(vma->vm_start, virt_to_phys(db->rawbuf), size, vma->vm_page_prot))
                return -EAGAIN;
        db->mapped = 1;
-       vma->vm_file = file;
-       file->f_count++;
        return 0;
 }
 
@@ -1597,6 +1595,7 @@ static int es1370_release(struct inode *inode, struct file *file)
        down(&s->open_sem);
        if (file->f_mode & FMODE_WRITE) {
                stop_dac2(s);
+               synchronize_irq();
                dealloc_dmabuf(&s->dma_dac2);
        }
        if (file->f_mode & FMODE_READ) {
@@ -1725,8 +1724,6 @@ static int es1370_mmap_dac(struct file *file, struct vm_area_struct *vma)
        if (remap_page_range(vma->vm_start, virt_to_phys(s->dma_dac1.rawbuf), size, vma->vm_page_prot))
                return -EAGAIN;
        s->dma_dac1.mapped = 1;
-       vma->vm_file = file;
-       file->f_count++;
        return 0;
 }
 
index e52f47d149d95dfeb104add8b38a658adfff6084..69aa867aaa8de41156f5fd646d5074035bb6d16d 100644 (file)
@@ -1675,8 +1675,6 @@ static int es1371_mmap(struct file *file, struct vm_area_struct *vma)
        if (remap_page_range(vma->vm_start, virt_to_phys(db->rawbuf), size, vma->vm_page_prot))
                return -EAGAIN;
        db->mapped = 1;
-       vma->vm_file = file;
-       file->f_count++;
        return 0;
 }
 
@@ -2172,8 +2170,6 @@ static int es1371_mmap_dac(struct file *file, struct vm_area_struct *vma)
        if (remap_page_range(vma->vm_start, virt_to_phys(s->dma_dac1.rawbuf), size, vma->vm_page_prot))
                return -EAGAIN;
        s->dma_dac1.mapped = 1;
-       vma->vm_file = file;
-       file->f_count++;
        return 0;
 }
 
index 0ad4fb0622dcab9274c2a1fde46eac5f580908e5..9f9c57039ed264cec16c3afe5beb7ee40f7fc8c9 100644 (file)
@@ -54,7 +54,7 @@
 #include "../soundvers.h"
 #endif
 
-#if SOUND_INTERNAL_VERSION >= 0x30803
+#if defined(SOUND_INTERNAL_VERSION) && SOUND_INTERNAL_VERSION >= 0x30803
 /* OSS/Free-3.8 */
 #define AWE_NO_PATCHMGR
 #define AWE_OSS38
@@ -151,18 +151,9 @@ static int _mem_start;  /* memory pointer for permanent buffers */
 #define my_malloc_memptr()     _mem_start
 #define my_free(ptr)   /* do nothing */
 
-static void *my_malloc(int size)
-{
-       char *ptr;
-       PERMANENT_MALLOC(ptr, char*, size, _mem_start);
-       return (void*)ptr;
-}
-#define my_kmalloc(size) my_malloc(size)
-#define kfree(ptr)     /* do nothing */
-
 /* allocate buffer only once */
 #define INIT_TABLE(buffer,index,nums,type) {\
-buffer = my_malloc(sizeof(type) * (nums)); index = (nums);\
+PERMANENT_MALLOC(buffer, char*, size, _mem_start); index = (nums);\
 }
 
 #else
@@ -173,8 +164,6 @@ buffer = my_malloc(sizeof(type) * (nums)); index = (nums);\
 #define my_malloc_memptr()     0
 #define my_malloc(size)                vmalloc(size)
 #define my_free(ptr)           if (ptr) {vfree(ptr);}
-#define my_kmalloc(size)       kmalloc(size,GFP_KERNEL)
-#define my_kfree(ptr)          kfree(ptr)
 
 /* do not allocate buffer at beginning */
 #define INIT_TABLE(buffer,index,nums,type) {buffer=NULL; index=0;}
@@ -255,6 +244,14 @@ buffer = my_malloc(sizeof(type) * (nums)); index = (nums);\
 
 #endif /* AWE_MODULE_SUPPORT */
 
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,0)
+inline static void interruptible_sleep_on_timeout(struct wait_queue **q, unsigned long timeout)
+{
+       current->timeout = jiffies + timeout;
+       interruptible_sleep_on(q);
+}
+#endif
+
 #endif /* CONFIG_AWE32_SYNTH */
 
 #endif /* AWE_COMPAT_H_DEF */
index 1c2472049b90d9d00b4a7d195a2c767acf7aa73c..8fd5431e6cbbcd681d3d07beca4f95c342d30482 100644 (file)
@@ -2,9 +2,9 @@
  * sound/awe_wave.c
  *
  * The low level driver for the AWE32/SB32/AWE64 wave table synth.
- *   version 0.4.3; Nov. 1, 1998
+ *   version 0.4.3; Feb. 1, 1999
  *
- * Copyright (C) 1996-1998 Takashi Iwai
+ * Copyright (C) 1996-1999 Takashi Iwai
  *
  * 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
@@ -204,16 +204,20 @@ static awe_chan_info channels[AWE_MAX_CHANNELS];
 #if defined(AWE_MODULE_SUPPORT) && defined(MODULE)
 /* replace awe_port variable with exported variable */
 #define awe_port       io
-#define BASEVAR_DECL   /**/
+#define awe_mem_size   memsize
+int io = AWE_DEFAULT_BASE_ADDR; /* Emu8000 base address */
+int memsize = AWE_DEFAULT_MEM_SIZE; /* memory size in Kbytes */
+#ifdef MODULE_PARM
+MODULE_PARM(io, "i");
+MODULE_PARM_DESC(io, "base i/o port of Emu8000");
+MODULE_PARM(memsize, "i");
+MODULE_PARM_DESC(memsize, "onboard DRAM size in Kbytes");
+#endif
 #else
-#define BASEVAR_DECL   static
+static int awe_port = AWE_DEFAULT_BASE_ADDR;
+static int awe_mem_size = AWE_DEFAULT_MEM_SIZE;
 #endif /* module */
 
-/* awe32 base address (overwritten at initialization) */
-BASEVAR_DECL int awe_port = AWE_DEFAULT_BASE_ADDR;
-/* memory byte size */
-BASEVAR_DECL int memsize = AWE_DEFAULT_MEM_SIZE; /* for module option */
-static int awe_mem_size = -1;
 /* DRAM start offset */
 static int awe_mem_start = AWE_DRAM_OFFSET;
 
@@ -669,7 +673,7 @@ static void _unload_awe(void)
 
 #include <linux/pnp.h>
 
-BASEVAR_DECL int pnp = 1;      /* use PnP as default */
+static int pnp = 1;    /* use PnP as default */
 
 #define AWE_NUM_CHIPS  3
 static unsigned int pnp_ids[AWE_NUM_CHIPS] = {
@@ -812,6 +816,7 @@ void cleanup_module(void)
 }
 
 #ifdef MODULE_PARM
+EXPORT_NO_SYMBOLS;
 MODULE_AUTHOR("Takashi Iwai <iwai@ww.uni-erlangen.de>");
 MODULE_DESCRIPTION("SB AWE32/64 WaveTable driver");
 MODULE_SUPPORTED_DEVICE("sound");
@@ -975,23 +980,9 @@ awe_wait(unsigned short delay)
 #else
 
 static struct wait_queue *awe_sleeper = NULL;
-static void awe_wakeup(unsigned long dummy)
-{
-       wake_up(&awe_sleeper);
-}
-
-static struct timer_list awe_timer =
-{NULL, NULL, 0, 0, awe_wakeup};
-
 static void awe_wait(unsigned short delay)
 {
-       unsigned long   flags;
-       awe_timer.expires = jiffies + (HZ * (unsigned long)delay + 44099) / 44100;
-       add_timer(&awe_timer);
-       save_flags (flags);
-       cli();
-       sleep_on(&awe_sleeper);
-       restore_flags(flags);
+       interruptible_sleep_on_timeout(&awe_sleeper, (HZ * (unsigned long)delay + 44099) / 44100);
 }
 #endif /* wait by loop */
 
@@ -1553,7 +1544,7 @@ awe_note_on(int voice)
                          vp->parm.moddcysus));
 
        if (parm->volatk >= 0x80 && parm->voldelay >= 0x8000) {
-               awe_poke(AWE_ENVVAL(voice), 0xBFFF);
+               awe_poke(AWE_ENVVOL(voice), 0xBFFF);
                vtarget = voltarget[voices[voice].avol%0x10]>>(voices[voice].avol>>4);
        } else {
                awe_poke(AWE_ENVVOL(voice),
@@ -3268,7 +3259,7 @@ static int info_duplicated(awe_voice_list *rec)
        sf_list *sf;
 
        /* search for all sharing lists */
-       for (sf_id = rec->v.sf_id; sf_id > 0; sf_id = sf->shared) {
+       for (sf_id = rec->v.sf_id; sf_id > 0 && sf_id <= current_sf_id; sf_id = sf->shared) {
                sf = &sflists[sf_id - 1];
                for (j = sf->infos; j >= 0; j = infos[j].next) {
                        awe_voice_list *p = &infos[j];
@@ -4201,7 +4192,7 @@ static int is_identical_id(int id1, int id2)
                if (id1 < id2) { /* make sure id1 > id2 */
                        int tmp; tmp = id1; id1 = id2; id2 = tmp;
                }
-               for (i = sflists[id1-1].shared; i > 0; i = sflists[i-1].shared) {
+               for (i = sflists[id1-1].shared; i > 0 && i <= current_sf_id; i = sflists[i-1].shared) {
                        if (i == id2)
                                return TRUE;
                }
@@ -4223,10 +4214,10 @@ static int search_sample_index(int sf, int sample, int level)
                        return i;
        }
 #ifdef AWE_ALLOW_SAMPLE_SHARING
-       if (sflists[sf-1].shared) { /* search recursively */
+       if ((i = sflists[sf-1].shared) > 0 && i <= current_sf_id) { /* search recursively */
                if (level > current_sf_id)
                        return -1; /* strange sharing loop.. quit */
-               return search_sample_index(sflists[sf-1].shared, sample, level + 1);
+               return search_sample_index(i, sample, level + 1);
        }
 #endif
        return -1;
@@ -4272,10 +4263,12 @@ awe_search_multi_voices(int rec, int note, int velocity, awe_voice_info **vlist)
                    note <= infos[rec].v.high &&
                    velocity >= infos[rec].v.vellow &&
                    velocity <= infos[rec].v.velhigh) {
-                       vlist[nvoices] = &infos[rec].v;
-                       if (infos[rec].type == V_ST_MAPPED) /* mapper */
+                       if (infos[rec].type == V_ST_MAPPED) {
+                               /* mapper */
+                               vlist[0] = &infos[rec].v;
                                return -1;
-                       nvoices++;
+                       }
+                       vlist[nvoices++] = &infos[rec].v;
                        if (nvoices >= AWE_MAX_VOICES)
                                break;
                }
@@ -5009,8 +5002,6 @@ awe_detect(void)
                DEBUG(0,printk("AWE32 not found\n"));
                return 0;
        }
-       if (memsize >= 0) /* given by config file or module option */
-               awe_mem_size = memsize * 1024; /* convert to Kbytes */
 
        return 1;
 }
@@ -5028,9 +5019,14 @@ awe_detect(void)
 static void
 awe_check_dram(void)
 {
-       if (awe_mem_size >= 0) /* already initialized */
+       if (awe_present) /* already initialized */
                return;
 
+       if (awe_mem_size >= 0) { /* given by config file or module option */
+               awe_mem_size *= 1024; /* convert to Kbytes */
+               return;
+       }
+
        awe_open_dram_for_check();
 
        awe_mem_size = 0;
index 41533aedaf24b0291d5a702f2b6764c82a2b7142..649c9861f51060c45a25fb7835a4784d94224661 100644 (file)
@@ -800,7 +800,7 @@ int probe_mad16_mpu(struct address_info *hw_config)
 
                mad_write(MC3_PORT, tmp | 0x04);
                hw_config->driver_use_1 = SB_MIDI_ONLY;
-               return sb_dsp_detect(hw_config);
+               return sb_dsp_detect(hw_config, 0, 0);
 #else
                return 0;
 #endif
index fd8fdcbd3ed4cf7351c32e85663cbf560ceefa67..a47d7099fd65f4024b211fe9beec30d477c13af7 100644 (file)
 #define MDL_AZTECH     13      /* Aztech Sound Galaxy family */
 #define MDL_ES1868MIDI 14      /* MIDI port of ESS1868 */
 #define MDL_AEDSP      15      /* Audio Excel DSP 16 */
+#define MDL_ESSPCI     16      /* ESS PCI card */
 
 #define SUBMDL_ALS007  42      /* ALS-007 differs from SB16 only in mixer */
                                /* register assignment */
 #define SUBMDL_ALS100  43      /* ALS-100 allows sampling rates of up */
                                /* to 48kHz */
+                               
 /*
  * Config flags
  */
@@ -60,6 +62,7 @@
 #define SB_NO_AUDIO    0x00000004
 #define SB_NO_RECORDING        0x00000008 /* No audio recording */
 #define SB_MIDI_ONLY   (SB_NO_AUDIO|SB_NO_MIXER)
+#define SB_PCI_IRQ     0x00000010 /* PCI shared IRQ */
 
 struct mixer_def {
        unsigned int regno: 8;
@@ -86,6 +89,8 @@ typedef struct sb_devc {
           int base;
           int irq;
           int dma8, dma16;
+          
+          int pcibase;         /* For ESS Maestro etc */
 
        /* State variables */
           int opened;
@@ -128,13 +133,24 @@ typedef struct sb_devc {
           void (*midi_input_intr) (int dev, unsigned char data);
           void *midi_irq_cookie;       /* IRQ cookie for the midi */
        } sb_devc;
+       
+/*
+ *     PCI card types
+ */
 
+#define        SB_PCI_ESSMAESTRO       1       /* ESS Maestro Legacy */
+#define        SB_PCI_YAMAHA           2       /* Yamaha Legacy */
+
+/* 
+ *     Functions
+ */
 int sb_dsp_command (sb_devc *devc, unsigned char val);
 int sb_dsp_get_byte(sb_devc * devc);
 int sb_dsp_reset (sb_devc *devc);
 void sb_setmixer (sb_devc *devc, unsigned int port, unsigned int value);
 unsigned int sb_getmixer (sb_devc *devc, unsigned int port);
-int sb_dsp_detect (struct address_info *hw_config);
+int sb_dsp_detect (struct address_info *hw_config, int pci, int pciio);
 int sb_dsp_init (struct address_info *hw_config);
 void sb_dsp_unload(struct address_info *hw_config, int sbmpu);
 int sb_mixer_init(sb_devc *devc);
index 5b6315a24ce0070bf3d08b47ebb2b22b445fa6b7..e2630f0b751c24f755e249f027291b41f8108657 100644 (file)
@@ -103,7 +103,7 @@ iobase=0x%x irq=%d lo_dma=%d hi_dma=%d\n",
                printk(KERN_ERR "sb_card: I/O port %x is already in use\n\n", hw_config->io_base);
                return 0;
        }
-       return sb_dsp_detect(hw_config);
+       return sb_dsp_detect(hw_config, 0, 0);
 }
 
 void unload_sb(struct address_info *hw_config)
@@ -135,6 +135,7 @@ int type = 0;               /* Can set this to a specific card type */
 int mad16 = 0;         /* Set mad16=1 to load this as support for mad16 */
 int trix = 0;          /* Set trix=1 to load this as support for trix */
 int pas2 = 0;          /* Set pas2=1 to load this as support for pas2 */
+int support = 0;       /* Set support to load this as a support module */
 int sm_games = 0;      /* Mixer - see sb_mixer.c */
 int acer = 0;          /* Do acer notebook init */
 
@@ -145,6 +146,7 @@ MODULE_PARM(dma16, "i");
 MODULE_PARM(mpu_io, "i");
 MODULE_PARM(type, "i");
 MODULE_PARM(mad16, "i");
+MODULE_PARM(support, "i");
 MODULE_PARM(trix, "i");
 MODULE_PARM(pas2, "i");
 MODULE_PARM(sm_games, "i");
@@ -156,7 +158,7 @@ int init_module(void)
 {
        printk(KERN_INFO "Soundblaster audio driver Copyright (C) by Hannu Savolainen 1993-1996\n");
 
-       if (mad16 == 0 && trix == 0 && pas2 == 0)
+       if (mad16 == 0 && trix == 0 && pas2 == 0 && support == 0)
        {
                if (io == -1 || dma == -1 || irq == -1)
                {
@@ -191,7 +193,7 @@ void cleanup_module(void)
 {
        if (smw_free)
                vfree(smw_free);
-       if (!mad16 && !trix && !pas2)
+       if (!mad16 && !trix && !pas2 && !support)
                unload_sb(&config);
        if (sbmpu)
                unload_sbmpu(&config_mpu);
index 9072509814489efba6c4379ddbaed84b62d12049..ab85fd3fb508126f8f444e68265054ff455ee585 100644 (file)
@@ -179,13 +179,25 @@ static void sb_intr (sb_devc *devc)
                status = inb(DSP_DATA_AVL16);
 }
 
+static void pci_intr(sb_devc *devc)
+{
+       int src = inb(devc->pcibase+0x1A);
+       src&=3;
+       if(src)
+               sb_intr(devc);
+}
+
 static void sbintr(int irq, void *dev_id, struct pt_regs *dummy)
 {
-    sb_devc *devc = dev_id;
+       sb_devc *devc = dev_id;
 
        devc->irq_ok = 1;
 
        switch (devc->model) {
+       case MDL_ESSPCI:
+               pci_intr (devc);
+               break;
+               
        case MDL_ESS:
                ess_intr (devc);
                break;
@@ -478,7 +490,7 @@ static void relocate_ess1688(sb_devc * devc)
 #endif
 }
 
-int sb_dsp_detect(struct address_info *hw_config)
+int sb_dsp_detect(struct address_info *hw_config, int pci, int pciio)
 {
        sb_devc sb_info;
        sb_devc *devc = &sb_info;
@@ -508,7 +520,22 @@ int sb_dsp_detect(struct address_info *hw_config)
        devc->dma8 = hw_config->dma;
 
        devc->dma16 = -1;
-
+       devc->pcibase = pciio;
+       
+       if(pci == SB_PCI_ESSMAESTRO)
+       {
+               devc->model = MDL_ESSPCI;
+               devc->caps |= SB_PCI_IRQ;
+               hw_config->driver_use_1 |= SB_PCI_IRQ;
+               hw_config->card_subtype = MDL_ESSPCI;
+       }
+       
+       if(pci == SB_PCI_YAMAHA)
+       {
+               devc->caps |= SB_PCI_IRQ;
+               hw_config->driver_use_1 |= SB_PCI_IRQ;
+       }
+       
        if (acer)
        {
                cli();
@@ -569,6 +596,10 @@ int sb_dsp_detect(struct address_info *hw_config)
                                }
                }
        }
+       
+       if(devc->type == MDL_ESSPCI)
+               devc->model = MDL_ESSPCI;
+               
        /*
         * Save device information for sb_dsp_init()
         */
@@ -619,7 +650,15 @@ int sb_dsp_init(struct address_info *hw_config)
 
        if (!(devc->caps & SB_NO_AUDIO && devc->caps & SB_NO_MIDI) && hw_config->irq > 0)
        {                       /* IRQ setup */
-               if (request_irq(hw_config->irq, sbintr, 0, "soundblaster", devc) < 0)
+               
+               /*
+                *      ESS PCI cards do shared PCI IRQ stuff. Since they
+                *      will get shared PCI irq lines we must cope.
+                */
+                
+               int i=(devc->caps&SB_PCI_IRQ)?SA_SHIRQ:0;
+               
+               if (request_irq(hw_config->irq, sbintr, i, "soundblaster", devc) < 0)
                {
                        printk(KERN_ERR "SB: Can't allocate IRQ%d\n", hw_config->irq);
                        return 0;
index 97ce1b39de590e38404edb33eb8074ebd06ed95e..4f10108b928f2fef8db6aa30928309f042a45d04 100644 (file)
@@ -673,6 +673,7 @@ int sb_mixer_init(sb_devc * devc)
 
        switch (devc->model)
        {
+               case MDL_ESSPCI:
                case MDL_SBPRO:
                case MDL_AZTECH:
                case MDL_JAZZ:
index 44207cb6276b6d2bbb6fb3d6d605b700cd8e962b..af40a2117455306c9c9e86785d64e28a49478779 100644 (file)
@@ -1105,7 +1105,7 @@ int sequencer_open(int dev, struct file *file)
                 */
 
                for (i = 0; i < max_mididev; i++)
-                       if (!midi_opened[i])
+                       if (!midi_opened[i] && midi_devs[i])
                        {
                                if ((retval = midi_devs[i]->open(i, mode,
                                        sequencer_midi_input, sequencer_midi_output)) >= 0)
@@ -1411,7 +1411,7 @@ int sequencer_ioctl(int dev, struct file *file, unsigned int cmd, caddr_t arg)
                case SNDCTL_SEQ_TESTMIDI:
                        if (__get_user(midi_dev, (int *)arg))
                                return -EFAULT;
-                       if (midi_dev < 0 || midi_dev >= max_mididev)
+                       if (midi_dev < 0 || midi_dev >= max_mididev || !midi_devs[midi_dev])
                                return -ENXIO;
 
                        if (!midi_opened[midi_dev] &&
@@ -1529,7 +1529,7 @@ int sequencer_ioctl(int dev, struct file *file, unsigned int cmd, caddr_t arg)
                case SNDCTL_MIDI_INFO:
                        if (get_user(dev, (int *)(&(((struct midi_info *)arg)->device))))
                                return -EFAULT;
-                       if (dev < 0 || dev >= max_mididev)
+                       if (dev < 0 || dev >= max_mididev || !midi_devs[dev])
                                return -ENXIO;
                        midi_devs[dev]->info.device = dev;
                        return copy_to_user(arg, &midi_devs[dev]->info, sizeof(struct midi_info))?-EFAULT:0;
index b1899e143944f4657efc29d609f6e0206faf1176..0ecb00c62ad015c6b85863e0a8e095cfdc762ede 100644 (file)
@@ -1431,8 +1431,6 @@ static int sv_mmap(struct file *file, struct vm_area_struct *vma)
        if (remap_page_range(vma->vm_start, virt_to_phys(db->rawbuf), size, vma->vm_page_prot))
                return -EAGAIN;
        db->mapped = 1;
-       vma->vm_file = file;
-       file->f_count++;
        return 0;
 }
 
index 115b9e33dd0430db0eac841f1d3ff4ae00d9e498..9bc08fbd03cf01129d39c10e7a98b59e1a0df28c 100644 (file)
@@ -39,7 +39,6 @@
 #include <linux/malloc.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/malloc.h>
 #include <linux/fs.h>
 #include <linux/sound.h>
 #include <linux/major.h>
index cf3b70feacabe72f0bfb8f9e4dc7b963e214dcb1..6731180b40259ed418abbfb337f5e76125f87c77 100644 (file)
@@ -67,7 +67,11 @@ caddr_t         sound_mem_blocks[1024];
 int             sound_nblocks = 0;
 
 /* Persistent DMA buffers */
-int            sound_dmap_flag = 0;    /* Off by default */
+#ifdef CONFIG_SOUND_DMAP
+int            sound_dmap_flag = 1;
+#else
+int            sound_dmap_flag = 0;
+#endif
 
 static int      soundcard_configured = 0;
 
@@ -751,9 +755,6 @@ static int sound_mmap(struct file *file, struct vm_area_struct *vma)
                vma->vm_page_prot))
                return -EAGAIN;
 
-       vma->vm_file = file;
-       file->f_count++;
-
        dmap->mapping_flags |= DMA_MAP_MAPPED;
 
        if( audio_devs[dev]->d->mmap)
@@ -802,13 +803,6 @@ bad1:
        return -1;
 }
 
-static void destroy_special_devices(void)
-{
-       unregister_sound_special(6);
-       unregister_sound_special(1);
-       unregister_sound_special(8);
-}
-
 #ifdef MODULE
 static void
 #else
@@ -849,12 +843,19 @@ soundcard_init(void)
 #endif         
 }
 
+#ifdef MODULE
+
+static void destroy_special_devices(void)
+{
+       unregister_sound_special(6);
+       unregister_sound_special(1);
+       unregister_sound_special(8);
+}
+
 static int      sound[20] = {
        0
 };
 
-#ifdef MODULE
-
 int traceinit = 0;
 static int dmabuf = 0;
 MODULE_PARM(traceinit, "i");
index 1a6b79c769d4e567ee38d546859b223719608817..70b4af6d381bb5a473366dfc0cae40c5e533eace 100644 (file)
@@ -323,7 +323,7 @@ int probe_trix_sb(struct address_info *hw_config)
 
        hw_config->name = "AudioTrix SB";
 #ifdef CONFIG_SBDSP
-       return sb_dsp_detect(hw_config);
+       return sb_dsp_detect(hw_config, 0, 0);
 #else
        return 0;
 #endif
index 613b5f20c4d52f047cf3fbff10e4eae29103210d..c3b95d7cc6b1af07b1be47f7f4bfb9191e24f2d8 100644 (file)
@@ -2323,8 +2323,6 @@ static int atyfb_mmap(struct fb_info *info, struct file *file,
        if (!map_size)
                return -EINVAL;
 
-       vma->vm_file = file;
-       file->f_count++;
        vma->vm_flags |= VM_IO;
 
        if (!fb->mmaped) {
index 56f0ac7904bd9e8e64525e89023f8509c79df344..f6e92fa478f9e137ce789e4fb5d34831756a9fb4 100644 (file)
@@ -495,8 +495,6 @@ fb_mmap(struct file *file, struct vm_area_struct * vma)
        if (remap_page_range(vma->vm_start, vma->vm_offset,
                             vma->vm_end - vma->vm_start, vma->vm_page_prot))
                return -EAGAIN;
-       vma->vm_file = file;
-       file->f_count++;
        return 0;
 }
 
index e3a86c86852aca09e3bc38c2ff422a46b97de283..d6173e77e7d6ee0cfcad736803491ed781708959 100644 (file)
@@ -304,8 +304,6 @@ static int igafb_mmap(struct fb_info *info, struct file *file,
        if (!map_size)
                return -EINVAL;
 
-       vma->vm_file = file;
-       file->f_count++;
        vma->vm_flags |= VM_IO;
 
        if (!fb->mmaped) {
index 88ecf574321db106ef018268519863b670b0c301..bc5bafa951fd249c439ced80a7c8302d53777e66 100644 (file)
@@ -244,8 +244,6 @@ static int sbusfb_mmap(struct fb_info *info, struct file *file,
                page += map_size;
        }
        
-       vma->vm_file = file;
-       file->f_count++;
        vma->vm_flags |= VM_IO;
        if (!fb->mmaped) {
                int lastconsole = 0;
index 74b4601b7a5fc0e83d1e863a17b5c2bba07e8b11..3b8d32fb3468cf97d2b6bc9f330fcb49522199cb 100644 (file)
@@ -100,10 +100,6 @@ fi
 endmenu
 fi
 
-if [ "$CONFIG_AFFS_FS" != "n" ]; then
-  define_bool CONFIG_AMIGA_PARTITION y
-fi
-
 mainmenu_option next_comment
 comment 'Partition Types'
 
@@ -116,6 +112,10 @@ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
 fi
 endmenu
 
+if [ "$CONFIG_AFFS_FS" != "n" ]; then
+  define_bool CONFIG_AMIGA_PARTITION y
+fi
+
 source fs/nls/Config.in
 
 endmenu
index c23e3b1b94b9d76435a893a25257decb69d718f0..9b05ec062ae1bff5e8530320a7cb0d511fc0dd5f 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/mm.h>
 #include <linux/string.h>
 #include <linux/locks.h>
-#include <linux/errno.h>
 #include <linux/genhd.h>
 #include <linux/amigaffs.h>
 #include <linux/major.h>
index 464b6df8aea3939fe650c770659b417df0a8d882..0c2a838f5ee3168d0fecdf318db48e60b3ceb0a4 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/mm.h>
 #include <linux/string.h>
 #include <linux/locks.h>
-#include <linux/errno.h>
 #include <linux/genhd.h>
 #include <linux/amigaffs.h>
 #include <linux/major.h>
index 8b7d07295a699e0e0043178f007fc9cb218a9c10..25f008e277049bf581eedced48ef71ad85c3111c 100644 (file)
@@ -483,7 +483,10 @@ got_it:
        if (dquot->dq_flags & (DQ_LOCKED | DQ_MOD)) {
                wait_on_dquot(dquot);
                if (dquot->dq_flags & DQ_MOD)
-                       write_dquot(dquot);
+               {
+                       if(dquot->dq_mnt != (struct vfsmount *)NULL)
+                               write_dquot(dquot);
+               }
                /*
                 * The dquot may be back in use now, so we
                 * must recheck the free list.
index 4cda7919657156be5b45c4b218c336627a1f7084..0494ad013605323f46fc82ae26ac7d4a94bde5ec 100644 (file)
@@ -113,8 +113,6 @@ int fat_mmap(struct file * file, struct vm_area_struct * vma)
                mark_inode_dirty(inode);
        }
 
-       vma->vm_file = file;
-       file->f_count++;
        vma->vm_ops = &fat_file_mmap;
        return 0;
 }
index 0a508c90bc0df2f4c3058536e046be12c81b3d2a..e2b4405d92eb2d1525148898e700e5a3bfcd7f00 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/stat.h>
 #include <linux/locks.h>
 #include <linux/fs.h>
-#include <linux/iso_fs.h>
 
 /*
  * We have mostly NULLs here: the current defaults are OK for
index 2c7610d0b80a2442ed5482fa297fec3134f99e11..6b321e6c984a571d57414a0d235efae57043557d 100644 (file)
@@ -137,8 +137,6 @@ int ncp_mmap(struct file *file, struct vm_area_struct *vma)
                inode->i_atime = CURRENT_TIME;
        }
 
-       vma->vm_file = file;
-       file->f_count++;
        vma->vm_ops = &ncp_file_mmap;
        return 0;
 }
index 292493dacb18049afb06bb9f5775f624b0a6647f..36f1650ac32b683e75eb30f16eaaa0dc18693c15 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
-#include <linux/errno.h>
 #include <linux/dirent.h>
 #include <linux/smb_fs.h>
 
@@ -142,7 +141,7 @@ smb_add_to_cache(struct cache_head * cachep, struct cache_dirent *entry,
 
 #ifdef SMBFS_DEBUG_VERBOSE
 printk("smb_add_to_cache: cache inode %p, status %d, adding %s at %ld\n",
-inode, cachep->status, entry->d_name, fpos);
+inode, cachep->status, entry->name, fpos);
 #endif
        /*
         * Don't do anything if we've had an error ...
@@ -171,7 +170,7 @@ inode, cachep->status, entry->d_name, fpos);
                cachep->entries++;
 #ifdef SMBFS_DEBUG_VERBOSE
 printk("smb_add_to_cache: added entry %s, len=%d, pos=%ld, entries=%d\n",
-entry->d_name, len, fpos, cachep->entries);
+entry->name, len, fpos, cachep->entries);
 #endif
                return;
        }
index 95fc207da025e27d259f9ce4919d25f214dd11dd..aed60f5c20525888f429a2f6c702ef16c2387471 100644 (file)
@@ -3,9 +3,9 @@
  *
  * Voice information definitions for the low level driver for the 
  * AWE32/SB32/AWE64 wave table synth.
- *   version 0.4.3; Mar. 1, 1998
+ *   version 0.4.3; Feb. 1, 1999
  *
- * Copyright (C) 1996-1998 Takashi Iwai
+ * Copyright (C) 1996-1999 Takashi Iwai
  *
  * 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
@@ -133,7 +133,7 @@ typedef struct _awe_voice_parm_block {
        unsigned short moddelay;        /* modulation delay (0x8000) */
        unsigned char modatk, modhld;
        unsigned char moddcy, modsus;
-       unsigned short modrel, moddummy;
+       unsigned char modrel, moddummy;
        short modkeyhold, modkeydecay;  /* envelope change per key (not used) */
        unsigned short voldelay;        /* volume delay (0x8000) */
        unsigned char volatk, volhld;
diff --git a/include/linux/dtlk.h b/include/linux/dtlk.h
new file mode 100644 (file)
index 0000000..07a6b82
--- /dev/null
@@ -0,0 +1,104 @@
+#if 0
+
+#define TRACE_TXT(text) \
+       { \
+         if(dtlk_trace) \
+         { \
+           console_print(text); \
+           console_print("\n"); \
+         } \
+       }
+
+#define TRACE_CHR(chr) \
+       { \
+         if(dtlk_trace) \
+           console_print(chr); \
+       } \
+
+#endif
+
+#define DTLK_MINOR     0
+#define DTLK_IO_EXTENT 0x02
+
+       /* ioctl's use magic number of 0xa3 */
+#define DTLK_INTERROGATE 0xa390        /* get settings from the DoubleTalk */
+#define DTLK_STATUS 0xa391     /* get status from the DoubleTalk */
+
+
+#define DTLK_CLEAR 0x18                /* stops speech */
+
+#define DTLK_MAX_RETRIES (loops_per_sec/10000)
+
+       /* TTS Port Status Flags */
+#define TTS_READABLE     0x80  /* mask for bit which is nonzero if a
+                                  byte can be read from the TTS port */
+#define TTS_SPEAKING     0x40  /* mask for SYNC bit, which is nonzero
+                                  while DoubleTalk is producing
+                                  output with TTS, PCM or CVSD
+                                  synthesizers or tone generators
+                                  (that is, all but LPC) */
+#define TTS_SPEAKING2    0x20  /* mask for SYNC2 bit,
+                                  which falls to zero up to 0.4 sec
+                                  before speech stops */
+#define TTS_WRITABLE     0x10  /* mask for RDY bit, which when set to
+                                  1, indicates the TTS port is ready
+                                  to accept a byte of data.  The RDY
+                                  bit goes zero 2-3 usec after
+                                  writing, and goes 1 again 180-190
+                                  usec later. */
+#define TTS_ALMOST_FULL  0x08  /* mask for AF bit: When set to 1,
+                                  indicates that less than 300 free
+                                  bytes are available in the TTS
+                                  input buffer. AF is always 0 in the
+                                  PCM, TGN and CVSD modes. */
+#define TTS_ALMOST_EMPTY 0x04  /* mask for AE bit: When set to 1,
+                                  indicates that less than 300 bytes
+                                  of data remain in DoubleTalk's
+                                  input (TTS or PCM) buffer. AE is
+                                  always 1 in the TGN and CVSD
+                                  modes. */
+
+       /* LPC speak commands */
+#define LPC_5220_NORMAL 0x60   /* 5220 format decoding table, normal rate */
+#define LPC_5220_FAST 0x64     /* 5220 format decoding table, fast rate */
+#define LPC_D6_NORMAL 0x20     /* D6 format decoding table, normal rate */
+#define LPC_D6_FAST 0x24       /* D6 format decoding table, fast rate */
+
+       /* LPC Port Status Flags (valid only after one of the LPC
+           speak commands) */
+#define LPC_SPEAKING     0x80  /* mask for TS bit: When set to 1,
+                                  indicates the LPC synthesizer is
+                                  producing speech.*/
+#define LPC_BUFFER_LOW   0x40  /* mask for BL bit: When set to 1,
+                                  indicates that the hardware LPC
+                                  data buffer has less than 30 bytes
+                                  remaining. (Total internal buffer
+                                  size = 4096 bytes.) */
+#define LPC_BUFFER_EMPTY 0x20  /* mask for BE bit: When set to 1,
+                                  indicates that the LPC data buffer
+                                  ran out of data (error condition if
+                                  TS is also 1).  */
+
+                               /* data returned by Interrogate command */
+struct dtlk_settings
+{
+  unsigned short serial_number;        /* 0-7Fh:0-7Fh */
+  unsigned char rom_version[24]; /* null terminated string */
+  unsigned char mode;          /* 0=Character; 1=Phoneme; 2=Text */
+  unsigned char punc_level;    /* nB; 0-7 */
+  unsigned char formant_freq;  /* nF; 0-9 */
+  unsigned char pitch;         /* nP; 0-99 */
+  unsigned char speed;         /* nS; 0-9 */
+  unsigned char volume;                /* nV; 0-9 */
+  unsigned char tone;          /* nX; 0-2 */
+  unsigned char expression;    /* nE; 0-9 */
+  unsigned char ext_dict_loaded; /* 1=exception dictionary loaded */
+  unsigned char ext_dict_status; /* 1=exception dictionary enabled */
+  unsigned char free_ram;      /* # pages (truncated) remaining for
+                                   text buffer */
+  unsigned char articulation;  /* nA; 0-9 */
+  unsigned char reverb;                /* nR; 0-9 */
+  unsigned char eob;           /* 7Fh value indicating end of
+                                   parameter block */
+  unsigned char has_indexing;  /* nonzero if indexing is implemented */
+};
index 0f1f90a83103032bc4e41531f6390ef5f7b24900..d4718b3113f294fe5c6016646fec0e6d862ac617 100644 (file)
@@ -16,7 +16,7 @@
 #define RTC_MINOR 135
 #define SUN_OPENPROM_MINOR 139
 #define NVRAM_MINOR 144
-#define RADIO_MINOR 152
+#define I2O_MINOR 166
 #define MISC_DYNAMIC_MINOR 255
 
 extern int misc_init(void);
index 96bafde00063a478cdc91c4202c156f2f0e2cb92..eb3feb9a64d698d3b68924c078b61a64ab354616 100644 (file)
@@ -3,7 +3,7 @@
  *
  *     PCI defines and function prototypes
  *     Copyright 1994, Drew Eckhardt
- *     Copyright 1997, 1998 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ *     Copyright 1997--1999 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
  *
  *     For more information, please consult the following manuals (look at
  *     http://www.pcisig.com/ for how to get them):
@@ -36,9 +36,9 @@
 #define  PCI_COMMAND_FAST_BACK 0x200   /* Enable back-to-back writes */
 
 #define PCI_STATUS             0x06    /* 16 bits */
+#define  PCI_STATUS_CAP_LIST   0x10    /* Support Capability List */
 #define  PCI_STATUS_66MHZ      0x20    /* Support 66 Mhz PCI 2.1 bus */
 #define  PCI_STATUS_UDF                0x40    /* Support User Definable Features */
-
 #define  PCI_STATUS_FAST_BACK  0x80    /* Accept fast-back to back */
 #define  PCI_STATUS_PARITY     0x100   /* Detected parity error */
 #define  PCI_STATUS_DEVSEL_MASK        0x600   /* DEVSEL timing */
 #define  PCI_ROM_ADDRESS_ENABLE        0x01
 #define PCI_ROM_ADDRESS_MASK   (~0x7ffUL)
 
-/* 0x34-0x3b are reserved */
+#define PCI_CAPABILITY_LIST    0x34    /* Offset of first capability list entry */
+
+/* 0x35-0x3b are reserved */
 #define PCI_INTERRUPT_LINE     0x3c    /* 8 bits */
 #define PCI_INTERRUPT_PIN      0x3d    /* 8 bits */
 #define PCI_MIN_GNT            0x3e    /* 8 bits */
 #define PCI_CB_LEGACY_MODE_BASE        0x44    /* 16-bit PC Card legacy mode base address (ExCa) */
 /* 0x48-0x7f reserved */
 
+/* Capability lists */
+#define PCI_CAP_LIST_ID                0       /* Capability ID */
+#define  PCI_CAP_ID_PM         0x01    /* Power Management */
+#define  PCI_CAP_ID_AGP                0x02    /* Accelerated Graphics Port */
+#define PCI_CAP_LIST_NEXT      1       /* Next capability in the list */
+
 /* Device classes and subclasses */
 
 #define PCI_CLASS_NOT_DEFINED          0x0000
 #define PCI_DEVICE_ID_DEC_21052                0x0021
 #define PCI_DEVICE_ID_DEC_21150                0x0022
 #define PCI_DEVICE_ID_DEC_21152                0x0024
+#define PCI_DEVICE_ID_DEC_21153                0x0025
 
 #define PCI_VENDOR_ID_CIRRUS           0x1013
 #define PCI_DEVICE_ID_CIRRUS_7548      0x0038
 #define PCI_VENDOR_ID_CBOARDS          0x1307
 #define PCI_DEVICE_ID_CBOARDS_DAS1602_16 0x0001
 
+#define PCI_VENDOR_ID_NETGEAR          0x1385
+#define PCI_DEVICE_ID_NETGEAR_GA620    0x620a
+
 #define PCI_VENDOR_ID_SYMPHONY         0x1c1c
 #define PCI_DEVICE_ID_SYMPHONY_101     0x0001
 
 #define PCI_DEVICE_ID_INTEL_82443BX_2  0x7192
 #define PCI_DEVICE_ID_INTEL_P6         0x84c4
 #define PCI_DEVICE_ID_INTEL_82450GX    0x84c5
+#define PCI_DEVICE_ID_INTEL_82451NX    0x84ca
 
 #define PCI_VENDOR_ID_KTI              0x8e2e
 #define PCI_DEVICE_ID_KTI_ET32P2       0x3000
@@ -1197,6 +1210,7 @@ void pci_init(void);
 void pci_setup(char *str, int *ints);
 void pci_quirks_init(void);
 unsigned int pci_scan_bus(struct pci_bus *bus);
+struct pci_bus *pci_scan_peer_bridge(int bus);
 void pci_proc_init(void);
 void proc_old_pci_init(void);
 int get_pci_list(char *buf);
index c0b69e54aa51b2aad01f1dd61e122256eb18a78c..1210b4e3ececbd641e479f57832644fe64c04a34 100644 (file)
@@ -258,6 +258,7 @@ struct br_stat {
 #define BR_UP          0x0001  /* bridging enabled */
 #define BR_DEBUG       0x0002  /* debugging enabled */
 #define BR_PROT_STATS  0x0004  /* protocol statistics enabled */
+#define BR_STP_DISABLED        0x0008  /* Spanning tree protocol disabled */
 
 struct br_cf {
        unsigned int cmd;
@@ -281,6 +282,7 @@ struct br_cf {
 #define BRCMD_ENABLE_PROT_STATS        13
 #define BRCMD_DISABLE_PROT_STATS 14
 #define BRCMD_ZERO_PROT_STATS  15
+#define BRCMD_TOGGLE_STP       16
 
 /* prototypes of exported bridging functions... */
 
@@ -295,7 +297,7 @@ struct fdb *br_avl_find_addr(unsigned char addr[6]);
 struct fdb *br_avl_insert (struct fdb * new_node);
 void sprintf_avl (char **pbuffer, struct fdb * tree, off_t *pos,int* len, off_t offset, int length);
 int br_tree_get_info(char *buffer, char **start, off_t offset, int length, int dummy);
-
+void br_avl_delete_by_port(int port);
 /* externs */
 
 extern struct br_stat br_stats;
index 8498f41767a44e430a5aa06ffefe99ce18d10473..d8983c009d2c0d1791478918368bbeba7ba7ff8d 100644 (file)
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Wed Oct 21 22:47:12 1998
- * Modified at:   Mon Dec 14 11:47:25 1998
+ * Modified at:   Sat Feb  6 07:37:49 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
@@ -34,6 +34,7 @@ typedef enum {
        ESI_DONGLE,
        ACTISYS_DONGLE,
        ACTISYS_PLUS_DONGLE,
+       GIRBIL_DONGLE,
 } DONGLE_T;
 
 struct dongle {
index a092d98082cdb812e966d6eacf23f3acf0a207a9..9ef035889554a1670de029e13b1316c08966e114 100644 (file)
@@ -149,6 +149,7 @@ struct ircomm_cb{
        int max_txbuff_size;          
        int maxsdusize;
        __u32 daddr;        /* Device address of the peer device */ 
+       __u32 saddr;
 
        void (*d_handler)(struct ircomm_cb *self);
        struct notify_t notify;     /* container of callbacks */
index 22458aa0ba0e9e7669432fa62fb2b6d6e41233eb..30835b9a941986144e23f90bef7080d220c9733e 100644 (file)
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Dec  9 21:13:12 1997
- * Modified at:   Sat Jan 16 01:23:15 1999
+ * Modified at:   Wed Jan 27 14:15:50 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
@@ -44,7 +44,7 @@
 
 extern __u32 irda_debug;
 
-#define IRDA_DEBUG 3
+#define IRDA_DEBUG 0
 
 #define DEBUG(n, args...) if (irda_debug >= (n)) printk( KERN_DEBUG args)
 #define ASSERT(expr, func) \
index d8e546bb5adadf9c118da7494f4338af2d0bb94f..7439f5ffb49a036b95f39fd14ecd2946b445f091 100644 (file)
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Haris Zukanovic <haris@stud.cs.uit.no>
  * Created at:    Tue Apr 14 12:41:42 1998
- * Modified at:   Mon Jan 18 10:52:10 1999
+ * Modified at:   Tue Feb  9 14:01:50 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Haris Zukanovic, <haris@stud.cs.uit.no>
 #include <net/irda/qos.h>
 #include <net/irda/irqueue.h>
 
-#define SIR_MODE       0x01
-#define MIR_MODE       0x02
-#define FIR_MODE       0x04
-#define IO_PIO         0x08
-#define IO_DMA         0x10
+/* Some non-standard interface flags (should not conflict with any in if.h */
+#define IFF_SIR        0x01 /* Supports SIR speeds */
+#define IFF_MIR        0x02 /* Supports MIR speeds */
+#define IFF_FIR        0x04 /* Supports FIR speeds */
+#define IFF_PIO        0x08 /* Supports PIO transfer of data */
+#define IFF_DMA                0x10 /* Supports DMA transfer of data */
+#define IFF_DONGLE      0x20 /* Interface has a dongle attached */
 
 #define IO_XMIT 0x01
 #define IO_RECV 0x02
@@ -93,7 +95,7 @@ struct irda_device {
        struct device netdev;   /* Yes! we are some kind of netdevice */
        struct enet_statistics stats;
 
-/*     int flags; */
+       int flags;            /* Interface flags (see defs above) */
 
        void *priv;           /* Pointer to low level implementation */
 
@@ -103,6 +105,7 @@ struct irda_device {
        struct iobuff_t tx_buff;
        struct iobuff_t rx_buff;
 
+       int xbofs;
        int media_busy;
        
        /* Media busy stuff */
index 495da351e704c309567d80c758cde1de1a9f5542..df214129d247d17edc7eba09182400d8b2c15cf7 100644 (file)
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      iriap.h
- * Version:       
+ * Version:       0.5
  * Description:   Information Access Protocol (IAP)
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Aug 21 00:02:07 1997
- * Modified at:   Sat Dec  5 13:45:37 1998
+ * Modified at:   Tue Jan 26 11:50:33 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
 typedef void (*CONFIRM_CALLBACK)( __u16 obj_id, struct ias_value *value,
                                  void *priv);
 
-struct iap_value {
-       char *full;
-        char *name;
-        char *attr;
-        __u16   obj_id;
-        __u8    ret_code;
-        __u8    type;
-        int     len;
-        int value_int;
-        char *value_char;
-};
-
 struct iriap_cb {
        QUEUE queue; /* Must be first */
        
        int          magic;  /* Magic cookie */
        int          mode;   /* Client or server */
+
+       __u32        saddr;
        __u32        daddr;
        __u8         operation;
 
@@ -95,10 +85,10 @@ struct iriap_cb {
 
 int  iriap_init(void);
 void iriap_cleanup(void);
-void iriap_getvaluebyclass_request( __u32 addr, char *name, char *attr, 
+void iriap_getvaluebyclass_request( char *name, char *attr, 
+                                   __u32 saddr, __u32 daddr,
                                    CONFIRM_CALLBACK callback, void *priv);
-void iriap_getvaluebyclass_confirm( struct iriap_cb *self, 
-                                   struct sk_buff *skb);
+void iriap_getvaluebyclass_confirm(struct iriap_cb *self, struct sk_buff *skb);
 
 void iriap_send_ack( struct iriap_cb *self);
 void iriap_data_indication( void *instance, void *sap, struct sk_buff *skb);
@@ -121,3 +111,5 @@ static inline void iriap_start_watchdog_timer( struct iriap_cb *self,
 }
 
 #endif
+
+
index efacac8548a5b7c94670192d88accfe3f7e8862b..4a76018b6ff8e0e46c8a3e0a7945a319d1c2a2e8 100644 (file)
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Oct  1 22:49:50 1998
- * Modified at:   Sun Oct 25 00:28:56 1998
+ * Modified at:   Wed Feb  3 10:38:02 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
@@ -25,7 +25,7 @@
 #ifndef LM_IAS_OBJECT_H
 #define LM_IAS_OBJECT_H
 
-#include "irqueue.h"
+#include <net/irda/irqueue.h>
 
 /* LM-IAS Attribute types */
 #define IAS_MISSING 0
  */
 struct ias_object {
        QUEUE queue;     /* Must be first! */
-
        int magic;
        
        char  *name;
        int   id;
-
        hashbin_t *attribs;
 };
 
@@ -51,8 +49,7 @@ struct ias_object {
  *  Values used by LM-IAS attributes
  */
 struct ias_value {
-       /* Value description */
-        __u8    type;
+        __u8    type;    /* Value description */
        int     charset; /* Only used by string type */
         int     len;
        
@@ -68,16 +65,11 @@ struct ias_value {
  *  Attributes used by LM-IAS objects
  */
 struct ias_attrib {
-       QUEUE queue;     /* Must be first! */
-
+       QUEUE queue; /* Must be first! */
        int magic;
 
-       /* Attribute name */
-        char *name;
- /*        char *attr; What do we need this for?  */
-
-       /* Attribute value */
-       struct ias_value *value;
+        char *name;             /* Attribute name */
+       struct ias_value *value; /* Attribute value */
 };
 
 char *strdup( char *str);
@@ -87,12 +79,12 @@ void irias_insert_object( struct ias_object *obj);
 void __irias_delete_object( struct ias_object *obj);
 void irias_delete_object( char *name);
 
-void irias_add_integer_attrib( struct ias_object *obj, char *name, 
-                              int value);
-void irias_add_string_attrib( struct ias_object *obj, char *name, 
-                             char *value);
-void irias_add_octseq_attrib( struct ias_object *obj, char *name, 
-                             __u8 *octets, int len);
+void irias_add_integer_attrib(struct ias_object *obj, char *name, int value);
+void irias_add_string_attrib(struct ias_object *obj, char *name, char *value);
+void irias_add_octseq_attrib(struct ias_object *obj, char *name, __u8 *octets,
+                            int len);
+int irias_object_change_attribute(char *obj_name, char *attrib_name, 
+                                 struct ias_value *new_value);
 struct ias_object *irias_find_object( char *name);
 struct ias_attrib *irias_find_attrib( struct ias_object *obj, char *name);
 
diff --git a/include/net/irda/irlan_cli.h b/include/net/irda/irlan_cli.h
deleted file mode 100644 (file)
index fb677af..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/*********************************************************************
- *                
- * Filename:      client.h
- * Version:       0.3
- * Description:   IrDA LAN access layer
- * Status:        Experimental.
- * Author:        Dag Brattli <dagb@cs.uit.no>
- * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Mon Oct 19 12:37:20 1998
- * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * 
- *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, 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.
- *
- *     Neither Dag Brattli nor University of Tromsø admit liability nor
- *     provide warranty for any of this software. This material is 
- *     provided "AS-IS" and at no charge.
- *
- ********************************************************************/
-
-#ifndef IRLAN_CLIENT_H
-#define IRLAN_CLIENT_H
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-
-int  irlan_client_init(void);
-void irlan_client_cleanup(void);
-
-void irlan_discovery_indication( DISCOVERY*);
-void irlan_client_disconnect_indication( void *instance, void *sap, 
-                                        LM_REASON reason, struct sk_buff *);
-
-void irlan_client_data_indication( void *instance, void *sap, 
-                                  struct sk_buff *skb);
-
-void irlan_client_control_data_indication( void *instance, void *sap, 
-                                          struct sk_buff *skb);
-
-void irlan_client_connect_confirm( void *instance, void *sap, 
-                                  struct qos_info *qos, int max_sdu_size,
-                                  struct sk_buff *);
-void irlan_client_connect_indication( void *instance, void *sap, 
-                                     struct sk_buff *);
-void irlan_client_connect_response( void *instance, void *sap, 
-                                   int max_sdu_size, struct sk_buff *skb);
-
-void irlan_client_open_tsaps( struct irlan_cb *self);
-
-void irlan_client_extract_params( struct irlan_cb *self, 
-                                 struct sk_buff *skb);
-void check_response_param( struct irlan_cb *self, char *param, 
-                          char *value, int val_len);
-void handle_request( struct irlan_cb *self);
-void irlan_client_register_server(void);
-void irlan_client_get_value_confirm( __u16 obj_id, struct ias_value *value, 
-                                    void *priv);
-
-#endif
diff --git a/include/net/irda/irlan_client.h b/include/net/irda/irlan_client.h
new file mode 100644 (file)
index 0000000..547868c
--- /dev/null
@@ -0,0 +1,44 @@
+/*********************************************************************
+ *                
+ * Filename:      irlan_client.h
+ * Version:       0.3
+ * Description:   IrDA LAN access layer
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Sun Aug 31 20:14:37 1997
+ * Modified at:   Wed Feb  3 14:29:49 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, 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.
+ *
+ *     Neither Dag Brattli nor University of Tromsø admit liability nor
+ *     provide warranty for any of this software. This material is 
+ *     provided "AS-IS" and at no charge.
+ *
+ ********************************************************************/
+
+#ifndef IRLAN_CLIENT_H
+#define IRLAN_CLIENT_H
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+
+#include <net/irda/irlan_event.h>
+
+void irlan_client_start_kick_timer(struct irlan_cb *self, int timeout);
+void irlan_client_discovery_indication(DISCOVERY*);
+void irlan_client_wakeup(struct irlan_cb *self, __u32 saddr, __u32 daddr);
+
+void irlan_client_open_ctrl_tsap( struct irlan_cb *self);
+
+void irlan_client_extract_params(struct irlan_cb *self, struct sk_buff *skb);
+void irlan_client_get_value_confirm( __u16 obj_id, struct ias_value *value, 
+                                    void *priv);
+#endif
index 33ba52377333dee52ebd1729e6d4133848aa1bcf..a07fdfd2f365b85011acbbe6b8e93dfed18dcfab 100644 (file)
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
- * Filename:      irlan.h
- * Version:       0.1
+ * Filename:      irlan_common.h
+ * Version:       0.8
  * Description:   IrDA LAN access layer
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Thu Oct 29 13:23:11 1998
+ * Modified at:   Wed Feb 17 23:28:53 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
 
-#include "irqueue.h"
-#include "irttp.h"
+#include <net/irda/irqueue.h>
+#include <net/irda/irttp.h>
 
-#define IRLAN_MTU 1518
+#define IRLAN_MTU        1518
+#define IRLAN_TIMEOUT    1000
 
 /* Command packet types */
 #define CMD_GET_PROVIDER_INFO   0
 #define MEDIA_802_5 2
 
 /* Filter parameters */
-#define DATA_CHAN 1
+#define DATA_CHAN   1
 #define FILTER_TYPE 2
 #define FILTER_MODE 3
 
 /* Filter types */
-#define IR_DIRECTED   1
-#define IR_FUNCTIONAL 2
-#define IR_GROUP      3
-#define IR_MAC_FRAME  4
-#define IR_MULTICAST  5
-#define IR_BROADCAST  6
-#define IR_IPX_SOCKET 7
+#define IRLAN_DIRECTED   0x01
+#define IRLAN_FUNCTIONAL 0x02
+#define IRLAN_GROUP      0x04
+#define IRLAN_MAC_FRAME  0x08
+#define IRLAN_MULTICAST  0x10
+#define IRLAN_BROADCAST  0x20
+#define IRLAN_IPX_SOCKET 0x40
 
 /* Filter modes */
-#define ALL    1
-#define FILTER 2
-#define NONE   3
+#define ALL     1
+#define FILTER  2
+#define NONE    3
 
 /* Filter operations */
 #define GET     1
 #define DYNAMIC 5
 
 /* Access types */
-#define DIRECT 1
-#define PEER   2
-#define HOSTED 3
+#define ACCESS_DIRECT  1
+#define ACCESS_PEER    2
+#define ACCESS_HOSTED  3
+
+#define IRLAN_BYTE   0
+#define IRLAN_SHORT  1
+#define IRLAN_ARRAY  2
 
 #define IRLAN_MAX_HEADER (TTP_HEADER+LMP_HEADER+LAP_HEADER)
 
 /*
- *  IrLAN client subclass
+ *  IrLAN client
  */
 struct irlan_client_cb {
-       /*
-        *  Client fields
-        */
+       int state;
+
        int open_retries;
+
+       struct tsap_cb *tsap_ctrl;
        
        __u8 reconnect_key[255];
        __u8 key_len;
        
+       __u16 recv_arb_val;
+       __u16 max_frame;
+       int filter_type;
+
        int unicast_open;
        int broadcast_open;
+
+       struct timer_list kick_timer;
+       int start_new_provider;
 };
 
 /*
- * IrLAN servers subclass
+ * IrLAN provider
  */
-struct irlan_server_cb {
+struct irlan_provider_cb {
+       int state;
        
+       struct tsap_cb *tsap_ctrl;
+
        /*
-        *  Store some values here which are used by the irlan_server to parse
-        *  FILTER_OPERATIONs
+        *  Store some values here which are used by the provider to parse
+        *  the filter operations
         */
        int data_chan;
        int filter_type;
@@ -124,11 +140,13 @@ struct irlan_server_cb {
        int filter_operation;
        int filter_entry;
 
+       __u16 send_arb_val;
+
        __u8 mac_address[6]; /* Generated MAC address for peer device */
 };
 
 /*
- *  IrLAN super class
+ *  IrLAN
  */
 struct irlan_cb {
        QUEUE queue; /* Must be first */
@@ -140,57 +158,52 @@ struct irlan_cb {
 
        __u32 saddr;        /* Source devcie address */
        __u32 daddr;        /* Destination device address */
-       int   connected;    /* TTP layer ready to exchange ether frames */
+       int   netdev_registered;
+       int   notify_irmanager;
        
-       int state;  /* Current state of IrLAN layer */
-
-       int media;      
+       int media;          /* Media type */
+       int access_type;    /* Currently used access type */
+       __u8 version[2];    /* IrLAN version */
        
-       struct tsap_cb *tsap_ctrl;
        struct tsap_cb *tsap_data;
 
        int  use_udata;  /* Use Unit Data transfers */
 
-       __u8 dtsap_sel_data; /* Destination data TSAP selector */
        __u8 stsap_sel_data; /* Source data TSAP selector */
+       __u8 dtsap_sel_data; /* Destination data TSAP selector */
        __u8 dtsap_sel_ctrl; /* Destination ctrl TSAP selector */
 
-       int client; /* Client or server */
-       union {
-               struct irlan_client_cb client;
-               struct irlan_server_cb server;
-       } t;
-
-       /* void (*irlan_dev_init)(struct irlan_cb *); */
-
-       /* 
-         *  Used by extract_params, placed here for now to avoid placing 
-         *  them on the stack. FIXME: remove these!
-         */
-        char name[255];
-        char value[1016];
+       struct irlan_client_cb client;     /* Client specific fields */
+       struct irlan_provider_cb provider; /* Provider specific fields */
+       
+       struct timer_list watchdog_timer;
 };
 
-struct irlan_cb *irlan_open(void);
-
-void irlan_get_provider_info( struct irlan_cb *self);
-void irlan_get_unicast_addr( struct irlan_cb *self);
-void irlan_get_media_char( struct irlan_cb *self);
-void irlan_open_data_channel( struct irlan_cb *self);
-void irlan_set_multicast_filter( struct irlan_cb *self, int status);
-void irlan_set_broadcast_filter( struct irlan_cb *self, int status);
-void irlan_open_unicast_addr( struct irlan_cb *self);
-
-int insert_byte_param( struct sk_buff *skb, char *param, __u8 value);
-int insert_string_param( struct sk_buff *skb, char *param, char *value);
-int insert_array_param( struct sk_buff *skb, char *name, __u8 *value, 
-                       __u16 value_len);
-
-int insert_param( struct sk_buff *skb, char *param, int type, char *value_char,
-                 __u8 value_byte, __u16 value_short);
-
-int irlan_get_response_param( __u8 *buf, char *name, char *value, int *len);
-void print_ret_code( __u8 code);
+struct irlan_cb *irlan_open(__u32 saddr, __u32 daddr, int netdev);
+void irlan_close(struct irlan_cb *self);
+int  irlan_register_netdev(struct irlan_cb *self);
+void irlan_ias_register(struct irlan_cb *self, __u8 tsap_sel);
+void irlan_start_watchdog_timer(struct irlan_cb *self, int timeout);
+
+void irlan_open_data_tsap(struct irlan_cb *self);
+
+void irlan_get_provider_info(struct irlan_cb *self);
+void irlan_get_unicast_addr(struct irlan_cb *self);
+void irlan_get_media_char(struct irlan_cb *self);
+void irlan_open_data_channel(struct irlan_cb *self);
+void irlan_close_data_channel(struct irlan_cb *self);
+void irlan_set_multicast_filter(struct irlan_cb *self, int status);
+void irlan_set_broadcast_filter(struct irlan_cb *self, int status);
+void irlan_open_unicast_addr(struct irlan_cb *self);
+
+int irlan_insert_byte_param(struct sk_buff *skb, char *param, __u8 value);
+int irlan_insert_short_param(struct sk_buff *skb, char *param, __u16 value);
+int irlan_insert_string_param(struct sk_buff *skb, char *param, char *value);
+int irlan_insert_array_param(struct sk_buff *skb, char *name, __u8 *value, 
+                            __u16 value_len);
+
+int irlan_get_param(__u8 *buf, char *name, char *value, __u16 *len);
+void print_ret_code(__u8 code);
 
 extern hashbin_t *irlan;
 
index 72f14ff75a80beddcbac7dbe23a4761571dab955..4cc2b12a875c0bbcdab669bbf0c15783a7bca10b 100644 (file)
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Oct 15 08:36:58 1998
- * Modified at:   Thu Oct 15 12:28:12 1998
+ * Modified at:   Fri Jan 29 15:20:45 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
 #ifndef IRLAN_ETH_H
 #define IRLAN_ETH_H
 
-int irlan_eth_init( struct device *dev);
-int irlan_eth_open( struct device *dev);
-int irlan_eth_close( struct device *dev);
-
-void irlan_eth_rx( void *instance, void *sap, struct sk_buff *skb);
-int irlan_eth_tx( struct sk_buff *skb, struct device *dev);
+void irlan_eth_receive( void *instance, void *sap, struct sk_buff *skb);
+int  irlan_eth_xmit( struct sk_buff *skb, struct device *dev);
 
 void irlan_eth_flow_indication( void *instance, void *sap, LOCAL_FLOW flow);
 
index d3a062af0f2d3e86e9789bf9c35af432fc1ab912..b9baac9eb8b676e585139d95132ee5b4cefb441e 100644 (file)
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Tue Oct 20 09:59:31 1998
+ * Modified at:   Tue Feb  2 09:45:17 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
@@ -44,7 +44,6 @@ typedef enum {
        IRLAN_SYNC
 } IRLAN_STATE;
 
-/* IrLAN Client Events */
 typedef enum {
        IRLAN_DISCOVERY_INDICATION,
        IRLAN_IAS_PROVIDER_AVAIL,
@@ -61,26 +60,22 @@ typedef enum {
        IRLAN_GET_MEDIA_CMD,
        IRLAN_OPEN_DATA_CMD,
        IRLAN_FILTER_CONFIG_CMD,
-} IRLAN_EVENT;
 
-struct irlan_info {
-       __u8   dlsap_sel;
-       __u32  daddr;
-       struct tsap_cb *tsap;
-};
+       IRLAN_CHECK_CON_ARB,
+       IRLAN_PROVIDER_SIGNAL,
+
+       IRLAN_WATCHDOG_TIMEOUT,
+} IRLAN_EVENT;
 
 extern char *irlan_state[];
 
-void irlan_do_client_event( struct irlan_cb *self, 
-                           IRLAN_EVENT event, 
-                           struct sk_buff *skb);
+void irlan_do_client_event(struct irlan_cb *self, IRLAN_EVENT event, 
+                          struct sk_buff *skb);
 
-void irlan_do_server_event( struct irlan_cb *self, 
-                           IRLAN_EVENT event, 
-                           struct sk_buff *skb, 
-                           struct irlan_info *info);
+void irlan_do_provider_event(struct irlan_cb *self, IRLAN_EVENT event, 
+                            struct sk_buff *skb);
 
-void irlan_next_state( struct irlan_cb *self, 
-                      IRLAN_STATE state);
+void irlan_next_client_state(struct irlan_cb *self, IRLAN_STATE state);
+void irlan_next_provider_state(struct irlan_cb *self, IRLAN_STATE state);
 
 #endif
diff --git a/include/net/irda/irlan_filter.h b/include/net/irda/irlan_filter.h
new file mode 100644 (file)
index 0000000..b68eec1
--- /dev/null
@@ -0,0 +1,33 @@
+/*********************************************************************
+ *                
+ * Filename:      irlan_filter.h
+ * Version:       
+ * Description:   
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Fri Jan 29 15:24:08 1999
+ * Modified at:   Sun Feb  7 23:35:31 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1998 Dag Brattli, 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.
+ *  
+ *     Neither Dag Brattli nor University of Tromsø admit liability nor
+ *     provide warranty for any of this software. This material is 
+ *     provided "AS-IS" and at no charge.
+ *     
+ ********************************************************************/
+
+#ifndef IRLAN_FILTER_H
+#define IRLAN_FILTER_H
+
+void irlan_check_command_param(struct irlan_cb *self, char *param, 
+                              char *value);
+void handle_filter_request(struct irlan_cb *self, struct sk_buff *skb);
+int irlan_print_filter(int filter_type, char *buf);
+
+#endif /* IRLAN_FILTER_H */
diff --git a/include/net/irda/irlan_provider.h b/include/net/irda/irlan_provider.h
new file mode 100644 (file)
index 0000000..a95b490
--- /dev/null
@@ -0,0 +1,57 @@
+/*********************************************************************
+ *                
+ * Filename:      irlan_provider.h
+ * Version:       0.1
+ * Description:   IrDA LAN access layer
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Sun Aug 31 20:14:37 1997
+ * Modified at:   Sat Jan 30 16:22:24 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, 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.
+ *
+ *     Neither Dag Brattli nor University of Tromsø admit liability nor
+ *     provide warranty for any of this software. This material is 
+ *     provided "AS-IS" and at no charge.
+ *
+ ********************************************************************/
+
+#ifndef IRLAN_SERVER_H
+#define IRLAN_SERVER_H
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+
+#include <net/irda/irlan_common.h>
+
+void irlan_provider_ctrl_disconnect_indication(void *instance, void *sap, 
+                                              LM_REASON reason, 
+                                              struct sk_buff *skb);
+
+void irlan_provider_ctrl_data_indication(void *instance, void *sap,
+                                        struct sk_buff *skb);
+
+void irlan_provider_connect_indication(void *instance, void *sap, 
+                                      struct qos_info *qos, int max_sdu_size,
+                                      struct sk_buff *skb);
+void irlan_provider_connect_response(struct irlan_cb *, struct tsap_cb *);
+
+int irlan_parse_open_data_cmd(struct irlan_cb *self, struct sk_buff *skb);
+int irlan_provider_extract_params(struct irlan_cb *self, int cmd,
+                                 struct sk_buff *skb);
+
+void irlan_provider_send_reply(struct irlan_cb *self, int command, 
+                              int ret_code);
+void irlan_provider_open_ctrl_tsap( struct irlan_cb *self);
+
+#endif
+
+
diff --git a/include/net/irda/irlan_srv.h b/include/net/irda/irlan_srv.h
deleted file mode 100644 (file)
index c187302..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*********************************************************************
- *                
- * Filename:      server.h
- * Version:       0.1
- * Description:   IrDA LAN access layer
- * Status:        Experimental.
- * Author:        Dag Brattli <dagb@cs.uit.no>
- * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Fri Oct 16 11:25:37 1998
- * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * 
- *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, 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.
- *
- *     Neither Dag Brattli nor University of Tromsø admit liability nor
- *     provide warranty for any of this software. This material is 
- *     provided "AS-IS" and at no charge.
- *
- ********************************************************************/
-
-#ifndef IRLAN_SERVER_H
-#define IRLAN_SERVER_H
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-
-#include <net/irda/irlan_common.h>
-
-int  irlan_server_init(void);
-void irlan_server_cleanup(void);
-struct irlan_cb *irlan_server_open(void);
-void irlan_server_close( struct irlan_cb *self);
-
-void irlan_server_disconnect_indication( void *instance, void *sap, 
-                                        LM_REASON reason, 
-                                        struct sk_buff *skb);
-
-void irlan_server_data_indication( void *instance, void *sap,
-                                  struct sk_buff *skb);
-void irlan_server_control_data_indication( void *instance, void *sap,
-                                          struct sk_buff *skb);
-
-void irlan_server_connect_indication( void *instance, void *sap, 
-                                     struct qos_info *qos, int max_sdu_size,
-                                     struct sk_buff *skb);
-void irlan_server_connect_response( struct irlan_cb *, struct tsap_cb *);
-
-int irlan_parse_open_data_cmd( struct irlan_cb *self, struct sk_buff *skb);
-int irlan_server_extract_params( struct irlan_cb *self, int cmd,
-                                 struct sk_buff *skb);
-
-void irlan_server_send_reply( struct irlan_cb *self, int command, 
-                             int ret_code);
-void irlan_server_register(void);
-
-#endif
index 524d2b79907b1391907ab19fd19737582f7d3b21..dd958b86b51d945665eebb8348cedabc98056d3a 100644 (file)
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      irlap.h
- * Version:       0.3
+ * Version:       0.8
  * Description:   An IrDA LAP driver for Linux
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Sat Dec 12 12:25:33 1998
+ * Modified at:   Mon Jan 25 13:58:59 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
@@ -105,6 +105,7 @@ struct irlap_cb {
        struct timer_list backoff_timer;
 
        /* Timeouts which will be different with different turn time */
+       int slot_timeout;
        int poll_timeout;
        int final_timeout;
        int wd_timeout;
@@ -118,14 +119,15 @@ struct irlap_cb {
        int     retry_count;  /* Times tried to establish connection */
        int     add_wait;     /* True if we are waiting for frame */
 
+       __u8    connect_pending;
+       __u8    disconnect_pending;
+
+       /*  To send a faster RR if tx queue empty */
 #ifdef CONFIG_IRDA_FAST_RR
-       /* 
-        *  To send a faster RR if tx queue empty 
-        */
        int     fast_RR_timeout;
        int     fast_RR;      
 #endif
-
+       
        int N1; /* N1 * F-timer = Negitiated link disconnect warning threshold */
        int N2; /* N2 * F-timer = Negitiated link disconnect time */
        int N3; /* Connection retry count */
index bf412893962368c242dfad2f41cd575e0983561b..db77cf5d93673516e591cd780e6bdd78c61830a6 100644 (file)
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Aug 16 00:59:29 1997
- * Modified at:   Thu Dec 17 11:58:10 1998
+ * Modified at:   Thu Feb 11 00:41:02 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
@@ -111,7 +111,7 @@ struct irlap_info {
        DISCOVERY *discovery; /* Discovery information */
 };
 
-extern char *irlap_state[];
+extern const char *irlap_state[];
 
 void irlap_do_event( struct irlap_cb *self, IRLAP_EVENT event, 
                     struct sk_buff *skb, struct irlap_info *info);
index a10a08fe1b14157117385a2e73ea72fc144f595e..82690a34aed5b619efabd6bbf2fd05f7775e65c2 100644 (file)
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 17 20:54:32 1997
- * Modified at:   Mon Dec  7 21:11:32 1998
+ * Modified at:   Thu Feb  4 11:06:24 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
 #include <linux/config.h>
 #include <linux/types.h>
 
-#include "irmod.h"
-#include "qos.h"
-#include "irlap.h"
-#include "irlmp_event.h"
-#include "irqueue.h"
+#include <net/irda/irmod.h>
+#include <net/irda/qos.h>
+#include <net/irda/irlap.h>
+#include <net/irda/irlmp_event.h>
+#include <net/irda/irqueue.h>
 
 /* LSAP-SEL's */
 #define LSAP_MASK     0x7f
 #define LSAP_IAS      0x00
 #define LSAP_ANY      0xff
 
+#define DEV_ADDR_ANY  0xffffffff
+
 /* Predefined LSAPs used by the various servers */
 #define TSAP_IRLAN    0x05
 #define LSAP_IRLPT    0x06
@@ -69,6 +71,8 @@
 #define HINT_HTTP        0x10
 #define HINT_OBEX        0x20
 
+#define LM_IDLE_TIMEOUT  200 /* 2 seconds for now */
+
 typedef enum {
        S_PNP,
        S_PDA,
@@ -150,6 +154,7 @@ struct lap_cb {
        hashbin_t *cachelog;    /* Discovered devices for this link */
 
        struct qos_info *qos;  /* LAP QoS for this session */
+       struct timer_list idle_timer;
 };
 
 /*
@@ -171,10 +176,8 @@ struct irlmp_cb {
 
        __u8 conflict_flag;
        
-       /* int discovery; */
-
-       DISCOVERY  discovery_rsp; /* Discovery response to use by IrLAP */
        DISCOVERY  discovery_cmd; /* Discovery command to use by IrLAP */
+       DISCOVERY  discovery_rsp; /* Discovery response to use by IrLAP */
 
        int free_lsap_sel;
 
@@ -205,7 +208,8 @@ void irlmp_register_irlap( struct irlap_cb *self, __u32 saddr,
                           struct notify_t *);
 void irlmp_unregister_irlap( __u32 saddr);
 
-void irlmp_connect_request( struct lsap_cb *, __u8 dlsap_sel, __u32 daddr, 
+int  irlmp_connect_request( struct lsap_cb *, __u8 dlsap_sel, 
+                           __u32 saddr, __u32 daddr,
                            struct qos_info *, struct sk_buff *);
 void irlmp_connect_indication( struct lsap_cb *self, struct sk_buff *skb);
 void irlmp_connect_response( struct lsap_cb *, struct sk_buff *);
@@ -231,9 +235,14 @@ void irlmp_status_indication( LINK_STATUS link, LOCK_STATUS lock);
 
 int  irlmp_slsap_inuse( __u8 slsap);
 __u8 irlmp_find_free_slsap(void);
-
 LM_REASON irlmp_convert_lap_reason( LAP_REASON);
 
+__u32 irlmp_get_saddr(struct lsap_cb *self);
+__u32 irlmp_get_daddr(struct lsap_cb *self);
+
+
+extern char *lmp_reasons[];
+extern int sysctl_discovery_slots;
 extern struct irlmp_cb *irlmp;
 
 #endif
index 1ffb6faa5537402001f66a33d60eae49426e7b8d..88076a9709288dbecef4d46be5f966a4f364aec9 100644 (file)
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Wed Oct 28 14:58:23 1998
+ * Modified at:   Thu Feb 11 00:42:41 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
@@ -72,7 +72,7 @@ typedef enum {
        LM_LAP_DISCONNECT_REQUEST,
        LM_LAP_DISCOVERY_REQUEST,
        LM_LAP_DISCOVERY_CONFIRM,
-
+       LM_LAP_IDLE_TIMEOUT,
 } IRLMP_EVENT;
 
 /*
@@ -95,11 +95,12 @@ struct irlmp_event {
        DISCOVERY *discovery;
 };
 
-extern char *irlmp_state[];
-extern char *irlsap_state[];
+extern const char *irlmp_state[];
+extern const char *irlsap_state[];
 
 void irlmp_watchdog_timer_expired( unsigned long data);
 void irlmp_discovery_timer_expired( unsigned long data);
+void irlmp_idle_timer_expired( unsigned long data);
 
 void irlmp_next_station_state( IRLMP_STATE state);
 void irlmp_next_lsap_state( struct lsap_cb *self, LSAP_STATE state);
index 64960f31dcc41ea78f80863168ff9cc6cbfd0cff..84e5136c7464168a32385ae7e5501aa96ea86b73 100644 (file)
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Aug 19 02:09:59 1997
- * Modified at:   Sun Oct 25 00:30:31 1998
+ * Modified at:   Tue Feb  2 11:07:45 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
@@ -42,8 +42,8 @@ void irlmp_send_lcf_pdu( struct lap_cb *self, __u8 dlsap, __u8 slsap,
                         __u8 opcode, struct sk_buff *skb);
 void irlmp_link_data_indication( struct lap_cb *, int reliable, 
                                 struct sk_buff *);
-void irlmp_link_connect_indication( struct lap_cb *, struct qos_info *qos, 
-                                   struct sk_buff *skb);
+void irlmp_link_connect_indication( struct lap_cb *, __u32 saddr, __u32 daddr,
+                                   struct qos_info *qos, struct sk_buff *skb);
 void irlmp_link_connect_request( __u32 daddr);
 void irlmp_link_connect_confirm( struct lap_cb *self, struct qos_info *qos, 
                                 struct sk_buff *skb);
index 1a54c68ebddff9472ca0fa3ca9c09b7d2b07e658..cd0807dd2a846f1646f05c72355804c74edf4a35 100644 (file)
@@ -1,6 +1,6 @@
 /*********************************************************************
  *                
- * Filename:      irlpt_client.h
+ * Filename:      irlpt_cli.h
  * Version:       0.1
  * Description:   
  * Status:        Experimental.
  */
 
 void irlpt_client_get_value_confirm(__u16 obj_id, 
-                                   struct ias_value *value, void *priv);
-void irlpt_client_connect_indication( void *instance, void *sap, 
+                                   struct ias_value *value, 
+                                   void *priv);
+void irlpt_client_connect_indication( void *instance, 
+                                     void *sap, 
                                      struct qos_info *qos, 
                                      int max_seg_size,
                                      struct sk_buff *skb);
index 4013c2f4dec26a0c1e72a3faa76e75502f24a922..b6fd153a5dbed1a3d913168a3e41cdf4092bd999 100644 (file)
@@ -1,19 +1,21 @@
 /*********************************************************************
  *                
- * Filename:      irlpt_client_fsm.h
+ * Filename:      irlpt_cli_fsm.h
  * Version:       0.1
  * Sources:       irlan_event.h
  * 
- *     Copyright (c) 1997 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
- *     Copyright (c) 1998, Thomas Davis, <ratbert@radiks.net>, All Rights Reserved.
+ *     Copyright (c) 1997 Dag Brattli <dagb@cs.uit.no>, 
+ *             All Rights Reserved.
+ *     Copyright (c) 1998, Thomas Davis, <ratbert@radiks.net>, 
+ *             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.
  *
- *     I, Thomas Davis, provide no warranty for any of this software. This material is 
- *     provided "AS-IS" and at no charge.
+ *     I, Thomas Davis, provide no warranty for any of this software. 
+ *     This material is provided "AS-IS" and at no charge.
  *
  ********************************************************************/
 
index 0e51b017a8d536d7a677830581a4653c95dcad97..83a9c307cc8fc0ca5b8bc6368c7ff6aba0f7e057 100644 (file)
@@ -1,6 +1,6 @@
 /*********************************************************************
  *
- * Filename:      irlpt.c
+ * Filename:      irlpt_common.h
  * Version:       
  * Description:   
  * Status:        Experimental.
@@ -67,7 +67,6 @@ typedef enum {
        IRLPT_CLIENT_QUERY,
        IRLPT_CLIENT_READY,
        IRLPT_CLIENT_WAITI,
-       IRLPT_CLIENT_WAITR,
        IRLPT_CLIENT_CONN,
 } IRLPT_CLIENT_STATE;
 
@@ -87,10 +86,6 @@ typedef enum {
        LMP_DISCONNECT,
        LMP_CONNECT_INDICATION,
        LMP_DISCONNECT_INDICATION,
-#if 0
-       TTP_CONNECT_INDICATION,
-       TTP_DISCONNECT_INDICATION,
-#endif
         IRLPT_DISCOVERY_INDICATION,
        IRLPT_CONNECT_REQUEST,
        IRLPT_DISCONNECT_REQUEST,
@@ -101,6 +96,7 @@ struct irlpt_info {
        struct lsap_cb *lsap;
        __u8 dlsap_sel;
        __u32 daddr;
+       __u32 saddr;
 };
 
 /* Command packet types */
@@ -142,7 +138,8 @@ struct irlpt_cb {
 
        int magic;              /* magic used to detect corruption of 
                                   the struct */
-       __u32 daddr;            /* my local address. */
+       __u32 daddr;            /* address of remote printer */
+       __u32 saddr;            /* my local address. */
 
        struct timer_list retry_timer;
        
@@ -168,6 +165,14 @@ struct irlpt_cb {
        struct wait_queue *write_wait;
        struct wait_queue *ex_wait;
 
+       /* this is used to remove the printer when it's gone */
+       struct timer_list lpt_timer;
+       void (*timeout) (unsigned long data);
+
+       void (*do_event) (struct irlpt_cb *self, IRLPT_EVENT event, 
+                         struct sk_buff *skb,
+                         struct irlpt_info *info);
+
        /* this is used by the server side of the system */
 
         IRLPT_SERVER_STATE connected;
index 7984a331ddaefa3679432220ae88796be86d9877..44e310f9571cf97e1ddb76c64912531dd6fea6eb 100644 (file)
@@ -1,6 +1,6 @@
 /*********************************************************************
  *                
- * Filename:      server.h
+ * Filename:      irlpt_server.h
  * Version:       0.1
  * Description:   
  * Status:        Experimental.
index 8f23226c33000b61ccc03a38a513908007f62944..c7ee3f8715609c923cc13653934857ab78d009e4 100644 (file)
@@ -1,19 +1,21 @@
 /*********************************************************************
  *                
- * Filename:      server_fsm.h<2>
+ * Filename:      server_server_fsm.h
  * Version:       0.1
  * Sources:       irlan_event.h
  * 
- *     Copyright (c) 1997 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
- *     Copyright (c) 1998, Thomas Davis, <ratbert@radiks.net>, All Rights Reserved.
+ *     Copyright (c) 1997 Dag Brattli <dagb@cs.uit.no>, 
+ *             All Rights Reserved.
+ *     Copyright (c) 1998, Thomas Davis, <ratbert@radiks.net>, 
+ *             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.
  *
- *     I, Thomas Davis, provide no warranty for any of this software. This material is 
- *     provided "AS-IS" and at no charge.
+ *     I, Thomas Davis, provide no warranty for any of this software. 
+ *     This material is provided "AS-IS" and at no charge.
  *
  ********************************************************************/
 
 #include <linux/kernel.h>
 #include <linux/skbuff.h>
 
-void irlpt_server_do_event( struct irlpt_cb *self,  IRLPT_EVENT event, 
-                           struct sk_buff *skb, struct irlpt_info *info);
-void irlpt_server_next_state( struct irlpt_cb *self, IRLPT_SERVER_STATE state);
+void irlpt_server_do_event( struct irlpt_cb *self, 
+                           IRLPT_EVENT event, 
+                           struct sk_buff *skb, 
+                           struct irlpt_info *info);
+void irlpt_server_next_state( struct irlpt_cb *self, 
+                             IRLPT_SERVER_STATE state);
 
 #endif
index a2f5925723f031d7e4024c66de65968e7d82e4b2..52d49330affe497787ae04e8c9c6199ab772627d 100644 (file)
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Dec 15 13:58:52 1997
- * Modified at:   Tue Jan 12 14:56:11 1999
+ * Modified at:   Thu Feb 11 15:14:30 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  *
  *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
@@ -45,6 +45,7 @@ typedef enum {
        EVENT_IRLAN_STOP,
        EVENT_IRLPT_START,
        EVENT_IRLPT_STOP,
+/*     EVENT_IROBEX_INIT, */
        EVENT_IROBEX_START,
        EVENT_IROBEX_STOP,
        EVENT_IRDA_STOP,
@@ -190,7 +191,13 @@ typedef enum {
        LM_CONNECT_FAILURE,   /* Failed to establish IrLAP connection */
        LM_LAP_RESET,         /* IrLAP reset */
        LM_INIT_DISCONNECT,   /* Link Management initiated disconnect */
-} LM_REASON; /* FIXME: Just for now */
+       LM_LSAP_NOTCONN,      /* Data delivered on unconnected LSAP */
+       LM_NON_RESP_CLIENT,   /* Non responsive LM-MUX client */
+       LM_NO_AVAIL_CLIENT,   /* No available LM-MUX client */
+       LM_CONN_HALF_OPEN,    /* Connection is half open */
+       LM_BAD_SOURCE_ADDR,   /* Illegal source address (i.e 0x00) */
+} LM_REASON;
+#define LM_UNKNOWN 0xff       /* Unspecified disconnect reason */
 
 /*
  *  IrLMP character code values
@@ -214,16 +221,17 @@ typedef enum {
 struct discovery_t {
        QUEUE queue;              /* Must be first! */
 
-       __u32       saddr;        /* Which link the device was discovered */
-       __u32       daddr;        /* Remote device address */
-       LAP_REASON  condition;    /* More info about the discovery */
+       __u32      saddr;        /* Which link the device was discovered */
+       __u32      daddr;        /* Remote device address */
+       LAP_REASON condition;    /* More info about the discovery */
 
-       __u8        hint[2];      /* Discovery hint bits */
-       __u8        charset;
-       char        info[32];     /* Usually the name of the device */
-       __u8        info_len;     /* Length of device info field */
+       __u8       hint[2];      /* Discovery hint bits */
+       __u8       charset;
+       char       info[32];     /* Usually the name of the device */
+       __u8       info_len;     /* Length of device info field */
 
-       int         gen_addr_bit; /* Need to generate a new device address? */
+       int        gen_addr_bit; /* Need to generate a new device address? */
+       int        nslots;       /* Number of slots to use when discovering */
 };
 
 typedef enum { FLOW_STOP, FLOW_START } LOCAL_FLOW;
@@ -254,12 +262,14 @@ struct notify_t {
 int irmod_init_module(void);
 void irmod_cleanup_module(void);
 
-inline int irda_lock( int *lock);
-inline int irda_unlock( int *lock);
+inline int irda_lock(int *lock);
+inline int irda_unlock(int *lock);
 
-void irda_notify_init( struct notify_t *notify);
+void irda_notify_init(struct notify_t *notify);
 
-void irda_execute_as_process( void *self, TODO_CALLBACK callback, __u32 param);
-void irmanager_notify( struct irmanager_event *event);
+void irda_execute_as_process(void *self, TODO_CALLBACK callback, __u32 param);
+void irmanager_notify(struct irmanager_event *event);
+
+extern void irda_proc_modcount(struct inode *, int);
 
 #endif
index 8f69707d01a6615a533538ed80f01f9fa07193c4..b07da06abe82eac902aaeb04951b22ee29768ccc 100644 (file)
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      irobex.h
- * Version:       
+ * Version:       0.8
  * Description:   
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Jul  4 22:43:57 1998
- * Modified at:   Wed Jan 13 15:55:28 1999
+ * Modified at:   Tue Jan 26 11:49:55 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
@@ -28,7 +28,6 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/skbuff.h>
-/* #include <linux/netdevice.h> */
 #include <linux/miscdevice.h>
 
 #include <net/irda/timer.h>
@@ -97,30 +96,7 @@ struct irobex_cb {
        LOCAL_FLOW rx_flow;
 };
 
-int    irobex_init(void);
-void   irobex_cleanup(void);
-struct irobex_cb *irobex_open(void);
-void   irobex_close( struct irobex_cb *self);
-
-void irobex_discovery_indication( DISCOVERY *);
-
-void irobex_data_request( int handle, struct sk_buff *skb);
-void irobex_data_indication( void *instance, void *sap, struct sk_buff *skb);
-void irobex_control_data_indication( void *instance, void *sap, 
-                                    struct sk_buff *skb);
-
-void irobex_connect_request( struct irobex_cb *self);
-void irobex_connect(struct irobex_cb *self, struct sk_buff *skb);
-void irobex_connect_confirm( void *instance, void *sap, struct qos_info *qos,
-                            int max_sdu_size, struct sk_buff *skb);
-void irobex_disconnect_indication( void *instance, void *sap, LM_REASON reason,
-                                  struct sk_buff *skb);
-void irobex_flow_indication( void *instance, void *sap, LOCAL_FLOW flow);
-
-void irobex_extract_params( struct sk_buff *skb);
-void irobex_get_value_confirm(__u16 obj_id, struct ias_value *value, 
-                             void *priv);
-void irobex_register_server( struct irobex_cb *self);
+int irobex_init(void);
 
 void irobex_watchdog_timer_expired( unsigned long data);
 
index 02a486dd54c34df90ab406bbdb33558769800ea1..4b75d8fa654f79473c3c8d8ec8cdb8e778105bc4 100644 (file)
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      irttp.h
- * Version:       0.3
+ * Version:       1.0
  * Description:   Tiny Transport Protocol (TTP) definitions
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 31 20:14:31 1997
- * Modified at:   Sat Dec  5 13:48:12 1998
+ * Modified at:   Tue Feb  2 10:55:18 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
 #include <net/irda/qos.h>
 #include <net/irda/irqueue.h>
 
-#define TTP_MAX_CONNECTIONS   LM_MAX_CONNECTIONS
-#define TTP_HEADER            1
-#define TTP_HEADER_WITH_SAR   6
-#define TTP_PARAMETERS        0x80
-#define TTP_MORE              0x80
+#define TTP_MAX_CONNECTIONS    LM_MAX_CONNECTIONS
+#define TTP_HEADER             1
+#define TTP_HEADER_WITH_SAR    6
+#define TTP_PARAMETERS         0x80
+#define TTP_MORE               0x80
 
 #define DEFAULT_INITIAL_CREDIT 22
 
-#define LOW_THRESHOLD  4
-#define HIGH_THRESHOLD 8
-#define TTP_MAX_QUEUE 22
+#define LOW_THRESHOLD   4
+#define HIGH_THRESHOLD  8
+#define TTP_MAX_QUEUE  22
 
 /* Some priorities for disconnect requests */
-#define P_NORMAL 0
-#define P_HIGH 1
+#define P_NORMAL    0
+#define P_HIGH      1
 
 #define SAR_DISABLE 0
 
  *  connection.
  */
 struct tsap_cb {
-       QUEUE queue;         /* For linking it into the hashbin */
-       int  magic;          /* Just in case */
+       QUEUE queue;          /* For linking it into the hashbin */
+       int  magic;           /* Just in case */
 
-       int max_seg_size;    /* Max data that fit into an IrLAP frame */
+       int max_seg_size;     /* Max data that fit into an IrLAP frame */
 
-       __u8 stsap_sel;      /* Source TSAP */
-       __u8 dtsap_sel;      /* Destination TSAP */
+       __u8 stsap_sel;       /* Source TSAP */
+       __u8 dtsap_sel;       /* Destination TSAP */
 
        struct lsap_cb *lsap; /* Corresponding LSAP to this TSAP */
 
@@ -85,8 +85,8 @@ struct tsap_cb {
        struct irda_statistics stats;
        struct timer_list todo_timer; 
        
-       int rx_sdu_busy;   /* RxSdu.busy */
-       int rx_sdu_size;   /* The current size of a partially received frame */
+       int rx_sdu_busy;     /* RxSdu.busy */
+       int rx_sdu_size;     /* Current size of a partially received frame */
        int rx_max_sdu_size; /* Max receive user data size */
 
        int tx_sdu_busy;     /* TxSdu.busy */
@@ -94,7 +94,8 @@ struct tsap_cb {
 
         int no_defrag;       /* Don't reassemble received fragments */
 
-       int disconnect_pend;   /* Disconnect, but still data to send */
+       int close_pend;      /* Close, but disconnect_pend */
+       int disconnect_pend; /* Disconnect, but still data to send */
        struct sk_buff *disconnect_skb;
 };
 
@@ -107,30 +108,41 @@ struct irttp_cb {
 int  irttp_init(void);
 void irttp_cleanup(void);
 
-struct tsap_cb *irttp_open_tsap( __u8 stsap, int credit, 
-                                struct notify_t *notify);
-void irttp_close_tsap( struct tsap_cb *self);
+struct tsap_cb *irttp_open_tsap(__u8 stsap_sel, int credit, 
+                               struct notify_t *notify);
+int irttp_close_tsap(struct tsap_cb *self);
 
-int  irttp_data_request( struct tsap_cb *self, struct sk_buff *skb);
-int  irttp_udata_request( struct tsap_cb *self, struct sk_buff *skb);
+int irttp_data_request(struct tsap_cb *self, struct sk_buff *skb);
+int irttp_udata_request(struct tsap_cb *self, struct sk_buff *skb);
 
-void irttp_connect_request( struct tsap_cb *self, __u8 dtsap_sel, __u32 daddr,
-                           struct qos_info *qos, int max_sdu_size, 
+void irttp_connect_request(struct tsap_cb *self, __u8 dtsap_sel, 
+                          __u32 saddr, __u32 daddr,
+                          struct qos_info *qos, int max_sdu_size, 
+                          struct sk_buff *userdata);
+void irttp_connect_confirm(void *instance, void *sap, struct qos_info *qos, 
+                          int max_sdu_size, struct sk_buff *skb);
+void irttp_connect_response(struct tsap_cb *self, int max_sdu_size, 
                            struct sk_buff *userdata);
-void irttp_connect_confirm( void *instance, void *sap, struct qos_info *qos, 
-                           int max_sdu_size, struct sk_buff *skb);
-void irttp_connect_response( struct tsap_cb *self, int max_sdu_size, 
-                            struct sk_buff *userdata);
 
-void irttp_disconnect_request( struct tsap_cb *self, struct sk_buff *skb,
-                              int priority);
-void irttp_flow_request( struct tsap_cb *self, LOCAL_FLOW flow);
+void irttp_disconnect_request(struct tsap_cb *self, struct sk_buff *skb,
+                             int priority);
+void irttp_flow_request(struct tsap_cb *self, LOCAL_FLOW flow);
 
-static __inline__ void irttp_no_reassemble( struct tsap_cb *self)
+static __inline__ void irttp_no_reassemble(struct tsap_cb *self)
 {
        self->no_defrag = TRUE;
 }
 
+static __inline __u32 irttp_get_saddr(struct tsap_cb *self)
+{
+       return irlmp_get_saddr(self->lsap);
+}
+
+static __inline __u32 irttp_get_daddr(struct tsap_cb *self)
+{
+       return irlmp_get_daddr(self->lsap);
+}
+
 extern struct irttp_cb *irttp;
 
 #endif /* IRTTP_H */
index 313a32d9b3ebb28efd09e8dde1bcf765471ea769..920909600e54f3051d68b095c92d096beece9051 100644 (file)
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      irtty.h
- * Version:       0.1
+ * Version:       1.0
  * Description:   
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Dec  9 21:13:12 1997
- * Modified at:   Mon Dec 14 11:22:37 1998
+ * Modified at:   Sun Feb  7 01:57:33 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  *  
  *     Copyright (c) 1997 Dag Brattli, All Rights Reserved.
@@ -65,4 +65,6 @@ struct irtty_cb {
 int irtty_register_dongle( struct dongle *dongle);
 void irtty_unregister_dongle( struct dongle *dongle);
 
+void irtty_set_dtr_rts(struct tty_struct *tty, int dtr, int rts);
+
 #endif
index ed47bdc1b94ac490d320ce95a44ea94f4bc1ded6..8be4feea1a2b6fc140cbd3f8c5f6b687bbe45305 100644 (file)
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Fri Nov 13 14:37:40 1998
- * Modified at:   Thu Dec 10 19:58:20 1998
+ * Modified at:   Mon Jan 25 23:10:25 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>
 #define FRM_ST_MAX_LEN  0x10 /* Max frame len exceeded */
 #define FRM_ST_PHY_ERR  0x08 /* Physical layer error */
 #define FRM_ST_BAD_CRC  0x04 
-#define FRM_ST_OVR2     0x02 /* Receive overrun */
-#define FRM_ST_OVR1     0x01 /* Frame status FIFO overrun */
+#define FRM_ST_OVR1     0x02 /* Receive overrun */
+#define FRM_ST_OVR2     0x01 /* Frame status FIFO overrun */
 
 #define RFLFL           0x06
 #define RFLFH           0x07
index 35a5be2604af391d29d9f5d5ae53c67fe9eba540..39719b5e3a6e4e2bb98e2c033d19157a0782e65f 100644 (file)
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Aug 16 00:59:29 1997
- * Modified at:   Mon Nov  2 14:31:55 1998
+ * Modified at:   Thu Feb  4 11:05:24 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997, 1998 Dag Brattli <dagb@cs.uit.no>, 
 #ifndef TIMER_H
 #define TIMER_H
 
-#include "irda.h"
-#include "irmod.h"
-#include "irlap.h"
-#include "irlmp.h"
-#include "irda_device.h"
+#include <net/irda/irda.h>
+#include <net/irda/irmod.h>
+#include <net/irda/irlap.h>
+#include <net/irda/irlmp.h>
+#include <net/irda/irda_device.h>
 
 /* 
  *  Timeout definitions, some defined in IrLAP p. 92
@@ -53,7 +53,6 @@
 #define QUERY_TIMEOUT          100
 
 #define WATCHDOG_TIMEOUT      2000                /* 20 sec */
-#define RETRY_TIMEOUT           51
 
 typedef void (*TIMER_CALLBACK)( unsigned long);
 
@@ -69,8 +68,10 @@ inline void irlap_start_backoff_timer( struct irlap_cb *self, int timeout);
 inline void irda_device_start_mbusy_timer( struct irda_device *self);
 
 struct lsap_cb;
+struct lap_cb;
 inline void irlmp_start_watchdog_timer( struct lsap_cb *, int timeout);
-inline void irlmp_start_discovery_timer( struct irlmp_cb *, int timeout); 
+inline void irlmp_start_discovery_timer( struct irlmp_cb *, int timeout);
+inline void irlmp_start_idle_timer(struct lap_cb *, int timeout);
 
 struct irobex_cb;
 inline void irobex_start_watchdog_timer( struct irobex_cb *, int timeout);
index 838713f31fbc14f0347b46a20f710db170bcdf33..ca21ebec51234808ab4cfa4f4db81920973a852a 100644 (file)
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      wrapper.h
- * Version:       
+ * Version:       1.0
  * Description:   IrDA Wrapper layer
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Thu Nov 19 13:17:56 1998
+ * Modified at:   Fri Jan 29 10:15:46 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
@@ -28,7 +28,7 @@
 #include <linux/types.h>
 #include <linux/skbuff.h>
 
-#include "irda_device.h"
+#include <net/irda/irda_device.h>
 
 #define BOF  0xc0 /* Beginning of frame */
 #define XBOF 0xff
@@ -40,9 +40,6 @@
 
 #define IR_TRANS 0x20    /* Asynchronous transparency modifier */       
 
-#define SOP BOF  /* Start of */
-#define EOP EOF  /* End of */
-
 enum {
        OUTSIDE_FRAME = 1, 
        BEGIN_FRAME, 
index 7bdb5d57a8e1540d45918630e6e4f92951ee2ede..9caf66fca8148b6ba0f068881099cc63767a9608 100644 (file)
@@ -1334,8 +1334,6 @@ int generic_file_mmap(struct file * file, struct vm_area_struct * vma)
        if (!inode->i_op || !inode->i_op->readpage)
                return -ENOEXEC;
        UPDATE_ATIME(inode);
-       vma->vm_file = file;
-       file->f_count++;
        vma->vm_ops = ops;
        return 0;
 }
index 9a9146754699451a26bfc601f6a3dbd6fb1ebbff..b5a4817df886e2d6616a8af953a23112b38e17b4 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -319,6 +319,8 @@ unsigned long do_mmap(struct file * file, unsigned long addr, unsigned long len,
                        file->f_dentry->d_inode->i_writecount++;
                if (error)
                        goto unmap_and_free_vma;
+               vma->vm_file = file;
+               file->f_count++;
        }
 
        /*
index dd66701b53d73526053a2d0777d0c1dc43485285..42ca4900aeedf3c6dd57df0c1722b53db5645e81 100644 (file)
@@ -556,7 +556,7 @@ asmlinkage int sys_swapon(const char * specialfile, int swap_flags)
                for (i = 0 ; i < nr_swapfiles ; i++) {
                        if (i == type)
                                continue;
-                       if (p->swap_file == swap_info[i].swap_file)
+                       if (swap_dentry->d_inode == swap_info[i].swap_file->d_inode)
                                goto bad_swap;
                }
        } else
@@ -701,6 +701,8 @@ bad_swap_2:
        p->swap_map = NULL;
        p->swap_lockmap = NULL;
        p->flags = 0;
+       if (!(swap_flags & SWAP_FLAG_PREFER))
+               ++least_priority;
 out:
        if (swap_header)
                free_page((long) swap_header);
index 6e0971c7af4238c155ed56036aa95901db3b0462..d6869098d4ff47bb3b1d8963dc0a212d4996d8fa 100644 (file)
@@ -128,7 +128,7 @@ endif
 ifeq ($(CONFIG_IRDA),y)
 SUB_DIRS += irda
 # There might be some irda features that are compiled as modules
-MOD_SUB_DIRS += irda
+MOD_IN_SUB_DIRS += irda
 else
   ifeq ($(CONFIG_IRDA),m)
   MOD_SUB_DIRS += irda
index f9392fe34527b779acc6eb03286a0ab65dd0675f..a2ad7111f9298bd54c1c9f630bdf20bb2347cfa5 100644 (file)
@@ -957,7 +957,7 @@ static int ax25_release(struct socket *sock, struct socket *peer)
                                                ax25_stop_t3timer(sk->protinfo.ax25);
                                                ax25_stop_idletimer(sk->protinfo.ax25);
                                                break;
-#ifdef AX25_CONFIG_DAMA_SLAVE
+#ifdef CONFIG_AX25_DAMA_SLAVE
                                        case AX25_PROTO_DAMA_SLAVE:
                                                ax25_stop_t3timer(sk->protinfo.ax25);
                                                ax25_stop_idletimer(sk->protinfo.ax25);
index 9a18af09a96a4536ebde8fbc9bce8f4c2f142416..996aeb7180b3b129d0230d591c92a90ea05facf2 100644 (file)
@@ -6,7 +6,7 @@
  *     More hacks to be able to switch protocols on and off by Christoph Lameter
  *     <clameter@debian.org>
  *     Software and more Documentation for the bridge is available from ftp.debian.org
- *     in the bridge package or at ftp.fuller.edu/Linux/bridge
+ *     in the bridgex package
  *
  *     This program is free software; you can redistribute it and/or
  *     modify it under the terms of the GNU General Public License
@@ -63,7 +63,6 @@
 #include <linux/net.h>
 #include <linux/inet.h>
 #include <linux/netdevice.h>
-#include <linux/string.h>
 #include <linux/skbuff.h>
 #include <linux/if_arp.h>
 #include <linux/ip.h>
@@ -1239,11 +1238,12 @@ static int send_config_bpdu(int port_no, Config_bpdu *config_bpdu)
        struct sk_buff *skb;
        
        /*
-        *      Keep silent when disabled
+        *      Keep silent when disabled or when STP disabled
         */
         
-       if(!(br_stats.flags & BR_UP))
+       if(!(br_stats.flags & BR_UP) || (br_stats.flags & BR_STP_DISABLED))
                return -1;
+
        /*
         *      Create and send the message
         */
@@ -1278,10 +1278,10 @@ static int send_tcn_bpdu(int port_no, Tcn_bpdu *bpdu)
        struct sk_buff *skb;
        
        /*
-        *      Keep silent when disabled
+        *      Keep silent when disabled or when STP disabled
         */
         
-       if(!(br_stats.flags & BR_UP))
+       if(!(br_stats.flags & BR_UP) || (br_stats.flags & BR_STP_DISABLED))
                return -1;
        
        
@@ -1350,13 +1350,25 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v
                                                        enable_port(i);
                                                set_path_cost(i, br_port_cost(dev));
                                                set_port_priority(i); 
-                                               make_forwarding(i);
+                                               if (br_stats.flags & BR_STP_DISABLED)
+                                                       port_info[i].state = Forwarding;
+                                               else
+                                                       make_forwarding(i);
                                        }
                                        return NOTIFY_DONE;
                                        break;
                                }
                        }
                        break;
+               case NETDEV_UNREGISTER:
+                       if (br_stats.flags & BR_DEBUG)
+                               printk(KERN_DEBUG "br_device_event: NETDEV_UNREGISTER...\n");
+                        i = find_port(dev);
+                        if (i > 0) {
+                               br_avl_delete_by_port(i);
+                               port_info[i].dev = NULL;
+                       }
+                       break;
        }
        return NOTIFY_DONE;
 }
@@ -1847,6 +1859,8 @@ static int find_port(struct device *dev)
  
 static int br_port_cost(struct device *dev)    /* 4.10.2 */
 {
+       if (strncmp(dev->name, "lec", 3) == 0)  /* ATM Lan Emulation (LANE) */
+               return(7);                      /* 155 Mbs */
        if (strncmp(dev->name, "eth", 3) == 0)  /* ethernet */
                return(100);
        if (strncmp(dev->name, "plip",4) == 0) /* plip */
@@ -1864,7 +1878,8 @@ static void br_bpdu(struct sk_buff *skb, int port) /* consumes skb */
        Tcn_bpdu *bpdu = (Tcn_bpdu *) (bufp + BRIDGE_LLC1_HS);
        Config_bpdu rcv_bpdu;
 
-       if((*bufp++ == BRIDGE_LLC1_DSAP) && (*bufp++ == BRIDGE_LLC1_SSAP) &&
+       if(!(br_stats.flags & BR_STP_DISABLED) &&
+               (*bufp++ == BRIDGE_LLC1_DSAP) && (*bufp++ == BRIDGE_LLC1_SSAP) &&
                (*bufp++ == BRIDGE_LLC1_CTRL) &&
                (bpdu->protocol_id == BRIDGE_BPDU_8021_PROTOCOL_ID) &&
                (bpdu->protocol_version_id == BRIDGE_BPDU_8021_PROTOCOL_VERSION_ID)) 
@@ -1984,6 +1999,10 @@ int br_ioctl(unsigned int cmd, void *arg)
                                                }
                                        }
                                        port_state_selection();   /* (4.8.1.5)   */
+                                       if (br_stats.flags & BR_STP_DISABLED)
+                                               for(i=One;i<=No_of_ports; i++)
+                                                       if((user_port_state[i] != Disabled) && port_info[i].dev)
+                                                               port_info[i].state = Forwarding;
                                        config_bpdu_generation();  /* (4.8.1.6)  */
                                        /* initialize system timer */
                                        tl.expires = jiffies+HZ;        /* 1 second */
@@ -2001,6 +2020,20 @@ int br_ioctl(unsigned int cmd, void *arg)
                                                if (port_info[i].state != Disabled)
                                                        disable_port(i);
                                        break;
+                               case BRCMD_TOGGLE_STP:
+                                       printk(KERN_DEBUG "br: %s spanning tree protcol\n",
+                                              (br_stats.flags & BR_STP_DISABLED) ? "enabling" : "disabling");
+                                       if (br_stats.flags & BR_STP_DISABLED) { /* enable STP */
+                                               for(i=One;i<=No_of_ports; i++)
+                                                       if((user_port_state[i] != Disabled) && port_info[i].dev)
+                                                               enable_port(i);
+                                       } else { /* STP was enabled, now disable it */
+                                               for (i = One; i <= No_of_ports; i++)
+                                                       if (port_info[i].state != Disabled && port_info[i].dev)
+                                                               port_info[i].state = Forwarding;
+                                       }
+                                       br_stats.flags ^= BR_STP_DISABLED;
+                                       break;
                                case BRCMD_PORT_ENABLE:
                                        if (port_info[bcf.arg1].dev == 0)
                                                return(-EINVAL);
index 0936a0f8b6b0f3b5a488dd5a0f5ba728a461a508..c1ed82f10875a52e7382d6710f8c34611a2c10de 100644 (file)
@@ -474,3 +474,27 @@ void sprintf_avl (char **pbuffer, struct fdb * tree, off_t *pos,
 
        return;
 }
+
+/*
+ * Delete all nodes learnt by the port
+ */
+void br_avl_delete_by_port(int port)
+{
+        struct fdb *fdb, *next;
+
+       if (!fdb_inited)
+               fdb_init();
+
+        for(fdb = port_info[port].fdb; fdb != NULL; fdb = next) {
+                next = fdb->fdb_next;
+                br_avl_remove(fdb);
+        }
+        port_info[port].fdb = NULL;
+
+        /* remove the local mac too */
+        next = br_avl_find_addr(port_info[port].dev->dev_addr);
+        if (next != NULL)
+                br_avl_remove(next);
+
+        return;
+}
index c28da7ebbd76a91c4c53428d7c8a663fcd39c2bc..48c7b79d8a2bb2e5583cc70665fda0631ba51efe 100644 (file)
@@ -27,7 +27,6 @@
 #include <asm/uaccess.h>
 
 #include <linux/inet.h>
-#include <linux/netdevice.h>
 #include <net/ip.h>
 #include <net/protocol.h>
 #include <net/rarp.h>
index b40bc8f82f06c5ee9c743c84cca65cd729e9a5fe..b76364371fb40df3e53a6d122c550bf6f7ef4b67 100644 (file)
@@ -4,7 +4,7 @@
  *     Authors:        Alan Cox <iiitac@pyr.swan.ac.uk>
  *                     Florian La Roche <rzsfl@rz.uni-sb.de>
  *
- *     Version:        $Id: skbuff.c,v 1.54 1998/09/15 02:11:09 davem Exp $
+ *     Version:        $Id: skbuff.c,v 1.55 1999/02/23 08:12:27 davem Exp $
  *
  *     Fixes:  
  *             Alan Cox        :       Fixed the worst of the load balancer bugs.
index 381ee8be416e7379086e59e4d9a3892791e6a4fb..fd9c6f9424a7577b93ab9fb9efd9e43b63080883 100644 (file)
@@ -7,7 +7,7 @@
  *             handler for protocols to use and generic option handler.
  *
  *
- * Version:    $Id: sock.c,v 1.75 1998/11/07 10:54:38 davem Exp $
+ * Version:    $Id: sock.c,v 1.76 1999/02/23 08:12:29 davem Exp $
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
index 8a3a72ae7eaa8de494cad0ca3dd76e8e7473bcdd..8930109b37a02300026362774aa8bccc6cda000f 100644 (file)
@@ -44,7 +44,6 @@
 #include <net/udp.h>
 #include <net/ip.h>
 #include <asm/spinlock.h>
-#include <linux/inetdevice.h>
 
 static struct proto_ops econet_ops;
 static struct sock *econet_sklist;
index 8e4b3945eafa16c66676752cc0c7131f13423484..43334d5bd089588b283566b85308e5212edbe8b6 100644 (file)
@@ -78,7 +78,6 @@ comment '(it is safe to leave these untouched)'
 tristate 'IP: Reverse ARP' CONFIG_INET_RARP
 #bool 'IP: Path MTU Discovery (normally enabled)' CONFIG_PATH_MTU_DISCOVERY
 #bool 'IP: Disable NAGLE algorithm (normally enabled)' CONFIG_TCP_NAGLE_OFF
-bool 'IP: Drop source routed frames' CONFIG_IP_NOSR
 bool 'IP: Allow large windows (not recommended if <16Mb of memory)' CONFIG_SKB_LARGE
 #if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then 
 #bool 'IP: support experimental checksum copy to user for UDP'  CONFIG_UDP_DELAY_CSUM
index efb16cc473da7c73d20d54d91c5c78a213f9710d..0af02ef51c453c3352f857dc7cec16d5c46c0435 100644 (file)
@@ -557,6 +557,19 @@ int arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
                if (htons(dev_type) != arp->ar_hrd)
                        goto out;
                break;
+#ifdef CONFIG_NET_ETHERNET
+       case ARPHRD_ETHER:
+               /*
+                * ETHERNET devices will accept ARP hardware types of either
+                * 1 (Ethernet) or 6 (IEEE 802.2).
+                */
+               if (arp->ar_hrd != __constant_htons(ARPHRD_ETHER) &&
+                   arp->ar_hrd != __constant_htons(ARPHRD_IEEE802))
+                       goto out;
+               if (arp->ar_pro != __constant_htons(ETH_P_IP))
+                       goto out;
+               break;
+#endif
 #ifdef CONFIG_FDDI
        case ARPHRD_FDDI:
                /*
index 544dd8937ce55cf9e3ed8fdd3d14e2b6838f4ab3..c21eed8faa19fefa8108c3d54664e882447689fc 100644 (file)
@@ -3,7 +3,7 @@
  *     
  *             Alan Cox, <alan@cymru.net>
  *
- *     Version: $Id: icmp.c,v 1.48 1999/01/02 16:51:41 davem Exp $
+ *     Version: $Id: icmp.c,v 1.49 1999/02/23 08:12:37 davem Exp $
  *
  *     This program is free software; you can redistribute it and/or
  *     modify it under the terms of the GNU General Public License
index 8378c2b03e90d05c03918823d271db869f16fbab..98b83adab205783f41b87fd8fe29acf30625b051 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:    $Id: tcp.c,v 1.135 1999/02/22 13:54:21 davem Exp $
+ * Version:    $Id: tcp.c,v 1.136 1999/03/07 13:26:01 davem Exp $
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -1070,6 +1070,7 @@ static void cleanup_rbuf(struct sock *sk, int copied)
        if(copied > 0) {
                struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
                __u32 rcv_window_now = tcp_receive_window(tp);
+               __u32 new_window = __tcp_select_window(sk);
 
                /* We won't be raising the window any further than
                 * the window-clamp allows.  Our window selection
@@ -1077,7 +1078,7 @@ static void cleanup_rbuf(struct sock *sk, int copied)
                 * checks are necessary to prevent spurious ACKs
                 * which don't advertize a larger window.
                 */
-               if((copied >= rcv_window_now) &&
+               if((new_window && (new_window >= rcv_window_now * 2)) &&
                   ((rcv_window_now + tp->mss_cache) <= tp->window_clamp))
                        tcp_read_wakeup(sk);
        }
index c93a874db5f5027ab13eada41d801e611a331f2e..3a2d398072987871e0739115ed0f46d0ae731d84 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:    $Id: tcp_input.c,v 1.156 1999/02/22 13:54:13 davem Exp $
+ * Version:    $Id: tcp_input.c,v 1.157 1999/03/05 09:35:06 davem Exp $
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -241,8 +241,8 @@ extern __inline__ void tcp_replace_ts_recent(struct sock *sk, struct tcp_opt *tp
 extern __inline__ int tcp_paws_discard(struct tcp_opt *tp, struct tcphdr *th, unsigned len)
 {
        /* ts_recent must be younger than 24 days */
-       return (((jiffies - tp->ts_recent_stamp) >= PAWS_24DAYS) ||
-               (((s32)(tp->rcv_tsval-tp->ts_recent) < 0) &&
+       return (((s32)(jiffies - tp->ts_recent_stamp) >= PAWS_24DAYS) ||
+               (((s32)(tp->rcv_tsval - tp->ts_recent) < 0) &&
                 /* Sorry, PAWS as specified is broken wrt. pure-ACKs -DaveM */
                 (len != (th->doff * 4))));
 }
index b8b23eb384397acdb5cfe8ea5a613ffa49566e84..0522d872eca872cf73df8796d5a030c007521689 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:    $Id: tcp_ipv4.c,v 1.165 1999/02/08 11:19:56 davem Exp $
+ * Version:    $Id: tcp_ipv4.c,v 1.166 1999/02/23 08:12:41 davem Exp $
  *
  *             IPv4 specific functions
  *
index 03c96e99c8707d5834cca9be6285fc82023cce13..83a05302eb6034dbe243a52dc4dd28da57ad4e85 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:    $Id: tcp_output.c,v 1.102 1999/02/22 13:54:26 davem Exp $
+ * Version:    $Id: tcp_output.c,v 1.104 1999/03/07 13:26:04 davem Exp $
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -580,6 +580,18 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
        if(tp->af_specific->rebuild_header(sk))
                return 1; /* Routing failure or similar. */
 
+       /* Some Solaris stacks overoptimize and ignore the FIN on a
+        * retransmit when old data is attached.  So strip it off
+        * since it is cheap to do so and saves bytes on the network.
+        */
+       if(skb->len > 0 &&
+          (TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN) &&
+          tp->snd_una == (TCP_SKB_CB(skb)->end_seq - 1)) {
+               TCP_SKB_CB(skb)->seq = TCP_SKB_CB(skb)->end_seq - 1;
+               skb_trim(skb, 0);
+               skb->csum = 0;
+       }
+
        /* Ok, we're gonna send it out, update state. */
        TCP_SKB_CB(skb)->sacked |= TCPCB_SACKED_RETRANS;
        tp->retrans_out++;
@@ -592,6 +604,7 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
                skb = skb_copy(skb, GFP_ATOMIC);
        else
                skb = skb_clone(skb, GFP_ATOMIC);
+
        tcp_transmit_skb(sk, skb);
 
        /* Update global TCP statistics and return success. */
index 00d9b099e741957b1b10eb392bda6882b2ada820..81871e5ea09c643af549da0f4063e41a79da6131 100644 (file)
@@ -5,7 +5,7 @@
  *     Authors:
  *     Pedro Roque             <roque@di.fc.ul.pt>     
  *
- *     $Id: tcp_ipv6.c,v 1.95 1999/02/08 11:20:03 davem Exp $
+ *     $Id: tcp_ipv6.c,v 1.96 1999/03/05 13:23:13 davem Exp $
  *
  *     Based on: 
  *     linux/net/ipv4/tcp.c
@@ -1238,7 +1238,6 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
                        goto reset;
                if (users)
                        goto ipv6_pktoptions;
-               release_sock(sk);
                return 0;
        }
 
index 4af71d35f667ce2ad5dd12b7a1e5110e7bdd2672..495614172cbb80e17e9dfe5e5b53ef8fc5a1a94b 100644 (file)
 ALL_SUB_DIRS := irlan ircomm irlpt compressors
 SUB_DIRS :=
 MOD_SUB_DIRS :=
+OX_OBJS :=
 
 O_TARGET := irda.o
-O_OBJS  := irmod.o iriap.o iriap_event.o irlmp.o irlmp_event.o irlmp_frame.o \
+O_OBJS  := iriap.o iriap_event.o irlmp.o irlmp_event.o irlmp_frame.o \
             irlap.o irlap_event.o irlap_frame.o timer.o qos.o irqueue.o \
             irttp.o irda_device.o irias_object.o crc.o wrapper.o af_irda.o
+OX_OBJS := irmod.o
+
 MOD_LIST_NAME := IRDA_MODULES
+
+ifeq ($(CONFIG_IRDA),m)
 M_OBJS   := $(O_TARGET)
+endif
 
 ifeq ($(CONFIG_IRDA_COMPRESSION),y)
 O_OBJS += irlap_comp.o
index 85c191b29a5ebf1abe56fd684e54ec348c08ce97..67e102a240e09c65979df6ab6cbdf07e6a861792 100644 (file)
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun May 31 10:12:43 1998
- * Modified at:   Thu Jan 14 13:42:16 1999
+ * Modified at:   Sat Feb 20 01:31:15 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Sources:       af_netroom.c, af_ax25.x
  * 
  *     
  ********************************************************************/
 
+#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/socket.h>
 #include <linux/sockios.h>
+#include <linux/init.h>
+#include <linux/if_arp.h>
+#include <linux/net.h>
+
+#include <asm/uaccess.h>
+
 #include <net/sock.h>
-#include <asm/segment.h>
 
 #include <net/irda/irda.h>
 #include <net/irda/irmod.h>
@@ -37,8 +43,12 @@ extern int irda_init(void);
 extern void irda_cleanup(void);
 extern int irlap_input(struct sk_buff *, struct device *, struct packet_type *);
 
+static struct proto_ops irda_proto_ops;
+
 #define IRDA_MAX_HEADER (TTP_HEADER+LMP_HEADER+LAP_HEADER)
 
+#define IRDA_SOCKETS
+
 #ifdef IRDA_SOCKETS
 
 /*
@@ -55,120 +65,6 @@ static int irda_getname( struct socket *sock, struct sockaddr *uaddr,
        return 0;
 }
 
-/*
- * Function irda_sendmsg (sock, msg, len, noblock, flags)
- *
- *    
- *
- */
-static int irda_sendmsg( struct socket *sock, struct msghdr *msg, int len, 
-                        int noblock, int flags)
-{
-#if 0
-       struct sock *sk = (struct sock *) sock->data;
-       /* struct sockaddr_irda *usax = (struct sockaddr_irda *)msg->msg_name; */
-       int err;
-       struct sk_buff *skb;
-       unsigned char *asmptr;
-       int size;
-       struct tsap_cb *tsap;
-       
-       DEBUG( 0, __FUNCTION__ "()\n");
-
-       if (sk->err)
-               return sock_error(sk);
-
-       if (flags)
-               return -EINVAL;
-       
-       if (sk->zapped)
-               return -EADDRNOTAVAIL;
-       
-       if (sk->debug)
-               printk( "IrDA: sendto: Addresses built.\n");
-       
-       /* Build a packet */
-       if (sk->debug)
-               printk( "IrDA: sendto: building packet.\n");
-       
-       size = len + IRDA_MAX_HEADER;
-       
-       if ((skb = sock_alloc_send_skb(sk, size, 0, 0, &err)) == NULL)
-               return err;
-       
-       skb->sk   = sk;
-       skb->free = 1;
-       skb->arp  = 1;
-       
-       skb_reserve(skb, size - len);
-       
-       memcpy_fromiovec( asmptr, msg->msg_iov, len);
-       
-       if (sk->debug)
-               printk( "IrDA: Transmitting buffer\n");
-       
-        if (sk->state != TCP_ESTABLISHED) {
-                kfree_skb( skb, FREE_WRITE);
-               return -ENOTCONN;
-       }
-       
-       tsap = (struct tsap_cb *) sk->protinfo.irda;
-       ASSERT( tsap != NULL, return -ENODEV;);
-       ASSERT( tsap->magic == TTP_TSAP_MAGIC, return -EBADR;);
-       
-       irttp_data_request( tsap, skb);
-#endif 
-       return len;
-}
-
-/*
- * Function irda_recvmsg (sock, msg, size, noblock, flags, addr_len)
- *
- *    
- *
- */
-static int irda_recvmsg( struct socket *sock, struct msghdr *msg, int size, 
-                        int noblock, int flags, int *addr_len)
-{
-       int copied=0;
-#if 0
-       struct sock *sk = (struct sock *)sock->data;
-       struct sockaddr_irda *sax = (struct sockaddr_irda *)msg->msg_name;
-       struct sk_buff *skb;
-       int er;
-
-       DEBUG( 0, __FUNCTION__ "()\n");
-
-       if (sk->err)
-               return sock_error(sk);
-       
-       if (addr_len != NULL)
-               *addr_len = sizeof(*sax);
-
-       /*
-        * This works for seqpacket too. The receiver has ordered the queue for
-        * us! We do one quick check first though
-        */
-       if (sk->state != TCP_ESTABLISHED)
-               return -ENOTCONN;
-
-       /* Now we can treat all alike */
-       if ((skb = skb_recv_datagram( sk, flags, noblock, &er)) == NULL)
-               return er;
-
-/*     if (!sk->nr->hdrincl) { */
-/*             skb_pull(skb, NR_NETWORK_LEN + NR_TRANSPORT_LEN); */
-/*             skb->h.raw = skb->data; */
-/*     } */
-
-       copied = (size < skb->len) ? size : skb->len;
-       skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
-
-       skb_free_datagram(sk, skb);
-#endif
-       return copied;
-}
-
 /*
  * Function irda_listen (sock, backlog)
  *
@@ -177,52 +73,17 @@ static int irda_recvmsg( struct socket *sock, struct msghdr *msg, int size,
  */
 static int irda_listen( struct socket *sock, int backlog)
 {
-#if 0
-       struct sock *sk = (struct sock *)sock->data;
+       struct sock *sk = sock->sk;
 
-       if (sk->state != TCP_LISTEN) {
+       if (sk->type == SOCK_SEQPACKET && sk->state != TCP_LISTEN) {
                sk->max_ack_backlog = backlog;
                sk->state           = TCP_LISTEN;
                return 0;
-        }
-#endif
+       }
+
        return -EOPNOTSUPP;
 }
 
-/*
- * Function irda_bind (sock, uaddr, addr_len)
- *
- *    Bind to a specified TSAP
- *
- */
-static int irda_bind( struct socket *sock, struct sockaddr *uaddr, 
-                     int addr_len)
-{
-#if 0  
-       struct sock *sk;
-       struct full_sockaddr_irda *addr = (struct full_sockaddr_irda *)uaddr;
-       struct device *dev;
-        irda_address *user, *source;
-        struct tsap_cb *tsap;
-       struct notify_t notify;
-
-       DEBUG( 0, __FUNCTION__ "()\n");
-
-       sk = (struct sock *) sock->data;
-
-       if ( sk->zapped == 0)
-               return -EIO;
-       
-       irda_notify_init( &notify);
-       tsap = irttp_open_tsap( LSAP_ANY, DEFAULT_INITIAL_CREDIT, &notify);
-
-       sk->zapped = 0;
-
-       if (sk->debug)
-               printk("IrDA: socket is bound\n");
-#endif
-       return 0;
-}
 
 /*
  * Function irda_connect (sock, uaddr, addr_len, flags)
@@ -289,83 +150,6 @@ static int irda_connect( struct socket *sock, struct sockaddr *uaddr,
 #endif
        return 0;
 }
-       
-static int irda_socketpair( struct socket *sock1, struct socket *sock2)
-{
-       DEBUG( 0, __FUNCTION__ "(), Not implemented\n");
-
-       return -EOPNOTSUPP;
-}
-
-static int irda_accept(struct socket *sock, struct socket *newsock, int flags)
-{
-       struct sock *sk;
-       struct sock *newsk;
-       struct sk_buff *skb;
-
-       DEBUG( 0, __FUNCTION__ "()\n");
-#if 0
-       if (newsock->data)
-               sk_free(newsock->data);
-
-       newsock->data = NULL;
-       
-       sk = (struct sock *)sock->data;
-
-       if (sk->type != SOCK_SEQPACKET)
-               return -EOPNOTSUPP;
-       
-       if (sk->state != TCP_LISTEN)
-               return -EINVAL;
-               
-       /*
-        *      The write queue this time is holding sockets ready to use
-        *      hooked into the SABM we saved
-        */
-       do {
-               cli();
-               if ((skb = skb_dequeue(&sk->receive_queue)) == NULL) {
-                       if (flags & O_NONBLOCK) {
-                               sti();
-                               return 0;
-                       }
-                       interruptible_sleep_on(sk->sleep);
-                       if (current->signal & ~current->blocked) {
-                               sti();
-                               return -ERESTARTSYS;
-                       }
-               }
-       } while (skb == NULL);
-
-       newsk = skb->sk;
-       newsk->pair = NULL;
-       sti();
-
-       /* Now attach up the new socket */
-       skb->sk = NULL;
-       kfree_skb(skb, FREE_READ);
-       sk->ack_backlog--;
-       newsock->data = newsk;
-#endif
-       return 0;
-}
-
-static void def_callback1(struct sock *sk)
-{
-       DEBUG( 0, __FUNCTION__ "()\n");
-
-        if (!sk->dead)
-                wake_up_interruptible(sk->sleep);
-}
-
-static void def_callback2(struct sock *sk, int len)
-{
-       DEBUG( 0, __FUNCTION__ "()\n");
-
-        if (!sk->dead)
-                wake_up_interruptible(sk->sleep);
-}
-
 
 /*
  * Function irda_create (sock, protocol)
@@ -373,47 +157,42 @@ static void def_callback2(struct sock *sk, int len)
  *    Create IrDA socket
  *
  */
-static int irda_create( struct socket *sock, int protocol)
+static int irda_create(struct socket *sock, int protocol)
 {
        struct sock *sk;
 
        DEBUG( 0, __FUNCTION__ "()\n");
-#if 0
-       if (sock->type != SOCK_SEQPACKET || protocol != 0)
-               return -ESOCKTNOSUPPORT;
+
+       /* Compatibility */
+       if (sock->type == SOCK_PACKET) {
+               static int warned; 
+               if (net_families[PF_PACKET]==NULL)
+               {
+#if defined(CONFIG_KMOD) && defined(CONFIG_PACKET_MODULE)
+                       char module_name[30];
+                       sprintf(module_name,"net-pf-%d", PF_PACKET);
+                       request_module(module_name);
+                       if (net_families[PF_PACKET] == NULL)
+#endif
+                               return -ESOCKTNOSUPPORT;
+               }
+               if (!warned++)
+                       printk(KERN_INFO "%s uses obsolete (PF_INET,SOCK_PACKET)\n", current->comm);
+               return net_families[PF_PACKET]->create(sock, protocol);
+       }
+       
+/*     if (sock->type != SOCK_SEQPACKET || protocol != 0) */
+/*             return -ESOCKTNOSUPPORT; */
 
        /* Allocate socket */
-       if ((sk = sk_alloc( GFP_ATOMIC)) == NULL)
+       if ((sk = sk_alloc(PF_IRDA, GFP_ATOMIC, 1)) == NULL)
                return -ENOMEM;
+       
+       sock_init_data(sock, sk);
+
+       sock->ops    = &irda_proto_ops;
+       sk->protocol = protocol;
 
-       skb_queue_head_init(&sk->receive_queue);
-       skb_queue_head_init(&sk->write_queue);
-       skb_queue_head_init(&sk->back_log);
-
-       init_timer( &sk->timer);
-
-       sk->socket        = sock;
-       sk->type          = sock->type;
-       sk->protocol      = protocol;
-       sk->allocation    = GFP_KERNEL;
-       sk->rcvbuf        = SK_RMEM_MAX;
-       sk->sndbuf        = SK_WMEM_MAX;
-       sk->state         = TCP_CLOSE;
-       sk->priority      = SOPRI_NORMAL;
-       sk->mtu           = 2048; /* FIXME, insert the right size*/
-       sk->zapped        = 1;
-/*     sk->window        = nr_default.window; */
-
-       sk->state_change = def_callback1;
-       sk->data_ready   = def_callback2;
-       sk->write_space  = def_callback1;
-       sk->error_report = def_callback1;
-
-       if (sock != NULL) {
-               sock->data = (void *)sk;
-               sk->sleep  = sock->wait;
-       }
-#endif
        return 0;
 }
 
@@ -463,26 +242,32 @@ static int irda_release( struct socket *sock, struct socket *peer)
         return 0;
 }
 
-
-/*
- * Function irda_dup (newsock, oldsock)
- *
- *    
- *
- */
-static int irda_dup( struct socket *newsock, struct socket *oldsock)
+static int irda_recvmsg(struct socket *sock, struct msghdr *msg, int size,
+                       int flags, struct scm_cookie *scm)
 {
-#if 0
-        struct sock *sk = (struct sock *)oldsock->data;
+       struct sock *sk = sock->sk;
+       struct sk_buff *skb;
+       int copied, err;
 
-       DEBUG( 0, __FUNCTION__ "()\n");
+       DEBUG(0, __FUNCTION__ "()\n");
 
-        if (sk == NULL || newsock == NULL)
-                return -EINVAL;
+       skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, 
+                               flags & MSG_DONTWAIT, &err);
+       if (!skb)
+               return err;
 
-        return irda_create( newsock, sk->protocol);
-#endif
-       return 0;
+       skb->h.raw = skb->data;
+       copied     = skb->len;
+       
+       if (copied > size) {
+               copied = size;
+               msg->msg_flags |= MSG_TRUNC;
+       }
+       skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+
+       skb_free_datagram(sk, skb);
+
+       return copied;
 }
 
 static int irda_shutdown( struct socket *sk, int how)
@@ -497,7 +282,8 @@ static int irda_shutdown( struct socket *sk, int how)
 unsigned int irda_poll( struct file *file, struct socket *sock, 
                        struct poll_table_struct *wait)
 {
-       
+       DEBUG(0, __FUNCTION__ "()\n");
+       return 0;
 }
 
 /*
@@ -506,172 +292,114 @@ unsigned int irda_poll( struct file *file, struct socket *sock,
  *    
  *
  */
-static int irda_ioctl( struct socket *sock, unsigned int cmd, 
-                      unsigned long arg)
-{
-#if 0
-        struct sock *sk = (struct sock *) sock->data;
-        int err;
-
-       DEBUG( 0, __FUNCTION__ "(), Not implemented!\n");
-#endif
-       return 0;
-}
-
-static int irda_setsockopt( struct socket *sock, int level, int optname,
-                           char *optval, int optlen)
-{
-#if 0
-        struct sock *sk = (struct sock *)sock->data;
-        int err, opt;
-
-       DEBUG( 0, __FUNCTION__ "()\n");
-
-        if (level == SOL_SOCKET)
-                return sock_setsockopt(sk, level, optname, optval, optlen);
-
-        /* if (level != SOL_AX25) */
-/*                 return -EOPNOTSUPP; */
-
-        if (optval == NULL)
-                return -EINVAL;
-
-        if ((err = verify_area(VERIFY_READ, optval, sizeof(int))) != 0)
-                return err;
-
-        opt = get_fs_long((int *)optval);
-
-        switch (optname) {  
-       default:
-               return -ENOPROTOOPT;
-        }
-#endif
-       return -ENOPROTOOPT;
-}
-
-static int irda_getsockopt(struct socket *sock, int level, int optname,
-        char *optval, int *optlen)
+static int irda_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 {
-#if 0
-        struct sock *sk = (struct sock *)sock->data;
-        int val = 0;
-        int err;
+       struct sock *sk = sock->sk;
 
        DEBUG( 0, __FUNCTION__ "()\n");
-
-        if (level == SOL_SOCKET)
-                return sock_getsockopt(sk, level, optname, optval, optlen);
-
-        /* if (level != SOL_AX25) */
-/*                 return -EOPNOTSUPP; */
-
-        switch (optname) {
-       default:
-               return -ENOPROTOOPT;
-        }
        
-        if ((err = verify_area(VERIFY_WRITE, optlen, sizeof(int))) != 0)
-                return err;
-
-        put_user(sizeof(int), optlen);
+       switch (cmd) {
+       case TIOCOUTQ: {
+               long amount;
+               amount = sk->sndbuf - atomic_read(&sk->wmem_alloc);
+               if (amount < 0)
+                       amount = 0;
+               if (put_user(amount, (unsigned int *)arg))
+                       return -EFAULT;
+               return 0;
+       }
        
-        if ((err = verify_area(VERIFY_WRITE, optval, sizeof(int))) != 0)
-                return err;
-
-        put_user(val, (int *)optval);
-#endif
-        return 0;
-}
-
-static int irda_fcntl(struct socket *sock, unsigned int cmd, unsigned long arg)
-{
-       DEBUG( 0, __FUNCTION__ "()\n");
-
-        return -EINVAL;
-}
-/*
- * Function irda_rcv (skb, dev, dev_addr, ptype)
- *
- *    
- *
- */
-static int irda_rcv( struct sk_buff *skb, struct device *dev, 
-                    irda_address *dev_addr, struct packet_type *ptype)
-{
-       DEBUG( 0, __FUNCTION__ "()\n");
+       case TIOCINQ: {
+               struct sk_buff *skb;
+               long amount = 0L;
+               /* These two are safe on a single CPU system as only user tasks fiddle here */
+               if ((skb = skb_peek(&sk->receive_queue)) != NULL)
+                       amount = skb->len;
+               if (put_user(amount, (unsigned int *)arg))
+                       return -EFAULT;
+               return 0;
+       }
+       
+       case SIOCGSTAMP:
+               if (sk != NULL) {
+                       if (sk->stamp.tv_sec == 0)
+                               return -ENOENT;
+                       if (copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval)))
+                               return -EFAULT;
+                       return 0;
+               }
+               return -EINVAL;
+               
+       case SIOCGIFADDR:
+       case SIOCSIFADDR:
+       case SIOCGIFDSTADDR:
+       case SIOCSIFDSTADDR:
+       case SIOCGIFBRDADDR:
+       case SIOCSIFBRDADDR:
+       case SIOCGIFNETMASK:
+       case SIOCSIFNETMASK:
+       case SIOCGIFMETRIC:
+       case SIOCSIFMETRIC:
+               return -EINVAL;
+               
+       default:
+               return dev_ioctl(cmd, (void *)arg);
+       }
 
+       /*NOTREACHED*/
        return 0;
 }
 
-/*
- * Function irda_driver_rcv (skb, dev, ptype)
- *
- *    
- *
- */
-static int irda_driver_rcv( struct sk_buff *skb, struct device *dev, 
-                           struct packet_type *ptype)
+static struct net_proto_family irda_family_ops =
 {
-        skb->sk = NULL;         /* Initially we don't know who it's for */
-       
-       DEBUG( 0, __FUNCTION__ "()\n");
-
-#if 0
-        if ((*skb->data & 0x0F) != 0) {
-                kfree_skb(skb, FREE_READ);      /* Not a KISS data frame */
-                return 0;
-        }
-
-        /* skb_pull(skb, AX25_KISS_HEADER_LEN);  */   /* Remove the KISS byte */
-
-        return irda_rcv( skb, dev, (irda_address *)dev->dev_addr, ptype);
-#endif
-       return NULL;
-}
+       PF_IRDA,
+       irda_create
+};
 
 static struct proto_ops irda_proto_ops = {
-       AF_IRDA,
+       PF_IRDA,
        
-       irda_create,
-       irda_dup,
+       sock_no_dup,
        irda_release,
-       irda_bind,
+       sock_no_bind,
        irda_connect,
-       irda_socketpair,
-       irda_accept,
+       sock_no_socketpair,
+       sock_no_accept,
        irda_getname,
        irda_poll,
        irda_ioctl,
        irda_listen,
        irda_shutdown,
-       irda_setsockopt,
-       irda_getsockopt,
-       irda_fcntl,
-       irda_sendmsg,
+       sock_no_setsockopt,
+       sock_no_getsockopt,
+       sock_no_fcntl,
+       sock_no_sendmsg,
        irda_recvmsg
 };
 
 #endif /* IRDA_SOCKETS */
 
-static int irda_device_event( struct notifier_block *this, unsigned long event,
-                             void *ptr)
+static int irda_device_event(struct notifier_block *this, unsigned long event,
+                            void *ptr)
 {
-       /* struct device *dev = (struct device *) ptr; */
+       struct device *dev = (struct device *) ptr;
        
-       DEBUG( 0, __FUNCTION__ "()\n");
+       DEBUG(3, __FUNCTION__ "()\n");
        
-        /* Reject non AX.25 devices */
-       /*  if (dev->type != ARPHRD_AX25) */
-/*                 return NOTIFY_DONE; */
+        /* Reject non IrDA devices */
+       if (dev->type != ARPHRD_IRDA) 
+               return NOTIFY_DONE;
        
         switch (event) {
        case NETDEV_UP:
-               /* ax25_dev_device_up(dev); */
+               DEBUG(3, __FUNCTION__ "(), NETDEV_UP\n");
+               /* irda_dev_device_up(dev); */
                break;
        case NETDEV_DOWN:
-               /* ax25_kill_by_device(dev); */
-/*                         ax25_rt_device_down(dev); */
-/*                         ax25_dev_device_down(dev); */
+               DEBUG(3, __FUNCTION__ "(), NETDEV_DOWN\n");
+               /* irda_kill_by_device(dev); */
+               /* irda_rt_device_down(dev); */
+               /* irda_dev_device_down(dev); */
                break;
        default:
                break;
@@ -701,17 +429,17 @@ static struct notifier_block irda_dev_notifier = {
  *    Initialize IrDA protocol layer
  *
  */
-void irda_proto_init(struct net_proto *pro)
+__initfunc(void irda_proto_init(struct net_proto *pro))
 {
        DEBUG( 4, __FUNCTION__ "\n");
 
-       /* sock_register( irda_proto_ops.family, &irda_proto_ops); */
+       sock_register(&irda_family_ops);
+
        irda_packet_type.type = htons(ETH_P_IRDA);
         dev_add_pack(&irda_packet_type);
 
-       /* register_netdevice_notifier( &irda_dev_notifier); */
+       register_netdevice_notifier( &irda_dev_notifier);
 
-       /* printk( KERN_INFO "IrDA Sockets for Linux (Dag Brattli)\n"); */
        irda_init();
 }
 
@@ -728,9 +456,9 @@ void irda_proto_cleanup(void)
        irda_packet_type.type = htons(ETH_P_IRDA);
         dev_remove_pack(&irda_packet_type);
 
-        /* unregister_netdevice_notifier( &irda_dev_notifier); */
+        unregister_netdevice_notifier( &irda_dev_notifier);
        
-       /* (void) sock_unregister( irda_proto_ops.family); */
+       sock_unregister(PF_IRDA);
        irda_cleanup();
        
         return;
index 1e5e373ee88dd7d9305971910a4eba04f310a8cd..7ec8e469ec569cccef7547703f5023556a0eed35 100644 (file)
@@ -44,7 +44,8 @@ struct ircomm_cb *discovering_instance;
 
 static void got_lsapsel(struct ircomm_cb * info);
 static void query_lsapsel(struct ircomm_cb * self);
-void ircomm_getvalue_confirm( __u16 obj_id, struct ias_value *value, void *priv );
+void ircomm_getvalue_confirm( __u16 obj_id, struct ias_value *value, 
+                             void *priv);
 
 #if 0
 static char *rcsid = "$Id: attach.c,v 1.11 1998/10/22 12:02:20 dagb Exp $";
@@ -55,14 +56,20 @@ static char *rcsid = "$Id: attach.c,v 1.11 1998/10/22 12:02:20 dagb Exp $";
  * handler for iriap_getvaluebyclass_request() 
  *
  */
-
-void ircomm_getvalue_confirm( __u16 obj_id, struct ias_value *value, void *priv ){
-
+void ircomm_getvalue_confirm( __u16 obj_id, struct ias_value *value,void *priv)
+{
        struct ircomm_cb *self = (struct ircomm_cb *) priv;
 
        ASSERT( self != NULL, return;);
        ASSERT( self->magic == IRCOMM_MAGIC, return;);
 
+       /* Check if request succeeded */
+       if ( !value) {
+               DEBUG( 0, __FUNCTION__ "(), got NULL value!\n");
+
+               return;
+       }
+
        DEBUG(0, __FUNCTION__"type(%d)\n", value->type);
 
        switch(value->type){
@@ -100,9 +107,8 @@ void ircomm_getvalue_confirm( __u16 obj_id, struct ias_value *value, void *priv
                break;
 
        case IAS_STRING:
-               DEBUG( 0, __FUNCTION__":STRING is not implemented\n");
-               DEBUG( 0, __FUNCTION__":received string:%s\n",
-                      value->t.string);
+               DEBUG(0, __FUNCTION__":STRING is not implemented\n");
+               DEBUG(0, __FUNCTION__":received string:%s\n", value->t.string);
                query_lsapsel(self);  /* experiment */
                break;
 
@@ -116,9 +122,8 @@ void ircomm_getvalue_confirm( __u16 obj_id, struct ias_value *value, void *priv
        }
 }
 
-
-static void got_lsapsel(struct ircomm_cb * self){
-
+static void got_lsapsel(struct ircomm_cb * self)
+{
        struct notify_t notify;
 
        DEBUG(0, "ircomm:got_lsapsel: got peersap!(%d)\n", self->dlsap );
@@ -136,11 +141,10 @@ static void got_lsapsel(struct ircomm_cb * self){
        strncpy( notify.name, "IrCOMM cli", NOTIFY_MAX_NAME);
        notify.instance = self;
        
-       self->tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT,
-                                    &notify );
+       self->tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT, 
+                                    &notify);
        ASSERT(self->tsap != NULL, return;);
 
-
        /*
         * invoke state machine  
         * and notify that I'm ready to accept connect_request
@@ -150,26 +154,22 @@ static void got_lsapsel(struct ircomm_cb * self){
        if(self->d_handler)
                self->d_handler(self);
 }
-
-
-
-
                
-static void query_lsapsel(struct ircomm_cb * self){
-
+static void query_lsapsel(struct ircomm_cb * self)
+{
        DEBUG(0, "ircomm:query_lsapsel..\n");
 
        /*  
         *  since we've got Parameters field of IAS, we are to get peersap.
         */
        
-       if(!(self->servicetype & THREE_WIRE_RAW)){
-               iriap_getvaluebyclass_request
-                       (self->daddr, "IrDA:IrCOMM", "IrDA:TinyTP:LsapSel",
-                        ircomm_getvalue_confirm, self );
+       if (!(self->servicetype & THREE_WIRE_RAW)) {
+               iriap_getvaluebyclass_request( 
+                       "IrDA:IrCOMM", "IrDA:TinyTP:LsapSel",
+                       self->saddr, self->daddr,
+                       ircomm_getvalue_confirm, self );
        } else {
-               DEBUG(0,"ircomm:query_lsap:"
-                     "THREE_WIRE_RAW is not implemented!\n");
+               DEBUG(0, __FUNCTION__ "THREE_WIRE_RAW is not implemented!\n");
        }
 }
 
@@ -183,7 +183,6 @@ static void query_lsapsel(struct ircomm_cb * self){
 
 void ircomm_discovery_indication( DISCOVERY *discovery)
 {
-
        struct ircomm_cb *self;
 
        DEBUG( 0, "ircomm_discovery_indication\n");
@@ -193,6 +192,7 @@ void ircomm_discovery_indication( DISCOVERY *discovery)
        ASSERT(self->magic == IRCOMM_MAGIC, return;);
 
        self->daddr = discovery->daddr;
+       self->saddr = discovery->saddr;
 
        DEBUG( 0, "ircomm_discovery_indication:daddr=%08x\n", self->daddr);
 
@@ -201,7 +201,6 @@ void ircomm_discovery_indication( DISCOVERY *discovery)
        DEBUG(0, "ircomm:querying parameters..\n");
 #if 0
        iriap_getvaluebyclass_request(self->daddr, "IrDA:IrCOMM",
-
                                      "Parameters",
                                      ircomm_getvalue_confirm,
                                      self);
@@ -214,8 +213,8 @@ void ircomm_discovery_indication( DISCOVERY *discovery)
 
 struct ircomm_cb * ircomm_attach_cable( __u8 servicetype,
                                        struct notify_t notify, 
-                                       void *handler ){
-
+                                       void *handler )
+{
        int i;
        struct ircomm_cb *self = NULL;
        struct notify_t server_notify;
@@ -317,15 +316,11 @@ struct ircomm_cb * ircomm_attach_cable( __u8 servicetype,
        return (self);
 }
 
-
-
-
-int ircomm_detach_cable(struct ircomm_cb *self){
-
+int ircomm_detach_cable(struct ircomm_cb *self)
+{
        ASSERT( self != NULL, return -EIO;);
        ASSERT( self->magic == IRCOMM_MAGIC, return -EIO;);
 
-
        DEBUG(0,"ircomm_detach_cable:\n");
 
        /* shutdown ircomm layer */
@@ -360,5 +355,6 @@ int ircomm_detach_cable(struct ircomm_cb *self){
 
        self->tsap = NULL;
        self->in_use = 0;
+
        return 0;
 }
index cfda567ceb677c0205c8eb8d5afeae8f9c9b5b88..d6004ed00e77e960de0926ba9947a558cd02065b 100644 (file)
@@ -236,7 +236,9 @@ void ircomm_cleanup(void)
  * ---------------------------------------------------------------------- 
  */
 
-void ircomm_accept_data_indication(void *instance, void *sap, struct sk_buff *skb){
+void ircomm_accept_data_indication(void *instance, void *sap, 
+                                  struct sk_buff *skb)
+{
        
        struct ircomm_cb *self = (struct ircomm_cb *)instance;
 
@@ -250,7 +252,8 @@ void ircomm_accept_data_indication(void *instance, void *sap, struct sk_buff *sk
 
 void ircomm_accept_connect_confirm(void *instance, void *sap,
                                   struct qos_info *qos, 
-                                  int maxsdusize, struct sk_buff *skb){
+                                  int maxsdusize, struct sk_buff *skb)
+{
 
        struct ircomm_cb *self = (struct ircomm_cb *)instance;
 
@@ -277,8 +280,8 @@ void ircomm_accept_connect_confirm(void *instance, void *sap,
 void ircomm_accept_connect_indication(void *instance, void *sap,
                                      struct qos_info *qos,
                                      int maxsdusize,
-                                     struct sk_buff *skb ){
-
+                                     struct sk_buff *skb )
+{
        struct ircomm_cb *self = (struct ircomm_cb *)instance;
 
        ASSERT( self != NULL, return;);
@@ -297,8 +300,10 @@ void ircomm_accept_connect_indication(void *instance, void *sap,
        ircomm_do_event( self, TTP_CONNECT_INDICATION, skb);
 }
 
-void ircomm_accept_disconnect_indication(void *instance, void *sap, LM_REASON reason,
-                                        struct sk_buff *skb){
+void ircomm_accept_disconnect_indication(void *instance, void *sap, 
+                                        LM_REASON reason,
+                                        struct sk_buff *skb)
+{
        struct ircomm_cb *self = (struct ircomm_cb *)instance;
 
        ASSERT( self != NULL, return;);
@@ -309,7 +314,8 @@ void ircomm_accept_disconnect_indication(void *instance, void *sap, LM_REASON re
        ircomm_do_event( self, TTP_DISCONNECT_INDICATION, skb);
 }
 
-void ircomm_accept_flow_indication( void *instance, void *sap, LOCAL_FLOW cmd){
+void ircomm_accept_flow_indication( void *instance, void *sap, LOCAL_FLOW cmd)
+{
        
        struct ircomm_cb *self = (struct ircomm_cb *)instance;
 
@@ -349,10 +355,9 @@ void ircomm_accept_flow_indication( void *instance, void *sap, LOCAL_FLOW cmd){
  * ----------------------------------------------------------------------
  */
 
-
 static void issue_connect_request(struct ircomm_cb *self,
-                                 struct sk_buff *userdata ){
-
+                                 struct sk_buff *userdata )
+{
        /* TODO: we have to send/build userdata field which contains 
           InitialControlParameters */
        /* but userdata field is not implemeted in irttp.c.. */
@@ -365,7 +370,8 @@ static void issue_connect_request(struct ircomm_cb *self,
                break;
 
        case DEFAULT: 
-               irttp_connect_request(self->tsap, self->dlsap, self->daddr,
+               irttp_connect_request(self->tsap, self->dlsap, 
+                                     self->saddr, self->daddr,
                                      NULL, self->maxsdusize, NULL);  
                break; 
                
@@ -373,7 +379,8 @@ static void issue_connect_request(struct ircomm_cb *self,
        case NINE_WIRE:
        case CENTRONICS:
 
-               irttp_connect_request(self->tsap, self->dlsap, self->daddr, 
+               irttp_connect_request(self->tsap, self->dlsap, 
+                                     self->saddr, self->daddr, 
                                      NULL, self->maxsdusize, NULL); 
                break;
 
@@ -383,8 +390,8 @@ static void issue_connect_request(struct ircomm_cb *self,
        }
 }      
 
-
-static void disconnect_indication(struct ircomm_cb *self, struct sk_buff *skb){
+static void disconnect_indication(struct ircomm_cb *self, struct sk_buff *skb)
+{
 
        /*
         * Not implemented parameter"Reason".That is optional.
@@ -399,7 +406,8 @@ static void disconnect_indication(struct ircomm_cb *self, struct sk_buff *skb){
 }
 
 static void connect_indication(struct ircomm_cb *self, struct qos_info *qos, 
-                              struct sk_buff *skb){
+                              struct sk_buff *skb)
+{
 
 /* If controlparameters don't exist, we use the servicetype"DEFAULT".*/
 /*     if( !ircomm_parse_controlchannel( self, data)) */
@@ -412,13 +420,15 @@ static void connect_indication(struct ircomm_cb *self, struct qos_info *qos,
     
 #if 0
 /*   it's for THREE_WIRE_RAW.*/
-static void connect_indication_three_wire_raw(void){ 
+static void connect_indication_three_wire_raw(void)
+{ 
        DEBUG(0,"ircomm:connect_indication_threewire():not implemented!");
 }    
 #endif 
 
 
-static void connect_confirmation(struct ircomm_cb *self, struct sk_buff *skb){
+static void connect_confirmation(struct ircomm_cb *self, struct sk_buff *skb)
+{
 
        /* give a connect_confirm to the client */
        if( self->notify.connect_confirm )
@@ -427,7 +437,8 @@ static void connect_confirmation(struct ircomm_cb *self, struct sk_buff *skb){
 }
 
 static void issue_connect_response(struct ircomm_cb *self,
-                                  struct sk_buff *skb ){
+                                  struct sk_buff *skb)
+{
 
        DEBUG(0,"ircomm:issue_connect_response:\n");
        
@@ -441,7 +452,8 @@ static void issue_connect_response(struct ircomm_cb *self,
 }
 
 static void issue_disconnect_request(struct ircomm_cb *self,
-                               struct sk_buff *userdata ){
+                                    struct sk_buff *userdata)
+{
        if(self->servicetype == THREE_WIRE_RAW){
                DEBUG(0,"ircomm:issue_disconnect_request():3wireraw is not implemented!");
        }
@@ -450,7 +462,8 @@ static void issue_disconnect_request(struct ircomm_cb *self,
 }
     
 static void issue_data_request(struct ircomm_cb *self,
-                              struct sk_buff *userdata ){
+                              struct sk_buff *userdata )
+{
        int err;
 
        if(self->servicetype == THREE_WIRE_RAW){
@@ -469,7 +482,8 @@ static void issue_data_request(struct ircomm_cb *self,
 }
 
 static void issue_control_request(struct ircomm_cb *self,
-                                 struct sk_buff *userdata ){
+                                 struct sk_buff *userdata )
+{
        if(self->servicetype == THREE_WIRE_RAW){
                DEBUG(0,"THREE_WIRE_RAW is not implemented\n");
                
@@ -478,8 +492,8 @@ static void issue_control_request(struct ircomm_cb *self,
        }
 }
 
-
-static void process_data(struct ircomm_cb *self, struct sk_buff *skb ){
+static void process_data(struct ircomm_cb *self, struct sk_buff *skb )
+{
        
        DEBUG(4,"ircomm:process_data:skb_len is(%d),clen_is(%d)\n",
              (int)skb->len ,(int)skb->data[0]);
@@ -496,7 +510,8 @@ static void process_data(struct ircomm_cb *self, struct sk_buff *skb ){
                                             skb);
 }
 
-void ircomm_data_indication(struct ircomm_cb *self, struct sk_buff *skb){
+void ircomm_data_indication(struct ircomm_cb *self, struct sk_buff *skb)
+{
        /* Not implemented yet:THREE_WIRE_RAW service uses this function.  */
        DEBUG(0,"ircomm_data_indication:not implemented yet!\n");
 }
@@ -510,14 +525,16 @@ void ircomm_data_indication(struct ircomm_cb *self, struct sk_buff *skb){
  */
 
 static void ircomm_do_event( struct ircomm_cb *self, IRCOMM_EVENT event,
-                            struct sk_buff *skb) {
+                            struct sk_buff *skb) 
+{
        
        DEBUG( 4, "ircomm_do_event: STATE = %s, EVENT = %s\n",
               ircommstate[self->state], ircommevent[event]);
        (*state[ self->state ]) ( self, event, skb);
 }
 
-void ircomm_next_state( struct ircomm_cb *self, IRCOMM_STATE state) {
+void ircomm_next_state( struct ircomm_cb *self, IRCOMM_STATE state) 
+{
        self->state = state;
        DEBUG( 0, "ircomm_next_state: NEXT STATE = %d(%s), sv(%d)\n", 
               (int)state, ircommstate[self->state],self->servicetype);
@@ -530,7 +547,8 @@ void ircomm_next_state( struct ircomm_cb *self, IRCOMM_STATE state) {
  */
 
 static void ircomm_state_discovery( struct ircomm_cb *self,
-                                   IRCOMM_EVENT event, struct sk_buff *skb ){
+                                   IRCOMM_EVENT event, struct sk_buff *skb )
+{
        DEBUG(0,"ircomm_state_discovery: "
              "why call me? \n");
        if(skb)
@@ -543,7 +561,8 @@ static void ircomm_state_discovery( struct ircomm_cb *self,
  */
 
 static void ircomm_state_idle( struct ircomm_cb *self, IRCOMM_EVENT event, 
-                              struct sk_buff *skb ){
+                              struct sk_buff *skb )
+{
        switch(event){
        case IRCOMM_CONNECT_REQUEST:
 
@@ -577,7 +596,8 @@ static void ircomm_state_idle( struct ircomm_cb *self, IRCOMM_EVENT event,
  */
 
 static void ircomm_state_waiti(struct ircomm_cb *self, IRCOMM_EVENT event, 
-                         struct sk_buff *skb ){
+                         struct sk_buff *skb )
+{
        switch(event){
        case TTP_CONNECT_CONFIRM:
                ircomm_next_state(self, COMM_CONN);
@@ -607,7 +627,8 @@ static void ircomm_state_waiti(struct ircomm_cb *self, IRCOMM_EVENT event,
  * ircomm_state_waitr
  */
 static void ircomm_state_waitr(struct ircomm_cb *self, IRCOMM_EVENT event, 
-                         struct sk_buff *skb ) {
+                         struct sk_buff *skb ) 
+{
        
        switch(event){
        case IRCOMM_CONNECT_RESPONSE:
@@ -651,7 +672,8 @@ static void ircomm_state_waitr(struct ircomm_cb *self, IRCOMM_EVENT event,
  */
 
 static void ircomm_state_conn(struct ircomm_cb *self, IRCOMM_EVENT event, 
-                         struct sk_buff *skb ){
+                             struct sk_buff *skb )
+{
        switch(event){
        case TTP_DATA_INDICATION:
                process_data(self, skb);
@@ -696,7 +718,8 @@ static void ircomm_state_conn(struct ircomm_cb *self, IRCOMM_EVENT event,
  */
 
 
-void ircomm_connect_request(struct ircomm_cb *self, int maxsdusize){
+void ircomm_connect_request(struct ircomm_cb *self, int maxsdusize)
+{
 
        /*
         * TODO:build a packet which contains "initial control parameters"
@@ -713,7 +736,8 @@ void ircomm_connect_request(struct ircomm_cb *self, int maxsdusize){
 }
 
 void ircomm_connect_response(struct ircomm_cb *self, struct sk_buff *userdata,
-                            int maxsdusize){
+                            int maxsdusize)
+{
 
        ASSERT( self != NULL, return;);
        ASSERT( self->magic == IRCOMM_MAGIC, return;);
@@ -746,7 +770,9 @@ void ircomm_connect_response(struct ircomm_cb *self, struct sk_buff *userdata,
        ircomm_do_event(self, IRCOMM_CONNECT_RESPONSE, userdata);
 }      
 
-void ircomm_disconnect_request(struct ircomm_cb *self, struct sk_buff *userdata){
+void ircomm_disconnect_request(struct ircomm_cb *self, 
+                              struct sk_buff *userdata)
+{
 
        ASSERT( self != NULL, return;);
        ASSERT( self->magic == IRCOMM_MAGIC, return;);
@@ -756,7 +782,8 @@ void ircomm_disconnect_request(struct ircomm_cb *self, struct sk_buff *userdata)
 }      
 
 
-void ircomm_data_request(struct ircomm_cb *self, struct sk_buff *userdata){
+void ircomm_data_request(struct ircomm_cb *self, struct sk_buff *userdata)
+{
 
        ASSERT( self != NULL, return;);
        ASSERT( self->magic == IRCOMM_MAGIC, return;);
@@ -780,7 +807,8 @@ void ircomm_data_request(struct ircomm_cb *self, struct sk_buff *userdata){
  *  ----------------------------------------------------------------------
  */
 
-static void ircomm_tx_ctrlbuffer(struct ircomm_cb *self ){
+static void ircomm_tx_ctrlbuffer(struct ircomm_cb *self )
+{
 
        __u8 clen;
        struct sk_buff *skb = self->ctrl_skb;
@@ -817,7 +845,8 @@ static void ircomm_tx_ctrlbuffer(struct ircomm_cb *self ){
 }
 
 
-void ircomm_control_request(struct ircomm_cb *self){
+void ircomm_control_request(struct ircomm_cb *self)
+{
        
        struct sk_buff *skb;
 
@@ -839,8 +868,9 @@ void ircomm_control_request(struct ircomm_cb *self){
 }
 
 
-static void append_tuple(struct ircomm_cb *self,
-                        __u8 instruction, __u8 pl , __u8 *value){
+static void append_tuple(struct ircomm_cb *self, __u8 instruction, __u8 pl , 
+                        __u8 *value)
+{
 
        __u8 *frame;
        struct sk_buff *skb;
@@ -886,7 +916,8 @@ static void append_tuple(struct ircomm_cb *self,
  * to peer device
  */
 
-void ircomm_append_ctrl(struct ircomm_cb *self,  __u8 instruction){
+void ircomm_append_ctrl(struct ircomm_cb *self,  __u8 instruction)
+{
 
        __u8  pv[70];
        __u8  *value = &pv[0];
@@ -1028,7 +1059,8 @@ void ircomm_append_ctrl(struct ircomm_cb *self,  __u8 instruction){
 
 static void ircomm_parse_control(struct ircomm_cb *self,
                                 struct sk_buff *skb,
-                                int type){
+                                int type)
+{
 
        __u8 *data;
        __u8 pi,pl,pv[64];
@@ -1210,7 +1242,8 @@ static void ircomm_parse_control(struct ircomm_cb *self,
 
 #ifdef MODULE
 
-int init_module(void) {
+int init_module(void) 
+{
        ircomm_init();
 
        DEBUG( 4, "ircomm:init_module:done\n");
@@ -1238,7 +1271,8 @@ void cleanup_module(void)
  *
  */
 int ircomm_proc_read(char *buf, char **start, off_t offset,
-                    int len, int unused){
+                    int len, int unused)
+{
        int i, index;
 
        len = 0;
@@ -1285,6 +1319,5 @@ int ircomm_proc_read(char *buf, char **start, off_t offset,
        return len;
 }
 
-
 #endif /* CONFIG_PROC_FS */
 
index 65a8605a7daf1b1a8e320a2ed97cdc405f892024..00698944d42e8bf70f053ba07825275a8ee14303 100644 (file)
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      irda_device.c
- * Version:       0.3
+ * Version:       0.4
  * Description:   Abstract device driver layer and helper functions
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Wed Sep  2 20:22:08 1998
- * Modified at:   Mon Jan 18 11:05:59 1999
+ * Modified at:   Tue Feb 16 17:36:04 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
 #include <linux/if_arp.h>
 #include <linux/netdevice.h>
 #include <linux/init.h>
+#include <linux/tty.h>
 
-#include <net/pkt_sched.h>
+#include <asm/ioctls.h>
+#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/dma.h>
 
+#include <net/pkt_sched.h>
+
 #include <net/irda/irda_device.h>
 #include <net/irda/irlap_frame.h>
 #include <net/irda/timer.h>
@@ -45,11 +50,10 @@ extern int w83977af_init(void);
 extern int esi_init(void);
 extern int tekram_init(void);
 extern int actisys_init(void);
+extern int girbil_init(void);
 
 hashbin_t *irda_device = NULL;
 
-void irda_device_start_todo_timer( struct irda_device *self, int timeout);
-
 /* Netdevice functions */
 static int irda_device_net_rebuild_header(struct sk_buff *skb);
 static int irda_device_net_hard_header(struct sk_buff *skb, 
@@ -67,8 +71,6 @@ int irda_device_proc_read( char *buf, char **start, off_t offset, int len,
 
 __initfunc(int irda_device_init( void))
 {
-       DEBUG( 4, __FUNCTION__ "()\n");
-
        /* Allocate master array */
        irda_device = hashbin_new( HB_LOCAL);
        if ( irda_device == NULL) {
@@ -98,7 +100,9 @@ __initfunc(int irda_device_init( void))
 #ifdef CONFIG_ACTISYS_DONGLE
        actisys_init();
 #endif
-
+#ifdef CONFIG_GIRBIL_DONGLE
+       girbil_init();
+#endif
        return 0;
 }
 
@@ -178,7 +182,7 @@ int irda_device_open( struct irda_device *self, char *name, void *priv)
         * a name like "irda0" and the self->descriptin will get a name
         * like "irda0 <-> irtty0" 
         */
-       strncpy( self->description, self->name, 4);
+       strncpy( self->description, self->name, 5);
        strcat( self->description, " <-> ");
        strncat( self->description, name, 23);
 
@@ -280,16 +284,11 @@ void irda_device_set_media_busy( struct irda_device *self, int status)
  */
 static void __irda_device_change_speed( struct irda_device *self, int speed)
 {
-       ASSERT( self != NULL, return;);
-
-       if ( self->magic != IRDA_DEVICE_MAGIC) {
-               DEBUG( 0, __FUNCTION__ 
-                      "(), irda device is gone! Maybe you need to update "
-                      "your irmanager and/or irattach!");
-                      
-                      return;
-       }
+       DEBUG(4, __FUNCTION__ "(), <%ld>\n", jiffies);
 
+       ASSERT( self != NULL, return;);
+       ASSERT( self->magic == IRDA_DEVICE_MAGIC, return;);
+       
        /*
         *  Is is possible to change speed yet? Wait until the last byte 
         *  has been transmitted.
@@ -304,9 +303,9 @@ static void __irda_device_change_speed( struct irda_device *self, int speed)
                        self->qos.baud_rate.value = speed;
                }
        } else {
-               DEBUG( 0, __FUNCTION__ "(), Warning, wait_until_sent() "
-                      "is not implemented by the irda_device!\n");
-     
+               DEBUG(0, __FUNCTION__ "(), Warning, wait_until_sent() "
+                     "has not implemented by the device driver!\n");
+               
        }
 }
 
@@ -323,9 +322,8 @@ inline void irda_device_change_speed( struct irda_device *self, int speed)
        ASSERT( self != NULL, return;);
        ASSERT( self->magic == IRDA_DEVICE_MAGIC, return;);
 
-       irda_execute_as_process( self, 
-                                (TODO_CALLBACK) __irda_device_change_speed, 
-                                speed);
+       irda_execute_as_process(
+               self, (TODO_CALLBACK) __irda_device_change_speed, speed);
 }
 
 inline int irda_device_is_media_busy( struct irda_device *self)
@@ -368,28 +366,6 @@ void irda_device_todo_expired( unsigned long data)
        __irda_device_change_speed( self, self->new_speed);
 }
 
-/*
- * Function irda_device_start_todo_timer (self, timeout)
- *
- *    Start todo timer. This function is used to delay execution of certain
- *    functions. Its implemented using timers since delaying a timer or a
- *    bottom halves function can be very difficult othervise.
- *
- */
-void irda_device_start_todo_timer( struct irda_device *self, int timeout)
-{
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == IRDA_DEVICE_MAGIC, return;);
-
-       del_timer( &self->todo_timer);
-       
-       self->todo_timer.data     = (unsigned long) self;
-       self->todo_timer.function = &irda_device_todo_expired;
-       self->todo_timer.expires  = jiffies + timeout;
-       
-       add_timer( &self->todo_timer);
-}
-
 static struct enet_statistics *irda_device_get_stats( struct device *dev)
 {
        struct irda_device *priv = (struct irda_device *) dev->priv;
@@ -420,7 +396,7 @@ int irda_device_setup( struct device *dev)
        dev->rebuild_header  = irda_device_net_rebuild_header;
        dev->set_config      = irda_device_net_set_config;
        dev->change_mtu      = irda_device_net_change_mtu;
-       dev->hard_header     = irda_device_net_hard_header;
+/*     dev->hard_header     = irda_device_net_hard_header; */
         dev->hard_header_len = 0;
         dev->addr_len        = 0;
 
@@ -435,7 +411,7 @@ int irda_device_setup( struct device *dev)
        
        dev_init_buffers( dev);
 
-       dev->flags = 0; /* IFF_NOARP | IFF_POINTOPOINT; */
+       dev->flags = 0;
        
        return 0;
 }
@@ -453,16 +429,15 @@ static int irda_device_net_rebuild_header( struct sk_buff *skb)
        return 0;
 }
 
-static int irda_device_net_hard_header (struct sk_buff *skb, 
-                                       struct device *dev,
-                                       unsigned short type, void *daddr, 
-                                       void *saddr, unsigned len)
+static int irda_device_net_hard_header(struct sk_buff *skb, struct device *dev,
+                                      unsigned short type, void *daddr, 
+                                      void *saddr, unsigned len)
 {
        DEBUG( 0, __FUNCTION__ "()\n");
 
        skb->mac.raw = skb->data;
         /* skb_push(skb,PPP_HARD_HDR_LEN); */
-/*         return PPP_HARD_HDR_LEN; */
+        /* return PPP_HARD_HDR_LEN; */
        
        return 0;
 }
@@ -535,14 +510,44 @@ void setup_dma( int channel, char *buffer, int count, int mode)
 }
 
 #ifdef CONFIG_PROC_FS
+
+int irda_device_print_flags(struct irda_device *idev, char *buf)
+{
+       int len=0;
+
+       len += sprintf( buf+len, "\t");
+
+       if (idev->netdev.flags & IFF_UP)
+               len += sprintf( buf+len, "UP ");
+       if (!idev->netdev.tbusy)
+               len += sprintf( buf+len, "RUNNING ");
+
+       if (idev->flags & IFF_SIR)
+               len += sprintf( buf+len, "SIR ");
+       if (idev->flags & IFF_MIR)
+               len += sprintf( buf+len, "MIR ");
+       if (idev->flags & IFF_FIR)
+               len += sprintf( buf+len, "FIR ");
+       if (idev->flags & IFF_PIO)
+               len += sprintf( buf+len, "PIO ");
+       if (idev->flags & IFF_DMA)
+               len += sprintf( buf+len, "DMA ");
+       if (idev->flags & IFF_DONGLE)
+               len += sprintf( buf+len, "DONGLE ");
+
+       len += sprintf( buf+len, "\n");
+
+       return len;
+}
+
 /*
- * Function irlap_proc_read (buf, start, offset, len, unused)
+ * Function irda_device_proc_read (buf, start, offset, len, unused)
  *
  *    Give some info to the /proc file system
  *
  */
-int irda_device_proc_read( char *buf, char **start, off_t offset, int len, 
-                          int unused)
+int irda_device_proc_read(char *buf, char **start, off_t offset, int len, 
+                         int unused)
 {
        struct irda_device *self;
        unsigned long flags;
@@ -552,32 +557,33 @@ int irda_device_proc_read( char *buf, char **start, off_t offset, int len,
 
        len = 0;
 
-       self = (struct irda_device *) hashbin_get_first( irda_device);
+       self = (struct irda_device *) hashbin_get_first(irda_device);
        while ( self != NULL) {
-               len += sprintf( buf+len, "device name: %s\n", self->name);
-               len += sprintf( buf+len, "description: %s\n", 
-                               self->description);
-               len += sprintf( buf+len, "  tbusy=%s\n", self->netdev.tbusy ? 
-                               "TRUE" : "FALSE");
-               len += sprintf( buf+len, "  bps\tmaxtt\tdsize\twinsize\taddbofs\tmintt\tldisc\n");
+               len += sprintf(buf+len, "%s,", self->name);
+               len += sprintf(buf+len, "\tbinding: %s\n", 
+                              self->description);
+               
+               len += irda_device_print_flags(self, buf+len);
+
+               len += sprintf(buf+len, "\tbps\tmaxtt\tdsize\twinsize\taddbofs\tmintt\tldisc\n");
+               
+               len += sprintf(buf+len, "\t%d\t", 
+                              self->qos.baud_rate.value);
+               len += sprintf(buf+len, "%d\t", 
+                              self->qos.max_turn_time.value);
+               len += sprintf(buf+len, "%d\t",
+                              self->qos.data_size.value);
+               len += sprintf(buf+len, "%d\t",
+                              self->qos.window_size.value);
+               len += sprintf(buf+len, "%d\t",
+                              self->qos.additional_bofs.value);
+               len += sprintf(buf+len, "%d\t", 
+                              self->qos.min_turn_time.value);
+               len += sprintf(buf+len, "%d", 
+                              self->qos.link_disc_time.value);
+               len += sprintf(buf+len, "\n");
                
-               len += sprintf( buf+len, "  %d\t", 
-                               self->qos.baud_rate.value);
-               len += sprintf( buf+len, "%d\t", 
-                               self->qos.max_turn_time.value);
-               len += sprintf( buf+len, "%d\t",
-                               self->qos.data_size.value);
-               len += sprintf( buf+len, "%d\t",
-                               self->qos.window_size.value);
-               len += sprintf( buf+len, "%d\t",
-                               self->qos.additional_bofs.value);
-               len += sprintf( buf+len, "%d\t", 
-                               self->qos.min_turn_time.value);
-               len += sprintf( buf+len, "%d", 
-                               self->qos.link_disc_time.value);
-               len += sprintf( buf+len, "\n");
-              
-               self = (struct irda_device *) hashbin_get_next( irda_device);
+               self = (struct irda_device *) hashbin_get_next(irda_device);
        }
        restore_flags(flags);
 
index f23d3faafe35dbea80f8a118d576a5dd275bfbf6..5f626abd27aa559beaf9a52eb79405474f1552a6 100644 (file)
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      iriap.c
- * Version:       0.1
+ * Version:       0.8
  * Description:   Information Access Protocol (IAP)
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Aug 21 00:02:07 1997
- * Modified at:   Tue Dec 15 16:00:35 1998
+ * Modified at:   Thu Feb 11 01:22:44 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, 
 
 #include <net/irda/irda.h>
 #include <net/irda/irttp.h>
+#include <net/irda/irmod.h>
 #include <net/irda/irlmp.h>
 #include <net/irda/irias_object.h>
 #include <net/irda/iriap_event.h>
 #include <net/irda/iriap.h>
 
+/* FIXME: This one should go in irlmp.c */
+static const char *ias_charset_types[] = {
+       "CS_ASCII",
+       "CS_ISO_8859_1",
+       "CS_ISO_8859_2",
+       "CS_ISO_8859_3",
+       "CS_ISO_8859_4",
+       "CS_ISO_8859_5",
+       "CS_ISO_8859_6",
+       "CS_ISO_8859_7",
+       "CS_ISO_8859_8",
+       "CS_ISO_8859_9",
+       "CS_UNICODE"
+};
+
 hashbin_t *iriap = NULL;
 
+extern char *lmp_reasons[];
+
 static struct iriap_cb *iriap_open( __u8 slsap, int mode);
 static void __iriap_close( struct iriap_cb *self);
-static void iriap_disconnect_indication( void *instance, void *sap, 
-                                        LM_REASON reason, 
-                                        struct sk_buff *skb);
+static void iriap_disconnect_indication(void *instance, void *sap, 
+                                       LM_REASON reason, struct sk_buff *skb);
 
 /*
  * Function iriap_init (void)
@@ -56,7 +73,7 @@ __initfunc(int iriap_init(void))
 {
        struct ias_object *obj;
 
-       DEBUG( 4, "--> iriap_init\n");
+       DEBUG( 4, __FUNCTION__ "()\n");
        
        /* Allocate master array */
        iriap = hashbin_new( HB_LOCAL);
@@ -91,8 +108,6 @@ __initfunc(int iriap_init(void))
         */
        iriap_open( LSAP_IAS, IAS_SERVER);
        
-       DEBUG( 4, "iriap_init -->\n");
-       
        return 0;
 }
 
@@ -151,14 +166,14 @@ struct iriap_cb *iriap_open( __u8 slsap_sel, int mode)
                DEBUG( 0, "iriap_open: Unable to allocated LSAP!\n");
                return NULL;
        }
-       DEBUG( 4, "iriap_register: source LSAP sel=%02x\n", slsap_sel);
+       DEBUG( 4, __FUNCTION__ "(), source LSAP sel=%02x\n", slsap_sel);
        
        self->magic = IAS_MAGIC;
        self->lsap = lsap;
        self->slsap_sel = slsap_sel;
        self->mode = mode;
 
-       init_timer( &self->watchdog_timer);
+       /* init_timer( &self->watchdog_timer); */
 
        hashbin_insert( iriap, (QUEUE*) self, slsap_sel, NULL);
        
@@ -178,10 +193,12 @@ struct iriap_cb *iriap_open( __u8 slsap_sel, int mode)
  */
 static void __iriap_close( struct iriap_cb *self)
 {
+       DEBUG( 4, __FUNCTION__ "()\n");
+
        ASSERT( self != NULL, return;);
        ASSERT( self->magic == IAS_MAGIC, return;);
 
-       del_timer( &self->watchdog_timer);
+       /* del_timer( &self->watchdog_timer); */
 
        self->magic = 0;
 
@@ -195,7 +212,9 @@ static void __iriap_close( struct iriap_cb *self)
  */
 void iriap_close( struct iriap_cb *self)
 {
-       DEBUG( 4, "iriap_close()\n");
+       struct iriap_cb *entry;
+
+       DEBUG( 4, __FUNCTION__ "()\n");
 
        ASSERT( self != NULL, return;);
        ASSERT( self->magic == IAS_MAGIC, return;);
@@ -205,7 +224,9 @@ void iriap_close( struct iriap_cb *self)
                self->lsap = NULL;
        }
 
-       hashbin_remove( iriap, self->slsap_sel, NULL);
+       entry = (struct iriap_cb *) hashbin_remove( iriap, self->slsap_sel, 
+                                                   NULL);
+       ASSERT( entry == self, return;);
 
        __iriap_close( self);
 }
@@ -221,7 +242,7 @@ void iriap_disconnect_indication( void *instance, void *sap, LM_REASON reason,
 {
        struct iriap_cb *self;
 
-       DEBUG( 4, __FUNCTION__ "()\n");
+       DEBUG(4, __FUNCTION__ "(), reason=%s\n", lmp_reasons[reason]);
 
        self = (struct iriap_cb *) instance;
 
@@ -230,20 +251,24 @@ void iriap_disconnect_indication( void *instance, void *sap, LM_REASON reason,
 
        ASSERT( iriap != NULL, return;);
 
-       del_timer( &self->watchdog_timer);
+       /* del_timer( &self->watchdog_timer); */
 
        if ( self->mode == IAS_CLIENT) {
                DEBUG( 4, __FUNCTION__ "(), disconnect as client\n");
 
-               /* Inform service user */
+               /* 
+                * Inform service user that the request failed by sending 
+                * it a NULL value.
+                */
                if ( self->confirm)
-                       self->confirm( 0, NULL, self->priv);
-
+                       self->confirm( 0, NULL, self->priv);
+               
+               
                iriap_do_client_event( self, IAP_LM_DISCONNECT_INDICATION, 
                                       NULL);
                /* Close instance only if client */
                iriap_close( self);
-
+               
        } else {
                DEBUG( 4, __FUNCTION__ "(), disconnect as server\n");
                iriap_do_server_event( self, IAP_LM_DISCONNECT_INDICATION, 
@@ -265,15 +290,15 @@ void iriap_disconnect_request( struct iriap_cb *self)
 {
        struct sk_buff *skb;
 
-       DEBUG( 4, "iriap_disconnect_request()\n");
+       DEBUG( 4, __FUNCTION__ "()\n");
 
        ASSERT( self != NULL, return;);
        ASSERT( self->magic == IAS_MAGIC, return;);
 
        skb = dev_alloc_skb( 64);
        if (skb == NULL) {
-               DEBUG( 0,"iriap_getvaluebyclass: "
-                      "Could not allocate an sk_buff of length %d\n", 64);
+               DEBUG( 0, __FUNCTION__
+                      "(), Could not allocate an sk_buff of length %d\n", 64);
                return;
        }
 
@@ -316,9 +341,9 @@ void iriap_getvalue(void)
  *    Retreive all values from attribute in all objects with given class
  *    name
  */
-void iriap_getvaluebyclass_request( __u32 daddr, char *name, char *attr, 
-                                   CONFIRM_CALLBACK callback,
-                                   void *priv)
+void iriap_getvaluebyclass_request( char *name, char *attr, 
+                                   __u32 saddr, __u32 daddr,
+                                   CONFIRM_CALLBACK callback, void *priv)
 {
        struct sk_buff *skb;
        struct iriap_cb *self;
@@ -326,16 +351,18 @@ void iriap_getvaluebyclass_request( __u32 daddr, char *name, char *attr,
        int name_len, attr_len;
        __u8 slsap = LSAP_ANY;  /* Source LSAP to use */
 
-       DEBUG( 4, "iriap_getvaluebyclass_request()\n");
+       DEBUG( 4, __FUNCTION__ "()\n");
        
        self = iriap_open( slsap, IAS_CLIENT);
-       if ( self == NULL)
+       if (!self)
                return;
 
        self->mode = IAS_CLIENT;
        self->confirm = callback;
        self->priv = priv;
+
        self->daddr = daddr;
+       self->saddr = saddr;
 
        /* 
         *  Save operation, so we know what the later indication is about
@@ -343,14 +370,11 @@ void iriap_getvaluebyclass_request( __u32 daddr, char *name, char *attr,
        self->operation = GET_VALUE_BY_CLASS; 
 
        /* Give ourselves 7 secs to finish this operation */
-       iriap_start_watchdog_timer( self, 700);
+       /* iriap_start_watchdog_timer( self, 700); */
        
        skb = dev_alloc_skb( 64);
-       if (skb == NULL) {
-               DEBUG( 0,"iriap_getvaluebyclass: "
-                      "Could not allocate an sk_buff of length %d\n", 64);
+       if (!skb)
                return;
-       }
 
        name_len = strlen( name);
        attr_len = strlen( attr);
@@ -377,8 +401,7 @@ void iriap_getvaluebyclass_request( __u32 daddr, char *name, char *attr,
  *    to service user.
  *
  */
-void iriap_getvaluebyclass_confirm( struct iriap_cb *self, 
-                                   struct sk_buff *skb) 
+void iriap_getvaluebyclass_confirm(struct iriap_cb *self, struct sk_buff *skb) 
 {
        struct ias_value *value;
        __u16 obj_id;
@@ -387,6 +410,7 @@ void iriap_getvaluebyclass_confirm( struct iriap_cb *self,
        int   value_len;
        __u8 *fp;
        int n;
+       int charset;
 
        ASSERT( self != NULL, return;);
        ASSERT( self->magic == IAS_MAGIC, return;);
@@ -399,7 +423,7 @@ void iriap_getvaluebyclass_confirm( struct iriap_cb *self,
        /* Get length, MSB first */
        len = ntohs( *(__u16 *)( fp+n)); n += 2;
 
-       DEBUG( 4, "iriap_getvaluebyclass_confirm: len=%d\n", len);
+       DEBUG( 4, __FUNCTION__ "(), len=%d\n", len);
 
        /* Get object ID, MSB first */
        obj_id = ntohs( *(__u16 *)( fp+n)); n += 2;
@@ -407,39 +431,54 @@ void iriap_getvaluebyclass_confirm( struct iriap_cb *self,
        type = fp[n++];
        DEBUG( 4, __FUNCTION__ "(), Value type = %d\n", type);
 
-
        switch( type) {
        case IAS_INTEGER:
                value = irias_new_integer_value( ntohl(*(__u32 *)(fp+n)));
                /* 
                 *  Legal values restricted to 0x01-0x6f, page 15 irttp 
                 */
-               DEBUG( 4, "iriap_getvaluebyclass_confirm: lsap=%d\n", 
-                      value->t.integer); 
+               DEBUG( 4, __FUNCTION__ "(), lsap=%d\n", value->t.integer); 
                break;
        case IAS_STRING:
-               /* FIXME: check len of string, and if string is/should be
-                *  null terminated? */
-               ASSERT( fp[n++] == 0, return;); /* ASCII only! */
+               charset = fp[n++];
+
+               switch(charset) {
+               case CS_ASCII:
+                       break;
+/*             case CS_ISO_8859_1: */
+/*             case CS_ISO_8859_2: */
+/*             case CS_ISO_8859_3: */
+/*             case CS_ISO_8859_4: */
+/*             case CS_ISO_8859_5: */
+/*             case CS_ISO_8859_6: */
+/*             case CS_ISO_8859_7: */
+/*             case CS_ISO_8859_8: */
+/*             case CS_ISO_8859_9: */
+/*             case CS_UNICODE: */
+               default:
+                       DEBUG(0, __FUNCTION__"(), charset %s, not supported\n",
+                             ias_charset_types[charset]);
+                       return;
+                       /* break; */
+               }
                value_len = fp[n++];
-               DEBUG( 0, __FUNCTION__ "(), strlen=%d\n", value_len);
+               DEBUG(4, __FUNCTION__ "(), strlen=%d\n", value_len);
                ASSERT( value_len < 64, return;);
                
-               DEBUG( 0, "Got string %s\n", fp+n);
-
+               /* Make sure the string is null-terminated */
+               fp[n+value_len] = 0x00;
+               
+               DEBUG(4, "Got string %s\n", fp+n);
                value = irias_new_string_value( fp+n);
-
                break;
        case IAS_OCT_SEQ:
                value_len = ntohs( *(__u16 *)( fp+n)); n += 2;
                
                /* FIXME:should be 1024, but.... */
-               DEBUG( 0, __FUNCTION__ "():octet sequence:len=%d\n",
-                      value_len);
+               DEBUG(0, __FUNCTION__ "():octet sequence:len=%d\n", value_len);
                ASSERT(value_len <= 55, return;);      
                
                value = irias_new_octseq_value( fp+n, value_len);
-               
                break;
        default:
                value = &missing;
@@ -458,39 +497,37 @@ void iriap_getvaluebyclass_confirm( struct iriap_cb *self,
 /*
  * Function iriap_getvaluebyclass_response ()
  *
- *    Send answer to getvaluebyclass_indication back to peer LM-IAS
+ *    Send answer back to remote LM-IAS
  * 
  */
-void iriap_getvaluebyclass_response( struct iriap_cb *self,
-                                    __u16 obj_id, 
-                                    __u8 ret_code,
-                                    struct ias_value *value)
+void iriap_getvaluebyclass_response(struct iriap_cb *self, __u16 obj_id, 
+                                   __u8 ret_code, struct ias_value *value)
 {
        struct sk_buff *skb;
        __u8 *fp;
        int n;
 
-       DEBUG( 4, "iriap_getvaluebyclass_response()\n");
+       DEBUG( 4, __FUNCTION__ "()\n");
 
        ASSERT( self != NULL, return;);
        ASSERT( self->magic == IAS_MAGIC, return;);
+       ASSERT( value != NULL, return;);
+       ASSERT( value->len <= 1024, return;);
 
        /* Initialize variables */
        n = 0;
 
        /* 
-        *  FIXME: adjust the size of the response after the length of the 
-        *  value 
+        *  We must adjust the size of the response after the length of the 
+        *  value. We add 9 bytes because of the 6 bytes for the frame and
+        *  max 3 bytes for the value coding.
         */
-       skb = dev_alloc_skb( 64);
-       if (skb == NULL) {
-               DEBUG( 0, __FUNCTION__ "(),"
-                      "Could not allocate an skb of length %d\n", 64);
+       skb = dev_alloc_skb(value->len + LMP_HEADER + LAP_HEADER + 9);
+       if (!skb)
                return;
-       }
 
        /* Reserve space for MUX and LAP header */
-       skb_reserve( skb, LMP_CONTROL_HEADER+LAP_HEADER);
+       skb_reserve( skb, LMP_HEADER+LAP_HEADER);
        skb_put( skb, 6);
        
        fp = skb->data;
@@ -520,13 +557,6 @@ void iriap_getvaluebyclass_response( struct iriap_cb *self,
                *((__u32 *)(fp+n)) = htonl(value->t.integer); n+=4;
                break;
        case IAS_OCT_SEQ:
-               
-               /* FIXME:
-                * we can send only 55 octets at this time. 
-                * we should be able to send 1024 octets.       TH
-                */
-
-               ASSERT(value->len <= 55, return ;);
                skb_put( skb, 3 + value->len);
                fp[n++] = value->type;
                *((__u16 *)(fp+n)) = htons(value->len); n+=2;
@@ -540,8 +570,7 @@ void iriap_getvaluebyclass_response( struct iriap_cb *self,
                break;
 
        default:
-               DEBUG( 0, "iriap_getvaluebyclass_response: "
-                      "type not implemented!\n");
+               DEBUG(0, __FUNCTION__ "(), type not implemented!\n");
                break;
        }
        iriap_do_r_connect_event( self, IAP_CALL_RESPONSE, skb);
@@ -553,8 +582,8 @@ void iriap_getvaluebyclass_response( struct iriap_cb *self,
  *    getvaluebyclass is requested from peer LM-IAS
  *
  */
-void iriap_getvaluebyclass_indication( struct iriap_cb *self,
-                                      struct sk_buff *skb)
+void iriap_getvaluebyclass_indication(struct iriap_cb *self, 
+                                     struct sk_buff *skb)
 {
        __u8 *fp;
        int n;
@@ -562,11 +591,10 @@ void iriap_getvaluebyclass_indication( struct iriap_cb *self,
        int attr_len;
        char name[64];
        char attr[64];
-       char both[128];
        struct ias_object *obj;
        struct ias_attrib *attrib;
 
-       DEBUG( 4, "iriap_getvaluebyclass_indication()\n");
+       DEBUG( 4, __FUNCTION__ "()\n");
 
        ASSERT( self != NULL, return;);
        ASSERT( self->magic == IAS_MAGIC, return;);
@@ -588,30 +616,26 @@ void iriap_getvaluebyclass_indication( struct iriap_cb *self,
        /* 
         *  Now, do some advanced parsing! :-) 
         */
-       DEBUG( 9, "LM-IAS: Looking up %s: %s\n", name, attr);
-
-       sprintf( both, "%s:%s", name, attr);
-       DEBUG( 0, "LM-IAS: looking for %s\n", both);
-
-       obj = irias_find_object( name);
-
+       DEBUG(4, "LM-IAS: Looking up %s: %s\n", name, attr);
+       obj = irias_find_object(name);
+       
        if ( obj == NULL) {
                DEBUG( 0, "LM-IAS: Object not found\n");
                iriap_getvaluebyclass_response( self, 0x1235, 
                                                IAS_CLASS_UNKNOWN, &missing);
                return;
        }
-       DEBUG( 0, "LM-IAS: found %s, id=%d\n", obj->name, obj->id);
+       DEBUG(4, "LM-IAS: found %s, id=%d\n", obj->name, obj->id);
        
        attrib = irias_find_attrib( obj, attr);
        if ( attrib == NULL) {
                DEBUG( 0, "LM-IAS: Attribute %s not found\n", attr);
-               iriap_getvaluebyclass_response( self, obj->id, 
-                                               IAS_ATTRIB_UNKNOWN, &missing);
+               iriap_getvaluebyclass_response(self, obj->id,
+                                              IAS_ATTRIB_UNKNOWN, &missing);
                return;
        }
        
-       DEBUG( 0, "LM-IAS: found %s\n", attrib->name);
+       DEBUG(4, "LM-IAS: found %s\n", attrib->name);
        
        /*
         * We have a match; send the value.
@@ -633,17 +657,14 @@ void iriap_send_ack( struct iriap_cb *self)
        struct sk_buff *skb;
        __u8 *frame;
 
-       DEBUG( 6, "iriap_send_ack()\n");
+       DEBUG( 6, __FUNCTION__ "()\n");
 
        ASSERT( self != NULL, return;);
        ASSERT( self->magic == IAS_MAGIC, return;);
 
-       skb =  dev_alloc_skb( 64);
-       if (skb == NULL) {
-               DEBUG( 0, "iriap_send_ack: "
-                      "Could not allocate an sk_buff of length %d\n", 64);
+       skb = dev_alloc_skb( 64);
+       if (!skb)
                return;
-       }
 
        /* Reserve space for MUX and LAP header */
        skb_reserve( skb, 4);
@@ -671,9 +692,9 @@ void iriap_connect_confirm( void *instance, void *sap, struct qos_info *qos,
        ASSERT( self->magic == IAS_MAGIC, return;);
        ASSERT( userdata != NULL, return;);
        
-       DEBUG( 4, "iriap_connect_confirm()\n");
+       DEBUG( 4, __FUNCTION__ "()\n");
        
-       del_timer( &self->watchdog_timer);
+       /* del_timer( &self->watchdog_timer); */
 
        iriap_do_client_event( self, IAP_LM_CONNECT_CONFIRM, userdata);
 }
@@ -684,13 +705,12 @@ void iriap_connect_confirm( void *instance, void *sap, struct qos_info *qos,
  *    Remote LM-IAS is requesting connection
  *
  */
-void iriap_connect_indication( void *instance, void *sap, 
-                              struct qos_info *qos, int max_sdu_size,
-                              struct sk_buff *userdata)
+void iriap_connect_indication(void *instance, void *sap, struct qos_info *qos,
+                             int max_sdu_size, struct sk_buff *userdata)
 {
        struct iriap_cb *self;
 
-       DEBUG( 4, "iriap_connect_indication()\n");
+       DEBUG( 4, __FUNCTION__ "()\n");
 
        self = ( struct iriap_cb *) instance;
 
@@ -713,7 +733,7 @@ void iriap_data_indication( void *instance, void *sap, struct sk_buff *skb)
        __u8  *frame;
        __u8  opcode;
        
-       DEBUG( 4, "iriap_data_indication()\n"); 
+       DEBUG( 4, __FUNCTION__ "()\n"); 
        
        self = ( struct iriap_cb *) instance;
 
@@ -769,8 +789,7 @@ void iriap_data_indication( void *instance, void *sap, struct sk_buff *skb)
                iriap_close( self);
                break;
        default:
-               DEBUG( 0, "iriap_data_indication: Unknown op-code: %02x\n", 
-                      opcode);
+               DEBUG(0, __FUNCTION__ "(), Unknown op-code: %02x\n", opcode);
                break;
        }
 }
@@ -786,7 +805,7 @@ void iriap_call_indication( struct iriap_cb *self, struct sk_buff *skb)
        __u8 *fp;
        __u8  opcode;
 
-       DEBUG( 4, "iriap_call_indication()\n");
+       DEBUG( 4, __FUNCTION__ "()\n");
 
        ASSERT( self != NULL, return;);
        ASSERT( self->magic == IAS_MAGIC, return;);
@@ -816,7 +835,9 @@ void iriap_watchdog_timer_expired( unsigned long data)
 {
        struct iriap_cb *self = ( struct iriap_cb *) data;
        
-       DEBUG( 4, __FUNCTION__ "()\n");
+       DEBUG( 0, __FUNCTION__ "()\n");
+
+       return;
 
        ASSERT( self != NULL, return;);
        ASSERT( self->magic == IAS_MAGIC, return;);
@@ -834,23 +855,7 @@ static char *ias_value_types[] = {
        "IAS_STRING"
 };
 
-/* FIXME: This one should go in irlmp.c */
-static char *ias_charset_types[] = {
-       "CS_ASCII",
-       "CS_ISO_8859_1",
-       "CS_ISO_8859_2",
-       "CS_ISO_8859_3",
-       "CS_ISO_8859_4",
-       "CS_ISO_8859_5",
-       "CS_ISO_8859_6",
-       "CS_ISO_8859_7",
-       "CS_ISO_8859_8",
-       "CS_ISO_8859_9",
-       "CS_UNICODE"
-};
-
-int irias_proc_read( char *buf, char **start, off_t offset, int len, 
-                    int unused)
+int irias_proc_read(char *buf, char **start, off_t offset, int len, int unused)
 {
        struct ias_object *obj;
        struct ias_attrib *attrib;
index c0ba0058e2247a8032c45d9bbd648db1e44dc52b..ccba78ecefc2d65d87640f1483324cc6066a730e 100644 (file)
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Aug 21 00:02:07 1997
- * Modified at:   Wed Dec  9 02:20:02 1998
+ * Modified at:   Tue Jan 26 12:29:36 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
@@ -184,6 +184,8 @@ void iriap_do_r_connect_event( struct iriap_cb *self, IRIAP_EVENT event,
 static void state_s_disconnect( struct iriap_cb *self, IRIAP_EVENT event, 
                                struct sk_buff *skb) 
 {
+       int ret;
+
        ASSERT( self != NULL, return;);
        ASSERT( self->magic == IAS_MAGIC, return;);
 
@@ -191,13 +193,14 @@ static void state_s_disconnect( struct iriap_cb *self, IRIAP_EVENT event,
        case IAP_CALL_REQUEST_GVBC:
                iriap_next_client_state( self, S_CONNECTING);
                self->skb = skb;
-               irlmp_connect_request( self->lsap, LSAP_IAS, self->daddr, 
-                                      NULL, NULL);
+               ret = irlmp_connect_request( self->lsap, LSAP_IAS, 
+                                            self->saddr, self->daddr, 
+                                            NULL, NULL);
                break;
        case IAP_LM_DISCONNECT_INDICATION:
                break;
        default:
-               DEBUG( 0, "state_s_disconnect: Unknown event %d\n", event);
+               DEBUG( 0, __FUNCTION__"(), Unknown event %d\n", event);
                break;
        }
 }
index a9a7b84f2ab013af857fb29f9d477adfd4c70240..7951d90abc911ae3d98c090ca291a0c99f4395c3 100644 (file)
@@ -1,7 +1 @@
-
 dep_tristate 'IrLAN protocol' CONFIG_IRLAN $CONFIG_IRDA
-
-if [ "$CONFIG_IRLAN" != "n" ]; then
-  dep_tristate '   IrLAN client support' CONFIG_IRLAN_CLIENT $CONFIG_IRLAN
-  dep_tristate '   IrLAN server support' CONFIG_IRLAN_SERVER $CONFIG_IRLAN
-fi
index d5b37b9d8b44f8f4f3b500fa09e13baadf8bbbf0..6d4cb84331321657bd92170d5335aa6940a991ea 100644 (file)
@@ -9,44 +9,13 @@
 
 MOD_LIST_NAME := IRDA_MODULES
 O_TARGET := irlan.o
-O_OBJS  := irlan_common.o irlan_eth.o irlan_event.o
+O_OBJS  := irlan_common.o irlan_eth.o irlan_event.o irlan_client.o irlan_provider.o irlan_filter.o irlan_provider_event.o irlan_client_event.o
 M_OBJS   := $(O_TARGET)
 MI_OBJS  :=
 
 OX_OBJS  += 
 
-ifeq ($(CONFIG_IRLAN_CLIENT),y)
-O_OBJS += irlan_cli.o irlan_cli_event.o
-else
-  ifeq ($(CONFIG_IRLAN_CLIENT),m)
-#  MI_OBJS += irlan_cli.o irlan_cli_event.o
-  M_OBJS += irlan_client.o
-  endif
-endif
-
-ifeq ($(CONFIG_IRLAN_SERVER),y)
-O_OBJS += irlan_srv.o irlan_srv_event.o
-else
-  ifeq ($(CONFIG_IRLAN_SERVER),m)
-#  MI_OBJS += irlan_srv.o irlan_srv_event.o
-  M_OBJS += irlan_server.o
-  endif
-endif
-
-# Special rule to build the composite modules
-ifeq ($(CONFIG_IRLAN),m)
-irlan_client.o: irlan_cli.o irlan_cli_event.o
-       $(LD) $(LD_RFLAG) -r -o $@ irlan_cli.o irlan_cli_event.o
-
-irlan_server.o: irlan_srv.o irlan_srv_event.o
-       $(LD) $(LD_RFLAG) -r -o $@ irlan_srv.o irlan_srv_event.o
-endif
-
 include $(TOPDIR)/Rules.make
 
 tar:
                tar -cvf /dev/f1 .
-
-
-
-
diff --git a/net/irda/irlan/irlan_cli.c b/net/irda/irlan/irlan_cli.c
deleted file mode 100644 (file)
index 700f25e..0000000
+++ /dev/null
@@ -1,676 +0,0 @@
-/*********************************************************************
- *                
- * Filename:      irlan_cli.c
- * Version:       0.8
- * Description:   IrDA LAN Access Protocol Client
- * Status:        Experimental.
- * Author:        Dag Brattli <dagb@cs.uit.no>
- * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Mon Jan 18 13:24:26 1999
- * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * Sources:       skeleton.c by Donald Becker <becker@CESDIS.gsfc.nasa.gov>
- *                slip.c by Laurence Culhane, <loz@holmes.demon.co.uk>
- *                          Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
- * 
- *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, 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.
- *
- *     Neither Dag Brattli nor University of Tromsø admit liability nor
- *     provide warranty for any of this software. This material is 
- *     provided "AS-IS" and at no charge.
- *
- ********************************************************************/
-
-#include <linux/module.h>
-
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/if_arp.h>
-#include <net/arp.h>
-
-#include <asm/system.h>
-#include <asm/bitops.h>
-#include <asm/byteorder.h>
-
-#include <net/irda/irda.h>
-#include <net/irda/irttp.h>
-#include <net/irda/irlmp.h>
-#include <net/irda/irias_object.h>
-#include <net/irda/iriap.h>
-#include <net/irda/timer.h>
-
-#include <net/irda/irlan_common.h>
-#include <net/irda/irlan_event.h>
-#include <net/irda/irlan_eth.h>
-#include <net/irda/irlan_cli.h>
-
-/*
- *  Private functions
- */
-static struct irlan_cb *irlan_client_open( __u32 saddr, __u32 daddr);
-static void irlan_client_close( struct irlan_cb *self);
-
-
-static int irlan_client_eth_open( struct device *dev)
-{
-       /* struct irlan_cb *self = (struct irlan_cb *) dev->priv; */
-       
-       DEBUG( 4, __FUNCTION__ "()\n");
-
-       ASSERT( dev != NULL, return -1;);
-
-       /* Ready to play! */
-       dev->tbusy = 0;
-       dev->interrupt = 0;
-       dev->start = 1;
-
-       MOD_INC_USE_COUNT;
-       
-       return 0;
-}
-
-/*
- * Function irlan_eth_close (dev)
- *
- *    Stop the Client ether network device, his function will be called by
- *    ifconfig down.
- */
-static int irlan_client_eth_close(struct device *dev)
-{
-       DEBUG( 4, __FUNCTION__ "()\n");
-       
-       ASSERT( dev != NULL, return -1;);
-       
-       /* Stop device */
-       dev->tbusy = 1;
-       dev->start = 0;
-
-       MOD_DEC_USE_COUNT;
-       
-       return 0;
-}
-
-/*
- * Function irlan_client_eth_init (dev)
- *
- *    
- *
- */
-int irlan_client_eth_init( struct device *dev) 
-{
-       irlan_eth_init( dev);
-
-       /* Overrride some functions */
-       dev->open  = irlan_client_eth_open;
-       dev->stop = irlan_client_eth_close;
-
-       return 0;
-}
-
-/*
- * Function irlan_client_init (dev)
- *
- *   Allocates the master array. Called by modprobe().
- */
-__initfunc(int irlan_client_init( void))
-{
-       DEBUG( 4, __FUNCTION__ "()\n");
-       
-       /* Register with IrLMP as a service user */
-       irlmp_register_layer( S_LAN, CLIENT, TRUE, 
-                             irlan_discovery_indication);
-
-       /* Do some fast discovery! */
-       irlmp_discovery_request( 8);
-
-       return 0;
-}
-
-/*
- * Function irlan_client_cleanup (void)
- *
- *    Removes all instances of the IrLAN network device driver, and the
- *    master array. Called by rmmod().
- *
- */
-void irlan_client_cleanup(void) 
-{
-       DEBUG( 4, __FUNCTION__ "()\n");
-
-       irlmp_unregister_layer( S_LAN, CLIENT);
-}
-
-/*
- * Function irlan_client_open (void)
- *
- *    This function allocates and opens a new instance of the IrLAN network
- *    device driver.
- *
- */
-static struct irlan_cb *irlan_client_open( __u32 saddr, __u32 daddr) 
-{
-       struct irlan_cb *self;
-       int result;
-
-       DEBUG( 4, "IrLAN: irlan_client_open()\n");
-
-       ASSERT( irlan != NULL, return NULL;);
-       
-       self = irlan_open();
-       if ( self == NULL)
-               return NULL;
-
-       /* Use default name instead! */
-       /* sprintf( self->ifname, "irlan%d", ); */
-       self->dev.name = self->ifname;
-       self->dev.priv = (void *) self;
-       self->dev.next = NULL;
-       self->dev.init = irlan_client_eth_init;
-       
-       self->saddr = saddr;
-       self->daddr = daddr;
-
-       /*
-        *  Insert ourself into the hashbin
-        */
-       hashbin_insert( irlan, (QUEUE *) self, saddr, NULL);
-
-       if (( result = register_netdev( &self->dev)) != 0) {
-               DEBUG( 0, "IrLAN, Register_netdev() failed!\n");
-               return NULL;
-       }
-
-       irlan_next_state( self, IRLAN_IDLE);
-
-       irlan_client_open_tsaps( self);
-       
-       return self;
-}
-
-/*
- * Function irlan_client_close (self)
- *
- *    
- *
- */
-static void irlan_client_close( struct irlan_cb *self)
-{
-       struct irlan_cb *entry;
-
-       DEBUG( 0, __FUNCTION__ "()\n");
-       
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == IRLAN_MAGIC, return;);
-
-       entry = hashbin_remove( irlan, self->daddr, NULL);
-
-       ASSERT( entry == self, return;);
-
-       /* __irlan_close( self); */
-}
-
-/*
- * Function irlan_discovery_indication (daddr)
- *
- *    Remote device with IrLAN server support discovered
- *
- */
-void irlan_discovery_indication( DISCOVERY *discovery) 
-{
-       struct irlan_cb *self;
-       __u32 saddr, daddr;
-       
-       ASSERT( irlan != NULL, return;);
-       ASSERT( discovery != NULL, return;);
-
-       saddr = discovery->saddr;
-       daddr = discovery->daddr;
-
-       /* 
-        *  Check if an instance is already dealing with this device
-        *  (saddr) 
-        */
-       self = (struct irlan_cb *) hashbin_find( irlan, saddr, NULL);
-       if ( self != NULL) {
-               ASSERT( self->magic == IRLAN_MAGIC, return;);
-
-               DEBUG( 4, __FUNCTION__ "(), Found instance!\n");
-               if ( self->state == IRLAN_IDLE) {
-                       /* daddr may have changed! */
-                       self->daddr = daddr;
-
-                       irlan_do_client_event( self, 
-                                              IRLAN_DISCOVERY_INDICATION, 
-                                              NULL);
-               } else {
-                       DEBUG( 0, __FUNCTION__ "(), state=%s\n", 
-                              irlan_state[ self->state]);
-                       /*  
-                        *  If we get here, it's obvious that the last 
-                        *  connection attempt has failed, so its best 
-                        *  to go back to idle!
-                        */
-                       irlan_do_client_event( self, IRLAN_LMP_DISCONNECT, 
-                                              NULL);
-               }
-               return;
-       }
-       
-       /* 
-        * We have no instance for daddr, so time to start a new instance.
-        */
-       DEBUG( 0, __FUNCTION__ "(), Opening new instance for saddr=%#x\n",
-              saddr);
-
-       if (( self = irlan_client_open( saddr, daddr)) == NULL) {
-               DEBUG( 0, "irlan_client_open failed!\n");
-               return;
-       }       
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == IRLAN_MAGIC, return;);
-       
-       DEBUG( 4, "Setting irlan_client state!\n");
-       if ( self->state == IRLAN_IDLE) {
-               irlan_do_client_event( self, IRLAN_DISCOVERY_INDICATION, NULL);
-       } else {
-               DEBUG( 0, __FUNCTION__ "(), Hmm, got here too!\n");
-       }
-}
-
-/*
- * Function irlan_client_disconnect_indication (handle)
- *
- *    Callback function for the IrTTP layer. Indicates a disconnection of
- *    the specified connection (handle)
- */
-void irlan_client_disconnect_indication( void *instance, void *sap, 
-                                        LM_REASON reason, 
-                                        struct sk_buff *userdata) 
-{
-       struct irlan_cb *self;
-       struct tsap_cb *tsap;
-
-       self = ( struct irlan_cb *) instance;
-       tsap = ( struct tsap_cb *) sap;
-
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == IRLAN_MAGIC, return;);   
-       ASSERT( tsap != NULL, return;);
-       ASSERT( tsap->magic == TTP_TSAP_MAGIC, return;);
-       
-       DEBUG( 4, __FUNCTION__ "(), reason=%d\n", reason);
-       
-       if ( tsap == self->tsap_data) {
-               DEBUG( 4, "IrLAN, data channel disconnected by peer!\n");
-               self->connected = FALSE;
-       } else if ( tsap == self->tsap_ctrl) {
-               DEBUG( 4, "IrLAN, control channel disconnected by peer!\n");
-       } else {
-               DEBUG( 0, "Error, disconnect on unknown handle!\n");
-       }
-       
-       /* Stop IP from transmitting more packets */
-       /* irlan_client_flow_indication( handle, FLOW_STOP, priv); */
-
-       irlan_do_client_event( self, IRLAN_LMP_DISCONNECT, NULL);
-}
-       
-/*
- * Function irlan_control_data_indication (handle, skb)
- *
- *    This function gets the data that is received on the control channel
- *
- */
-void irlan_client_ctrl_data_indication( void *instance, void *sap, 
-                                       struct sk_buff *skb)
-{
-       struct irlan_cb *self;
-
-       DEBUG( 4, __FUNCTION__ "()\n");
-       
-       self = ( struct irlan_cb *) instance;
-
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == IRLAN_MAGIC, return;);
-       ASSERT( skb != NULL, return;);
-       
-       DEBUG( 4, "Got IRLAN_DATA_INDICATION!\n");
-       irlan_do_client_event( self, IRLAN_DATA_INDICATION, skb); 
-}
-
-/*
- * Function irlan_client_open_tsaps (self)
- *
- *    Initialize callbacks and open IrTTP TSAPs
- *
- */
-void irlan_client_open_tsaps( struct irlan_cb *self) 
-{
-       /* struct irlan_frame frame; */
-       struct notify_t notify_ctrl;
-       struct notify_t notify_data;
-
-       DEBUG( 4, __FUNCTION__ "()\n");
-       
-       irda_notify_init( &notify_ctrl);
-       irda_notify_init( &notify_data);
-
-       /* Set up callbacks */
-       notify_ctrl.data_indication       = irlan_client_ctrl_data_indication;
-       notify_ctrl.connect_confirm       = irlan_client_connect_confirm;
-       notify_ctrl.disconnect_indication = irlan_client_disconnect_indication;
-       notify_ctrl.instance              = self;
-       strncpy( notify_ctrl.name, "IrLAN ctrl", NOTIFY_MAX_NAME);
-       
-       notify_data.data_indication       = irlan_eth_rx;
-       notify_data.udata_indication      = irlan_eth_rx;
-       notify_data.connect_confirm       = irlan_client_connect_confirm;
-       notify_data.flow_indication       = irlan_eth_flow_indication;
-       notify_data.disconnect_indication = irlan_client_disconnect_indication;
-       notify_data.instance              = self;
-       strncpy( notify_data.name, "IrLAN data", NOTIFY_MAX_NAME);
-
-       /* Create TSAP's */
-       self->tsap_ctrl = irttp_open_tsap( LSAP_ANY, 
-                                          DEFAULT_INITIAL_CREDIT, 
-                                          &notify_ctrl);
-       self->tsap_data = irttp_open_tsap( LSAP_ANY, 
-                                          DEFAULT_INITIAL_CREDIT,
-                                          &notify_data);
-}
-
-/*
- * Function irlan_client_connect_confirm (handle, skb)
- *
- *    Connection to peer IrLAN laye confirmed
- *
- */
-void irlan_client_connect_confirm( void *instance, void *sap, 
-                                  struct qos_info *qos, int max_sdu_size,
-                                  struct sk_buff *skb) 
-{
-       struct irlan_cb *self;
-
-       DEBUG( 4, __FUNCTION__ "()\n");
-
-       self = ( struct irlan_cb *) instance;
-
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == IRLAN_MAGIC, return;);
-
-       /* TODO: we could set the MTU depending on the max_sdu_size */
-
-       irlan_do_client_event( self, IRLAN_CONNECT_COMPLETE, NULL);
-}
-
-/*
- * Function irlan_client_reconnect_data_channel (self)
- *
- *    Try to reconnect data channel (currently not used)
- *
- */
-void irlan_client_reconnect_data_channel( struct irlan_cb *self) 
-{
-       struct sk_buff *skb;
-       __u8 *frame;
-               
-       DEBUG( 4, __FUNCTION__ "()\n");
-
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == IRLAN_MAGIC, return;);
-       
-       skb =  dev_alloc_skb( 128);
-       if (skb == NULL) {
-               DEBUG( 0, __FUNCTION__
-                      "(), Could not allocate an sk_buff of length %d\n", 64);
-               return;
-       }
-
-       /* Reserve space for TTP, LMP, and LAP header */
-       skb_reserve( skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
-       skb_put( skb, 2);
-       
-       frame = skb->data;
-       
-       frame[0] = CMD_RECONNECT_DATA_CHAN;
-       frame[1] = 0x01;
-       insert_array_param( skb, "RECONNECT_KEY", 
-                           self->t.client.reconnect_key, 
-                           self->t.client.key_len);
-       
-       irttp_data_request( self->tsap_ctrl, skb);      
-}
-
-/*
- * Function irlan_client_extract_params (skb)
- *
- *    Extract all parameters from received buffer, then feed them to 
- *    check_params for parsing
- *
- */
-void irlan_client_extract_params( struct irlan_cb *self, 
-                                 struct sk_buff *skb)
-{
-       __u8 *frame;
-       __u8 *ptr;
-       int count;
-       int ret;
-       int val_len;
-       int i;
-
-       ASSERT( skb != NULL, return;);  
-       
-       DEBUG( 4, __FUNCTION__ "() skb->len=%d\n", (int) skb->len);
-       
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == IRLAN_MAGIC, return;);
-       
-       if ( skb == NULL) {
-               DEBUG( 0, __FUNCTION__ "(), Got NULL skb!\n");
-               return;
-       }
-       frame = skb->data;
-
-       /* 
-        *  Check return code and print it if not success 
-        */
-       if ( frame[0])
-               print_ret_code( frame[0]);
-       
-       /* How many parameters? */
-       count = frame[1];
-
-       DEBUG( 4, "Got %d parameters\n", count);
-       
-       ptr = frame+2;
-
-       /* For all parameters */
-       for ( i=0; i<count;i++) {
-               ret = irlan_get_response_param( ptr, self->name, self->value, 
-                                               &val_len);
-               if ( ret == -1) {
-                       DEBUG( 0, __FUNCTION__ "(), IrLAN, Error!\n");
-                       return;
-               }
-               ptr+=ret;
-               check_response_param( self, self->name, self->value, val_len);
-       }
-}
-
-/*
- * Function check_param (param, value)
- *
- *    Check which parameter is received and update local variables
- *
- */
-void check_response_param( struct irlan_cb *self, char *param, 
-                          char *value, int val_len) 
-{
-       int i;
-       __u8 *bytes;
-
-       DEBUG( 4, __FUNCTION__ "()\n");
-
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == IRLAN_MAGIC, return;);
-
-       /*
-        *  Media type
-        */
-       if ( strcmp( param, "MEDIA") == 0) {
-               if ( strcmp( value, "802.3") == 0)
-                       self->media = MEDIA_802_3;
-               else
-                       self->media = MEDIA_802_5;
-               return;
-       }
-       /*
-        *  IRLAN version
-        */
-       if ( strcmp( param, "IRLAN_VER") == 0) {
-               DEBUG( 4, "IrLAN version %d.%d\n", 
-                       (__u8) value[0], (__u8) value[1]);
-               return;
-       }
-       /*
-        *  Which remote TSAP to use for data channel
-        */
-       if ( strcmp( param, "DATA_CHAN") == 0) {
-               self->dtsap_sel_data = value[0];
-               DEBUG( 4, "Data TSAP = %02x\n", self->dtsap_sel_data);
-               return;
-       }
-       /*
-        *  RECONNECT_KEY, in case the link goes down!
-        */
-       if ( strcmp( param, "RECONNECT_KEY") == 0) {
-               DEBUG( 4, "Got reconnect key: ");
-               /* for (i = 0; i < val_len; i++) */
-/*                     printk( "%02x", value[i]); */
-               memcpy( self->t.client.reconnect_key, value, val_len);
-               self->t.client.key_len = val_len;
-               DEBUG( 4, "\n");
-       }
-       /*
-        *  FILTER_ENTRY, have we got the ethernet address?
-        */
-       if ( strcmp( param, "FILTER_ENTRY") == 0) {
-               bytes = value;
-               DEBUG( 4, "Ethernet address = %02x:%02x:%02x:%02x:%02x:%02x\n",
-                      bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], 
-                      bytes[5]);
-               for (i = 0; i < 6; i++) 
-                       self->dev.dev_addr[i] = bytes[i];
-#if 0
-       /*
-        * When we get a new MAC address do a gratuitous ARP. This is useful
-        * if we have changed access points on the same subnet.
-        */
-               DEBUG( 4, "IrLAN: Sending gratuitous ARP\n");
-               arp_send( ARPOP_REQUEST, ETH_P_ARP, self->dev.pa_addr,
-                       &self->dev, self->dev.pa_addr, NULL,
-                       self->dev.dev_addr, NULL);
-#endif
-       }
-}
-
-/*
- * Function irlan_client_get_value_confirm (obj_id, value)
- *
- *    Got results from previous GetValueByClass request
- *
- */
-void irlan_client_get_value_confirm( __u16 obj_id, struct ias_value *value,
-                                    void *priv) 
-{
-       struct irlan_cb *self;
-       
-       DEBUG( 4, __FUNCTION__ "()\n");
-
-       ASSERT( priv != NULL, return;);
-
-       self = ( struct irlan_cb *) priv;
-
-       ASSERT( self->magic == IRLAN_MAGIC, return;);
-
-       switch ( value->type) {
-       case IAS_INTEGER:
-               self->dtsap_sel_ctrl = value->t.integer;
-
-               if ( value->t.integer != -1) {
-                       irlan_do_client_event( self, IRLAN_IAS_PROVIDER_AVAIL,
-                                              NULL);
-                       return;
-               }
-               break;
-       case IAS_STRING:
-               DEBUG( 0, __FUNCTION__ "(), got string %s\n", value->t.string);
-               break;
-       case IAS_OCT_SEQ:
-               DEBUG( 0, __FUNCTION__ "(), OCT_SEQ not implemented\n");
-               break;
-       case IAS_MISSING:
-               DEBUG( 0, __FUNCTION__ "(), MISSING not implemented\n");
-               break;
-       default:
-               DEBUG( 0, __FUNCTION__ "(), unknown type!\n");
-               break;
-       }
-       irlan_do_client_event( self, IRLAN_IAS_PROVIDER_NOT_AVAIL, NULL);
-}
-
-#ifdef MODULE
-
-MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
-MODULE_DESCRIPTION("The Linux IrDA LAN protocol"); 
-
-/*
- * Function init_module (void)
- *
- *    Initialize the IrLAN module, this function is called by the
- *    modprobe(1) program.
- */
-int init_module(void) 
-{
-       DEBUG( 4, __FUNCTION__ "(), irlan_client.c\n");
-
-       irlan_client_init();
-
-       return 0;
-}
-
-/*
- * Function cleanup_module (void)
- *
- *    Remove the IrLAN module, this function is called by the rmmod(1)
- *    program
- */
-void cleanup_module(void) 
-{
-       DEBUG( 4, "--> irlan, cleanup_module\n");
-       /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
-
-       /* Free some memory */
-       irlan_client_cleanup();
-
-       DEBUG( 4, "irlan, cleanup_module -->\n");
-}
-
-#endif /* MODULE */
-
-
-
-
-
-
-
-
-
diff --git a/net/irda/irlan/irlan_cli_event.c b/net/irda/irlan/irlan_cli_event.c
deleted file mode 100644 (file)
index 2f01a4b..0000000
+++ /dev/null
@@ -1,494 +0,0 @@
-/*********************************************************************
- *                
- * Filename:      irlan_cli_event.c
- * Version:       0.1
- * Description:   IrLAN Client FSM (Finite State Machine)
- * Status:        Experimental.
- * Author:        Dag Brattli <dagb@cs.uit.no>
- * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Wed Dec  9 02:36:49 1998
- * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * 
- *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, 
- *     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.
- *
- *     Neither Dag Brattli nor University of Tromsø admit liability nor
- *     provide warranty for any of this software. This material is 
- *     provided "AS-IS" and at no charge.
- *
- ********************************************************************/
-
-#include <linux/skbuff.h>
-
-#include <net/irda/irda.h>
-#include <net/irda/irmod.h>
-#include <net/irda/iriap.h>
-#include <net/irda/irlmp.h>
-#include <net/irda/irttp.h>
-
-#include <net/irda/irlan_common.h>
-#include <net/irda/irlan_cli.h>
-#include <net/irda/irlan_event.h>
-
-static int irlan_client_state_idle ( struct irlan_cb *self, 
-                                    IRLAN_EVENT event, 
-                                    struct sk_buff *skb);
-static int irlan_client_state_query( struct irlan_cb *self, 
-                                    IRLAN_EVENT event, 
-                                    struct sk_buff *skb);
-static int irlan_client_state_conn ( struct irlan_cb *self, 
-                                    IRLAN_EVENT event, 
-                                    struct sk_buff *skb);
-static int irlan_client_state_info ( struct irlan_cb *self, 
-                                    IRLAN_EVENT event, 
-                                    struct sk_buff *skb);
-static int irlan_client_state_media( struct irlan_cb *self, 
-                                    IRLAN_EVENT event, 
-                                    struct sk_buff *skb);
-static int irlan_client_state_open ( struct irlan_cb *self, 
-                                    IRLAN_EVENT event, 
-                                    struct sk_buff *skb);
-static int irlan_client_state_wait ( struct irlan_cb *self, 
-                                    IRLAN_EVENT event, 
-                                    struct sk_buff *skb);
-static int irlan_client_state_arb  ( struct irlan_cb *self, 
-                                    IRLAN_EVENT event, 
-                                    struct sk_buff *skb);
-static int irlan_client_state_data ( struct irlan_cb *self, 
-                                    IRLAN_EVENT event, 
-                                    struct sk_buff *skb);
-static int irlan_client_state_close( struct irlan_cb *self, 
-                                    IRLAN_EVENT event, 
-                                    struct sk_buff *skb);
-static int irlan_client_state_sync ( struct irlan_cb *self, 
-                                    IRLAN_EVENT event, 
-                                    struct sk_buff *skb);
-
-static int (*state[])( struct irlan_cb *, IRLAN_EVENT event, 
-                      struct sk_buff *) = 
-{ 
-       irlan_client_state_idle,
-       irlan_client_state_query,
-       irlan_client_state_conn,
-       irlan_client_state_info,
-       irlan_client_state_media,
-       irlan_client_state_open,
-       irlan_client_state_wait,
-       irlan_client_state_arb,
-       irlan_client_state_data,
-       irlan_client_state_close,
-       irlan_client_state_sync
-};
-
-void irlan_do_client_event( struct irlan_cb *self, 
-                           IRLAN_EVENT event, 
-                           struct sk_buff *skb) 
-{
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == IRLAN_MAGIC, return;);
-
-       (*state[ self->state]) ( self, event, skb);
-}
-
-/*
- * Function irlan_client_state_idle (event, skb, info)
- *
- *    IDLE, We are waiting for an indication that there is a provider
- *    available.
- */
-static int irlan_client_state_idle( struct irlan_cb *self, 
-                                   IRLAN_EVENT event, 
-                                   struct sk_buff *skb) 
-{
-       DEBUG( 4, "irlan_client_state_idle()\n");
-
-       ASSERT( self != NULL, return -1;);
-       ASSERT( self->magic == IRLAN_MAGIC, return -1;);
-       
-       switch( event) {
-       case IRLAN_DISCOVERY_INDICATION:
-               /* Get some values from peer IAS */
-#if 0
-               iriap_getvaluebyclass_request( self->daddr,
-                                              /*  "PnP", "DeviceID",  */
-                                              "Device", "DeviceName",
-                                              irlan_client_get_value_confirm,
-                                              self);
-#endif
-               iriap_getvaluebyclass_request( self->daddr,
-                                              "IrLAN", "IrDA:TinyTP:LsapSel",
-                                              irlan_client_get_value_confirm,
-                                              self);
-
-               irlan_next_state( self, IRLAN_QUERY);
-               break;
-       default:
-               DEBUG( 4, __FUNCTION__ "(), Unknown event %d\n", event);
-               break;
-       }
-       if ( skb) {
-               dev_kfree_skb( skb);
-       }
-       return 0;
-}
-
-/*
- * Function irlan_client_state_query (event, skb, info)
- *
- *    QUERY, We have queryed the remote IAS and is ready to connect
- *    to provider, just waiting for the confirm.
- *
- */
-static int irlan_client_state_query( struct irlan_cb *self, 
-                                    IRLAN_EVENT event, 
-                                    struct sk_buff *skb) 
-{
-       DEBUG( 4, __FUNCTION__ "()\n");
-
-       ASSERT( self != NULL, return -1;);
-       ASSERT( self->magic == IRLAN_MAGIC, return -1;);
-       
-       switch( event) {
-       case IRLAN_IAS_PROVIDER_AVAIL:
-               ASSERT( self->dtsap_sel_ctrl != 0, return -1;);
-
-               self->t.client.open_retries = 0;
-               
-               irttp_connect_request( self->tsap_ctrl, self->dtsap_sel_ctrl, 
-                                      self->daddr, NULL, IRLAN_MTU, NULL);
-               irlan_next_state( self, IRLAN_CONN);
-               break;
-       case IRLAN_IAS_PROVIDER_NOT_AVAIL:
-               DEBUG( 0, __FUNCTION__ "(), IAS_PROVIDER_NOT_AVAIL\n");
-               irlan_next_state( self, IRLAN_IDLE);
-               break;
-       case IRLAN_LMP_DISCONNECT:
-       case IRLAN_LAP_DISCONNECT:
-               irlan_next_state( self, IRLAN_IDLE);
-               break;
-       default:
-               DEBUG( 0, __FUNCTION__"(), Unknown event %d\n", event);
-               break;
-       }
-       if ( skb) {
-               dev_kfree_skb( skb);
-       }
-       
-       return 0;
-}
-
-/*
- * Function irlan_client_state_conn (event, skb, info)
- *
- *    CONN, We have connected to a provider but has not issued any
- *    commands yet.
- *
- */
-static int irlan_client_state_conn( struct irlan_cb *self, 
-                                   IRLAN_EVENT event, 
-                                   struct sk_buff *skb) 
-{
-       DEBUG( 4, __FUNCTION__ "()\n");
-       
-       ASSERT( self != NULL, return -1;);
-       
-       switch( event) {
-       case IRLAN_CONNECT_COMPLETE:
-               /* Send getinfo cmd */
-               irlan_get_provider_info( self);
-               irlan_next_state( self, IRLAN_INFO);
-               break;
-       case IRLAN_LMP_DISCONNECT:
-       case IRLAN_LAP_DISCONNECT:
-               irlan_next_state( self, IRLAN_IDLE);
-               break;
-       default:
-               DEBUG( 0, __FUNCTION__ "(), Unknown event %d\n", event);
-               break;
-       }
-       if ( skb) {
-               dev_kfree_skb( skb);
-       }
-       
-       return 0;
-}
-
-/*
- * Function irlan_client_state_info (self, event, skb, info)
- *
- *    INFO, We have issued a GetInfo command and is awaiting a reply.
- */
-static int irlan_client_state_info( struct irlan_cb *self, 
-                                   IRLAN_EVENT event, 
-                                   struct sk_buff *skb) 
-{
-       DEBUG( 4, __FUNCTION__ "()\n");
-
-       ASSERT( self != NULL, return -1;);
-       
-       switch( event) {
-       case IRLAN_DATA_INDICATION:
-               ASSERT( skb != NULL, return -1;);
-       
-               irlan_client_extract_params( self, skb);
-               
-               irlan_next_state( self, IRLAN_MEDIA);
-               
-               irlan_get_media_char( self);
-               break;
-               
-       case IRLAN_LMP_DISCONNECT:
-       case IRLAN_LAP_DISCONNECT:
-               irlan_next_state( self, IRLAN_IDLE);
-               break;
-       default:
-               DEBUG( 0, __FUNCTION__ "(), Unknown event %d\n", event);
-               break;
-       }
-       if ( skb) {
-               dev_kfree_skb( skb);
-       }
-       
-       return 0;
-}
-
-/*
- * Function irlan_client_state_media (self, event, skb, info)
- *
- *    MEDIA, The irlan_client has issued a GetMedia command and is awaiting a
- *    reply.
- *
- */
-static int irlan_client_state_media( struct irlan_cb *self, 
-                                    IRLAN_EVENT event, 
-                                    struct sk_buff *skb) 
-{
-       DEBUG( 4, __FUNCTION__ "()\n");
-       
-       ASSERT( self != NULL, return -1;);
-
-       switch( event) {
-       case IRLAN_DATA_INDICATION:
-               irlan_client_extract_params( self, skb);
-               irlan_open_data_channel( self);
-               irlan_next_state( self, IRLAN_OPEN);
-               break;
-       case IRLAN_LMP_DISCONNECT:
-       case IRLAN_LAP_DISCONNECT:
-               irlan_next_state( self, IRLAN_IDLE);
-               break;
-       default:
-               DEBUG( 0, "irlan_client_state_media, Unknown event %d\n", 
-                      event);
-               break;
-       }
-       if ( skb) {
-               dev_kfree_skb( skb);
-       }
-       
-       return 0;
-}
-
-/*
- * Function irlan_client_state_open (self, event, skb, info)
- *
- *    OPEN, The irlan_client has issued a OpenData command and is awaiting a
- *    reply
- *
- */
-static int irlan_client_state_open( struct irlan_cb *self, 
-                                   IRLAN_EVENT event, 
-                                   struct sk_buff *skb) 
-{
-       struct qos_info qos;
-
-       DEBUG( 4, __FUNCTION__ "()\n");
-       
-       ASSERT( self != NULL, return -1;);
-
-       switch( event) {
-       case IRLAN_DATA_INDICATION:
-               irlan_client_extract_params( self, skb);
-               
-               /*
-                *  Check if we have got the remote TSAP for data 
-                *  communications
-                */
-               ASSERT( self->dtsap_sel_data != 0, return -1;);
-
-               qos.link_disc_time.bits = 0x01; /* 3 secs */
-
-               irttp_connect_request( self->tsap_data, 
-                                      self->dtsap_sel_data, self->daddr,
-                                      NULL, IRLAN_MTU, NULL);
-               
-               irlan_next_state( self, IRLAN_DATA);
-               break;
-
-       case IRLAN_LMP_DISCONNECT:
-       case IRLAN_LAP_DISCONNECT:
-               irlan_next_state( self, IRLAN_IDLE);
-               break;
-       default:
-               DEBUG( 0, __FUNCTION__ "(), Unknown event %d\n", 
-                      event);
-               break;
-       }
-       
-       if ( skb) {
-               dev_kfree_skb( skb);
-       }
-
-       return 0;
-}
-
-/*
- * Function irlan_client_state_wait (self, event, skb, info)
- *
- *    WAIT, The irlan_client is waiting for the local provider to enter the
- *    provider OPEN state.
- *
- */
-static int irlan_client_state_wait( struct irlan_cb *self, 
-                                   IRLAN_EVENT event, 
-                                   struct sk_buff *skb) 
-{
-       DEBUG( 4, "irlan_client_state_wait()\n");
-       
-       ASSERT( self != NULL, return -1;);
-       
-       switch( event) {
-       case IRLAN_LMP_DISCONNECT:
-       case IRLAN_LAP_DISCONNECT:
-               irlan_next_state( self, IRLAN_IDLE);
-               break;
-       default:
-               DEBUG( 0, __FUNCTION__ "(), Unknown event %d\n", 
-                      event);
-               break;
-       }
-       if ( skb) {
-               dev_kfree_skb( skb);
-       }
-       
-       return 0;
-}
-
-static int irlan_client_state_arb( struct irlan_cb *self, 
-                                  IRLAN_EVENT event, 
-                                  struct sk_buff *skb) 
-{
-       DEBUG( 0, __FUNCTION__ "(), not implemented!\n");
-       
-       if ( skb) {
-               dev_kfree_skb( skb);
-       }
-       return 0;
-}
-
-/*
- * Function irlan_client_state_data (self, event, skb, info)
- *
- *    DATA, The data channel is connected, allowing data transfers between
- *    the local and remote machines.
- *
- */
-static int irlan_client_state_data( struct irlan_cb *self, 
-                                   IRLAN_EVENT event, 
-                                   struct sk_buff *skb) 
-{
-       struct irmanager_event mgr_event;
-
-       DEBUG( 4, __FUNCTION__ "()\n");
-
-       ASSERT( self != NULL, return -1;);
-       ASSERT( self->magic == IRLAN_MAGIC, return -1;);
-
-       switch( event) {
-       case IRLAN_CONNECT_COMPLETE:
-               irlan_get_unicast_addr( self);
-               irlan_open_unicast_addr( self);
-               /* irlan_set_broadcast_filter( self, TRUE);  */
-
-               DEBUG( 4, "IrLAN, We are now connected!\n");
-
-               /* irlan_next_state( LAN_DATA); */
-               break;
-       case IRLAN_DATA_INDICATION:
-               irlan_client_extract_params( self, skb);
-
-               /* irlan_client_flow_indication( self->data_tsap, FLOW_START,  */
-/*                                     self); */
-
-               /* Make sure the code below only runs once */
-               if ( !self->connected) {
-                       mgr_event.event = EVENT_IRLAN_START;
-                       sprintf( mgr_event.devname, "%s", self->ifname);
-                       irmanager_notify( &mgr_event);
-
-                       self->connected = TRUE;
-               }
-               break;
-               
-       case IRLAN_LMP_DISCONNECT:
-       case IRLAN_LAP_DISCONNECT:
-               mgr_event.event = EVENT_IRLAN_STOP;
-               sprintf( mgr_event.devname, "%s", self->ifname);
-               irmanager_notify( &mgr_event);
-
-               irlan_next_state( self, IRLAN_IDLE);
-               break;
-       default:
-               DEBUG( 0, __FUNCTION__ "(), Unknown event %d\n", event);
-               break;
-       }
-       if ( skb) {
-               dev_kfree_skb( skb);
-       }
-       
-       return 0;
-}
-
-/*
- * Function irlan_client_state_close (self, event, skb, info)
- *
- *    
- *
- */
-static int irlan_client_state_close( struct irlan_cb *self, 
-                                    IRLAN_EVENT event, 
-                                    struct sk_buff *skb) 
-{
-       DEBUG( 0, __FUNCTION__ "()\n");
-
-       if ( skb) {
-               dev_kfree_skb( skb);
-       }
-
-       return 0;
-}
-
-/*
- * Function irlan_client_state_sync (self, event, skb, info)
- *
- *    
- *
- */
-static int irlan_client_state_sync( struct irlan_cb *self, 
-                                   IRLAN_EVENT event, 
-                                   struct sk_buff *skb) 
-{
-       DEBUG( 0, __FUNCTION__ "()\n");
-       
-       if ( skb) {
-               dev_kfree_skb( skb);
-       }
-       
-       return 0;
-}
-
diff --git a/net/irda/irlan/irlan_client.c b/net/irda/irlan/irlan_client.c
new file mode 100644 (file)
index 0000000..78e33c4
--- /dev/null
@@ -0,0 +1,617 @@
+/*********************************************************************
+ *                
+ * Filename:      irlan_client.c
+ * Version:       0.9
+ * Description:   IrDA LAN Access Protocol (IrLAN) Client
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Sun Aug 31 20:14:37 1997
+ * Modified at:   Wed Feb 17 23:29:34 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * Sources:       skeleton.c by Donald Becker <becker@CESDIS.gsfc.nasa.gov>
+ *                slip.c by Laurence Culhane, <loz@holmes.demon.co.uk>
+ *                          Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
+ * 
+ *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, 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.
+ *
+ *     Neither Dag Brattli nor University of Tromsø admit liability nor
+ *     provide warranty for any of this software. This material is 
+ *     provided "AS-IS" and at no charge.
+ *
+ ********************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/inetdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/if_arp.h>
+#include <net/arp.h>
+
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/byteorder.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irttp.h>
+#include <net/irda/irlmp.h>
+#include <net/irda/irias_object.h>
+#include <net/irda/iriap.h>
+#include <net/irda/timer.h>
+
+#include <net/irda/irlan_common.h>
+#include <net/irda/irlan_event.h>
+#include <net/irda/irlan_eth.h>
+#include <net/irda/irlan_provider.h>
+#include <net/irda/irlan_client.h>
+
+#undef CONFIG_IRLAN_GRATUITOUS_ARP
+
+static void irlan_client_ctrl_disconnect_indication(void *instance, void *sap, 
+                                                   LM_REASON reason, 
+                                                   struct sk_buff *);
+
+static void irlan_client_ctrl_data_indication(void *instance, void *sap, 
+                                             struct sk_buff *skb);
+
+static void irlan_client_ctrl_connect_confirm(void *instance, void *sap, 
+                                             struct qos_info *qos, 
+                                             int max_sdu_size,
+                                             struct sk_buff *);
+
+static void irlan_check_response_param(struct irlan_cb *self, char *param, 
+                                      char *value, int val_len);
+
+static void irlan_client_kick_timer_expired(unsigned long data)
+{
+       struct irlan_cb *self = (struct irlan_cb *) data;
+       
+       DEBUG(2, __FUNCTION__ "()\n");
+
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == IRLAN_MAGIC, return;);
+       
+       /*  
+        * If we are in peer mode, the client may not have got the discovery
+        * indication it needs to make progress. If the client is still in 
+        * IDLE state, we must kick it to, but only if the provider is not IDLE
+        */
+       if ((self->access_type == ACCESS_PEER) && 
+           (self->client.state == IRLAN_IDLE) &&
+           (self->provider.state != IRLAN_IDLE)) {
+               irlan_client_wakeup(self, self->saddr, self->daddr);
+       }
+}
+
+void irlan_client_start_kick_timer(struct irlan_cb *self, int timeout)
+{
+       DEBUG(4, __FUNCTION__ "()\n");
+       
+       irda_start_timer(&self->client.kick_timer, timeout, 
+                        (unsigned long) self, 
+                        irlan_client_kick_timer_expired);
+}
+
+void irlan_client_wakeup(struct irlan_cb *self, __u32 saddr, __u32 daddr)
+{
+       struct irmanager_event mgr_event;
+
+       DEBUG(2, __FUNCTION__ "()\n");
+
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+       if (self->client.state == IRLAN_IDLE) {
+               /* saddr may have changed! */
+               self->saddr = saddr;
+               
+               /* Check if network device is up */
+               if (self->dev.start) {
+                       /* Open TSAPs */
+                       irlan_client_open_ctrl_tsap(self);
+                       irlan_provider_open_ctrl_tsap(self);
+                       irlan_open_data_tsap(self);
+                       
+                       irlan_do_client_event(self, IRLAN_DISCOVERY_INDICATION,
+                                             NULL);
+               } else if (self->notify_irmanager) {
+                       /* 
+                        * Tell irmanager that the device can now be 
+                        * configured but only if the device was not taken
+                        * down by the user
+                        */
+                       mgr_event.event = EVENT_IRLAN_START;
+                       sprintf(mgr_event.devname, "%s", self->ifname);
+                       irmanager_notify(&mgr_event);
+
+                       /* 
+                        * We set this so that we only notify once, since if 
+                        * configuration of the network device fails, the user
+                        * will have to sort it out first anyway. No need to 
+                        * try again.
+                        */
+                       self->notify_irmanager = FALSE;
+               }
+               /* Restart watchdog timer */
+               irlan_start_watchdog_timer(self, IRLAN_TIMEOUT);
+
+               /* Start kick timer */
+               irlan_client_start_kick_timer(self, 200);
+       } else {
+               DEBUG(2, __FUNCTION__ "(), state=%s\n", 
+                     irlan_state[ self->client.state]);
+               /*  
+                *  If we get here, it's obvious that the last 
+                *  connection attempt has failed, so its best 
+                *  to go back to idle!
+                */
+               irlan_do_client_event(self, IRLAN_LMP_DISCONNECT, NULL);
+       }
+}
+
+/*
+ * Function irlan_discovery_indication (daddr)
+ *
+ *    Remote device with IrLAN server support discovered
+ *
+ */
+void irlan_client_discovery_indication(DISCOVERY *discovery) 
+{
+       struct irlan_cb *self, *entry;
+       __u32 saddr, daddr;
+       
+       DEBUG(2, __FUNCTION__"()\n");
+
+       ASSERT(irlan != NULL, return;);
+       ASSERT(discovery != NULL, return;);
+
+       saddr = discovery->saddr;
+       daddr = discovery->daddr;
+
+       /* 
+        *  Check if we already have an instance for dealing with this 
+        *  provider.
+        */
+       self = (struct irlan_cb *) hashbin_find(irlan, daddr, NULL);
+       if (self) {
+               ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+               DEBUG(2, __FUNCTION__ "(), Found instance!\n");
+               
+               irlan_client_wakeup(self, saddr, daddr);
+
+               return;
+       }
+       
+       /* 
+        * We have no instance for daddr, so try and find an unused one
+        */
+       self = hashbin_find(irlan, DEV_ADDR_ANY, NULL);
+       if (self) {
+               DEBUG(2, __FUNCTION__ "(), Found instance with DEV_ADDR_ANY!\n");
+               /*
+                * Rehash instance, now we have a client (daddr) to serve.
+                */
+               entry = hashbin_remove(irlan, self->daddr, NULL);
+               ASSERT( entry == self, return;);
+
+               self->daddr = daddr;
+               self->saddr = saddr;
+
+               DEBUG(2, __FUNCTION__ "(), daddr=%08x\n", self->daddr);
+               hashbin_insert(irlan, (QUEUE*) self, self->daddr, NULL);
+               
+               /* Check if network device has been registered */
+               if (!self->netdev_registered)
+                       irlan_register_netdev(self);
+               
+               /* Remember that we might have to start a new provider */
+               self->client.start_new_provider = TRUE;
+       } else {
+               DEBUG(2, __FUNCTION__ "(), Found none, starting new one!\n");
+               /* No instance available, so we have to start one! */
+               self = irlan_open(saddr, daddr, TRUE);
+               if (!self) {
+                       DEBUG(2, __FUNCTION__ "(), irlan_open failed!\n");
+                       return;
+               }
+               ASSERT( self != NULL, return;);
+       }
+       /* Restart watchdog timer */
+       irlan_start_watchdog_timer(self, IRLAN_TIMEOUT);
+}
+       
+/*
+ * Function irlan_client_data_indication (handle, skb)
+ *
+ *    This function gets the data that is received on the control channel
+ *
+ */
+static void irlan_client_ctrl_data_indication(void *instance, void *sap, 
+                                             struct sk_buff *skb)
+{
+       struct irlan_cb *self;
+       
+       DEBUG(4, __FUNCTION__ "()\n");
+       
+       self = (struct irlan_cb *) instance;
+       
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == IRLAN_MAGIC, return;);
+       ASSERT(skb != NULL, return;);
+       
+       irlan_do_client_event(self, IRLAN_DATA_INDICATION, skb); 
+}
+
+static void irlan_client_ctrl_disconnect_indication(void *instance, void *sap, 
+                                                   LM_REASON reason, 
+                                                   struct sk_buff *userdata) 
+{
+       struct irlan_cb *self;
+       struct tsap_cb *tsap;
+
+       DEBUG(4, __FUNCTION__ "(), reason=%d\n", reason);
+       
+       self = (struct irlan_cb *) instance;
+       tsap = (struct tsap_cb *) sap;
+
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == IRLAN_MAGIC, return;);    
+       ASSERT(tsap != NULL, return;);
+       ASSERT(tsap->magic == TTP_TSAP_MAGIC, return;);
+       
+       ASSERT(tsap == self->client.tsap_ctrl, return;);
+
+       irlan_do_client_event(self, IRLAN_LMP_DISCONNECT, NULL);
+}
+
+/*
+ * Function irlan_client_open_tsaps (self)
+ *
+ *    Initialize callbacks and open IrTTP TSAPs
+ *
+ */
+void irlan_client_open_ctrl_tsap(struct irlan_cb *self)
+{
+       struct notify_t notify;
+       struct tsap_cb *tsap;
+
+       DEBUG(4, __FUNCTION__ "()\n");
+
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+       /* Check if already open */
+       if (self->client.tsap_ctrl)
+               return;
+
+       irda_notify_init(&notify);
+
+       /* Set up callbacks */
+       notify.data_indication       = irlan_client_ctrl_data_indication;
+       notify.connect_confirm       = irlan_client_ctrl_connect_confirm;
+       notify.disconnect_indication = irlan_client_ctrl_disconnect_indication;
+       notify.instance = self;
+       strncpy(notify.name, "IrLAN ctrl (c)", NOTIFY_MAX_NAME);
+       
+       tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT, &notify);
+       if (!tsap) {
+               DEBUG(2, __FUNCTION__ "(), Got no tsap!\n");
+               return;
+       }
+       self->client.tsap_ctrl = tsap;
+}
+
+/*
+ * Function irlan_client_connect_confirm (handle, skb)
+ *
+ *    Connection to peer IrLAN laye confirmed
+ *
+ */
+static void irlan_client_ctrl_connect_confirm(void *instance, void *sap, 
+                                             struct qos_info *qos, 
+                                             int max_sdu_size,
+                                             struct sk_buff *skb) 
+{
+       struct irlan_cb *self;
+
+       DEBUG(4, __FUNCTION__ "()\n");
+
+       self = (struct irlan_cb *) instance;
+
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+       /* TODO: we could set the MTU depending on the max_sdu_size */
+
+       irlan_do_client_event(self, IRLAN_CONNECT_COMPLETE, NULL);
+}
+
+/*
+ * Function irlan_client_reconnect_data_channel (self)
+ *
+ *    Try to reconnect data channel (currently not used)
+ *
+ */
+void irlan_client_reconnect_data_channel(struct irlan_cb *self) 
+{
+       struct sk_buff *skb;
+       __u8 *frame;
+               
+       DEBUG(4, __FUNCTION__ "()\n");
+
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == IRLAN_MAGIC, return;);
+       
+       skb = dev_alloc_skb(128);
+       if (!skb)
+               return;
+
+       /* Reserve space for TTP, LMP, and LAP header */
+       skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+       skb_put(skb, 2);
+       
+       frame = skb->data;
+       
+       frame[0] = CMD_RECONNECT_DATA_CHAN;
+       frame[1] = 0x01;
+       irlan_insert_array_param(skb, "RECONNECT_KEY", 
+                                self->client.reconnect_key,
+                                self->client.key_len);
+       
+       irttp_data_request(self->client.tsap_ctrl, skb);        
+}
+
+/*
+ * Function irlan_client_extract_params (skb)
+ *
+ *    Extract all parameters from received buffer, then feed them to 
+ *    check_params for parsing
+ *
+ */
+void irlan_client_extract_params(struct irlan_cb *self, struct sk_buff *skb)
+{
+       __u8 *frame;
+       __u8 *ptr;
+       int count;
+       int ret;
+       __u16 val_len;
+       int i;
+        char *name;
+        char *value;
+
+       ASSERT(skb != NULL, return;);   
+       
+       DEBUG(4, __FUNCTION__ "() skb->len=%d\n", (int) skb->len);
+       
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == IRLAN_MAGIC, return;);
+       
+       if (!skb) {
+               DEBUG(2, __FUNCTION__ "(), Got NULL skb!\n");
+               return;
+       }
+       frame = skb->data;
+       
+       /* 
+        *  Check return code and print it if not success 
+        */
+       if (frame[0]) {
+               print_ret_code(frame[0]);
+               return;
+       }
+       
+       name = kmalloc(255, GFP_ATOMIC);
+       if (!name)
+               return;
+       value = kmalloc(1016, GFP_ATOMIC);
+       if (!value) {
+               kfree(name);
+               return;
+       }
+
+       /* How many parameters? */
+       count = frame[1];
+
+       DEBUG(4, __FUNCTION__ "(), got %d parameters\n", count);
+       
+       ptr = frame+2;
+
+       /* For all parameters */
+       for (i=0; i<count;i++) {
+               ret = irlan_get_param(ptr, name, value, &val_len);
+               if (ret == -1) {
+                       DEBUG(2, __FUNCTION__ "(), IrLAN, Error!\n");
+                       break;
+               }
+               ptr+=ret;
+               irlan_check_response_param(self, name, value, val_len);
+       }
+       /* Cleanup */
+       kfree(name);
+       kfree(value);
+}
+
+/*
+ * Function check_param (param, value)
+ *
+ *    Check which parameter is received and update local variables
+ *
+ */
+static void irlan_check_response_param(struct irlan_cb *self, char *param, 
+                                      char *value, int val_len) 
+{
+       struct in_device *in_dev;
+       __u8 *bytes;
+       int i;
+
+       DEBUG(4, __FUNCTION__ "(), parm=%s\n", param);
+
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+       /*
+        *  Media type
+        */
+       if (strcmp(param, "MEDIA") == 0) {
+               if (strcmp(value, "802.3") == 0)
+                       self->media = MEDIA_802_3;
+               else
+                       self->media = MEDIA_802_5;
+               return;
+       }
+       if (strcmp(param, "FILTER_TYPE") == 0) {
+               if (strcmp(value, "DIRECTED") == 0)
+                       self->client.filter_type |= IRLAN_DIRECTED;
+               else if (strcmp(value, "FUNCTIONAL") == 0)
+                       self->client.filter_type |= IRLAN_FUNCTIONAL;
+               else if (strcmp(value, "GROUP") == 0)
+                       self->client.filter_type |= IRLAN_GROUP;
+               else if (strcmp(value, "MAC_FRAME") == 0)
+                       self->client.filter_type |= IRLAN_MAC_FRAME;
+               else if (strcmp(value, "MULTICAST") == 0)
+                       self->client.filter_type |= IRLAN_MULTICAST;
+               else if (strcmp(value, "BROADCAST") == 0)
+                       self->client.filter_type |= IRLAN_BROADCAST;
+               else if (strcmp(value, "IPX_SOCKET") == 0)
+                       self->client.filter_type |= IRLAN_IPX_SOCKET;
+               
+       }
+       if (strcmp(param, "ACCESS_TYPE") == 0) {
+               if (strcmp(value, "DIRECT") == 0)
+                       self->access_type = ACCESS_DIRECT;
+               else if (strcmp(value, "PEER") == 0)
+                       self->access_type = ACCESS_PEER;
+               else if (strcmp(value, "HOSTED") == 0)
+                       self->access_type = ACCESS_HOSTED;
+               else {
+                       DEBUG(2, __FUNCTION__ "(), unknown access type!\n");
+               }
+       }
+       /*
+        *  IRLAN version
+        */
+       if (strcmp(param, "IRLAN_VER") == 0) {
+               DEBUG(4, "IrLAN version %d.%d\n", (__u8) value[0], 
+                     (__u8) value[1]);
+
+               self->version[0] = value[0];
+               self->version[1] = value[1];
+               return;
+       }
+       /*
+        *  Which remote TSAP to use for data channel
+        */
+       if (strcmp(param, "DATA_CHAN") == 0) {
+               self->dtsap_sel_data = value[0];
+               DEBUG(4, "Data TSAP = %02x\n", self->dtsap_sel_data);
+               return;
+       }
+       if (strcmp(param, "CON_ARB") == 0) {
+               self->client.recv_arb_val = le16_to_cpup(value);
+               DEBUG(2, __FUNCTION__ "(), receive arb val=%d\n", 
+                     self->client.recv_arb_val);
+       }
+       if (strcmp(param, "MAX_FRAME") == 0) {
+               self->client.max_frame = le16_to_cpup(value);
+               DEBUG(4, __FUNCTION__ "(), max frame=%d\n", 
+                     self->client.max_frame);
+       }
+        
+       /*
+        *  RECONNECT_KEY, in case the link goes down!
+        */
+       if (strcmp(param, "RECONNECT_KEY") == 0) {
+               DEBUG(4, "Got reconnect key: ");
+               /* for (i = 0; i < val_len; i++) */
+/*                     printk("%02x", value[i]); */
+               memcpy(self->client.reconnect_key, value, val_len);
+               self->client.key_len = val_len;
+               DEBUG(4, "\n");
+       }
+       /*
+        *  FILTER_ENTRY, have we got an ethernet address?
+        */
+       if (strcmp(param, "FILTER_ENTRY") == 0) {
+               bytes = value;
+               DEBUG(4, "Ethernet address = %02x:%02x:%02x:%02x:%02x:%02x\n",
+                     bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], 
+                     bytes[5]);
+               for (i = 0; i < 6; i++) 
+                       self->dev.dev_addr[i] = bytes[i];
+
+#ifdef CONFIG_IRLAN_GRATUITOUS_ARP
+               /* 
+                * When we get a new MAC address do a gratuitous ARP. This
+                * is useful if we have changed access points on the same
+                * subnet.  
+                */
+               DEBUG(4, "IrLAN: Sending gratuitous ARP\n");
+               in_dev = self->dev.ip_ptr;
+               arp_send(ARPOP_REQUEST, ETH_P_ARP, 
+                         in_dev->ifa_list->ifa_address,
+                         &self->dev, 
+                         in_dev->ifa_list->ifa_address,
+                         NULL, self->dev.dev_addr, NULL);
+#endif
+       }
+}
+
+/*
+ * Function irlan_client_get_value_confirm (obj_id, value)
+ *
+ *    Got results from remote LM-IAS
+ *
+ */
+void irlan_client_get_value_confirm(__u16 obj_id, struct ias_value *value,
+                                   void *priv) 
+{
+       struct irlan_cb *self;
+       
+       DEBUG(4, __FUNCTION__ "()\n");
+
+       ASSERT(priv != NULL, return;);
+
+       self = (struct irlan_cb *) priv;
+       ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+       /* Check if request succeeded */
+       if (!value) {
+               DEBUG(2, __FUNCTION__ "(), got NULL value!\n");
+               irlan_do_client_event(self, IRLAN_IAS_PROVIDER_NOT_AVAIL, 
+                                     NULL);
+               return;
+       }
+
+       switch (value->type) {
+       case IAS_INTEGER:
+               self->dtsap_sel_ctrl = value->t.integer;
+
+               if (value->t.integer != -1) {
+                       irlan_do_client_event(self, IRLAN_IAS_PROVIDER_AVAIL,
+                                             NULL);
+                       return;
+               }
+               break;
+       case IAS_STRING:
+               DEBUG(2, __FUNCTION__ "(), got string %s\n", value->t.string);
+               break;
+       case IAS_OCT_SEQ:
+               DEBUG(2, __FUNCTION__ "(), OCT_SEQ not implemented\n");
+               break;
+       case IAS_MISSING:
+               DEBUG(2, __FUNCTION__ "(), MISSING not implemented\n");
+               break;
+       default:
+               DEBUG(2, __FUNCTION__ "(), unknown type!\n");
+               break;
+       }
+       irlan_do_client_event(self, IRLAN_IAS_PROVIDER_NOT_AVAIL, NULL);
+}
diff --git a/net/irda/irlan/irlan_client_event.c b/net/irda/irlan/irlan_client_event.c
new file mode 100644 (file)
index 0000000..ec666c3
--- /dev/null
@@ -0,0 +1,532 @@
+/*********************************************************************
+ *                
+ * Filename:      irlan_client_event.c
+ * Version:       0.9
+ * Description:   IrLAN client state machine
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Sun Aug 31 20:14:37 1997
+ * Modified at:   Thu Feb  4 16:08:07 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, 
+ *     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.
+ *
+ *     Neither Dag Brattli nor University of Tromsø admit liability nor
+ *     provide warranty for any of this software. This material is 
+ *     provided "AS-IS" and at no charge.
+ *
+ ********************************************************************/
+
+#include <linux/skbuff.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/timer.h>
+#include <net/irda/irmod.h>
+#include <net/irda/iriap.h>
+#include <net/irda/irlmp.h>
+#include <net/irda/irttp.h>
+
+#include <net/irda/irlan_common.h>
+#include <net/irda/irlan_client.h>
+#include <net/irda/irlan_event.h>
+
+static int irlan_client_state_idle (struct irlan_cb *self, IRLAN_EVENT event, 
+                                   struct sk_buff *skb);
+static int irlan_client_state_query(struct irlan_cb *self, IRLAN_EVENT event, 
+                                   struct sk_buff *skb);
+static int irlan_client_state_conn (struct irlan_cb *self, IRLAN_EVENT event, 
+                                   struct sk_buff *skb);
+static int irlan_client_state_info (struct irlan_cb *self, IRLAN_EVENT event, 
+                                   struct sk_buff *skb);
+static int irlan_client_state_media(struct irlan_cb *self, IRLAN_EVENT event, 
+                                   struct sk_buff *skb);
+static int irlan_client_state_open (struct irlan_cb *self, IRLAN_EVENT event, 
+                                   struct sk_buff *skb);
+static int irlan_client_state_wait (struct irlan_cb *self, IRLAN_EVENT event, 
+                                   struct sk_buff *skb);
+static int irlan_client_state_arb  (struct irlan_cb *self, IRLAN_EVENT event, 
+                                   struct sk_buff *skb);
+static int irlan_client_state_data (struct irlan_cb *self, IRLAN_EVENT event, 
+                                   struct sk_buff *skb);
+static int irlan_client_state_close(struct irlan_cb *self, IRLAN_EVENT event, 
+                                   struct sk_buff *skb);
+static int irlan_client_state_sync (struct irlan_cb *self, IRLAN_EVENT event, 
+                                   struct sk_buff *skb);
+
+static int (*state[])(struct irlan_cb *, IRLAN_EVENT event, struct sk_buff *) =
+{ 
+       irlan_client_state_idle,
+       irlan_client_state_query,
+       irlan_client_state_conn,
+       irlan_client_state_info,
+       irlan_client_state_media,
+       irlan_client_state_open,
+       irlan_client_state_wait,
+       irlan_client_state_arb,
+       irlan_client_state_data,
+       irlan_client_state_close,
+       irlan_client_state_sync
+};
+
+void irlan_do_client_event(struct irlan_cb *self, IRLAN_EVENT event, 
+                          struct sk_buff *skb) 
+{
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+       (*state[ self->client.state]) (self, event, skb);
+}
+
+/*
+ * Function irlan_client_state_idle (event, skb, info)
+ *
+ *    IDLE, We are waiting for an indication that there is a provider
+ *    available.
+ */
+static int irlan_client_state_idle(struct irlan_cb *self, IRLAN_EVENT event, 
+                                  struct sk_buff *skb) 
+{
+       DEBUG(4, __FUNCTION__ "()\n");
+
+       ASSERT(self != NULL, return -1;);
+       ASSERT(self->magic == IRLAN_MAGIC, return -1;);
+       
+       switch(event) {
+       case IRLAN_DISCOVERY_INDICATION:
+               /* Get some values from peer IAS */
+               iriap_getvaluebyclass_request(
+                       "IrLAN", "IrDA:TinyTP:LsapSel",
+                       self->saddr, self->daddr,
+                       irlan_client_get_value_confirm, self);
+               
+               irlan_next_client_state(self, IRLAN_QUERY);
+               break;
+       case IRLAN_WATCHDOG_TIMEOUT:
+               DEBUG(2, __FUNCTION__ "(), IRLAN_WATCHDOG_TIMEOUT\n");
+               break;
+       default:
+               DEBUG(4, __FUNCTION__ "(), Unknown event %d\n", event);
+               break;
+       }
+       if (skb) 
+               dev_kfree_skb(skb);
+
+       return 0;
+}
+
+/*
+ * Function irlan_client_state_query (event, skb, info)
+ *
+ *    QUERY, We have queryed the remote IAS and is ready to connect
+ *    to provider, just waiting for the confirm.
+ *
+ */
+static int irlan_client_state_query(struct irlan_cb *self, IRLAN_EVENT event, 
+                                   struct sk_buff *skb) 
+{
+       DEBUG(4, __FUNCTION__ "()\n");
+
+       ASSERT(self != NULL, return -1;);
+       ASSERT(self->magic == IRLAN_MAGIC, return -1;);
+       
+       switch(event) {
+       case IRLAN_IAS_PROVIDER_AVAIL:
+               ASSERT(self->dtsap_sel_ctrl != 0, return -1;);
+
+               self->client.open_retries = 0;
+               
+               irttp_connect_request(self->client.tsap_ctrl, 
+                                     self->dtsap_sel_ctrl, 
+                                     self->saddr, self->daddr, NULL, 
+                                     IRLAN_MTU, NULL);
+               irlan_next_client_state(self, IRLAN_CONN);
+               break;
+       case IRLAN_IAS_PROVIDER_NOT_AVAIL:
+               DEBUG(2, __FUNCTION__ "(), IAS_PROVIDER_NOT_AVAIL\n");
+               irlan_next_client_state(self, IRLAN_IDLE);
+
+               /* Give the client a kick! */
+               if ((self->access_type == ACCESS_PEER) && 
+                   (self->provider.state != IRLAN_IDLE))
+                       irlan_client_wakeup(self, self->saddr, self->daddr);
+               break;
+       case IRLAN_LMP_DISCONNECT:
+       case IRLAN_LAP_DISCONNECT:
+               irlan_next_client_state(self, IRLAN_IDLE);
+               break;
+       case IRLAN_WATCHDOG_TIMEOUT:
+               DEBUG(2, __FUNCTION__ "(), IRLAN_WATCHDOG_TIMEOUT\n");
+               break;
+       default:
+               DEBUG(2, __FUNCTION__"(), Unknown event %d\n", event);
+               break;
+       }
+       if (skb)
+               dev_kfree_skb(skb);
+       
+       return 0;
+}
+
+/*
+ * Function irlan_client_state_conn (event, skb, info)
+ *
+ *    CONN, We have connected to a provider but has not issued any
+ *    commands yet.
+ *
+ */
+static int irlan_client_state_conn(struct irlan_cb *self, IRLAN_EVENT event, 
+                                  struct sk_buff *skb) 
+{
+       DEBUG(4, __FUNCTION__ "()\n");
+       
+       ASSERT(self != NULL, return -1;);
+       
+       switch(event) {
+       case IRLAN_CONNECT_COMPLETE:
+               /* Send getinfo cmd */
+               irlan_get_provider_info(self);
+               irlan_next_client_state(self, IRLAN_INFO);
+               break;
+       case IRLAN_LMP_DISCONNECT:
+       case IRLAN_LAP_DISCONNECT:
+               irlan_next_client_state(self, IRLAN_IDLE);
+               break;
+       case IRLAN_WATCHDOG_TIMEOUT:
+               DEBUG(2, __FUNCTION__ "(), IRLAN_WATCHDOG_TIMEOUT\n");
+               break;
+       default:
+               DEBUG(2, __FUNCTION__ "(), Unknown event %d\n", event);
+               break;
+       }
+       if (skb)
+               dev_kfree_skb(skb);
+       
+       return 0;
+}
+
+/*
+ * Function irlan_client_state_info (self, event, skb, info)
+ *
+ *    INFO, We have issued a GetInfo command and is awaiting a reply.
+ */
+static int irlan_client_state_info(struct irlan_cb *self, IRLAN_EVENT event, 
+                                  struct sk_buff *skb) 
+{
+       DEBUG(4, __FUNCTION__ "()\n");
+
+       ASSERT(self != NULL, return -1;);
+       
+       switch(event) {
+       case IRLAN_DATA_INDICATION:
+               ASSERT(skb != NULL, return -1;);
+       
+               irlan_client_extract_params(self, skb);
+               
+               irlan_next_client_state(self, IRLAN_MEDIA);
+               
+               irlan_get_media_char(self);
+               break;
+               
+       case IRLAN_LMP_DISCONNECT:
+       case IRLAN_LAP_DISCONNECT:
+               irlan_next_client_state(self, IRLAN_IDLE);
+               break;
+       case IRLAN_WATCHDOG_TIMEOUT:
+               DEBUG(2, __FUNCTION__ "(), IRLAN_WATCHDOG_TIMEOUT\n");
+               break;
+       default:
+               DEBUG(2, __FUNCTION__ "(), Unknown event %d\n", event);
+               break;
+       }
+       if (skb)
+               dev_kfree_skb(skb);
+       
+       return 0;
+}
+
+/*
+ * Function irlan_client_state_media (self, event, skb, info)
+ *
+ *    MEDIA, The irlan_client has issued a GetMedia command and is awaiting a
+ *    reply.
+ *
+ */
+static int irlan_client_state_media(struct irlan_cb *self, IRLAN_EVENT event, 
+                                   struct sk_buff *skb) 
+{
+       DEBUG(4, __FUNCTION__ "()\n");
+       
+       ASSERT(self != NULL, return -1;);
+
+       switch(event) {
+       case IRLAN_DATA_INDICATION:
+               irlan_client_extract_params(self, skb);
+               irlan_open_data_channel(self);
+               irlan_next_client_state(self, IRLAN_OPEN);
+               break;
+       case IRLAN_LMP_DISCONNECT:
+       case IRLAN_LAP_DISCONNECT:
+               irlan_next_client_state(self, IRLAN_IDLE);
+               break;
+       case IRLAN_WATCHDOG_TIMEOUT:
+               DEBUG(2, __FUNCTION__ "(), IRLAN_WATCHDOG_TIMEOUT\n");
+               break;
+       default:
+               DEBUG(2, __FUNCTION__ "(), Unknown event %d\n", event);
+               break;
+       }
+       if (skb)
+               dev_kfree_skb(skb);
+       
+       return 0;
+}
+
+/*
+ * Function irlan_client_state_open (self, event, skb, info)
+ *
+ *    OPEN, The irlan_client has issued a OpenData command and is awaiting a
+ *    reply
+ *
+ */
+static int irlan_client_state_open(struct irlan_cb *self, IRLAN_EVENT event, 
+                                  struct sk_buff *skb) 
+{
+       struct qos_info qos;
+
+       DEBUG(4, __FUNCTION__ "()\n");
+       
+       ASSERT(self != NULL, return -1;);
+
+       switch(event) {
+       case IRLAN_DATA_INDICATION:
+               irlan_client_extract_params(self, skb);
+               
+               /*
+                *  Check if we have got the remote TSAP for data 
+                *  communications
+                */
+               ASSERT(self->dtsap_sel_data != 0, return -1;);
+
+               /* Check which access type we are dealing with */
+               switch(self->access_type) {
+               case ACCESS_PEER:
+                   if (self->provider.state == IRLAN_OPEN) {
+                           
+                           irlan_next_client_state(self, IRLAN_ARB);
+                           irlan_do_client_event(self, IRLAN_CHECK_CON_ARB, 
+                                                 NULL);
+                   } else {
+                       
+                           irlan_next_client_state(self, IRLAN_WAIT);
+                   }
+                   break;
+               case ACCESS_DIRECT:
+               case ACCESS_HOSTED:
+                       qos.link_disc_time.bits = 0x01; /* 3 secs */
+                       
+                       irttp_connect_request(self->tsap_data, 
+                                             self->dtsap_sel_data, 
+                                             self->saddr, self->daddr, &qos, 
+                                             IRLAN_MTU, NULL);
+                       
+                       irlan_next_client_state(self, IRLAN_DATA);
+
+                       if (self->client.start_new_provider) {
+                               irlan_open(DEV_ADDR_ANY, DEV_ADDR_ANY, FALSE);
+                               self->client.start_new_provider = FALSE;
+                       }
+                       break;
+               default:
+                       DEBUG(2, __FUNCTION__ "(), unknown access type!\n");
+                       break;
+               }
+               break;
+       case IRLAN_LMP_DISCONNECT:
+       case IRLAN_LAP_DISCONNECT:
+               irlan_next_client_state(self, IRLAN_IDLE);
+               break;
+       case IRLAN_WATCHDOG_TIMEOUT:
+               DEBUG(2, __FUNCTION__ "(), IRLAN_WATCHDOG_TIMEOUT\n");
+               break;
+       default:
+               DEBUG(2, __FUNCTION__ "(), Unknown event %d\n", event);
+               break;
+       }
+       
+       if (skb)
+               dev_kfree_skb(skb);
+
+       return 0;
+}
+
+/*
+ * Function irlan_client_state_wait (self, event, skb, info)
+ *
+ *    WAIT, The irlan_client is waiting for the local provider to enter the
+ *    provider OPEN state.
+ *
+ */
+static int irlan_client_state_wait(struct irlan_cb *self, IRLAN_EVENT event, 
+                                  struct sk_buff *skb) 
+{
+       DEBUG(4, __FUNCTION__ "()\n");
+       
+       ASSERT(self != NULL, return -1;);
+       
+       switch(event) {
+       case IRLAN_PROVIDER_SIGNAL:
+               irlan_next_client_state(self, IRLAN_ARB);
+               irlan_do_client_event(self, IRLAN_CHECK_CON_ARB, NULL);
+               break;
+       case IRLAN_LMP_DISCONNECT:
+       case IRLAN_LAP_DISCONNECT:
+               irlan_next_client_state(self, IRLAN_IDLE);
+               break;
+       case IRLAN_WATCHDOG_TIMEOUT:
+               DEBUG(2, __FUNCTION__ "(), IRLAN_WATCHDOG_TIMEOUT\n");
+               break;
+       default:
+               DEBUG(2, __FUNCTION__ "(), Unknown event %d\n", event);
+               break;
+       }
+       if (skb)
+               dev_kfree_skb(skb);
+       
+       return 0;
+}
+
+static int irlan_client_state_arb(struct irlan_cb *self, IRLAN_EVENT event, 
+                                 struct sk_buff *skb) 
+{
+       struct qos_info qos;
+
+       DEBUG(2, __FUNCTION__ "()\n");
+
+       ASSERT(self != NULL, return -1;);
+       
+       switch(event) {
+       case IRLAN_CHECK_CON_ARB:
+               if (self->client.recv_arb_val == self->provider.send_arb_val) {
+                       irlan_next_client_state(self, IRLAN_CLOSE);
+                       irlan_close_data_channel(self);
+               } else if (self->client.recv_arb_val < 
+                          self->provider.send_arb_val) 
+               {
+                       qos.link_disc_time.bits = 0x01; /* 3 secs */
+
+                       irlan_next_client_state(self, IRLAN_DATA);
+                       irttp_connect_request(self->tsap_data, 
+                                             self->dtsap_sel_data, 
+                                             self->saddr, self->daddr, &qos, 
+                                             IRLAN_MTU, NULL);
+               } else if (self->client.recv_arb_val >
+                          self->provider.send_arb_val) 
+               {
+                       DEBUG(2, __FUNCTION__ "(), lost the battle :-(\n");
+               }
+               break;
+       case IRLAN_DATA_CONNECT_INDICATION:
+               irlan_next_client_state(self, IRLAN_DATA);
+               break;
+       case IRLAN_LMP_DISCONNECT:
+       case IRLAN_LAP_DISCONNECT:
+               irlan_next_client_state(self, IRLAN_IDLE);
+               break;
+       case IRLAN_WATCHDOG_TIMEOUT:
+               DEBUG(2, __FUNCTION__ "(), IRLAN_WATCHDOG_TIMEOUT\n");
+               break;
+       default:
+               DEBUG(2, __FUNCTION__ "(), Unknown event %d\n", event);
+               break;
+       }
+       if (skb)
+               dev_kfree_skb(skb);
+       
+       return 0;
+}
+
+/*
+ * Function irlan_client_state_data (self, event, skb, info)
+ *
+ *    DATA, The data channel is connected, allowing data transfers between
+ *    the local and remote machines.
+ *
+ */
+static int irlan_client_state_data(struct irlan_cb *self, IRLAN_EVENT event, 
+                                  struct sk_buff *skb) 
+{
+       DEBUG(4, __FUNCTION__ "()\n");
+
+       ASSERT(self != NULL, return -1;);
+       ASSERT(self->magic == IRLAN_MAGIC, return -1;);
+
+       switch(event) {
+       case IRLAN_DATA_INDICATION:
+               irlan_client_extract_params(self, skb);
+               break;          
+       case IRLAN_LMP_DISCONNECT: /* FALLTHROUGH */
+       case IRLAN_LAP_DISCONNECT:
+               irlan_next_client_state(self, IRLAN_IDLE);
+               break;
+       default:
+               DEBUG(2, __FUNCTION__ "(), Unknown event %d\n", event);
+               break;
+       }
+       if (skb)
+               dev_kfree_skb(skb);
+       
+       return 0;
+}
+
+/*
+ * Function irlan_client_state_close (self, event, skb, info)
+ *
+ *    
+ *
+ */
+static int irlan_client_state_close(struct irlan_cb *self, IRLAN_EVENT event, 
+                                   struct sk_buff *skb) 
+{
+       DEBUG(2, __FUNCTION__ "()\n");
+
+       if (skb)
+               dev_kfree_skb(skb);
+
+       return 0;
+}
+
+/*
+ * Function irlan_client_state_sync (self, event, skb, info)
+ *
+ *    
+ *
+ */
+static int irlan_client_state_sync(struct irlan_cb *self, IRLAN_EVENT event, 
+                                  struct sk_buff *skb) 
+{
+       DEBUG(2, __FUNCTION__ "()\n");
+       
+       if (skb)
+               dev_kfree_skb(skb);
+       
+       return 0;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
index 90be583f5b9dc9bad12f7ad0af594002da9cf4be..1ff3b5a5215be3c052360192b36699ffd9f00b4c 100644 (file)
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      irlan_common.c
- * Version:       0.1
+ * Version:       0.9
  * Description:   IrDA LAN Access Protocol Implementation
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Tue Jan 19 23:11:30 1999
+ * Modified at:   Wed Feb 17 23:49:10 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
 #include <net/irda/timer.h>
 
 #include <net/irda/irlan_common.h>
+#include <net/irda/irlan_client.h>
+#include <net/irda/irlan_provider.h> 
+#include <net/irda/irlan_eth.h>
+#include <net/irda/irlan_filter.h>
 
-static void __irlan_close( struct irlan_cb *self);
+/* extern char sysctl_devname[]; */
 
 /*
  *  Master structure
  */
 hashbin_t *irlan = NULL;
 
+/* Module parameters */
+static int eth = 0; /* Use "eth" or "irlan" name for devices */
+static int access = ACCESS_PEER; /* PEER, DIRECT or HOSTED */
+static int timeout = IRLAN_TIMEOUT;
+
+static char *irlan_state[] = {
+       "IRLAN_IDLE",
+       "IRLAN_QUERY",
+       "IRLAN_CONN", 
+       "IRLAN_INFO",
+       "IRLAN_MEDIA",
+       "IRLAN_OPEN",
+       "IRLAN_WAIT",
+       "IRLAN_ARB", 
+       "IRLAN_DATA",
+       "IRLAN_CLOSE",
+       "IRLAN_SYNC"
+};
+
+static char *irlan_access[] = {
+       "UNKNOWN",
+       "DIRECT",
+       "PEER",
+       "HOSTED"
+};
+
+static char *irlan_media[] = {
+       "UNKNOWN",
+       "802.3",
+       "802.5"
+};
+
+static void __irlan_close(struct irlan_cb *self);
+static int __irlan_insert_param(struct sk_buff *skb, char *param, int type, 
+                               __u8 value_byte, __u16 value_short, 
+                               __u8 *value_array, __u16 value_len);
+static void irlan_close_tsaps(struct irlan_cb *self);
+
 #ifdef CONFIG_PROC_FS
-static int irlan_proc_read( char *buf, char **start, off_t offset
-                           int len, int unused);
+static int irlan_proc_read(char *buf, char **start, off_t offset, int len
+                          int unused);
 
 extern struct proc_dir_entry proc_irda;
 
@@ -64,7 +106,164 @@ struct proc_dir_entry proc_irlan = {
        0, NULL,
        &irlan_proc_read,
 };
+#endif /* CONFIG_PROC_FS */
+
+void irlan_watchdog_timer_expired(unsigned long data)
+{
+       struct irmanager_event mgr_event;
+       struct irlan_cb *self = (struct irlan_cb *) data;
+       
+       DEBUG(2, __FUNCTION__ "()\n");
+
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+       /* Check if device still configured */
+       if (self->dev.start) {
+               mgr_event.event = EVENT_IRLAN_STOP;
+               sprintf(mgr_event.devname, "%s", self->ifname);
+               irmanager_notify(&mgr_event);
+
+               /*
+                *  We set this to false, so that irlan_dev_close known that
+                *  notify_irmanager should actually be set to TRUE again 
+                *  instead of FALSE, since this close has not been initiated
+                *  by the user.
+                */
+               self->notify_irmanager = FALSE;
+       } else
+               irlan_close(self);
+}
+
+void irlan_start_watchdog_timer(struct irlan_cb *self, int timeout)
+{
+       DEBUG(4, __FUNCTION__ "()\n");
+       
+       irda_start_timer(&self->watchdog_timer, timeout, (unsigned long) self,
+                        irlan_watchdog_timer_expired);
+}
+
+static int irlan_eth_open(struct device *dev)
+{
+       struct irlan_cb *self;
+       
+       DEBUG(4, __FUNCTION__ "()\n");
+
+       ASSERT(dev != NULL, return -1;);
+
+       self = (struct irlan_cb *) dev->priv;
+
+       ASSERT(self != NULL, return -1;);
+
+       /* Ready to play! */
+/*     dev->tbusy = 0; */ /* Wait until data link is ready */
+       dev->interrupt = 0;
+       dev->start = 1;
+
+       self->notify_irmanager = TRUE;
+
+       MOD_INC_USE_COUNT;
+       
+       return 0;
+}
+
+/*
+ * Function irlan_eth_close (dev)
+ *
+ *    Stop the ether network device, his function will usually be called by
+ *    ifconfig down. We should now disconnect the link, We start the 
+ *    close timer, so that the instance will be removed if we are unable
+ *    to discover the remote device after the disconnect.
+ */
+static int irlan_eth_close(struct device *dev)
+{
+       struct irlan_cb *self = (struct irlan_cb *) dev->priv;
+
+       DEBUG(4, __FUNCTION__ "()\n");
+       
+       /* Stop device */
+       dev->tbusy = 1;
+       dev->start = 0;
+
+       MOD_DEC_USE_COUNT;
+
+       irlan_close_data_channel(self);
+
+       irlan_close_tsaps(self);
+
+       irlan_do_client_event(self, IRLAN_LMP_DISCONNECT, NULL);
+       irlan_do_provider_event(self, IRLAN_LMP_DISCONNECT, NULL);      
+       
+       irlan_start_watchdog_timer(self, IRLAN_TIMEOUT);
+
+       /* Device closed by user */
+       if (self->notify_irmanager)
+               self->notify_irmanager = FALSE;
+       else
+               self->notify_irmanager = TRUE;
+
+       return 0;
+}
+/*
+ * Function irlan_eth_init (dev)
+ *
+ *    The network device initialization function.
+ *
+ */
+int irlan_eth_init(struct device *dev)
+{
+       struct irmanager_event mgr_event;
+       struct irlan_cb *self;
+
+       DEBUG(4, __FUNCTION__"()\n");
+
+       ASSERT(dev != NULL, return -1;);
+       
+       self = (struct irlan_cb *) dev->priv;
+
+       dev->open               = irlan_eth_open;
+       dev->stop               = irlan_eth_close;
+       dev->hard_start_xmit    = irlan_eth_xmit; 
+       dev->get_stats          = irlan_eth_get_stats;
+       dev->set_multicast_list = irlan_eth_set_multicast_list;
+
+       dev->tbusy = 1;
+       
+       ether_setup(dev);
+       
+       dev->tx_queue_len = TTP_MAX_QUEUE;
+
+#ifdef 0
+       /*  
+        *  OK, since we are emulating an IrLAN sever we will have to give
+        *  ourself an ethernet address!
+        *  FIXME: this must be more dynamically
+        */
+       dev->dev_addr[0] = 0x40;
+       dev->dev_addr[1] = 0x00;
+       dev->dev_addr[2] = 0x00;
+       dev->dev_addr[3] = 0x00;
+       dev->dev_addr[4] = 0x23;
+       dev->dev_addr[5] = 0x45;
 #endif
+       /* 
+        * Network device has now been registered, so tell irmanager about
+        * it, so it can be configured with network parameters
+        */
+       mgr_event.event = EVENT_IRLAN_START;
+       sprintf(mgr_event.devname, "%s", self->ifname);
+       irmanager_notify(&mgr_event);
+
+       /* 
+        * We set this so that we only notify once, since if 
+        * configuration of the network device fails, the user
+        * will have to sort it out first anyway. No need to 
+        * try again.
+        */
+       self->notify_irmanager = FALSE;
+
+       return 0;
+}
 
 /*
  * Function irlan_init (void)
@@ -72,61 +271,147 @@ struct proc_dir_entry proc_irlan = {
  *    Initialize IrLAN layer
  *
  */
-__initfunc(int irlan_init( void))
+__initfunc(int irlan_init(void))
 {
+       struct irlan_cb *new;
+
+       DEBUG(4, __FUNCTION__"()\n");
+
        /* Allocate master array */
-       irlan = hashbin_new( HB_LOCAL); 
-       if ( irlan == NULL) {
-               printk( KERN_WARNING "IrLAN: Can't allocate hashbin!\n");
+       irlan = hashbin_new(HB_LOCAL); 
+       if (irlan == NULL) {
+               printk(KERN_WARNING "IrLAN: Can't allocate hashbin!\n");
                return -ENOMEM;
        }
 #ifdef CONFIG_PROC_FS
-       proc_register( &proc_irda, &proc_irlan);
+       proc_register(&proc_irda, &proc_irlan);
 #endif /* CONFIG_PROC_FS */
 
+       DEBUG(4, __FUNCTION__ "()\n");
+       
+       /* Register with IrLMP as a service user */
+       irlmp_register_layer(S_LAN, CLIENT, TRUE, 
+                            irlan_client_discovery_indication);
+       
+       /* Register with IrLMP as a service */
+       irlmp_register_layer(S_LAN, SERVER, FALSE, NULL);
+
+       /* Start the first IrLAN instance */
+       new = irlan_open(DEV_ADDR_ANY, DEV_ADDR_ANY, FALSE);
+
+       /* Do some fast discovery! */
+       irlmp_discovery_request(8);
+
        return 0;
 }
 
 void irlan_cleanup(void) 
 {
-       DEBUG( 4, __FUNCTION__ "()\n");
+       DEBUG(4, __FUNCTION__ "()\n");
+
+       irlmp_unregister_layer(S_LAN, SERVER);
+
+       irlmp_unregister_layer(S_LAN, CLIENT);
 
 #ifdef CONFIG_PROC_FS
-       proc_unregister( &proc_irda, proc_irlan.low_ino);
-#endif
+       proc_unregister(&proc_irda, proc_irlan.low_ino);
+#endif /* CONFIG_PROC_FS */
        /*
         *  Delete hashbin and close all irlan client instances in it
         */
-       hashbin_delete( irlan, (FREE_FUNC) __irlan_close);
+       hashbin_delete(irlan, (FREE_FUNC) __irlan_close);
 }
 
+/*
+ * Function irlan_register_netdev (self)
+ *
+ *    Registers the network device to be used. We should don't register until
+ *    we have been binded to a particular provider or client.
+ */
+int irlan_register_netdev(struct irlan_cb *self)
+{
+       int i=0;
+
+       DEBUG(4, __FUNCTION__ "()\n");
+
+       /* Check if we should call the device eth<x> or irlan<x> */
+       if (!eth) {
+               /* Get the first free irlan<x> name */
+               do {
+                       sprintf(self->ifname, "%s%d", "irlan", i++);
+               } while (dev_get(self->ifname) != NULL);
+       }
+       self->dev.name = self->ifname;
+       
+       if (register_netdev(&self->dev) != 0) {
+               DEBUG(2, __FUNCTION__ 
+                     "(), register_netdev() failed!\n");
+               return -1;
+       }
+       self->netdev_registered = TRUE;
+       
+       return 0;
+}
 
 /*
  * Function irlan_open (void)
  *
- *    
- *
+ *    Open new instance of a client/provider, we should only register the 
+ *    network device if this instance is ment for a particular client/provider
  */
-struct irlan_cb *irlan_open(void)
+struct irlan_cb *irlan_open(__u32 saddr, __u32 daddr, int netdev)
 {
        struct irlan_cb *self;
 
-       DEBUG( 4, __FUNCTION__ "()\n");
+       DEBUG(2, __FUNCTION__ "()\n");
 
        /* 
         *  Initialize the irlan structure. 
         */
-       self = kmalloc( sizeof(struct irlan_cb), GFP_ATOMIC);
-       if ( self == NULL)
+       self = kmalloc(sizeof(struct irlan_cb), GFP_ATOMIC);
+       if (self == NULL)
                return NULL;
        
-       memset( self, 0, sizeof( struct irlan_cb));
+       memset(self, 0, sizeof(struct irlan_cb));
 
        /*
         *  Initialize local device structure
         */
        self->magic = IRLAN_MAGIC;
 
+       ASSERT(irlan != NULL, return NULL;);
+       
+       sprintf(self->ifname, "%s", "unknown");
+
+       self->dev.priv = (void *) self;
+       self->dev.next = NULL;
+       self->dev.init = irlan_eth_init;
+       
+       self->saddr = saddr;
+       self->daddr = daddr;
+
+       /* Provider access can only be PEER, DIRECT, or HOSTED */
+       self->access_type = access;
+       self->media = MEDIA_802_3;
+
+       self->notify_irmanager = TRUE;
+
+       init_timer(&self->watchdog_timer);
+       init_timer(&self->client.kick_timer);
+
+       hashbin_insert(irlan, (QUEUE *) self, daddr, NULL);
+               
+       irlan_next_client_state(self, IRLAN_IDLE);
+       irlan_next_provider_state(self, IRLAN_IDLE);
+
+       irlan_open_data_tsap(self);
+       irlan_provider_open_ctrl_tsap(self);
+       irlan_client_open_ctrl_tsap(self);
+
+       /* Register network device now, or wait until some later time? */
+       if (netdev)
+               irlan_register_netdev(self);
+
        return self;
 }
 /*
@@ -137,63 +422,281 @@ struct irlan_cb *irlan_open(void)
  *    hashbin_remove() first!!!
  *
  */
-void __irlan_close( struct irlan_cb *self)
+static void __irlan_close(struct irlan_cb *self)
 {
-       DEBUG( 4, __FUNCTION__ "()\n");
+       DEBUG(2, __FUNCTION__ "()\n");
        
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == IRLAN_MAGIC, return;);
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == IRLAN_MAGIC, return;);
 
-       /* 
-        *  Disconnect open TSAP connections
-        */
-       if ( self->tsap_data) {
-               irttp_disconnect_request( self->tsap_data, NULL, P_HIGH);
-               
-               /* FIXME: this will close the tsap before the disconenct
-                * frame has been sent 
+       del_timer(&self->watchdog_timer);
+       del_timer(&self->client.kick_timer);
+
+       /* Close all open connections and remove TSAPs */
+       irlan_close_tsaps(self);
+
+       if (self->netdev_registered)
+               unregister_netdev(&self->dev);
+       
+       self->magic = 0;
+       kfree(self);
+}
+
+/*
+ * Function irlan_close (self)
+ *
+ *    Close instance
+ *
+ */
+void irlan_close(struct irlan_cb *self)
+{
+       struct irlan_cb *entry;
+       
+       DEBUG(2, __FUNCTION__ "()\n");
+
+        ASSERT(self != NULL, return;);
+       ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+       /* Check if device is still configured */
+       if (self->dev.start) {
+               DEBUG(2, __FUNCTION__ 
+                      "(), Device still configured, closing later!\n");
+               return;
+       }
+       DEBUG(2, __FUNCTION__ "(), daddr=%08x\n", self->daddr);
+       entry = hashbin_remove(irlan, self->daddr, NULL);
+
+       ASSERT(entry == self, return;);
+       
+        __irlan_close(self);
+}
+
+void irlan_connect_indication(void *instance, void *sap, struct qos_info *qos,
+                             int max_sdu_size, struct sk_buff *skb)
+{
+       struct irlan_cb *self;
+       struct tsap_cb *tsap;
+
+       DEBUG(2, __FUNCTION__ "()\n");
+       
+       self = (struct irlan_cb *) instance;
+       tsap = (struct tsap_cb *) sap;
+       
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == IRLAN_MAGIC, return;);
+       ASSERT(tsap == self->tsap_data,return;);
+
+       DEBUG(2, "IrLAN, We are now connected!\n");
+       del_timer(&self->watchdog_timer);
+
+       irlan_do_provider_event(self, IRLAN_DATA_CONNECT_INDICATION, skb);
+       irlan_do_client_event(self, IRLAN_DATA_CONNECT_INDICATION, skb);
+
+       if (self->access_type == ACCESS_PEER) {
+               /* 
+                * Data channel is open, so we are now allowed to
+                * configure the remote filter 
                 */
-               /* irttp_close_tsap( self->tsap_data); */
+               irlan_get_unicast_addr(self);
+               irlan_open_unicast_addr(self);
        }
-       if ( self->tsap_ctrl) {
-               irttp_disconnect_request( self->tsap_ctrl, NULL, P_HIGH);
-               
-               /* irttp_close_tsap( self->tsap_control); */
+       /* Ready to transfer Ethernet frames */
+       self->dev.tbusy = 0;
+}
+
+void irlan_connect_confirm(void *instance, void *sap, struct qos_info *qos, 
+                          int max_sdu_size, struct sk_buff *skb) 
+{
+       struct irlan_cb *self;
+
+       DEBUG(2, __FUNCTION__ "()\n");
+
+       self = (struct irlan_cb *) instance;
+
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+       /* TODO: we could set the MTU depending on the max_sdu_size */
+
+       DEBUG(2, "IrLAN, We are now connected!\n");
+       del_timer(&self->watchdog_timer);
+
+       /* 
+        * Data channel is open, so we are now allowed to configure the remote
+        * filter 
+        */
+       irlan_get_unicast_addr(self);
+       irlan_open_unicast_addr(self);
+
+       /* Ready to transfer Ethernet frames */
+       self->dev.tbusy = 0;
+}
+
+/*
+ * Function irlan_client_disconnect_indication (handle)
+ *
+ *    Callback function for the IrTTP layer. Indicates a disconnection of
+ *    the specified connection (handle)
+ */
+void irlan_disconnect_indication(void *instance, void *sap, LM_REASON reason, 
+                                struct sk_buff *userdata) 
+{
+       struct irlan_cb *self;
+       struct tsap_cb *tsap;
+
+       DEBUG(2, __FUNCTION__ "(), reason=%d\n", reason);
+       
+       self = (struct irlan_cb *) instance;
+       tsap = (struct tsap_cb *) sap;
+
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == IRLAN_MAGIC, return;);    
+       ASSERT(tsap != NULL, return;);
+       ASSERT(tsap->magic == TTP_TSAP_MAGIC, return;);
+       
+       ASSERT(tsap == self->tsap_data, return;);
+
+       DEBUG(2, "IrLAN, data channel disconnected by peer!\n");
+
+       switch(reason) {
+       case LM_USER_REQUEST: /* User request */
+               irlan_close(self);
+               break;
+       case LM_LAP_DISCONNECT: /* Unexpected IrLAP disconnect */
+               irlan_start_watchdog_timer(self, IRLAN_TIMEOUT);
+               break;
+       case LM_CONNECT_FAILURE: /* Failed to establish IrLAP connection */
+               DEBUG(2, __FUNCTION__ "(), LM_CONNECT_FAILURE not impl\n");
+               break;
+       case LM_LAP_RESET:  /* IrLAP reset */
+               DEBUG(2, __FUNCTION__ "(), LM_CONNECT_FAILURE not impl\n");
+               break;
+       case LM_INIT_DISCONNECT:
+               DEBUG(2, __FUNCTION__ "(), LM_CONNECT_FAILURE not impl\n");
+               break;
+       default:
+               break;
        }
        
-       unregister_netdev( &self->dev);
+       /* Stop IP from transmitting more packets */
+       /* irlan_client_flow_indication(handle, FLOW_STOP, priv); */
 
-       /*
-        *  Make sure that nobody uses this instance anymore!
+       irlan_do_client_event(self, IRLAN_LMP_DISCONNECT, NULL);
+       irlan_do_provider_event(self, IRLAN_LMP_DISCONNECT, NULL);
+}
+
+void irlan_open_data_tsap(struct irlan_cb *self)
+{
+       struct notify_t notify;
+       struct tsap_cb *tsap;
+
+       DEBUG(4, __FUNCTION__ "()\n");
+
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+       /* Check if already open */
+       if (self->tsap_data)
+               return;
+
+       irda_notify_init(&notify);
+
+       notify.data_indication       = irlan_eth_receive;
+       notify.udata_indication      = irlan_eth_receive;
+       notify.connect_indication    = irlan_connect_indication;
+       notify.connect_confirm       = irlan_connect_confirm;
+       notify.flow_indication       = irlan_eth_flow_indication;
+       notify.disconnect_indication = irlan_disconnect_indication;
+       notify.instance              = self;
+       strncpy(notify.name, "IrLAN data", NOTIFY_MAX_NAME);
+
+       tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT, &notify);
+       if (!tsap) {
+               DEBUG(2, __FUNCTION__ "(), Got no tsap!\n");
+               return;
+       }
+       self->tsap_data = tsap;
+
+       /* 
+        *  This is the data TSAP selector which we will pass to the client
+        *  when the client ask for it.
         */
-       self->magic = 0;
-       
-       /*
-        *  Dealloacte structure
+       self->stsap_sel_data = self->tsap_data->stsap_sel;
+}
+
+static void irlan_close_tsaps(struct irlan_cb *self)
+{
+       DEBUG(4, __FUNCTION__ "()\n");
+
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+       /* 
+        *  Disconnect and close all open TSAP connections
         */
-       kfree( self);
+       if (self->tsap_data) {
+               irttp_disconnect_request(self->tsap_data, NULL, P_NORMAL);
+               irttp_close_tsap(self->tsap_data);
+               self->tsap_data = NULL;
+               
+       }
+       if (self->client.tsap_ctrl) {
+               irttp_disconnect_request(self->client.tsap_ctrl, NULL, 
+                                        P_NORMAL);
+               irttp_close_tsap(self->client.tsap_ctrl);
+               self->client.tsap_ctrl = NULL;
+       }
+       if (self->provider.tsap_ctrl) {
+               irttp_disconnect_request(self->provider.tsap_ctrl, NULL, 
+                                        P_NORMAL);
+               irttp_close_tsap(self->provider.tsap_ctrl);
+               self->provider.tsap_ctrl = NULL;
+       }
 }
 
 /*
- * Function irlan_close (self)
+ * Function irlan_ias_register (self, tsap_sel)
  *
- *    
+ *    Register with LM-IAS
  *
  */
-void irlan_close( struct irlan_cb *self)
+void irlan_ias_register(struct irlan_cb *self, __u8 tsap_sel)
 {
-       struct irlan_cb *entry;
-       
-       DEBUG( 4, __FUNCTION__ "()\n");
+       struct ias_object *obj;
+       struct ias_value *new_value;
 
-        ASSERT( self != NULL, return;);
-       ASSERT( self->magic == IRLAN_MAGIC, return;);
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == IRLAN_MAGIC, return;);
        
-       entry = hashbin_remove( irlan, self->daddr, NULL);
-
-       ASSERT( entry == self, return;);
+       /* 
+        * Check if object has already been registred by a previous provider.
+        * If that is the case, we just change the value of the attribute
+        */
+       if (!irias_find_object("IrLAN")) {
+               obj = irias_new_object("IrLAN", IAS_IRLAN_ID);
+               irias_add_integer_attrib(obj, "IrDA:TinyTP:LsapSel", tsap_sel);
+               irias_insert_object(obj);
+       } else {
+               new_value = irias_new_integer_value(tsap_sel);
+               irias_object_change_attribute("IrLAN", "IrDA:TinyTP:LsapSel",
+                                             new_value);
+       }
        
-        __irlan_close( self);
+        /* Register PnP object only if not registred before */
+        if (!irias_find_object("PnP")) {
+               obj = irias_new_object("PnP", IAS_PNP_ID);
+#if 0
+               irias_add_string_attrib(obj, "Name", sysctl_devname);
+#else
+               irias_add_string_attrib(obj, "Name", "Linux");
+#endif
+               irias_add_string_attrib(obj, "DeviceID", "HWP19F0");
+               irias_add_integer_attrib(obj, "CompCnt", 2);
+               irias_add_string_attrib(obj, "Comp#01", "PNP8294");
+               irias_add_string_attrib(obj, "Comp#02", "PNP8389");
+               irias_add_string_attrib(obj, "Manufacturer", "Linux-IrDA Project");
+               irias_insert_object(obj);
+       }
 }
 
 /*
@@ -202,33 +705,30 @@ void irlan_close( struct irlan_cb *self)
  *    Send Get Provider Information command to peer IrLAN layer
  *
  */
-void irlan_get_provider_info( struct irlan_cb *self)
+void irlan_get_provider_info(struct irlan_cb *self)
 {
        struct sk_buff *skb;
        __u8 *frame;
 
-       DEBUG( 4, __FUNCTION__ "()\n");
+       DEBUG(4, __FUNCTION__ "()\n");
        
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == IRLAN_MAGIC, return;);
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == IRLAN_MAGIC, return;);
 
-       skb = dev_alloc_skb( 64);
-       if (skb == NULL) {
-               DEBUG( 0, __FUNCTION__
-                      "(), Could not allocate an skb of length %d\n", 64);
+       skb = dev_alloc_skb(64);
+       if (!skb)
                return;
-       }
 
        /* Reserve space for TTP, LMP, and LAP header */
-       skb_reserve( skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
-       skb_put( skb, 2);
+       skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+       skb_put(skb, 2);
        
        frame = skb->data;
        
        frame[0] = CMD_GET_PROVIDER_INFO;
        frame[1] = 0x00;                 /* Zero parameters */
        
-       irttp_data_request( self->tsap_ctrl, skb);
+       irttp_data_request(self->client.tsap_ctrl, skb);
 }
 
 /*
@@ -237,26 +737,22 @@ void irlan_get_provider_info( struct irlan_cb *self)
  *    Send an Open Data Command to provider
  *
  */
-void irlan_open_data_channel( struct irlan_cb *self) 
+void irlan_open_data_channel(struct irlan_cb *self) 
 {
        struct sk_buff *skb;
        __u8 *frame;
        
-       DEBUG( 4, __FUNCTION__ "()\n");
+       DEBUG(4, __FUNCTION__ "()\n");
 
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == IRLAN_MAGIC, return;);
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == IRLAN_MAGIC, return;);
        
-       skb =  dev_alloc_skb( 64);
-       if (skb == NULL) {
-               DEBUG( 0, __FUNCTION__
-                      "(), Could not allocate an skb of length %d\n", 64);
+       skb = dev_alloc_skb(64);
+       if (!skb)
                return;
-       }
 
-       /* Reserve space for TTP, LMP, and LAP header */
-       skb_reserve( skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
-       skb_put( skb, 2);
+       skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+       skb_put(skb, 2);
        
        frame = skb->data;
        
@@ -264,13 +760,41 @@ void irlan_open_data_channel( struct irlan_cb *self)
        frame[0] = CMD_OPEN_DATA_CHANNEL;
        frame[1] = 0x02; /* Two parameters */
 
-       insert_string_param( skb, "MEDIA", "802.3");
-       insert_string_param( skb, "ACCESS_TYPE", "DIRECT");
-       /* insert_string_param( skb, "MODE", "UNRELIABLE"); */
+       irlan_insert_string_param(skb, "MEDIA", "802.3");
+       irlan_insert_string_param(skb, "ACCESS_TYPE", "DIRECT");
+       /* irlan_insert_string_param(skb, "MODE", "UNRELIABLE"); */
 
 /*     self->use_udata = TRUE; */
 
-       irttp_data_request( self->tsap_ctrl, skb);
+       irttp_data_request(self->client.tsap_ctrl, skb);
+}
+
+void irlan_close_data_channel(struct irlan_cb *self) 
+{
+       struct sk_buff *skb;
+       __u8 *frame;
+       
+       DEBUG(4, __FUNCTION__ "()\n");
+
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+       skb = dev_alloc_skb(64);
+       if (!skb)
+               return;
+
+       skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+       skb_put(skb, 2);
+       
+       frame = skb->data;
+       
+       /* Build frame */
+       frame[0] = CMD_CLOSE_DATA_CHAN;
+       frame[1] = 0x01; /* Two parameters */
+
+       irlan_insert_byte_param(skb, "DATA_CHAN", self->dtsap_sel_data);
+
+       irttp_data_request(self->client.tsap_ctrl, skb);
 }
 
 /*
@@ -280,84 +804,74 @@ void irlan_open_data_channel( struct irlan_cb *self)
  *    address.
  *
  */
-void irlan_open_unicast_addr( struct irlan_cb *self) 
+void irlan_open_unicast_addr(struct irlan_cb *self) 
 {
        struct sk_buff *skb;
        __u8 *frame;
        
-       DEBUG( 4, __FUNCTION__ "()\n");
+       DEBUG(4, __FUNCTION__ "()\n");
 
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == IRLAN_MAGIC, return;);   
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == IRLAN_MAGIC, return;);    
        
-       skb = dev_alloc_skb( 128);
-       if (skb == NULL) {
-               DEBUG( 0, __FUNCTION__
-                      "(), Could not allocate an skb of length %d\n", 64);
+       skb = dev_alloc_skb(128);
+       if (!skb)
                return;
-       }
 
        /* Reserve space for TTP, LMP, and LAP header */
-       skb_reserve( skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
-       skb_put( skb, 2);
+       skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+       skb_put(skb, 2);
        
        frame = skb->data;
        
        frame[0] = CMD_FILTER_OPERATION;
        frame[1] = 0x03;                 /* Three parameters */
-       insert_byte_param( skb, "DATA_CHAN" , self->dtsap_sel_data);
-       insert_string_param( skb, "FILTER_TYPE", "DIRECTED");
-       insert_string_param( skb, "FILTER_MODE", "FILTER"); 
+       irlan_insert_byte_param(skb, "DATA_CHAN" , self->dtsap_sel_data);
+       irlan_insert_string_param(skb, "FILTER_TYPE", "DIRECTED");
+       irlan_insert_string_param(skb, "FILTER_MODE", "FILTER"); 
        
-       irttp_data_request( self->tsap_ctrl, skb);
+       irttp_data_request(self->client.tsap_ctrl, skb);
 }
 
 /*
  * Function irlan_set_broadcast_filter (self, status)
  *
  *    Make IrLAN provider accept ethernet frames addressed to the broadcast
- *    address. Be careful with the use of this one, sice there may be a lot
+ *    address. Be careful with the use of this one, since there may be a lot
  *    of broadcast traffic out there. We can still function without this
  *    one but then _we_ have to initiate all communication with other
- *    hosts, sice ARP request for this host will not be answered.
+ *    hosts, since ARP request for this host will not be answered.
  */
-void irlan_set_broadcast_filter( struct irlan_cb *self, int status) 
+void irlan_set_broadcast_filter(struct irlan_cb *self, int status) 
 {
        struct sk_buff *skb;
        __u8 *frame;
        
-       DEBUG( 4, __FUNCTION__ "()\n");
+       DEBUG(2, __FUNCTION__ "()\n");
 
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == IRLAN_MAGIC, return;);
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == IRLAN_MAGIC, return;);
        
-       /* Should only be used by client */
-       if (!self->client)
+       skb = dev_alloc_skb(128);
+       if (!skb)
                return;
 
-       skb =  dev_alloc_skb( 128);
-       if (skb == NULL) {
-               DEBUG( 0, __FUNCTION__
-                      "(), Could not allocate an skb of length %d\n", 64);
-               return;
-       }
-
        /* Reserve space for TTP, LMP, and LAP header */
-       skb_reserve( skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
-       skb_put( skb, 2);
+       skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+       skb_put(skb, 2);
        
        frame = skb->data;
        
        frame[0] = CMD_FILTER_OPERATION;
        frame[1] = 0x03;                 /* Three parameters */
-       insert_byte_param( skb, "DATA_CHAN", self->dtsap_sel_data);
-       insert_string_param( skb, "FILTER_TYPE", "BROADCAST");
-       if ( status)
-               insert_string_param( skb, "FILTER_MODE", "FILTER"); 
+       irlan_insert_byte_param(skb, "DATA_CHAN", self->dtsap_sel_data);
+       irlan_insert_string_param(skb, "FILTER_TYPE", "BROADCAST");
+       if (status)
+               irlan_insert_string_param(skb, "FILTER_MODE", "FILTER"); 
        else
-               insert_string_param( skb, "FILTER_MODE", "NONE"); 
+               irlan_insert_string_param(skb, "FILTER_MODE", "NONE"); 
        
-       irttp_data_request( self->tsap_ctrl, skb);
+       irttp_data_request(self->client.tsap_ctrl, skb);
 }
 
 /*
@@ -367,43 +881,36 @@ void irlan_set_broadcast_filter( struct irlan_cb *self, int status)
  *    address. 
  *
  */
-void irlan_set_multicast_filter( struct irlan_cb *self, int status) 
+void irlan_set_multicast_filter(struct irlan_cb *self, int status) 
 {
        struct sk_buff *skb;
        __u8 *frame;
        
-       DEBUG( 4, __FUNCTION__ "()\n");
+       DEBUG(2, __FUNCTION__ "()\n");
 
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == IRLAN_MAGIC, return;);
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == IRLAN_MAGIC, return;);
 
-       /* Should only be used by client */
-       if (!self->client)
+       skb = dev_alloc_skb(128);
+       if (!skb)
                return;
        
-       skb =  dev_alloc_skb( 128);
-       if (skb == NULL) {
-               DEBUG( 0, __FUNCTION__
-                      "(), Could not allocate an skb of length %d\n", 64);
-               return;
-       }
-
        /* Reserve space for TTP, LMP, and LAP header */
-       skb_reserve( skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
-       skb_put( skb, 2);
+       skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+       skb_put(skb, 2);
        
        frame = skb->data;
        
        frame[0] = CMD_FILTER_OPERATION;
        frame[1] = 0x03;                 /* Three parameters */
-       insert_byte_param( skb, "DATA_CHAN", self->dtsap_sel_data);
-       insert_string_param( skb, "FILTER_TYPE", "MULTICAST");
-       if ( status)
-               insert_string_param( skb, "FILTER_MODE", "ALL"); 
+       irlan_insert_byte_param(skb, "DATA_CHAN", self->dtsap_sel_data);
+       irlan_insert_string_param(skb, "FILTER_TYPE", "MULTICAST");
+       if (status)
+               irlan_insert_string_param(skb, "FILTER_MODE", "ALL"); 
        else
-               insert_string_param( skb, "FILTER_MODE", "NONE"); 
+               irlan_insert_string_param(skb, "FILTER_MODE", "NONE"); 
        
-       irttp_data_request( self->tsap_ctrl, skb);
+       irttp_data_request(self->client.tsap_ctrl, skb);
 }
 
 /*
@@ -414,36 +921,33 @@ void irlan_set_multicast_filter( struct irlan_cb *self, int status)
  *    can construct its packets.
  *
  */
-void irlan_get_unicast_addr( struct irlan_cb *self) 
+void irlan_get_unicast_addr(struct irlan_cb *self) 
 {
        struct sk_buff *skb;
        __u8 *frame;
                
-       DEBUG( 4, __FUNCTION__ "()\n");
+       DEBUG(2, __FUNCTION__ "()\n");
 
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == IRLAN_MAGIC, return;);
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == IRLAN_MAGIC, return;);
        
-       skb =  dev_alloc_skb( 128);
-       if (skb == NULL) {
-               DEBUG( 0, "irlan_client_get_unicast_addr: "
-                      "Could not allocate an sk_buff of length %d\n", 64);
+       skb = dev_alloc_skb(128);
+       if (!skb)
                return;
-       }
 
        /* Reserve space for TTP, LMP, and LAP header */
-       skb_reserve( skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
-       skb_put( skb, 2);
+       skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+       skb_put(skb, 2);
        
        frame = skb->data;
        
        frame[0] = CMD_FILTER_OPERATION;
        frame[1] = 0x03;                 /* Three parameters */
-       insert_byte_param( skb, "DATA_CHAN", self->dtsap_sel_data);
-       insert_string_param( skb, "FILTER_TYPE", "DIRECTED");
-       insert_string_param( skb, "FILTER_OPERATION", "DYNAMIC"); 
+       irlan_insert_byte_param(skb, "DATA_CHAN", self->dtsap_sel_data);
+       irlan_insert_string_param(skb, "FILTER_TYPE", "DIRECTED");
+       irlan_insert_string_param(skb, "FILTER_OPERATION", "DYNAMIC"); 
        
-       irttp_data_request( self->tsap_ctrl, skb);
+       irttp_data_request(self->client.tsap_ctrl, skb);
 }
 
 /*
@@ -452,26 +956,23 @@ void irlan_get_unicast_addr( struct irlan_cb *self)
  *    
  *
  */
-void irlan_get_media_char( struct irlan_cb *self) 
+void irlan_get_media_char(struct irlan_cb *self) 
 {
        struct sk_buff *skb;
        __u8 *frame;
        
-       DEBUG( 4, __FUNCTION__ "()\n");
+       DEBUG(4, __FUNCTION__ "()\n");
 
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == IRLAN_MAGIC, return;);
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == IRLAN_MAGIC, return;);
        
-       skb = dev_alloc_skb( 64);
-       if (skb == NULL) {
-               DEBUG( 0,"irlan_server_get_media_char: "
-                      "Could not allocate an sk_buff of length %d\n", 64);
+       skb = dev_alloc_skb(64);
+       if (!skb)
                return;
-       }
 
        /* Reserve space for TTP, LMP, and LAP header */
-       skb_reserve( skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
-       skb_put( skb, 2);
+       skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+       skb_put(skb, 2);
        
        frame = skb->data;
        
@@ -479,9 +980,9 @@ void irlan_get_media_char( struct irlan_cb *self)
        frame[0] = CMD_GET_MEDIA_CHAR;
        frame[1] = 0x01; /* One parameter */
        
-       insert_string_param( skb, "MEDIA", "802.3");
+       irlan_insert_string_param(skb, "MEDIA", "802.3");
        
-       irttp_data_request( self->tsap_ctrl, skb);
+       irttp_data_request(self->client.tsap_ctrl, skb);
 }
 
 /*
@@ -490,47 +991,14 @@ void irlan_get_media_char( struct irlan_cb *self)
  *    Insert byte parameter into frame
  *
  */
-int insert_byte_param( struct sk_buff *skb, char *param, __u8 value)
+int irlan_insert_byte_param(struct sk_buff *skb, char *param, __u8 value)
 {
-       __u8 *frame;
-       __u8 len_param;
-       __u16 len_value;
-       int n=0;
-       
-       if ( skb == NULL) {
-               DEBUG( 0, "insert_param: Got NULL skb\n");
-               return 0;
-       }
-       
-       len_param = strlen( param);
-       len_value = 1;
-
-       /*
-        *  Insert at end of sk-buffer
-        */
-       frame = skb->tail;
-
-       /* Make space for data */
-       if ( skb_tailroom(skb) < (len_param+len_value+3)) {
-               DEBUG( 0, "insert_param: No more space at end of skb\n");
-               return 0;
-       }       
-       skb_put( skb, len_param+len_value+3);
-
-       /* Insert parameter length */
-       frame[n++] = len_param;
-       
-       /* Insert parameter */
-       memcpy( frame+n, param, len_param); 
-       n += len_param;
-       
-       /* Insert value length ( 2 byte little endian format, LSB first) */
-       frame[n++] = len_value & 0xff;
-       frame[n++] = len_value >> 8;
+       return __irlan_insert_param(skb, param, IRLAN_BYTE, value, 0, NULL, 0);
+}
 
-       frame[n++] = value;
-       
-       return len_param+len_value+3;
+int irlan_insert_short_param(struct sk_buff *skb, char *param, __u16 value)
+{
+       return __irlan_insert_param(skb, param, IRLAN_SHORT, 0, value, NULL, 0);
 }
 
 /*
@@ -539,96 +1007,25 @@ int insert_byte_param( struct sk_buff *skb, char *param, __u8 value)
  *    Insert string parameter into frame
  *
  */
-int insert_string_param( struct sk_buff *skb, char *param, char *value)
+int irlan_insert_string_param(struct sk_buff *skb, char *param, char *string)
 {
-       __u8 *frame;
-       __u8 len_param;
-       __u16 len_value;
-       int n=0;
-       
-       if ( skb == NULL) {
-               DEBUG( 0, "insert_param: Got NULL skb\n");
-               return 0;
-       }       
-       len_param = strlen( param);
-       len_value = strlen( value);
+       int string_len = strlen(string);
 
-       /*
-        *  Insert at end of sk-buffer
-        */
-       frame = skb->tail;
-
-       /* Make space for data */
-       if ( skb_tailroom(skb) < (len_param+len_value+3)) {
-               DEBUG( 0, "insert_param: No more space at end of skb\n");
-               return 0;
-       }       
-       skb_put( skb, len_param+len_value+3);
-
-       /* Insert parameter length */
-       frame[n++] = len_param;
-       
-       /* Insert parameter */
-       memcpy( frame+n, param, len_param); 
-       n += len_param;
-       
-       /* Insert value length ( 2 byte little endian format, LSB first) */
-       frame[n++] = len_value & 0xff;
-       frame[n++] = len_value >> 8;
-
-       memcpy( frame+n, value, len_value); 
-       n+=len_value;
-       
-       return len_param+len_value+3;
+       return __irlan_insert_param(skb, param, IRLAN_ARRAY, 0, 0, string, 
+                                   string_len);
 }
 
 /*
- * Function insert_array_param( skb, param, value, len_value)
+ * Function insert_array_param(skb, param, value, len_value)
  *
  *    Insert array parameter into frame
  *
  */
-int insert_array_param( struct sk_buff *skb, char *name, __u8 *value, 
-                       __u16 value_len)
+int irlan_insert_array_param(struct sk_buff *skb, char *name, __u8 *array,
+                            __u16 array_len)
 {
-       __u8 *frame;
-       __u8 name_len;
-       int n=0;
-       
-       if ( skb == NULL) {
-               DEBUG( 0, __FUNCTION__ "(), Got NULL skb\n");
-               return 0;
-       }       
-       name_len = strlen( name);
-
-       /*
-        *  Insert at end of sk-buffer
-        */
-       frame = skb->tail;
-
-       /* Make space for data */
-       if ( skb_tailroom(skb) < (name_len+value_len+3)) {
-               DEBUG( 0, __FUNCTION__ "(), No more space at end of skb\n");
-               return 0;
-       }       
-       skb_put( skb, name_len+value_len+3);
-
-       /* Insert parameter length */
-       frame[n++] = name_len;
-       
-       /* Insert parameter */
-       memcpy( frame+n, name, name_len); 
-       n += name_len;
-       
-       /* Insert value length ( 2 byte little endian format, LSB first) */
-       /* FIXME: should we use htons() here? */
-       frame[n++] = value_len & 0xff;
-       frame[n++] = value_len >> 8;
-
-       memcpy( frame+n, value, value_len); 
-       n+=value_len;
-       
-       return name_len+value_len+3;
+       return __irlan_insert_param(skb, name, IRLAN_ARRAY, 0, 0, array, 
+                                   array_len);
 }
 
 /*
@@ -640,130 +1037,121 @@ int insert_array_param( struct sk_buff *skb, char *name, __u8 *value,
  *    | Name Length[1] | Param Name[1..255] | Val Length[2] | Value[0..1016]|
  *    -----------------------------------------------------------------------
  */
-int insert_param( struct sk_buff *skb, char *param, int type, char *value_char,
-                 __u8 value_byte, __u16 value_short) 
+static int __irlan_insert_param(struct sk_buff *skb, char *param, int type, 
+                               __u8 value_byte, __u16 value_short, 
+                               __u8 *value_array, __u16 value_len)
 {
        __u8 *frame;
-       __u8 len_param;
-       __u16 len_value;
-       int n;
+       __u8 param_len;
+       int n=0;
        
-       if ( skb == NULL) {
-               DEBUG( 0, "insert_param: Got NULL skb\n");
+       if (skb == NULL) {
+               DEBUG(2, __FUNCTION__ "(), Got NULL skb\n");
                return 0;
-       }
-       
-       n = 0;
+       }       
 
-       len_param = strlen( param);
-       switch ( type) {
-       case 1:
-               ASSERT( value_char != NULL, return 0;);
-               len_value = strlen( value_char);
+       param_len = strlen(param);
+       switch (type) {
+       case IRLAN_BYTE:
+               value_len = 1;
                break;
-       case 2:
-               len_value = 1;
+       case IRLAN_SHORT:
+               value_len = 2;
                break;
-       case 3:
-               len_value = 2;
+       case IRLAN_ARRAY:
+               ASSERT(value_array != NULL, return 0;);
+               ASSERT(value_len > 0, return 0;);
                break;
        default:
-               DEBUG( 0, "Error in insert_param!\n");
+               DEBUG(2, __FUNCTION__ "(), Unknown parameter type!\n");
                return 0;
                break;
        }
        
-       /*
-        *  Insert at end of sk-buffer
-        */
+       /* Insert at end of sk-buffer */
        frame = skb->tail;
 
        /* Make space for data */
-       if ( skb_tailroom(skb) < (len_param+len_value+3)) {
-               DEBUG( 0, "insert_param: No more space at end of skb\n");
+       if (skb_tailroom(skb) < (param_len+value_len+3)) {
+               DEBUG(2, __FUNCTION__ "(), No more space at end of skb\n");
                return 0;
        }       
-       skb_put( skb, len_param+len_value+3);
-
+       skb_put(skb, param_len+value_len+3);
+       
        /* Insert parameter length */
-       frame[n++] = len_param;
+       frame[n++] = param_len;
        
        /* Insert parameter */
-       memcpy( frame+n, param, len_param); n += len_param;
+       memcpy(frame+n, param, param_len); n += param_len;
        
-       /* Insert value length ( 2 byte little endian format, LSB first) */
-       frame[n++] = len_value & 0xff;
-       frame[n++] = len_value >> 8;
+       /* Insert value length (2 byte little endian format, LSB first) */
+       *((__u16 *) (frame+n)) = cpu_to_le16(value_len); n += 2;
 
        /* Insert value */
        switch (type) {
-       case 1:
-               memcpy( frame+n, value_char, len_value); n+=len_value;
-               break;
-       case 2:
+       case IRLAN_BYTE:
                frame[n++] = value_byte;
                break;
-       case 3:
-               frame[n++] = value_short & 0xff;
-               frame[n++] = (value_short >> 8) & 0xff;
+       case IRLAN_SHORT:
+               *((__u16 *) (frame+n)) = cpu_to_le16(value_short); n += 2;
+               break;
+       case IRLAN_ARRAY:
+               memcpy(frame+n, value_array, value_len); n+=value_len;
                break;
        default:
                break;
        }
-       ASSERT( n == (len_param+len_value+3), return 0;);
+       ASSERT(n == (param_len+value_len+3), return 0;);
 
-       return len_param+len_value+3;
+       return param_len+value_len+3;
 }
 
 /*
  * Function irlan_get_response_param (buf, param, value)
  *
  *    Extracts a single parameter name/value pair from buffer and updates
- *    the buffer pointer to point to the next name/value pair.
- * 
+ *    the buffer pointer to point to the next name/value pair. 
  */
-int irlan_get_response_param( __u8 *buf, char *name, char *value, int *len)
+int irlan_get_param(__u8 *buf, char *name, char *value, __u16 *len)
 {
        __u8 name_len;
        __u16 val_len;
        int n=0;
-
-       DEBUG( 4, "irlan_get_response_param()\n");
        
-       /* get length of parameter name ( 1 byte) */
+       DEBUG(4, __FUNCTION__ "()\n");
+       
+       /* get length of parameter name (1 byte) */
        name_len = buf[n++];
        
        if (name_len > 254) {
-               DEBUG( 0, __FUNCTION__ "(), name_len > 254\n");
-               return -1;
+               DEBUG(2, __FUNCTION__ "(), name_len > 254\n");
+               return -RSP_INVALID_COMMAND_FORMAT;
        }
        
        /* get parameter name */
-       memcpy( name, buf+n, name_len);
+       memcpy(name, buf+n, name_len);
        name[ name_len] = '\0';
        n+=name_len;
        
        /*  
-        *  Get length of parameter value ( 2 bytes in little endian 
+        *  Get length of parameter value (2 bytes in little endian 
         *  format) 
         */
-       val_len = buf[n++] & 0xff;
-       val_len |= buf[n++] << 8;
+       val_len = le16_to_cpup(buf+n); n+=2;
        
        if (val_len > 1016) {
-               DEBUG( 0, __FUNCTION__ "(), parameter length to long\n");
-               return -1;
+               DEBUG(2, __FUNCTION__ "(), parameter length to long\n");
+               return -RSP_INVALID_COMMAND_FORMAT;
        }
-       
        *len = val_len;
 
        /* get parameter value */
-       memcpy( value, buf+n, val_len);
+       memcpy(value, buf+n, val_len);
        value[ val_len] = '\0';
        n+=val_len;
        
-       DEBUG( 4, "Parameter: %s ", name); 
-       DEBUG( 4, "Value: %s\n", value); 
+       DEBUG(4, "Parameter: %s ", name); 
+       DEBUG(4, "Value: %s\n", value); 
 
        return n;
 }
@@ -774,37 +1162,55 @@ int irlan_get_response_param( __u8 *buf, char *name, char *value, int *len)
  *
  *    Give some info to the /proc file system
  */
-static int irlan_proc_read( char *buf, char **start, off_t offset
-                           int len, int unused)
+static int irlan_proc_read(char *buf, char **start, off_t offset, int len
+                          int unused)
 {
        struct irlan_cb *self;
-       
-       ASSERT( irlan != NULL, return 0;);
+       unsigned long flags;
+     
+       save_flags(flags);
+       cli();
+
+       ASSERT(irlan != NULL, return 0;);
        
        len = 0;
        
-       len += sprintf( buf+len, "IrLAN\n");
-
-       self = ( struct irlan_cb *) hashbin_get_first( irlan);
-       while ( self != NULL) {
-               ASSERT( self->magic == IRLAN_MAGIC, return len;);
-
-               len += sprintf( buf+len, "ifname: %s, ",
-                               self->ifname);
-               /* len += sprintf( buf+len, "state: %s, ", */
-/*                             irlan_client_state[ self->state]); */
-               len += sprintf( buf+len, "saddr: %#08x\n",
-                               self->saddr);
-               len += sprintf( buf+len, "daddr: %#08x\n",
-                               self->daddr);
-               len += sprintf( buf+len, "tbusy: %s\n", self->dev.tbusy ? 
-                               "TRUE" : "FALSE");
+       len += sprintf(buf+len, "IrLAN instances:\n");
+       
+       self = (struct irlan_cb *) hashbin_get_first(irlan);
+       while (self != NULL) {
+               ASSERT(self->magic == IRLAN_MAGIC, return len;);
                
-               len += sprintf( buf+len, "\n");
-
-               self = ( struct irlan_cb *) hashbin_get_next( irlan);
-               DEBUG( 4, "self=%p\n", self);
+               len += sprintf(buf+len, "ifname: %s,\n",
+                              self->ifname);
+               len += sprintf(buf+len, "client state: %s, ",
+                              irlan_state[ self->client.state]);
+               len += sprintf(buf+len, "provider state: %s,\n",
+                              irlan_state[ self->provider.state]);
+               len += sprintf(buf+len, "saddr: %#08x, ",
+                              self->saddr);
+               len += sprintf(buf+len, "daddr: %#08x\n",
+                              self->daddr);
+               len += sprintf(buf+len, "version: %d.%d,\n",
+                              self->version[1], self->version[0]);
+               len += sprintf(buf+len, "access type: %s\n", 
+                              irlan_access[ self->access_type]);
+               len += sprintf(buf+len, "media: %s\n", 
+                              irlan_media[ self->media]);
+
+               len += sprintf(buf+len, "local filter:\n");
+               len += sprintf(buf+len, "remote filter: ");
+               len += irlan_print_filter(self->client.filter_type, buf+len);
+
+               len += sprintf(buf+len, "tx busy: %s\n", self->dev.tbusy ? 
+                              "TRUE" : "FALSE");
+
+               len += sprintf(buf+len, "\n");
+
+               self = (struct irlan_cb *) hashbin_get_next(irlan);
        } 
+       restore_flags(flags);
+
        return len;
 }
 #endif
@@ -815,41 +1221,41 @@ static int irlan_proc_read( char *buf, char **start, off_t offset,
  *    Print return code of request to peer IrLAN layer.
  *
  */
-void print_ret_code( __u8 code) 
+void print_ret_code(__u8 code) 
 {
-       switch( code) {
+       switch(code) {
        case 0:
-               printk( KERN_INFO "Success\n");
+               printk(KERN_INFO "Success\n");
                break;
        case 1:
-               printk( KERN_WARNING "Insufficient resources\n");
+               printk(KERN_WARNING "Insufficient resources\n");
                break;
        case 2:
-               printk( KERN_WARNING "Invalid command format\n");
+               printk(KERN_WARNING "Invalid command format\n");
                break;
        case 3:
-               printk( KERN_WARNING "Command not supported\n");
+               printk(KERN_WARNING "Command not supported\n");
                break;
        case 4:
-               printk( KERN_WARNING "Parameter not supported\n");
+               printk(KERN_WARNING "Parameter not supported\n");
                break;
        case 5:
-               printk( KERN_WARNING "Value not supported\n");
+               printk(KERN_WARNING "Value not supported\n");
                break;
        case 6:
-               printk( KERN_WARNING "Not open\n");
+               printk(KERN_WARNING "Not open\n");
                break;
        case 7:
-               printk( KERN_WARNING "Authentication required\n");
+               printk(KERN_WARNING "Authentication required\n");
                break;
        case 8:
-               printk( KERN_WARNING "Invalid password\n");
+               printk(KERN_WARNING "Invalid password\n");
                break;
        case 9:
-               printk( KERN_WARNING "Protocol error\n");
+               printk(KERN_WARNING "Protocol error\n");
                break;
        case 255:
-               printk( KERN_WARNING "Asynchronous status\n");
+               printk(KERN_WARNING "Asynchronous status\n");
                break;
        }
 }
@@ -859,6 +1265,10 @@ void print_ret_code( __u8 code)
 MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
 MODULE_DESCRIPTION("The Linux IrDA LAN protocol"); 
 
+MODULE_PARM(eth, "i");
+MODULE_PARM(access, "i");
+MODULE_PARM(timeout, "i");
+
 /*
  * Function init_module (void)
  *
@@ -867,8 +1277,6 @@ MODULE_DESCRIPTION("The Linux IrDA LAN protocol");
  */
 int init_module(void) 
 {
-       DEBUG( 4, __FUNCTION__ "(), irlan.c\n");
-
        irlan_init();
 
        return 0;
@@ -882,15 +1290,9 @@ int init_module(void)
  */
 void cleanup_module(void) 
 {
-       DEBUG( 4, "--> irlan, cleanup_module\n");
-       /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
-
        /* Free some memory */
        irlan_cleanup();
-
-       DEBUG( 4, "irlan, cleanup_module -->\n");
 }
 
 #endif /* MODULE */
 
-
index c84aa0aa9165fccccb87f4701d149af95322b560..d09df36524f9f009022b953ac9108e3a8ec6af3c 100644 (file)
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Oct 15 08:37:58 1998
- * Modified at:   Wed Dec  9 11:14:53 1998
+ * Modified at:   Wed Feb  3 19:58:28 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Sources:       skeleton.c by Donald Becker <becker@CESDIS.gsfc.nasa.gov>
  *                slip.c by Laurence Culhane,   <loz@holmes.demon.co.uk>
 #include <net/irda/irlan_common.h>
 #include <net/irda/irlan_eth.h>
 
-/*
- * Function irlan_eth_init (dev)
- *
- *    The network device initialization function. Called only once.
- *
- */
-int irlan_eth_init( struct device *dev)
-{
-       struct irlan_cb *self;
-
-       DEBUG( 4, __FUNCTION__"()\n");
-
-       ASSERT( dev != NULL, return -1;);
-       
-       self = (struct irlan_cb *) dev->priv;
-
-/*     dev->open               = irlan_eth_open;  */
-/*     dev->stop               = irlan_eth_close; */
-
-       dev->hard_start_xmit    = irlan_eth_tx; 
-       dev->get_stats          = irlan_eth_get_stats;
-       dev->set_multicast_list = irlan_eth_set_multicast_list;
-
-       dev->tbusy = 1;
-       
-       ether_setup( dev);
-       
-       dev->tx_queue_len = TTP_MAX_QUEUE;
-
-       return 0;
-}
-
-/*
- * Function irlan_eth_open (dev)
- *
- *    Start the IrLAN ether network device, this function will be called by
- *    "ifconfig irlan0 up".
- *
- */
-int irlan_eth_open( struct device *dev)
-{
-       /* struct irlan_cb *self = (struct irlan_cb *) dev->priv; */
-       
-       DEBUG( 4, __FUNCTION__ "()\n");
-
-       ASSERT( dev != NULL, return -1;);
-
-       /* Ready to play! */
-       dev->tbusy = 0;
-       dev->interrupt = 0;
-       dev->start = 1;
-
-       /* MOD_INC_USE_COUNT; */
-       
-       return 0;
-}
-
-/*
- * Function irlan_eth_close (dev)
- *
- *    Stop the Client ether network device, his function will be called by
- *    ifconfig down.
- */
-int irlan_eth_close(struct device *dev)
-{
-       DEBUG( 4, __FUNCTION__ "()\n");
-       
-       ASSERT( dev != NULL, return -1;);
-       
-       /* Stop device */
-       dev->tbusy = 1;
-       dev->start = 0;
-
-       /* MOD_DEC_USE_COUNT; */
-       
-       return 0;
-}
-
 /*
  * Function irlan_eth_tx (skb)
  *
  *    Transmits ethernet frames over IrDA link.
  *
  */
-int irlan_eth_tx( struct sk_buff *skb, struct device *dev)
+int irlan_eth_xmit(struct sk_buff *skb, struct device *dev)
 {
        struct irlan_cb *self;
 
-       DEBUG( 4, __FUNCTION__ "()\n");
+       DEBUG(4, __FUNCTION__ "()\n");
        
        self = (struct irlan_cb *) dev->priv;
 
-       ASSERT( self != NULL, return 0;);
-       ASSERT( self->magic == IRLAN_MAGIC, return 0;);
+       ASSERT(self != NULL, return 0;);
+       ASSERT(self->magic == IRLAN_MAGIC, return 0;);
 
-       if ( dev->tbusy) {
+       /* Lock transmit buffer */
+       if (irda_lock((void *) &dev->tbusy) == FALSE) {
                /*
                 * If we get here, some higher level has decided we are broken.
                 * There should really be a "kick me" function call instead.
                 */
                int tickssofar = jiffies - dev->trans_start; 
-               DEBUG( 4, __FUNCTION__ "(), tbusy==TRUE\n");
                
-               if ( tickssofar < 5) 
+               if (tickssofar < 5) 
                        return -EBUSY;
                
                dev->tbusy = 0;
                dev->trans_start = jiffies;
        }
-       /*
-        * If some higher layer thinks we've missed an tx-done interrupt
-        * we are passed NULL. Caution: dev_tint() handles the cli()/sti()
-        * itself.
-        */
-       if ( skb == NULL) {
-               DEBUG( 0, __FUNCTION__ "(), skb==NULL\n");
-
-               return 0;
-       }
-       /*
-        *  Check that we are connected
-         */
-       if ( !self->connected) {
-               DEBUG( 4, __FUNCTION__ "(), Not connected, dropping frame!\n");
-
-               dev_kfree_skb( skb);
-                ++self->stats.tx_dropped;
-               
-                return 0;
-       }
        
-       /*
-        * Block a timer-based transmit from overlapping. This could better be
-        * done with atomic_swap(1, dev->tbusy), but set_bit() works as well.
-        */
-       if ( test_and_set_bit(0, (void*) &dev->tbusy) != 0) {
-               printk( KERN_WARNING "%s: Transmitter access conflict.\n", 
-                       dev->name);
-               return 0;
-       }       
-       DEBUG( 4, "Room left at head: %d\n", skb_headroom(skb));
-       DEBUG( 4, "Room left at tail: %d\n", skb_tailroom(skb));
-       DEBUG( 4, "Required room: %d\n", IRLAN_MAX_HEADER);
+       DEBUG(4, "Room left at head: %d\n", skb_headroom(skb));
+       DEBUG(4, "Room left at tail: %d\n", skb_tailroom(skb));
+       DEBUG(4, "Required room: %d\n", IRLAN_MAX_HEADER);
        
-       /* Skb headroom large enough to contain IR-headers? */
-       if (( skb_headroom( skb) < IRLAN_MAX_HEADER) || ( skb_shared( skb))) {
+       /* skb headroom large enough to contain IR-headers? */
+       if ((skb_headroom(skb) < IRLAN_MAX_HEADER) || (skb_shared(skb))) {
                struct sk_buff *new_skb = 
                        skb_realloc_headroom(skb, IRLAN_MAX_HEADER);
-               ASSERT( new_skb != NULL, return 0;);
-               ASSERT( skb_headroom( new_skb) >= IRLAN_MAX_HEADER, return 0;);
+               ASSERT(new_skb != NULL, return 0;);
+               ASSERT(skb_headroom(new_skb) >= IRLAN_MAX_HEADER, return 0;);
 
                /*  Free original skb, and use the new one */
-               dev_kfree_skb( skb);
+               dev_kfree_skb(skb);
                skb = new_skb;
        } 
 
@@ -198,14 +90,14 @@ int irlan_eth_tx( struct sk_buff *skb, struct device *dev)
         *  Now queue the packet in the transport layer
         *  FIXME: clean up the code below! DB
         */
-       if ( self->use_udata) {
-               irttp_udata_request( self->tsap_data, skb);
+       if (self->use_udata) {
+               irttp_udata_request(self->tsap_data, skb);
                dev->tbusy = 0;
        
                return 0;
        }
 
-       if ( irttp_data_request( self->tsap_data, skb) == -1) {
+       if (irttp_data_request(self->tsap_data, skb) == -1) {
                /*  
                 *  IrTTPs tx queue is full, so we just have to drop the
                 *  frame! You might think that we should just return -1
@@ -215,53 +107,51 @@ int irlan_eth_tx( struct sk_buff *skb, struct device *dev)
                 *  really confuse do_dev_queue_xmit() in dev.c! I have
                 *  tried :-) DB
                 */
-               DEBUG( 4, __FUNCTION__ "(), Dropping frame\n");
-               dev_kfree_skb( skb);
+               dev_kfree_skb(skb);
                ++self->stats.tx_dropped;
                
                return 0;
        }
-       dev->tbusy = 0;
+       dev->tbusy = 0; /* Finished! */
        
        return 0;
 }
 
 /*
- * Function irlan_eth_rx (handle, skb)
+ * Function irlan_eth_receive (handle, skb)
  *
  *    This function gets the data that is received on the data channel
  *
  */
-void irlan_eth_rx( void *instance, void *sap, struct sk_buff *skb)
+void irlan_eth_receive(void *instance, void *sap, struct sk_buff *skb)
 {
        struct irlan_cb *self;
 
-       self = ( struct irlan_cb *) instance;
+       self = (struct irlan_cb *) instance;
 
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == IRLAN_MAGIC, return;);
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == IRLAN_MAGIC, return;);
 
        if (skb == NULL) {
                ++self->stats.rx_dropped; 
                return;
        }
-       IS_SKB( skb, return;);
-       ASSERT( skb->len > 1, return;);
+       ASSERT(skb->len > 1, return;);
                
-       DEBUG( 4, "Got some ether data: length=%d\n", (int)skb->len); 
-       
        /* 
         * Adopt this frame! Important to set all these fields since they 
         * might have been previously set by the low level IrDA network
         * device driver 
         */
        skb->dev = &self->dev;
-       skb->protocol=eth_type_trans( skb, skb->dev); /* Remove eth header */
+       skb->protocol=eth_type_trans(skb, skb->dev); /* Remove eth header */
        
-       netif_rx( skb);   /* Eat it! */
+       netif_rx(skb);   /* Eat it! */
        
        self->stats.rx_packets++;
        self->stats.rx_bytes += skb->len; 
+
+/*     net_bh(); */
 }
 
 /*
@@ -270,25 +160,25 @@ void irlan_eth_rx( void *instance, void *sap, struct sk_buff *skb)
  *    Do flow control between IP/Ethernet and IrLAN/IrTTP. This is done by 
  *    controlling the dev->tbusy variable.
  */
-void irlan_eth_flow_indication( void *instance, void *sap, LOCAL_FLOW flow)
+void irlan_eth_flow_indication(void *instance, void *sap, LOCAL_FLOW flow)
 {
        struct irlan_cb *self;
        struct device *dev;
 
-       DEBUG( 4, __FUNCTION__ "()\n");
+       DEBUG(4, __FUNCTION__ "()\n");
 
        self = (struct irlan_cb *) instance;
 
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == IRLAN_MAGIC, return;);
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == IRLAN_MAGIC, return;);
        
        dev = &self->dev;
 
-       ASSERT( dev != NULL, return;);
+       ASSERT(dev != NULL, return;);
        
-       switch ( flow) {
+       switch (flow) {
        case FLOW_STOP:
-               DEBUG( 4, "IrLAN, stopping Ethernet layer\n");
+               DEBUG(4, "IrLAN, stopping Ethernet layer\n");
 
                dev->tbusy = 1;
                break;
@@ -296,7 +186,7 @@ void irlan_eth_flow_indication( void *instance, void *sap, LOCAL_FLOW flow)
                /* 
                 *  Tell upper layers that its time to transmit frames again
                 */
-               DEBUG( 4, "IrLAN, starting Ethernet layer\n");
+               DEBUG(4, "IrLAN, starting Ethernet layer\n");
 
                dev->tbusy = 0;
 
@@ -304,10 +194,10 @@ void irlan_eth_flow_indication( void *instance, void *sap, LOCAL_FLOW flow)
                 *  Ready to receive more frames, so schedule the network
                 *  layer
                 */
-               mark_bh( NET_BH);               
+               mark_bh(NET_BH);                
                break;
        default:
-               DEBUG( 0, __FUNCTION__ "(), Unknown flow command!\n");
+               DEBUG(0, __FUNCTION__ "(), Unknown flow command!\n");
        }
 }
 
@@ -317,13 +207,13 @@ void irlan_eth_flow_indication( void *instance, void *sap, LOCAL_FLOW flow)
  *    If we don't want to use ARP. Currently not used!!
  *
  */
-void irlan_eth_rebuild_header( void *buff, struct device *dev, 
-                              unsigned long dest, struct sk_buff *skb)
+void irlan_eth_rebuild_header(void *buff, struct device *dev, 
+                             unsigned long dest, struct sk_buff *skb)
 {
-       struct ethhdr *eth = ( struct ethhdr *) buff;
+       struct ethhdr *eth = (struct ethhdr *) buff;
 
-       memcpy( eth->h_source, dev->dev_addr, dev->addr_len);
-       memcpy( eth->h_dest, dev->dev_addr, dev->addr_len);
+       memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
+       memcpy(eth->h_dest, dev->dev_addr, dev->addr_len);
 
        /* return 0; */
 }
@@ -335,47 +225,47 @@ void irlan_eth_rebuild_header( void *buff, struct device *dev,
  *
  */
 #define HW_MAX_ADDRS 4 /* Must query to get it! */
-void irlan_eth_set_multicast_list( struct device *dev) 
+void irlan_eth_set_multicast_list(struct device *dev) 
 {
        struct irlan_cb *self;
 
        self = dev->priv; 
 
-       DEBUG( 4, __FUNCTION__ "()\n");
-
-       ASSERT( self != NULL, return;); 
-       ASSERT( self->magic == IRLAN_MAGIC, return;);
+       DEBUG(0, __FUNCTION__ "()\n");
+       return;
+       ASSERT(self != NULL, return;); 
+       ASSERT(self->magic == IRLAN_MAGIC, return;);
 
        if (dev->flags&IFF_PROMISC) {
                /* Enable promiscuous mode */
-               DEBUG( 0, "Promiscous mode not implemented\n");
+               DEBUG(0, "Promiscous mode not implemented\n");
                /* outw(MULTICAST|PROMISC, ioaddr); */
        }
-       else if ((dev->flags&IFF_ALLMULTI) || dev->mc_count > HW_MAX_ADDRS) {
+       else if ((dev->flags & IFF_ALLMULTI) || dev->mc_count > HW_MAX_ADDRS) {
                /* Disable promiscuous mode, use normal mode. */
-               DEBUG( 4, __FUNCTION__ "(), Setting multicast filter\n");
+               DEBUG(4, __FUNCTION__ "(), Setting multicast filter\n");
                /* hardware_set_filter(NULL); */
 
-               irlan_set_multicast_filter( self, TRUE);
+               irlan_set_multicast_filter(self, TRUE);
        }
        else if (dev->mc_count) {
-               DEBUG( 4, __FUNCTION__ "(), Setting multicast filter\n");
+               DEBUG(4, __FUNCTION__ "(), Setting multicast filter\n");
                /* Walk the address list, and load the filter */
                /* hardware_set_filter(dev->mc_list); */
 
-               irlan_set_multicast_filter( self, TRUE);
+               irlan_set_multicast_filter(self, TRUE);
        }
        else {
-               DEBUG( 4, __FUNCTION__ "(), Clearing multicast filter\n");
-               irlan_set_multicast_filter( self, FALSE);
+               DEBUG(4, __FUNCTION__ "(), Clearing multicast filter\n");
+               irlan_set_multicast_filter(self, FALSE);
        }
 
-       if ( dev->flags & IFF_BROADCAST) {
-               DEBUG( 4, __FUNCTION__ "(), Setting broadcast filter\n");
-               irlan_set_broadcast_filter( self, TRUE);
+       if (dev->flags & IFF_BROADCAST) {
+               DEBUG(4, __FUNCTION__ "(), Setting broadcast filter\n");
+               irlan_set_broadcast_filter(self, TRUE);
        } else {
-               DEBUG( 4, __FUNCTION__ "(), Clearing broadcast filter\n");
-               irlan_set_broadcast_filter( self, FALSE);
+               DEBUG(4, __FUNCTION__ "(), Clearing broadcast filter\n");
+               irlan_set_broadcast_filter(self, FALSE);
        }
 }
 
@@ -385,12 +275,12 @@ void irlan_eth_set_multicast_list( struct device *dev)
  *    Get the current statistics for this device
  *
  */
-struct enet_statistics *irlan_eth_get_stats( struct device *dev) 
+struct enet_statistics *irlan_eth_get_stats(struct device *dev) 
 {
        struct irlan_cb *self = (struct irlan_cb *) dev->priv;
 
-       ASSERT( self != NULL, return NULL;);
-       ASSERT( self->magic == IRLAN_MAGIC, return NULL;);
+       ASSERT(self != NULL, return NULL;);
+       ASSERT(self->magic == IRLAN_MAGIC, return NULL;);
 
        return &self->stats;
 }
index 96fbccb58ef9a37f52c538fcf6ac343ad21b3ddc..d54e7cc122c06ff4e7e41d53d5c18d002d6bdf67 100644 (file)
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Oct 20 09:10:16 1998
- * Modified at:   Sat Dec  5 14:52:22 1998
+ * Modified at:   Wed Feb  3 21:42:27 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
@@ -38,11 +38,23 @@ char *irlan_state[] = {
        "IRLAN_SYNC",
 };
 
-void irlan_next_state( struct irlan_cb *self, 
-                      IRLAN_STATE state) 
+void irlan_next_client_state( struct irlan_cb *self, IRLAN_STATE state) 
 {
+       DEBUG(2, __FUNCTION__"(), %s\n", irlan_state[state]);
+
        ASSERT( self != NULL, return;);
        ASSERT( self->magic == IRLAN_MAGIC, return;);
 
-       self->state = state;
+       self->client.state = state;
 }
+
+void irlan_next_provider_state( struct irlan_cb *self, IRLAN_STATE state) 
+{
+       DEBUG(2, __FUNCTION__"(), %s\n", irlan_state[state]);
+
+       ASSERT( self != NULL, return;);
+       ASSERT( self->magic == IRLAN_MAGIC, return;);
+
+       self->provider.state = state;
+}
+
diff --git a/net/irda/irlan/irlan_filter.c b/net/irda/irlan/irlan_filter.c
new file mode 100644 (file)
index 0000000..5419b32
--- /dev/null
@@ -0,0 +1,235 @@
+/*********************************************************************
+ *                
+ * Filename:      irlan_filter.c
+ * Version:       
+ * Description:   
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Fri Jan 29 11:16:38 1999
+ * Modified at:   Sun Feb  7 23:48:07 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1998 Dag Brattli, 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.
+ *  
+ *     Neither Dag Brattli nor University of Tromsø admit liability nor
+ *     provide warranty for any of this software. This material is 
+ *     provided "AS-IS" and at no charge.
+ *     
+ ********************************************************************/
+
+#include <linux/skbuff.h>
+
+#include <net/irda/irlan_common.h>
+
+/*
+ * Function handle_filter_request (self, skb)
+ *
+ *    Handle filter request from client peer device
+ *
+ */
+void handle_filter_request(struct irlan_cb *self, struct sk_buff *skb)
+{
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+       if ((self->provider.filter_type == IRLAN_DIRECTED) && 
+           (self->provider.filter_operation == DYNAMIC))
+       {
+               DEBUG(0, "Giving peer a dynamic Ethernet address\n");
+
+               self->provider.mac_address[0] = 0x40;
+               self->provider.mac_address[1] = 0x00;
+               self->provider.mac_address[2] = 0x00;
+               self->provider.mac_address[3] = 0x00;
+               
+               /* Use arbitration value to generate MAC address */
+               if (self->access_type == ACCESS_PEER) {
+                       self->provider.mac_address[4] = 
+                               self->provider.send_arb_val & 0xff;
+                       self->provider.mac_address[5] = 
+                               (self->provider.send_arb_val >> 8) & 0xff;;
+               } else {
+                       /* Just generate something for now */
+                       self->provider.mac_address[4] = jiffies & 0xff;
+                       self->provider.mac_address[5] = (jiffies >> 8) & 0xff;
+               }
+
+               skb->data[0] = 0x00; /* Success */
+               skb->data[1] = 0x03;
+               irlan_insert_string_param(skb, "FILTER_MODE", "NONE");
+               irlan_insert_short_param(skb, "MAX_ENTRY", 0x0001);
+               irlan_insert_array_param(skb, "FILTER_ENTRY", self->provider.mac_address, 6);
+               return;
+       }
+       
+       if ((self->provider.filter_type == IRLAN_DIRECTED) && 
+           (self->provider.filter_mode == FILTER))
+       {
+               DEBUG(0, "Directed filter on\n");
+               skb->data[0] = 0x00; /* Success */
+               skb->data[1] = 0x00;
+               return;
+       }
+       if ((self->provider.filter_type == IRLAN_DIRECTED) && 
+           (self->provider.filter_mode == NONE))
+       {
+               DEBUG(0, "Directed filter off\n");
+               skb->data[0] = 0x00; /* Success */
+               skb->data[1] = 0x00;
+               return;
+       }
+
+       if ((self->provider.filter_type == IRLAN_BROADCAST) && 
+           (self->provider.filter_mode == FILTER))
+       {
+               DEBUG(0, "Broadcast filter on\n");
+               skb->data[0] = 0x00; /* Success */
+               skb->data[1] = 0x00;
+               return;
+       }
+       if ((self->provider.filter_type == IRLAN_BROADCAST) && 
+           (self->provider.filter_mode == NONE))
+       {
+               DEBUG(0, "Broadcast filter off\n");
+               skb->data[0] = 0x00; /* Success */
+               skb->data[1] = 0x00;
+               return;
+       }
+       if ((self->provider.filter_type == IRLAN_MULTICAST) && 
+           (self->provider.filter_mode == FILTER))
+       {
+               DEBUG(0, "Multicast filter on\n");
+               skb->data[0] = 0x00; /* Success */
+               skb->data[1] = 0x00;
+               return;
+       }
+       if ((self->provider.filter_type == IRLAN_MULTICAST) && 
+           (self->provider.filter_mode == NONE))
+       {
+               DEBUG(0, "Multicast filter off\n");
+               skb->data[0] = 0x00; /* Success */
+               skb->data[1] = 0x00;
+               return;
+       }
+       if ((self->provider.filter_type == IRLAN_MULTICAST) && 
+           (self->provider.filter_operation == GET))
+       {
+               DEBUG(0, "Multicast filter get\n");
+               skb->data[0] = 0x00; /* Success? */
+               skb->data[1] = 0x02;
+               irlan_insert_string_param(skb, "FILTER_MODE", "NONE");
+               irlan_insert_short_param(skb, "MAX_ENTRY", 16);
+               return;
+       }
+       skb->data[0] = 0x00; /* Command not supported */
+       skb->data[1] = 0x00;
+
+       DEBUG(0, "Not implemented!\n");
+}
+
+/*
+ * Function check_request_param (self, param, value)
+ *
+ *    Check parameters in request from peer device
+ *
+ */
+static void irlan_check_command_param(struct irlan_cb *self, char *param, 
+                                     char *value)
+{
+       __u8 *bytes;
+
+       DEBUG(4, __FUNCTION__ "()\n");
+
+       bytes = value;
+
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+       DEBUG(4, "%s, %s\n", param, value);
+
+       /*
+        *  This is experimental!! DB.
+        */
+        if (strcmp(param, "MODE") == 0) {
+               DEBUG(0, __FUNCTION__ "()\n");
+               self->use_udata = TRUE;
+               return;
+       }
+
+       /*
+        *  FILTER_TYPE
+        */
+       if (strcmp(param, "FILTER_TYPE") == 0) {
+               if (strcmp(value, "DIRECTED") == 0) {
+                       self->provider.filter_type = IRLAN_DIRECTED;
+                       return;
+               }
+               if (strcmp(value, "MULTICAST") == 0) {
+                       self->provider.filter_type = IRLAN_MULTICAST;
+                       return;
+               }
+               if (strcmp(value, "BROADCAST") == 0) {
+                       self->provider.filter_type = IRLAN_BROADCAST;
+                       return;
+               }
+       }
+       /*
+        *  FILTER_MODE
+        */
+       if (strcmp(param, "FILTER_MODE") == 0) {
+               if (strcmp(value, "ALL") == 0) {
+                       self->provider.filter_mode = ALL;
+                       return;
+               }
+               if (strcmp(value, "FILTER") == 0) {
+                       self->provider.filter_mode = FILTER;
+                       return;
+               }
+               if (strcmp(value, "NONE") == 0) {
+                       self->provider.filter_mode = FILTER;
+                       return;
+               }
+       }
+       /*
+        *  FILTER_OPERATION
+        */
+       if (strcmp(param, "FILTER_OPERATION") == 0) {
+               if (strcmp(value, "DYNAMIC") == 0) {
+                       self->provider.filter_operation = DYNAMIC;
+                       return;
+               }
+               if (strcmp(value, "GET") == 0) {
+                       self->provider.filter_operation = GET;
+                       return;
+               }
+       }
+}
+
+int irlan_print_filter(int filter_type, char *buf)
+{
+       int len = 0;
+
+       if (filter_type & IRLAN_DIRECTED)
+               len += sprintf(buf+len, "%s", "DIRECTED ");
+       if (filter_type & IRLAN_FUNCTIONAL)
+               len += sprintf(buf+len, "%s", "FUNCTIONAL ");
+       if (filter_type & IRLAN_GROUP)
+               len += sprintf(buf+len, "%s", "GROUP ");
+       if (filter_type & IRLAN_MAC_FRAME)
+               len += sprintf(buf+len, "%s", "MAC_FRAME ");
+       if (filter_type & IRLAN_MULTICAST)
+               len += sprintf(buf+len, "%s", "MULTICAST ");
+       if (filter_type & IRLAN_BROADCAST)
+               len += sprintf(buf+len, "%s", "BROADCAST ");
+       if (filter_type & IRLAN_IPX_SOCKET)
+               len += sprintf(buf+len, "%s", "IPX_SOCKET");
+
+       len += sprintf(buf+len, "\n");
+
+       return len;
+}
diff --git a/net/irda/irlan/irlan_provider.c b/net/irda/irlan/irlan_provider.c
new file mode 100644 (file)
index 0000000..eb8f035
--- /dev/null
@@ -0,0 +1,431 @@
+/*********************************************************************
+ *                
+ * Filename:      irlan_provider.c
+ * Version:       0.9
+ * Description:   IrDA LAN Access Protocol Implementation
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Sun Aug 31 20:14:37 1997
+ * Modified at:   Thu Feb  4 16:08:33 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * Sources:       skeleton.c by Donald Becker <becker@CESDIS.gsfc.nasa.gov>
+ *                slip.c by Laurence Culhane,   <loz@holmes.demon.co.uk>
+ *                          Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
+ * 
+ *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, 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.
+ *
+ *     Neither Dag Brattli nor University of Tromsø admit liability nor
+ *     provide warranty for any of this software. This material is 
+ *     provided "AS-IS" and at no charge.
+ *
+ ********************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/init.h>
+
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/byteorder.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irttp.h>
+#include <net/irda/irlmp.h>
+#include <net/irda/irias_object.h>
+#include <net/irda/iriap.h>
+#include <net/irda/timer.h>
+
+#include <net/irda/irlan_common.h>
+#include <net/irda/irlan_eth.h>
+#include <net/irda/irlan_event.h>
+#include <net/irda/irlan_provider.h>
+#include <net/irda/irlan_filter.h>
+#include <net/irda/irlan_client.h>
+
+/*
+ * Function irlan_provider_control_data_indication (handle, skb)
+ *
+ *    This function gets the data that is received on the control channel
+ *
+ */
+void irlan_provider_data_indication(void *instance, void *sap, 
+                                   struct sk_buff *skb) 
+{
+       struct irlan_cb *self;
+       __u8 code;
+       
+       DEBUG(4, __FUNCTION__ "()\n");
+       
+       self = (struct irlan_cb *) instance;
+
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+       ASSERT(skb != NULL, return;);
+
+       code = skb->data[0];
+       switch(code) {
+       case CMD_GET_PROVIDER_INFO:
+               DEBUG(4, "Got GET_PROVIDER_INFO command!\n");
+               irlan_do_provider_event(self, IRLAN_GET_INFO_CMD, skb); 
+               break;
+
+       case CMD_GET_MEDIA_CHAR:
+               DEBUG(4, "Got GET_MEDIA_CHAR command!\n");
+               irlan_do_provider_event(self, IRLAN_GET_MEDIA_CMD, skb); 
+               break;
+       case CMD_OPEN_DATA_CHANNEL:
+               DEBUG(4, "Got OPEN_DATA_CHANNEL command!\n");
+               irlan_do_provider_event(self, IRLAN_OPEN_DATA_CMD, skb); 
+               break;
+       case CMD_FILTER_OPERATION:
+               DEBUG(4, "Got FILTER_OPERATION command!\n");
+               irlan_do_provider_event(self, IRLAN_FILTER_CONFIG_CMD, skb);
+               break;
+       case CMD_RECONNECT_DATA_CHAN:
+               DEBUG(2, __FUNCTION__"(), Got RECONNECT_DATA_CHAN command\n");
+               DEBUG(2, __FUNCTION__"(), NOT IMPLEMENTED\n");
+               break;
+       case CMD_CLOSE_DATA_CHAN:
+               DEBUG(2, "Got CLOSE_DATA_CHAN command!\n");
+               DEBUG(2, __FUNCTION__"(), NOT IMPLEMENTED\n");
+               break;
+       default:
+               DEBUG(2, __FUNCTION__ "(), Unknown command!\n");
+               break;
+       }
+}
+
+/*
+ * Function irlan_provider_connect_indication (handle, skb, priv)
+ *
+ *    Got connection from peer IrLAN layer
+ *
+ */
+void irlan_provider_connect_indication(void *instance, void *sap, 
+                                      struct qos_info *qos, int max_sdu_size,
+                                      struct sk_buff *skb)
+{
+       struct irlan_cb *self, *entry, *new;
+       struct tsap_cb *tsap;
+
+       DEBUG(2, __FUNCTION__ "()\n");
+       
+       self = (struct irlan_cb *) instance;
+       tsap = (struct tsap_cb *) sap;
+       
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == IRLAN_MAGIC, return;);
+       
+       ASSERT(tsap == self->provider.tsap_ctrl,return;);
+       ASSERT(self->provider.state == IRLAN_IDLE, return;);
+
+       /* Check if this provider is unused */
+       if (self->daddr == DEV_ADDR_ANY) {
+               /*
+                * Rehash instance, now we have a client (daddr) to serve.
+                */
+               entry = hashbin_remove(irlan, self->daddr, NULL);
+               ASSERT( entry == self, return;);
+               
+               self->daddr = irttp_get_daddr(tsap);
+               DEBUG(2, __FUNCTION__ "(), daddr=%08x\n", self->daddr);
+               hashbin_insert(irlan, (QUEUE*) self, self->daddr, NULL);
+       } else {
+               /*
+                * If we already have the daddr set, this means that the
+                * client must already have started (peer mode). We must
+                * make sure that this connection attempt is from the same
+                * device as the client is dealing with!  
+                */
+               ASSERT(self->daddr == irttp_get_daddr(tsap), return;);
+       }
+       
+       /* Update saddr, since client may have moved to a new link */
+       self->saddr = irttp_get_saddr(tsap);
+       DEBUG(2, __FUNCTION__ "(), saddr=%08x\n", self->saddr);
+       
+       /* Check if network device has been registered */
+       if (!self->netdev_registered)
+               irlan_register_netdev(self);
+       
+       irlan_do_provider_event(self, IRLAN_CONNECT_INDICATION, NULL);
+
+       /*  
+        * If we are in peer mode, the client may not have got the discovery
+        * indication it needs to make progress. If the client is still in 
+        * IDLE state, we must kick it to 
+        */
+       if ((self->access_type == ACCESS_PEER) && 
+           (self->client.state == IRLAN_IDLE))
+               irlan_client_wakeup(self, self->saddr, self->daddr);
+
+       /* 
+        * This provider is now in use, so start a new provider instance to
+         * serve other clients. This will also change the LM-IAS entry so that
+        * other clients don't try to connect to us, now that we are busy.
+        */
+       new = irlan_open(DEV_ADDR_ANY, DEV_ADDR_ANY, FALSE);
+       self->client.start_new_provider = FALSE;
+}
+
+/*
+ * Function irlan_provider_connect_response (handle)
+ *
+ *    Accept incomming connection
+ *
+ */
+void irlan_provider_connect_response(struct irlan_cb *self,
+                                    struct tsap_cb *tsap)
+{
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+       /* Just accept */
+       irttp_connect_response(tsap, IRLAN_MTU, NULL);
+
+       /* Check if network device has been registered */
+       if (!self->netdev_registered)
+               irlan_register_netdev(self);
+               
+}
+
+void irlan_provider_disconnect_indication(void *instance, void *sap, 
+                                         LM_REASON reason, 
+                                         struct sk_buff *userdata) 
+{
+       struct irlan_cb *self;
+       struct tsap_cb *tsap;
+
+       DEBUG(4, __FUNCTION__ "(), reason=%d\n", reason);
+       
+       self = (struct irlan_cb *) instance;
+       tsap = (struct tsap_cb *) sap;
+
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == IRLAN_MAGIC, return;);    
+       ASSERT(tsap != NULL, return;);
+       ASSERT(tsap->magic == TTP_TSAP_MAGIC, return;);
+       
+       ASSERT(tsap == self->provider.tsap_ctrl, return;);
+       
+       irlan_do_provider_event(self, IRLAN_LMP_DISCONNECT, NULL);
+}
+
+/*
+ * Function irlan_parse_open_data_cmd (self, skb)
+ *
+ *    
+ *
+ */
+int irlan_parse_open_data_cmd(struct irlan_cb *self, struct sk_buff *skb)
+{
+       int ret;
+       
+       ret = irlan_provider_extract_params(self, CMD_OPEN_DATA_CHANNEL, skb);
+
+       return ret;
+}
+
+/*
+ * Function extract_params (skb)
+ *
+ *    Extract all parameters from received buffer, then feed them to 
+ *    check_params for parsing
+ *
+ */
+int irlan_provider_extract_params(struct irlan_cb *self, int cmd,
+                                 struct sk_buff *skb) 
+{
+       __u8 *frame;
+       __u8 *ptr;
+       int count;
+       __u8 name_len;
+       __u16 val_len;
+       int i;
+       char *name;
+        char *value;
+       int ret = RSP_SUCCESS;
+       
+       ASSERT(skb != NULL, return -RSP_PROTOCOL_ERROR;);
+       
+       DEBUG(4, __FUNCTION__ "(), skb->len=%d\n", (int)skb->len);
+
+       ASSERT(self != NULL, return -RSP_PROTOCOL_ERROR;);
+       ASSERT(self->magic == IRLAN_MAGIC, return -RSP_PROTOCOL_ERROR;);
+       
+       if (!skb)
+               return -RSP_PROTOCOL_ERROR;
+
+       frame = skb->data;
+
+       name = kmalloc(255, GFP_ATOMIC);
+       if (!name)
+               return -RSP_INSUFFICIENT_RESOURCES;
+       value = kmalloc(1016, GFP_ATOMIC);
+       if (!value) {
+               kfree(name);
+               return -RSP_INSUFFICIENT_RESOURCES;
+       }
+
+       /* How many parameters? */
+       count = frame[1];
+
+       DEBUG(4, "Got %d parameters\n", count);
+       
+       ptr = frame+2;
+       
+       /* For all parameters */
+       for (i=0; i<count;i++) {
+               ret = irlan_get_param(ptr, name, value, &val_len);
+               if (ret < 0) {
+                       DEBUG(2, __FUNCTION__ "(), IrLAN, Error!\n");
+                       break;
+               }
+               ptr+=ret;
+               ret = RSP_SUCCESS;
+               irlan_check_command_param(self, name, value);
+       }
+       /* Cleanup */
+       kfree(name);
+       kfree(value);
+
+       return ret;
+}
+
+/*
+ * Function irlan_provider_send_reply (self, info)
+ *
+ *    Send reply to query to peer IrLAN layer
+ *
+ */
+void irlan_provider_send_reply(struct irlan_cb *self, int command, 
+                              int ret_code)
+{
+       struct sk_buff *skb;
+
+       DEBUG(4, __FUNCTION__ "()\n");
+
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+       skb = dev_alloc_skb(128);
+       if (!skb)
+               return;
+
+       /* Reserve space for TTP, LMP, and LAP header */
+       skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+       skb_put(skb, 2);
+       
+       switch (command) {
+       case CMD_GET_PROVIDER_INFO:
+               skb->data[0] = 0x00; /* Success */
+               skb->data[1] = 0x02; /* 2 parameters */
+               switch (self->media) {
+               case MEDIA_802_3:
+                       irlan_insert_string_param(skb, "MEDIA", "802.3");
+                       break;
+               case MEDIA_802_5:
+                       irlan_insert_string_param(skb, "MEDIA", "802.5");
+                       break;
+               default:
+                       DEBUG(2, __FUNCTION__ "(), unknown media type!\n");
+                       break;
+               }
+               irlan_insert_short_param(skb, "IRLAN_VER", 0x0101);
+               break;
+       case CMD_GET_MEDIA_CHAR:
+               skb->data[0] = 0x00; /* Success */
+               skb->data[1] = 0x05; /* 5 parameters */
+               irlan_insert_string_param(skb, "FILTER_TYPE", "DIRECTED");
+               irlan_insert_string_param(skb, "FILTER_TYPE", "BROADCAST");
+               irlan_insert_string_param(skb, "FILTER_TYPE", "MULTICAST");
+
+               switch(self->access_type) {
+               case ACCESS_DIRECT:
+                       irlan_insert_string_param(skb, "ACCESS_TYPE", "DIRECT");
+                       break;
+               case ACCESS_PEER:
+                       irlan_insert_string_param(skb, "ACCESS_TYPE", "PEER");
+                       break;
+               case ACCESS_HOSTED:
+                       irlan_insert_string_param(skb, "ACCESS_TYPE", "HOSTED");
+                       break;
+               default:
+                       DEBUG(2, __FUNCTION__ "(), Unknown access type\n");
+                       break;
+               }
+               irlan_insert_short_param(skb, "MAX_FRAME", 0x05ee);
+               break;
+       case CMD_OPEN_DATA_CHANNEL:
+               skb->data[0] = 0x00; /* Success */
+               if (self->provider.send_arb_val) {
+                       skb->data[1] = 0x03; /* 3 parameters */
+                       irlan_insert_short_param(skb, "CON_ARB", 
+                                                self->provider.send_arb_val);
+               } else
+                       skb->data[1] = 0x02; /* 2 parameters */
+               irlan_insert_byte_param(skb, "DATA_CHAN", self->stsap_sel_data);
+               irlan_insert_array_param(skb, "RECONNECT_KEY", "LINUX RULES!",
+                                        12);
+               break;
+       case CMD_FILTER_OPERATION:
+               handle_filter_request(self, skb);
+               break;
+       default:
+               DEBUG(2, __FUNCTION__ "(), Unknown command!\n");
+               break;
+       }
+
+       irttp_data_request(self->provider.tsap_ctrl, skb);
+}
+
+/*
+ * Function irlan_provider_register(void)
+ *
+ *    Register provider support so we can accept incomming connections.
+ * 
+ */
+void irlan_provider_open_ctrl_tsap(struct irlan_cb *self)
+{
+       struct notify_t notify;
+       struct tsap_cb *tsap;
+       
+       DEBUG(4, __FUNCTION__ "()\n");
+
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == IRLAN_MAGIC, return;);
+
+       /* Check if already open */
+       if (self->provider.tsap_ctrl)
+               return;
+       
+       /*
+        *  First register well known control TSAP
+        */
+       irda_notify_init(&notify);
+       notify.data_indication       = irlan_provider_data_indication;
+       notify.connect_indication    = irlan_provider_connect_indication;
+       notify.disconnect_indication = irlan_provider_disconnect_indication;
+       notify.instance = self;
+       strncpy(notify.name, "IrLAN ctrl (p)", 16);
+
+       tsap = irttp_open_tsap(LSAP_ANY, 1, &notify);
+       if (!tsap) {
+               DEBUG(2, __FUNCTION__ "(), Got no tsap!\n");
+               return;
+       }
+       self->provider.tsap_ctrl = tsap;
+
+       /* Register with LM-IAS */
+       irlan_ias_register(self,tsap->stsap_sel);
+}
+
diff --git a/net/irda/irlan/irlan_provider_event.c b/net/irda/irlan/irlan_provider_event.c
new file mode 100644 (file)
index 0000000..c8dc9b4
--- /dev/null
@@ -0,0 +1,240 @@
+/*********************************************************************
+ *                
+ * Filename:      irlan_provider_event.c
+ * Version:       0.9
+ * Description:   IrLAN provider state machine)
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Sun Aug 31 20:14:37 1997
+ * Modified at:   Wed Feb  3 21:43:06 1999
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, 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.
+ *
+ *     Neither Dag Brattli nor University of Tromsø admit liability nor
+ *     provide warranty for any of this software. This material is 
+ *     provided "AS-IS" and at no charge.
+ *
+ ********************************************************************/
+
+#include <net/irda/irda.h>
+#include <net/irda/iriap.h>
+#include <net/irda/irlmp.h>
+#include <net/irda/irttp.h>
+
+#include <net/irda/irlan_provider.h>
+#include <net/irda/irlan_event.h>
+
+static int irlan_provider_state_idle(struct irlan_cb *self, IRLAN_EVENT event, 
+                                    struct sk_buff *skb);
+static int irlan_provider_state_info(struct irlan_cb *self, IRLAN_EVENT event, 
+                                    struct sk_buff *skb);
+static int irlan_provider_state_open(struct irlan_cb *self, IRLAN_EVENT event, 
+                                    struct sk_buff *skb);
+static int irlan_provider_state_data(struct irlan_cb *self, IRLAN_EVENT event, 
+                                    struct sk_buff *skb);
+
+static int (*state[])(struct irlan_cb *self, IRLAN_EVENT event, 
+                     struct sk_buff *skb) = 
+{ 
+       irlan_provider_state_idle,
+       NULL, /* Query */
+       NULL, /* Info */
+       irlan_provider_state_info,
+       NULL, /* Media */
+       irlan_provider_state_open,
+       NULL, /* Wait */
+       NULL, /* Arb */
+       irlan_provider_state_data,
+       NULL, /* Close */
+       NULL, /* Sync */
+};
+
+void irlan_do_provider_event(struct irlan_cb *self, IRLAN_EVENT event, 
+                            struct sk_buff *skb) 
+{
+       ASSERT(*state[ self->provider.state] != NULL, return;);
+
+       (*state[self->provider.state]) (self, event, skb);
+}
+
+/*
+ * Function irlan_provider_state_idle (event, skb, info)
+ *
+ *    IDLE, We are waiting for an indication that there is a provider
+ *    available.
+ */
+static int irlan_provider_state_idle(struct irlan_cb *self, IRLAN_EVENT event,
+                                    struct sk_buff *skb)
+{
+       DEBUG(4, __FUNCTION__ "()\n");
+       
+       ASSERT(self != NULL, return -1;);
+       
+       switch(event) {
+       case IRLAN_CONNECT_INDICATION:
+            irlan_provider_connect_response( self, self->provider.tsap_ctrl);
+            irlan_next_provider_state( self, IRLAN_INFO);
+            break;
+       default:
+               DEBUG(4, __FUNCTION__ "(), Unknown event %d\n", event);
+               break;
+       }
+       if (skb)
+               dev_kfree_skb(skb);
+
+       return 0;
+}
+
+/*
+ * Function irlan_provider_state_info (self, event, skb, info)
+ *
+ *    INFO, We have issued a GetInfo command and is awaiting a reply.
+ */
+static int irlan_provider_state_info(struct irlan_cb *self, IRLAN_EVENT event, 
+                                    struct sk_buff *skb) 
+{
+       int ret;
+
+       DEBUG(4, __FUNCTION__ "()\n");
+       
+       ASSERT(self != NULL, return -1;);
+
+       switch(event) {
+       case IRLAN_GET_INFO_CMD:
+               /* Be sure to use 802.3 in case of peer mode */
+               if (self->access_type == ACCESS_PEER)
+                       self->media = MEDIA_802_3;
+
+               irlan_provider_send_reply(self, CMD_GET_PROVIDER_INFO, 
+                                         RSP_SUCCESS);
+               /* Keep state */
+               break;
+       case IRLAN_GET_MEDIA_CMD: 
+               irlan_provider_send_reply(self, CMD_GET_MEDIA_CHAR, 
+                                         RSP_SUCCESS);
+               /* Keep state */
+               break;          
+       case IRLAN_OPEN_DATA_CMD:
+               ret = irlan_parse_open_data_cmd(self, skb);
+               if (self->access_type == ACCESS_PEER) {
+                       /* FIXME: make use of random functions! */
+                       self->provider.send_arb_val = (jiffies & 0xffff);
+               }
+               irlan_provider_send_reply(self, CMD_OPEN_DATA_CHANNEL, ret);
+
+               if (ret == RSP_SUCCESS) {
+                       irlan_next_provider_state(self, IRLAN_OPEN);
+
+                       /* Signal client that we are now open */
+                       irlan_do_client_event(self, IRLAN_PROVIDER_SIGNAL, NULL);
+               }
+               break;
+       case IRLAN_LMP_DISCONNECT:  /* FALLTHROUGH */
+       case IRLAN_LAP_DISCONNECT:
+               irlan_next_provider_state(self, IRLAN_IDLE);
+               break;
+       default:
+               DEBUG( 0, __FUNCTION__ "(), Unknown event %d\n", event);
+               break;
+       }
+       if (skb)
+               dev_kfree_skb(skb);
+       
+       return 0;
+}
+
+/*
+ * Function irlan_provider_state_open (self, event, skb, info)
+ *
+ *    OPEN, The client has issued a OpenData command and is awaiting a
+ *    reply
+ *
+ */
+static int irlan_provider_state_open(struct irlan_cb *self, IRLAN_EVENT event, 
+                                    struct sk_buff *skb)
+{
+       DEBUG(4, __FUNCTION__ "()\n");
+
+       ASSERT(self != NULL, return -1;);
+
+       switch(event) {
+       case IRLAN_FILTER_CONFIG_CMD:
+               irlan_provider_extract_params(self, CMD_FILTER_OPERATION, skb);
+               irlan_provider_send_reply(self, CMD_FILTER_OPERATION, 
+                                         RSP_SUCCESS);
+               /* Keep state */
+               break;
+       case IRLAN_DATA_CONNECT_INDICATION: 
+               irlan_next_provider_state(self, IRLAN_DATA);
+               irlan_provider_connect_response(self, self->tsap_data);
+               break;
+       case IRLAN_LMP_DISCONNECT:  /* FALLTHROUGH */
+       case IRLAN_LAP_DISCONNECT:
+               irlan_next_provider_state(self, IRLAN_IDLE);
+               break;
+       default:
+               DEBUG(2, __FUNCTION__ "(), Unknown event %d\n", event);
+               break;
+       }
+       if (skb)
+               dev_kfree_skb(skb);
+
+       return 0;
+}
+
+/*
+ * Function irlan_provider_state_data (self, event, skb, info)
+ *
+ *    DATA, The data channel is connected, allowing data transfers between
+ *    the local and remote machines.
+ *
+ */
+static int irlan_provider_state_data(struct irlan_cb *self, IRLAN_EVENT event, 
+                                    struct sk_buff *skb) 
+{
+       struct irmanager_event mgr_event;
+
+       DEBUG(4, __FUNCTION__ "()\n");
+
+       ASSERT(self != NULL, return -1;);
+       ASSERT(self->magic == IRLAN_MAGIC, return -1;);
+
+       switch(event) {
+       case IRLAN_FILTER_CONFIG_CMD:
+               irlan_provider_extract_params(self, CMD_FILTER_OPERATION, skb);
+               irlan_provider_send_reply(self, CMD_FILTER_OPERATION, 
+                                         RSP_SUCCESS);
+               break;
+       case IRLAN_LMP_DISCONNECT: /* FALLTHROUGH */
+       case IRLAN_LAP_DISCONNECT:
+               mgr_event.event = EVENT_IRLAN_STOP;
+               sprintf(mgr_event.devname, "%s", self->ifname);
+               irmanager_notify(&mgr_event);
+
+               irlan_next_provider_state(self, IRLAN_IDLE);
+               break;
+       default:
+               DEBUG( 0, __FUNCTION__ "(), Unknown event %d\n", event);
+               break;
+       }
+       if (skb)
+               dev_kfree_skb(skb);
+       
+       return 0;
+}
+
+
+
+
+
+
+
+
+
+
diff --git a/net/irda/irlan/irlan_srv.c b/net/irda/irlan/irlan_srv.c
deleted file mode 100644 (file)
index df4c6f9..0000000
+++ /dev/null
@@ -1,915 +0,0 @@
-/*********************************************************************
- *                
- * Filename:      irlan_srv.c
- * Version:       0.1
- * Description:   IrDA LAN Access Protocol Implementation
- * Status:        Experimental.
- * Author:        Dag Brattli <dagb@cs.uit.no>
- * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Mon Dec 14 19:10:49 1998
- * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * Sources:       skeleton.c by Donald Becker <becker@CESDIS.gsfc.nasa.gov>
- *                slip.c by Laurence Culhane,   <loz@holmes.demon.co.uk>
- *                          Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
- * 
- *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, 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.
- *
- *     Neither Dag Brattli nor University of Tromsø admit liability nor
- *     provide warranty for any of this software. This material is 
- *     provided "AS-IS" and at no charge.
- *
- ********************************************************************/
-
-#include <linux/module.h> 
-
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/init.h>
-
-#include <asm/system.h>
-#include <asm/bitops.h>
-#include <asm/byteorder.h>
-
-
-#include <net/irda/irda.h>
-#include <net/irda/irttp.h>
-#include <net/irda/irlmp.h>
-#include <net/irda/irias_object.h>
-#include <net/irda/iriap.h>
-#include <net/irda/timer.h>
-
-#include <net/irda/irlan_common.h>
-#include <net/irda/irlan_eth.h>
-#include <net/irda/irlan_event.h>
-#include <net/irda/irlan_srv.h>
-
-/*
- *  Private functions
- */
-static void __irlan_server_close( struct irlan_cb *self);
-static int irlan_server_dev_init( struct device *dev);
-static int irlan_server_dev_open(struct device *dev);
-static int irlan_server_dev_close(struct device *dev);
-static void irlan_check_param( struct irlan_cb *self, char *param, char *value);
-
-/*
- * Function irlan_server_init (dev)
- *
- *   Allocates the master array. Called by modprobe().
- */
-__initfunc(int irlan_server_init( void))
-{
-       DEBUG( 4, "--> irlan_server_init\n");
-
-       /* Register with IrLMP as a service */
-       irlmp_register_layer( S_LAN, SERVER, FALSE, NULL);
-       
-       irlan_server_register();
-               
-       DEBUG( 4, "irlan_server_init -->\n");
-               
-       return 0;
-}
-
-/*
- * Function irlan_server_cleanup (void)
- *
- *    Removes all instances of the IrLAN network device driver, and the
- *    master array. Called by rmmod().
- */
-void irlan_server_cleanup(void) 
-{
-       DEBUG( 4, "--> irlan_server_cleanup\n");
-
-       irlmp_unregister_layer( S_LAN, SERVER);
-
-       /*
-        *  Delete hashbin and close all irlan client instances in it
-        */
-       /* hashbin_delete( irlan, (FREE_FUNC) __irlan_server_close); */
-       
-       DEBUG( 4, "irlan_server_cleanup -->\n");
-}
-
-/*
- * Function irlan_server_open (void)
- *
- *    This function allocates and opens a new instance of the IrLAN network
- *    device driver.
- */
-struct irlan_cb *irlan_server_open(void) 
-{
-       struct irlan_cb *self;
-       int result;
-
-       DEBUG( 4, __FUNCTION__ "()\n");
-
-       /* 
-        *  Initialize the irlan_server structure. 
-        */
-
-       self = kmalloc( sizeof(struct irlan_cb), GFP_ATOMIC);
-       if ( self == NULL) {
-               DEBUG( 0, __FUNCTION__ "(), Unable to kmalloc!\n");
-               return NULL;
-       }
-       memset( self, 0, sizeof(struct irlan_cb));
-
-       /*
-        *  Initialize local device structure
-        */
-       self->magic = IRLAN_MAGIC;
-
-       self->dev.name = self->ifname;
-       self->dev.init = irlan_server_dev_init;
-       self->dev.priv = (void *) self;
-       self->dev.next = NULL;
-
-       if (( result = register_netdev( &self->dev)) != 0) {
-               DEBUG( 0, __FUNCTION__ "(), register_netdev() failed!\n");
-               return NULL;
-       }
-
-       irlan_next_state( self, IRLAN_IDLE);
-
-       hashbin_insert( irlan , (QUEUE *) self, (int) self, NULL);
-       
-       return self;
-}
-
-/*
- * Function irlan_server_dev_init (dev)
- *
- *    The network device initialization function. Called only once.
- *
- */
-static int irlan_server_dev_init( struct device *dev)
-{
-       DEBUG( 4, __FUNCTION__ "()\n");
-
-       ASSERT( dev != NULL, return -1;);
-       
-       irlan_eth_init( dev);
-
-       /* Overrride some functions */
-       dev->open               = irlan_server_dev_open;
-       dev->stop               = irlan_server_dev_close;
-       
-       /*  
-        *  OK, since we are emulating an IrLAN sever we will have to give
-        *  ourself an ethernet address!
-        *  FIXME: this must be more dynamically
-        */
-       dev->dev_addr[0] = 0x40;
-       dev->dev_addr[1] = 0x00;
-       dev->dev_addr[2] = 0x00;
-       dev->dev_addr[3] = 0x00;
-       dev->dev_addr[4] = 0x23;
-       dev->dev_addr[5] = 0x45;
-
-       return 0;
-}
-
-/*
- * Function irlan_server_dev_open (dev)
- *
- *    Start the Servers ether network device, this function will be called by
- *    "ifconfig server0 up".  
- */
-static int irlan_server_dev_open( struct device *dev)
-{
-       /* struct irlan_cb *self = (struct irlan_cb *) dev->priv; */
-       
-       DEBUG( 4, "irlan_server_dev_open()\n");
-
-       ASSERT( dev != NULL, return -1;);
-
-       dev->tbusy = 0;
-       dev->interrupt = 0;
-       dev->start = 1;
-
-       MOD_INC_USE_COUNT;
-       
-       return 0;
-}
-
-static void __irlan_server_close( struct irlan_cb *self)
-{
-       DEBUG( 4, "--> irlan_server_close()\n");
-       
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == IRLAN_MAGIC, return;);
-       
-       /* 
-        *  Disconnect open TSAP connections
-        */
-       if ( self->tsap_data) {
-               irttp_disconnect_request( self->tsap_data, NULL, P_HIGH);
-               
-               /* FIXME: this will close the tsap before the disconenct
-                * frame has been sent 
-                */
-               /* irttp_close_tsap( self->tsap_data); */
-       }
-       if ( self->tsap_ctrl) {
-               irttp_disconnect_request( self->tsap_ctrl, NULL, P_HIGH);
-               
-               /* irttp_close_tsap( self->tsap_control); */
-       }
-
-       unregister_netdev( &self->dev);
-
-       self->magic = ~IRLAN_MAGIC;
-       
-       kfree( self);
-
-       DEBUG( 4, "irlan_server_close() -->\n");
-}
-
-/*
- * Function irlan_server_close (self)
- *
- *    This function closes and marks the IrLAN instance as not in use. 
- */
-void irlan_server_close( struct irlan_cb *self)
-{
-       struct irlan_cb *entry;
-
-       DEBUG( 4, "--> irlan_server_close()\n");
-       
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == IRLAN_MAGIC, return;);
-       
-       entry = hashbin_remove( irlan, (int) self, NULL);
-
-       ASSERT( entry == self, return;);
-       
-       __irlan_server_close( self);
-
-       DEBUG( 4, "irlan_server_close() -->\n");        
-}
-
-/*
- * Function irlan_server_dev_close (dev)
- *
- *    Stop the IrLAN ether network device, his function will be called by
- *    ifconfig down.
- */
-static int irlan_server_dev_close( struct device *dev)
-{
-       DEBUG( 4, __FUNCTION__ "()\n");
-
-       ASSERT( dev != NULL, return -1;);
-       
-       dev->tbusy = 1;
-       dev->start = 0;
-
-       MOD_DEC_USE_COUNT;
-       
-       return 0;
-}
-
-
-/*
- * Function irlan_server_disconnect_indication (handle, reason, priv)
- *
- *    Callback function for the IrTTP layer. Indicates a disconnection of
- *    the specified connection (handle)
- *
- */
-void irlan_server_disconnect_indication( void *instance, void *sap, 
-                                        LM_REASON reason, 
-                                        struct sk_buff *skb) 
-{
-       struct irlan_info info;
-       struct irlan_cb *self;
-       struct tsap_cb *tsap;
-       
-       DEBUG( 4, __FUNCTION__ "(), Reason=%d\n", reason);
-       
-       self = ( struct irlan_cb *) instance;
-       tsap = ( struct tsap_cb *) sap;
-       
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == IRLAN_MAGIC, return;);   
-
-       info.daddr = self->daddr;
-       
-       if ( tsap == self->tsap_data) {
-               DEBUG( 0, "IrLAN, data channel disconnected by peer!\n");
-               self->connected = FALSE;
-       } else if ( tsap == self->tsap_ctrl) {
-               DEBUG( 0, "IrLAN, control channel disconnected by peer!\n");
-       } else {
-               DEBUG( 0, "Error, disconnect on unknown handle!\n");
-       }
-       
-       /* Stop IP from transmitting more packets */
-       /* irlan_flow_indication( handle, FLOW_STOP, priv); */
-
-       irlan_do_server_event( self, IRLAN_LMP_DISCONNECT, NULL, NULL);
-}
-       
-/*
- * Function irlan_server_control_data_indication (handle, skb)
- *
- *    This function gets the data that is received on the control channel
- *
- */
-void irlan_server_control_data_indication( void *instance, void *sap, 
-                                          struct sk_buff *skb) 
-{
-       struct irlan_cb *self;
-       __u8 code;
-       
-       DEBUG( 4, __FUNCTION__ "()\n");
-       
-       self = ( struct irlan_cb *) instance;
-
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == IRLAN_MAGIC, return;);
-
-       ASSERT( skb != NULL, return;);
-
-       code = skb->data[0];
-       switch( code) {
-       case CMD_GET_PROVIDER_INFO:
-               DEBUG( 4, "Got GET_PROVIDER_INFO command!\n");
-               irlan_do_server_event( self, IRLAN_GET_INFO_CMD, skb, NULL); 
-               break;
-
-       case CMD_GET_MEDIA_CHAR:
-               DEBUG( 4, "Got GET_MEDIA_CHAR command!\n");
-               irlan_do_server_event( self, IRLAN_GET_MEDIA_CMD, skb, NULL); 
-               break;
-       case CMD_OPEN_DATA_CHANNEL:
-               DEBUG( 4, "Got OPEN_DATA_CHANNEL command!\n");
-               irlan_do_server_event( self, IRLAN_OPEN_DATA_CMD, skb, NULL); 
-               break;
-       case CMD_FILTER_OPERATION:
-               DEBUG( 4, "Got FILTER_OPERATION command!\n");
-               irlan_do_server_event( self, IRLAN_FILTER_CONFIG_CMD, skb, 
-                                      NULL);
-               break;
-       case CMD_RECONNECT_DATA_CHAN:
-               DEBUG( 0, __FUNCTION__"(), Got RECONNECT_DATA_CHAN command\n");
-               DEBUG( 0, __FUNCTION__"(), NOT IMPLEMENTED\n");
-               break;
-       case CMD_CLOSE_DATA_CHAN:
-               DEBUG( 0, "Got CLOSE_DATA_CHAN command!\n");
-               DEBUG( 0, __FUNCTION__"(), NOT IMPLEMENTED\n");
-               break;
-       default:
-               DEBUG( 0, __FUNCTION__ "(), Unknown command!\n");
-               break;
-       }
-}
-
-/*
- * Function irlan_server_connect_indication (handle, skb, priv)
- *
- *    Got connection from peer IrLAN layer
- *
- */
-void irlan_server_connect_indication( void *instance, void *sap, 
-                                     struct qos_info *qos, int max_sdu_size,
-                                     struct sk_buff *skb)
-{
-       struct irlan_cb *self;
-       struct irlan_info info;
-       struct tsap_cb *tsap;
-
-       DEBUG( 4, __FUNCTION__ "()\n");
-       
-       self = ( struct irlan_cb *) instance;
-       tsap = ( struct tsap_cb *) sap;
-       
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == IRLAN_MAGIC, return;);
-       
-       info.tsap = tsap;
-       
-       if ( tsap == self->tsap_data)
-               irlan_do_server_event( self, IRLAN_DATA_CONNECT_INDICATION, 
-                                      NULL, &info);
-       else
-               irlan_do_server_event( self, IRLAN_CONNECT_INDICATION, NULL, 
-                                      &info);
-}
-
-/*
- * Function irlan_server_connect_response (handle)
- *
- *    Accept incomming connection
- *
- */
-void irlan_server_connect_response( struct irlan_cb *self, 
-                                   struct tsap_cb *tsap)
-{
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == IRLAN_MAGIC, return;);
-
-       /* FIXME: define this value */
-       irttp_connect_response( tsap, 1518, NULL);
-}
-
-/*
- * Function irlan_server_get_provider_info (self)
- *
- *    Send Get Provider Information command to peer IrLAN layer
- *
- */
-void irlan_server_get_provider_info( struct irlan_cb *self) 
-{
-       struct sk_buff *skb;
-       __u8 *frame;
-
-       DEBUG( 4, __FUNCTION__ "()\n");
-       
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == IRLAN_MAGIC, return;);
-
-       skb =  dev_alloc_skb( 64);
-       if (skb == NULL) {
-               DEBUG( 0,"irlan_server_get_provider_info: "
-                      "Could not allocate an sk_buff of length %d\n", 64);
-               return;
-       }
-
-       /* Reserve space for TTP, LMP, and LAP header */
-       skb_reserve( skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
-       skb_put( skb, 2);
-       
-       frame = skb->data;
-       
-       frame[0] = CMD_GET_PROVIDER_INFO;
-       frame[1] = 0x00;                 /* Zero parameters */
-       
-       irttp_data_request( self->tsap_ctrl, skb);
-}
-
-/*
- * Function irlan_parse_open_data_cmd (self, skb)
- *
- *    
- *
- */
-int irlan_parse_open_data_cmd( struct irlan_cb *self, struct sk_buff *skb)
-{
-       int ret = RSP_SUCCESS;
-       
-       irlan_server_extract_params( self, CMD_OPEN_DATA_CHANNEL, skb);
-
-       return ret;
-}
-
-/*
- * Function extract_params (skb)
- *
- *    Extract all parameters from received buffer, then feed them to 
- *    check_params for parsing
- *
- */
-int irlan_server_extract_params( struct irlan_cb *self, int cmd,
-                               struct sk_buff *skb) 
-{
-       __u8 *frame;
-       __u8 *ptr;
-       int count;
-       __u8 name_len;
-       __u16 val_len;
-       int i;
-       
-       ASSERT( skb != NULL, return -RSP_PROTOCOL_ERROR;);
-       
-       DEBUG( 4, __FUNCTION__ "(), skb->len=%d\n", (int)skb->len);
-
-       ASSERT( self != NULL, return -RSP_PROTOCOL_ERROR;);
-       ASSERT( self->magic == IRLAN_MAGIC, return -RSP_PROTOCOL_ERROR;);
-       
-       if ( skb == NULL) {
-               DEBUG( 0, "extract_params: Got NULL skb!\n");
-               return -RSP_PROTOCOL_ERROR;
-       }
-       frame = skb->data;
-
-       /* How many parameters? */
-       count = frame[1];
-
-       DEBUG( 4, "Got %d parameters\n", count);
-       
-       ptr = frame+2;
-
-       /* For all parameters */
-       for ( i=0; i<count;i++) {
-               /* get length of parameter name ( 1 byte) */
-               name_len = *ptr++;
-
-               if (name_len > 255) {
-                       DEBUG( 0, "extract_params, name_len > 255\n");
-                       return -RSP_PROTOCOL_ERROR;
-               }
-
-               /* get parameter name */
-               memcpy( self->name, ptr, name_len);
-               self->name[ name_len] = '\0';
-               ptr+=name_len;
-               
-               /*  
-                *  Get length of parameter value ( 2 bytes in little endian 
-                *  format) 
-                */
-               val_len = *ptr++ & 0xff;        
-               val_len |= *ptr++ << 8;
-               
-               if (val_len > 1016) {
-                       DEBUG( 0, 
-                              "extract_params, parameter length to long\n");
-                       return -RSP_PROTOCOL_ERROR;
-               }
-               
-               /* get parameter value */
-               memcpy( self->value, ptr, val_len);
-               self->value[ val_len] = '\0';
-               ptr+=val_len;
-               
-               DEBUG( 4, "Parameter: %s ", self->name); 
-               DEBUG( 4, "Value: %s\n", self->value); 
-               
-               irlan_check_param( self, self->name, self->value);
-       }
-       return RSP_SUCCESS;
-}
-
-/*
- * Function handle_filter_request (self, skb)
- *
- *    Handle filter request from client peer device
- *
- */
-void handle_filter_request( struct irlan_cb *self, struct sk_buff *skb)
-{
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == IRLAN_MAGIC, return;);
-
-       if (( self->t.server.filter_type == IR_DIRECTED) && 
-           ( self->t.server.filter_operation == DYNAMIC))
-       {
-               DEBUG( 0, "Giving peer a dynamic Ethernet address\n");
-
-               self->t.server.mac_address[0] = 0x40;
-               self->t.server.mac_address[1] = 0x00;
-               self->t.server.mac_address[2] = 0x00;
-               self->t.server.mac_address[3] = 0x00;
-               self->t.server.mac_address[4] = 0x12;
-               self->t.server.mac_address[5] = 0x34;
-
-               skb->data[0] = 0x00; /* Success */
-               skb->data[1] = 0x03;
-               insert_param( skb, "FILTER_MODE", 1, "NONE", 0, 0);
-               insert_param( skb, "MAX_ENTRY", 3, NULL, 0, 0x0001);
-               insert_array_param( skb, "FILTER_ENTRY", self->t.server.mac_address, 6);
-               return;
-       }
-       
-       if (( self->t.server.filter_type == IR_DIRECTED) && 
-           ( self->t.server.filter_mode == FILTER))
-       {
-               DEBUG( 0, "Directed filter on\n");
-               skb->data[0] = 0x00; /* Success */
-               skb->data[1] = 0x00;
-               return;
-       }
-       if (( self->t.server.filter_type == IR_DIRECTED) && 
-           ( self->t.server.filter_mode == NONE))
-       {
-               DEBUG( 0, "Directed filter off\n");
-               skb->data[0] = 0x00; /* Success */
-               skb->data[1] = 0x00;
-               return;
-       }
-
-       if (( self->t.server.filter_type == IR_BROADCAST) && 
-           ( self->t.server.filter_mode == FILTER))
-       {
-               DEBUG( 0, "Broadcast filter on\n");
-               skb->data[0] = 0x00; /* Success */
-               skb->data[1] = 0x00;
-               return;
-       }
-       if (( self->t.server.filter_type == IR_BROADCAST) && 
-           ( self->t.server.filter_mode == NONE))
-       {
-               DEBUG( 0, "Broadcast filter off\n");
-               skb->data[0] = 0x00; /* Success */
-               skb->data[1] = 0x00;
-               return;
-       }
-       if (( self->t.server.filter_type == IR_MULTICAST) && 
-           ( self->t.server.filter_mode == FILTER))
-       {
-               DEBUG( 0, "Multicast filter on\n");
-               skb->data[0] = 0x00; /* Success */
-               skb->data[1] = 0x00;
-               return;
-       }
-       if (( self->t.server.filter_type == IR_MULTICAST) && 
-           ( self->t.server.filter_mode == NONE))
-       {
-               DEBUG( 0, "Multicast filter off\n");
-               skb->data[0] = 0x00; /* Success */
-               skb->data[1] = 0x00;
-               return;
-       }
-       if (( self->t.server.filter_type == IR_MULTICAST) && 
-           ( self->t.server.filter_operation == GET))
-       {
-               DEBUG( 0, "Multicast filter get\n");
-               skb->data[0] = 0x00; /* Success? */
-               skb->data[1] = 0x02;
-               insert_param( skb, "FILTER_MODE", 1, "NONE", 0, 0);
-               insert_param( skb, "MAX_ENTRY", 3, NULL, 0, 16);
-               return;
-       }
-       skb->data[0] = 0x00; /* Command not supported */
-       skb->data[1] = 0x00;
-
-       DEBUG( 0, "Not implemented!\n");
-}
-
-/*
- * Function check_request_param (self, param, value)
- *
- *    Check parameters in request from peer device
- *
- */
-static void irlan_check_param( struct irlan_cb *self, char *param, char *value)
-{
-       __u8 *bytes;
-
-       DEBUG( 4, __FUNCTION__ "()\n");
-
-       bytes = value;
-
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == IRLAN_MAGIC, return;);
-
-       DEBUG( 4, "%s, %s\n", param, value);
-
-       /*
-        *  This is experimental!! DB.
-        */
-        if ( strcmp( param, "MODE") == 0) {
-               DEBUG( 0, __FUNCTION__ "()\n");
-               self->use_udata = TRUE;
-               return;
-       }
-
-       /*
-        *  FILTER_TYPE
-        */
-       if ( strcmp( param, "FILTER_TYPE") == 0) {
-               if ( strcmp( value, "DIRECTED") == 0) {
-                       self->t.server.filter_type = IR_DIRECTED;
-                       return;
-               }
-               if ( strcmp( value, "MULTICAST") == 0) {
-                       self->t.server.filter_type = IR_MULTICAST;
-                       return;
-               }
-               if ( strcmp( value, "BROADCAST") == 0) {
-                       self->t.server.filter_type = IR_BROADCAST;
-                       return;
-               }
-       }
-       /*
-        *  FILTER_MODE
-        */
-       if ( strcmp( param, "FILTER_MODE") == 0) {
-               if ( strcmp( value, "ALL") == 0) {
-                       self->t.server.filter_mode = ALL;
-                       return;
-               }
-               if ( strcmp( value, "FILTER") == 0) {
-                       self->t.server.filter_mode = FILTER;
-                       return;
-               }
-               if ( strcmp( value, "NONE") == 0) {
-                       self->t.server.filter_mode = FILTER;
-                       return;
-               }
-       }
-       /*
-        *  FILTER_OPERATION
-        */
-       if ( strcmp( param, "FILTER_OPERATION") == 0) {
-               if ( strcmp( value, "DYNAMIC") == 0) {
-                       self->t.server.filter_operation = DYNAMIC;
-                       return;
-               }
-               if ( strcmp( value, "GET") == 0) {
-                       self->t.server.filter_operation = GET;
-                       return;
-               }
-       }
-}
-
-/*
- * Function irlan_server_send_reply (self, info)
- *
- *    Send reply to query to peer IrLAN layer
- *
- */
-void irlan_server_send_reply( struct irlan_cb *self, int command, int ret_code)
-{
-       struct sk_buff *skb;
-
-       DEBUG( 4, "irlan_server_send_reply()\n");
-
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == IRLAN_MAGIC, return;);
-
-       skb =  dev_alloc_skb( 128);
-       if (skb == NULL) {
-               DEBUG( 0,"irlan_server_send_reply: "
-                      "Could not allocate an sk_buff of length %d\n", 128);
-               return;
-       }
-
-       /* Reserve space for TTP, LMP, and LAP header */
-       skb_reserve( skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
-       skb_put( skb, 2);
-       
-       switch ( command) {
-       case CMD_GET_PROVIDER_INFO:
-               skb->data[0] = 0x00; /* Success */
-               skb->data[1] = 0x02; /* 2 parameters */
-               insert_param( skb, "MEDIA", 1, "802.3", 0, 0);
-               insert_param( skb, "IRLAN_VER", 3, NULL, 0, 0x0101);
-               break;
-       case CMD_GET_MEDIA_CHAR:
-               skb->data[0] = 0x00; /* Success */
-               skb->data[1] = 0x05; /* 5 parameters */
-               insert_param( skb, "FILTER_TYPE", 1, "DIRECTED", 0, 0);
-               insert_param( skb, "FILTER_TYPE", 1, "BROADCAST", 0, 0);
-               insert_param( skb, "FILTER_TYPE", 1, "MULTICAST", 0, 0);
-               insert_param( skb, "ACCESS_TYPE", 1, "DIRECTED", 0, 0);
-               insert_param( skb, "MAX_FRAME", 3, NULL, 0, 0x05ee);
-               break;
-       case CMD_OPEN_DATA_CHANNEL:
-               skb->data[0] = 0x00; /* Success */
-               skb->data[1] = 0x02; /* 2 parameters */
-               insert_param( skb, "DATA_CHAN", 2, NULL, self->stsap_sel_data, 0);
-               insert_param( skb, "RECONNECT_KEY", 1, "LINUX RULES!", 0, 0);
-               break;
-       case CMD_FILTER_OPERATION:
-               handle_filter_request( self, skb);
-               break;
-       default:
-               DEBUG( 0, __FUNCTION__ "(), Unknown command!\n");
-               break;
-       }
-
-       irttp_data_request( self->tsap_ctrl, skb);
-}
-
-/*
- * Function irlan_server_register(void)
- *
- *    Register server support so we can accept incomming connections. We
- *    must register both a TSAP for control and data
- * 
- */
-void irlan_server_register(void)
-{
-       struct notify_t notify;
-       struct irlan_cb *self;
-       struct ias_object *obj;
-       struct tsap_cb *tsap;
-       
-       DEBUG( 4, __FUNCTION__ "()\n");
-
-       /*
-        *  Open irlan_server instance
-        */
-       self = irlan_server_open();
-       if ( !self || self->magic != IRLAN_MAGIC) {
-               DEBUG( 0, __FUNCTION__"(), Unable to open server!\n");
-               return;
-       }
-       /*
-        *  First register well known control TSAP
-        */
-       irda_notify_init( &notify);
-       notify.data_indication       = irlan_server_control_data_indication;
-       notify.connect_indication    = irlan_server_connect_indication;
-       notify.disconnect_indication = irlan_server_disconnect_indication;
-       notify.instance = self;
-       strncpy( notify.name, "IrLAN srv. ctrl", 16);
-
-       /* FIXME: should not use a static value here! */
-       tsap = irttp_open_tsap( TSAP_IRLAN, 1, &notify);
-       if ( tsap == NULL) {
-               DEBUG( 0, __FUNCTION__ "(), Got no handle!!\n");
-               return;
-       }
-       self->tsap_ctrl = tsap;
-
-       /*
-        *  Now register data TSAP
-        */
-       irda_notify_init( &notify);
-       notify.data_indication       = irlan_eth_rx;
-       notify.udata_indication      = irlan_eth_rx;
-       notify.connect_indication    = irlan_server_connect_indication;
-       notify.disconnect_indication = irlan_server_disconnect_indication;
-       notify.instance = self;
-       strncpy( notify.name, "IrLAN srv. data", 16);
-
-       /*
-        *  Register well known address with IrTTP
-        */ 
-       tsap = irttp_open_tsap( LSAP_ANY, DEFAULT_INITIAL_CREDIT, &notify);
-       if ( tsap == NULL) {
-               DEBUG( 0, __FUNCTION__ "(), Got no handle!\n");
-               return;
-       }
-       self->tsap_data = tsap;
-
-       /* 
-        *  This is the data TSAP selector which we will pass to the client
-        *  when the client ask for it.
-        */
-       self->stsap_sel_data = tsap->stsap_sel;
-       ASSERT( self->stsap_sel_data > 0, return;);
-
-       DEBUG( 0, "irlan_server_register(), Using Source TSAP selector=%02x\n",
-              self->stsap_sel_data);
-       
-       /* 
-        *  Register with LM-IAS
-        */
-       obj = irias_new_object( "IrLAN", IAS_IRLAN_ID);
-       irias_add_integer_attrib( obj, "IrDA:TinyTP:LsapSel", TSAP_IRLAN);
-       irias_insert_object( obj);
-
-       obj = irias_new_object( "PnP", IAS_PNP_ID);
-       irias_add_string_attrib( obj, "Name", "Linux");
-       irias_add_string_attrib( obj, "DeviceID", "HWP19F0");
-       irias_add_integer_attrib( obj, "CompCnt", 2);
-       irias_add_string_attrib( obj, "Comp#01", "PNP8294");
-       irias_add_string_attrib( obj, "Comp#01", "PNP8389");
-       irias_add_string_attrib( obj, "Manufacturer", "Linux/IR Project");
-       irias_insert_object( obj);
-}
-
-#ifdef MODULE
-
-MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
-MODULE_DESCRIPTION("The Linux IrDA LAN Server protocol"); 
-
-/*
- * Function init_module (void)
- *
- *    Initialize the IrLAN module, this function is called by the
- *    modprobe(1) program.
- */
-int init_module(void) 
-{
-/*     int result; */
-
-       DEBUG( 4, "--> IrLAN irlan_server: init_module\n");
-
-       irlan_server_init();
-
-       DEBUG( 4, "IrLAN irlan_server: init_module -->\n");     
-
-       return 0;
-}
-
-/*
- * Function cleanup_module (void)
- *
- *    Remove the IrLAN module, this function is called by the rmmod(1)
- *    program
- */
-void cleanup_module(void) 
-{
-       DEBUG( 4, "--> irlan_server, cleanup_module\n");
-       /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
-
-       /* Free some memory */
-       irlan_server_cleanup();
-
-       DEBUG( 4, "irlan_server, cleanup_module -->\n");
-}
-
-#endif /* MODULE */
diff --git a/net/irda/irlan/irlan_srv_event.c b/net/irda/irlan/irlan_srv_event.c
deleted file mode 100644 (file)
index 6ad8d2f..0000000
+++ /dev/null
@@ -1,268 +0,0 @@
-/*********************************************************************
- *                
- * Filename:      irlan_srv_event.c
- * Version:       0.1
- * Description:   IrLAN Server FSM (Finite State Machine)
- * Status:        Experimental.
- * Author:        Dag Brattli <dagb@cs.uit.no>
- * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Wed Dec  9 02:39:05 1998
- * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * 
- *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, 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.
- *
- *     Neither Dag Brattli nor University of Tromsø admit liability nor
- *     provide warranty for any of this software. This material is 
- *     provided "AS-IS" and at no charge.
- *
- ********************************************************************/
-
-#include <net/irda/irda.h>
-#include <net/irda/iriap.h>
-#include <net/irda/irlmp.h>
-#include <net/irda/irttp.h>
-
-#include <net/irda/irlan_srv.h>
-#include <net/irda/irlan_event.h>
-
-static int irlan_server_state_idle ( struct irlan_cb *self, 
-                                    IRLAN_EVENT event, 
-                                    struct sk_buff *skb, 
-                                    struct irlan_info *info);
-static int irlan_server_state_info ( struct irlan_cb *self, 
-                                    IRLAN_EVENT event, 
-                                    struct sk_buff *skb, 
-                                    struct irlan_info *info);
-static int irlan_server_state_open ( struct irlan_cb *self, 
-                                    IRLAN_EVENT event, 
-                                    struct sk_buff *skb, 
-                                    struct irlan_info *info);
-static int irlan_server_state_data ( struct irlan_cb *self, 
-                                    IRLAN_EVENT event, 
-                                    struct sk_buff *skb, 
-                                    struct irlan_info *info);
-
-static int (*state[])( struct irlan_cb *self, IRLAN_EVENT event, 
-                      struct sk_buff *skb, struct irlan_info *info) = 
-{ 
-       irlan_server_state_idle,
-       NULL, /* Query */
-       NULL, /* Info */
-       irlan_server_state_info,
-       NULL, /* Media */
-       irlan_server_state_open,
-       NULL, /* Wait */
-       NULL, /* Arb */
-       irlan_server_state_data,
-       NULL, /* Close */
-       NULL, /* Sync */
-};
-
-void irlan_do_server_event( struct irlan_cb *self, 
-                           IRLAN_EVENT event, 
-                           struct sk_buff *skb, 
-                           struct irlan_info *info) 
-{
-       (*state[ self->state]) ( self, event, skb, info);
-}
-
-/*
- * Function irlan_server_state_idle (event, skb, info)
- *
- *    IDLE, We are waiting for an indication that there is a provider
- *    available.
- */
-static int irlan_server_state_idle( struct irlan_cb *self, 
-                                   IRLAN_EVENT event, 
-                                   struct sk_buff *skb, 
-                                   struct irlan_info *info) 
-{
-       DEBUG( 4, __FUNCTION__ "()\n");
-       
-       ASSERT( self != NULL, return -1;);
-       
-       switch( event) {
-       case IRLAN_CONNECT_INDICATION:
-            ASSERT( info != NULL, return 0;);
-            irlan_server_connect_response( self, info->tsap);
-            irlan_next_state( self, IRLAN_INFO);
-            break;
-       default:
-               DEBUG( 4, __FUNCTION__ "(), Unknown event %d\n", 
-                      event);
-               break;
-       }
-       if ( skb) {
-               dev_kfree_skb( skb);
-       }
-       return 0;
-}
-
-/*
- * Function irlan_server_state_info (self, event, skb, info)
- *
- *    INFO, We have issued a GetInfo command and is awaiting a reply.
- */
-static int irlan_server_state_info( struct irlan_cb *self, 
-                                   IRLAN_EVENT event, 
-                                   struct sk_buff *skb, 
-                                   struct irlan_info *info) 
-{
-       int ret;
-
-       DEBUG( 4, __FUNCTION__ "()\n");
-       
-       ASSERT( self != NULL, return -1;);
-
-       switch( event) {
-       case IRLAN_GET_INFO_CMD: 
-               irlan_server_send_reply( self, CMD_GET_PROVIDER_INFO, 
-                                        RSP_SUCCESS);
-               /* Keep state */
-               break;
-
-       case IRLAN_GET_MEDIA_CMD: 
-               irlan_server_send_reply( self, CMD_GET_MEDIA_CHAR, 
-                                        RSP_SUCCESS);
-               /* Keep state */
-               break;
-               
-       case IRLAN_OPEN_DATA_CMD:
-               ret = irlan_parse_open_data_cmd( self, skb);
-               irlan_server_send_reply( self, CMD_OPEN_DATA_CHANNEL, ret);
-
-               if ( ret == RSP_SUCCESS)
-                       irlan_next_state( self, IRLAN_OPEN);
-               break;
-       case IRLAN_LMP_DISCONNECT:
-       case IRLAN_LAP_DISCONNECT:
-               irlan_next_state( self, IRLAN_IDLE);
-               break;
-       default:
-               DEBUG( 0, "irlan_server_state_info, Unknown event %d\n", 
-                      event);
-               break;
-       }
-       if ( skb) {
-               dev_kfree_skb( skb);
-       }
-       
-       return 0;
-}
-
-/*
- * Function irlan_server_state_open (self, event, skb, info)
- *
- *    OPEN, The client has issued a OpenData command and is awaiting a
- *    reply
- *
- */
-static int irlan_server_state_open( struct irlan_cb *self, 
-                                   IRLAN_EVENT event, 
-                                   struct sk_buff *skb, 
-                                   struct irlan_info *info) 
-{
-       DEBUG( 4, __FUNCTION__ "()\n");
-
-       ASSERT( self != NULL, return -1;);
-
-       switch( event) {
-       case IRLAN_FILTER_CONFIG_CMD:
-               irlan_server_extract_params( self, CMD_FILTER_OPERATION, skb);
-               irlan_server_send_reply( self, CMD_FILTER_OPERATION, 
-                                        RSP_SUCCESS);
-               /* Keep state */
-               break;
-               
-       case IRLAN_DATA_CONNECT_INDICATION: 
-               DEBUG( 4, "DATA_CONNECT_INDICATION\n");
-               irlan_next_state( self, IRLAN_DATA);
-               irlan_server_connect_response( self, info->tsap);
-               break;
-               
-       case IRLAN_LMP_DISCONNECT:
-       case IRLAN_LAP_DISCONNECT:
-               irlan_next_state( self, IRLAN_IDLE);
-               break;
-       default:
-               DEBUG( 0, __FUNCTION__ "(), Unknown event %d\n", 
-                      event);
-               break;
-       }
-       
-       if ( skb) {
-               dev_kfree_skb( skb);
-       }
-
-       return 0;
-}
-
-/*
- * Function irlan_server_state_data (self, event, skb, info)
- *
- *    DATA, The data channel is connected, allowing data transfers between
- *    the local and remote machines.
- *
- */
-static int irlan_server_state_data( struct irlan_cb *self, 
-                                   IRLAN_EVENT event, 
-                                   struct sk_buff *skb, 
-                                   struct irlan_info *info) 
-{
-       struct irmanager_event mgr_event;
-
-       DEBUG( 4, __FUNCTION__ "()\n");
-
-       ASSERT( self != NULL, return -1;);
-       ASSERT( self->magic == IRLAN_MAGIC, return -1;);
-
-       switch( event) {
-       case IRLAN_FILTER_CONFIG_CMD:
-               irlan_server_extract_params( self, CMD_FILTER_OPERATION, skb);
-               irlan_server_send_reply( self, CMD_FILTER_OPERATION, 
-                                        RSP_SUCCESS);
-
-               /* Make sure the code below only runs once */
-               if ( !self->connected) {
-                       mgr_event.event = EVENT_IRLAN_START;
-                       sprintf( mgr_event.devname, "%s", self->ifname);
-                       irmanager_notify( &mgr_event);
-
-                       self->connected = TRUE;
-               }
-               break;
-               
-       case IRLAN_LMP_DISCONNECT:
-       case IRLAN_LAP_DISCONNECT:
-               mgr_event.event = EVENT_IRLAN_STOP;
-               sprintf( mgr_event.devname, "%s", self->ifname);
-               irmanager_notify( &mgr_event);
-
-               irlan_next_state( self, IRLAN_IDLE);
-               break;
-       default:
-               DEBUG( 0, "irlan_server_state_data, Unknown event %d\n", 
-                      event);
-               break;
-       }
-       if ( skb) {
-               dev_kfree_skb( skb);
-       }
-       
-       return 0;
-}
-
-
-
-
-
-
-
-
-
-
index 633d29220219156a0cf5befd992851c5c38840ba..c14191276cd9ebf598aa970aeec710426f33d542 100644 (file)
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      irlap.c
- * Version:       0.8
+ * Version:       0.9
  * Description:   An IrDA LAP driver for Linux
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Sat Jan 16 22:19:27 1999
+ * Modified at:   Sat Feb 20 01:39:58 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, 
 #include <net/irda/irlap_comp.h>
 
 hashbin_t *irlap = NULL;
+int sysctl_slot_timeout = SLOT_TIMEOUT;
 
 static void __irlap_close( struct irlap_cb *self);
 
+static char *lap_reasons[] = {
+       "ERROR, NOT USED",
+       "LAP_DISC_INDICATION",
+       "LAP_NO_RESPONSE",
+       "LAP_RESET_INDICATION",
+       "LAP_FOUND_NONE",
+       "LAP_MEDIA_BUSY",
+       "LAP_PRIMARY_CONFLICT",
+       "ERROR, NOT USED",
+};
+
 #ifdef CONFIG_PROC_FS
-int irlap_proc_read( char *buf, char **start, off_t offset, int len, 
-                    int unused);
+int irlap_proc_read( char *, char **, off_t, int, int);
 
 #endif /* CONFIG_PROC_FS */
 
@@ -138,8 +149,6 @@ struct irlap_cb *irlap_open( struct irda_device *irdev)
 
        irlmp_register_irlap( self, self->saddr, &self->notify);
        
-       DEBUG( 4, "irlap_open -->\n");
-
        return self;
 }
 
@@ -166,7 +175,7 @@ static void __irlap_close( struct irlap_cb *self)
        irlap_flush_all_queues( self);
        
        self->irdev = NULL;
-       self->magic = ~LAP_MAGIC;
+       self->magic = 0;
        
        kfree( self);
 }
@@ -194,7 +203,7 @@ void irlap_close( struct irlap_cb *self)
        /* Be sure that we manage to remove ourself from the hash */
        lap = hashbin_remove( irlap, self->saddr, NULL);
        if ( !lap) {
-               DEBUG( 0, __FUNCTION__ "(), Didn't find myself!\n");
+               DEBUG( 1, __FUNCTION__ "(), Didn't find myself!\n");
                return;
        }
        __irlap_close( lap);
@@ -206,17 +215,17 @@ void irlap_close( struct irlap_cb *self)
  *    Another device is attempting to make a connection
  *
  */
-void irlap_connect_indication( struct irlap_cb *self, struct sk_buff *skb) 
+void irlap_connect_indication(struct irlap_cb *self, struct sk_buff *skb) 
 {
-       DEBUG( 4, __FUNCTION__ "()\n");
+       DEBUG(4, __FUNCTION__ "()\n");
 
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == LAP_MAGIC, return;);
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == LAP_MAGIC, return;);
 
-       irlap_init_qos_capabilities( self, NULL); /* No user QoS! */
+       irlap_init_qos_capabilities(self, NULL); /* No user QoS! */
        
-       irlmp_link_connect_indication( self->notify.instance, &self->qos_tx
-                                      skb);
+       irlmp_link_connect_indication(self->notify.instance, self->saddr
+                                     self->daddr, &self->qos_tx, skb);
 }
 
 /*
@@ -247,21 +256,17 @@ void irlap_connect_request( struct irlap_cb *self, __u32 daddr,
        ASSERT( self->magic == LAP_MAGIC, return;);
 
        self->daddr = daddr;
-
+       
        /*
         *  If the service user specifies QoS values for this connection, 
         *  then use them
         */
        irlap_init_qos_capabilities( self, qos_user);
        
-       if ( self->state == LAP_NDM) {
+       if ( self->state == LAP_NDM)
                irlap_do_event( self, CONNECT_REQUEST, NULL, NULL);
-       } else {
-               DEBUG( 0, __FUNCTION__ "() Wrong state!\n");
-               
-               irlap_disconnect_indication( self, LAP_MEDIA_BUSY);
-       }
-              
+       else
+               self->connect_pending = TRUE;
 }
 
 /*
@@ -302,12 +307,11 @@ inline void irlap_data_indication( struct irlap_cb *self, struct sk_buff *skb)
        if ( self->qos_tx.compression.value) {
                skb = irlap_decompress_frame( self, skb);
                if ( !skb) {
-                       DEBUG( 0, __FUNCTION__ "(), Decompress error!\n");
+                       DEBUG( 1, __FUNCTION__ "(), Decompress error!\n");
                        return;
                }
        }
 #endif
-
        irlmp_link_data_indication( self->notify.instance, LAP_RELIABLE, skb);
 }
 
@@ -319,7 +323,7 @@ inline void irlap_data_indication( struct irlap_cb *self, struct sk_buff *skb)
  */
 void irlap_unit_data_indication( struct irlap_cb *self, struct sk_buff *skb)
 {
-       DEBUG( 0, __FUNCTION__ "()\n"); 
+       DEBUG( 1, __FUNCTION__ "()\n"); 
 
        ASSERT( self != NULL, return;);
        ASSERT( self->magic == LAP_MAGIC, return;);
@@ -333,7 +337,7 @@ void irlap_unit_data_indication( struct irlap_cb *self, struct sk_buff *skb)
                
                skb = irlap_decompress_frame( self, skb);
                if ( !skb) {
-                       DEBUG( 0, __FUNCTION__ "(), Decompress error!\n");
+                       DEBUG( 1, __FUNCTION__ "(), Decompress error!\n");
                        return;
                }
        }
@@ -356,14 +360,14 @@ inline void irlap_data_request( struct irlap_cb *self, struct sk_buff *skb,
        ASSERT( self->magic == LAP_MAGIC, return;);
        ASSERT( skb != NULL, return;);
 
-       DEBUG( 4, "irlap_data_request: tx_list=%d\n", 
+       DEBUG( 4, __FUNCTION__ "(), tx_list=%d\n", 
                   skb_queue_len( &self->tx_list));
 
 #ifdef CONFIG_IRDA_COMPRESSION
        if ( self->qos_tx.compression.value) {
                skb = irlap_compress_frame( self, skb);
                if ( !skb) {
-                       DEBUG( 0, __FUNCTION__ "(), Compress error!\n");
+                       DEBUG( 1, __FUNCTION__ "(), Compress error!\n");
                        return;
                }
        }
@@ -401,8 +405,7 @@ inline void irlap_data_request( struct irlap_cb *self, struct sk_buff *skb,
                }
                irlap_do_event( self, SEND_I_CMD, skb, NULL);
        } else
-               skb_queue_tail( &self->tx_list, skb);
-       
+               skb_queue_tail( &self->tx_list, skb);   
 }
 
 /*
@@ -410,14 +413,26 @@ inline void irlap_data_request( struct irlap_cb *self, struct sk_buff *skb,
  *
  *    Request to disconnect connection by service user
  */
-void irlap_disconnect_request( struct irlap_cb *self) 
+void irlap_disconnect_request(struct irlap_cb *self) 
 {
-       DEBUG( 4, __FUNCTION__ "()\n");
+       DEBUG(3, __FUNCTION__ "()\n");
 
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == LAP_MAGIC, return;);
-
-       irlap_do_event( self, DISCONNECT_REQUEST, NULL, NULL);
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == LAP_MAGIC, return;);
+       
+       switch (self->state) {
+       case LAP_XMIT_P:        /* FALLTROUGH */
+       case LAP_XMIT_S:        /* FALLTROUGH */
+       case LAP_CONN:          /* FALLTROUGH */
+       case LAP_RESET_WAIT:    /* FALLTROUGH */
+       case LAP_RESET_CHECK:   
+               irlap_do_event(self, DISCONNECT_REQUEST, NULL, NULL);
+               break;
+       default:
+               DEBUG(0, __FUNCTION__ "(), disconnect pending!\n");
+               self->disconnect_pending = TRUE;
+               break;
+       }
 }
 
 /*
@@ -428,7 +443,7 @@ void irlap_disconnect_request( struct irlap_cb *self)
  */
 void irlap_disconnect_indication( struct irlap_cb *self, LAP_REASON reason) 
 {
-       DEBUG( 4, __FUNCTION__ "()\n"); 
+       DEBUG( 1, __FUNCTION__ "(), reason=%s\n", lap_reasons[reason]); 
 
        ASSERT( self != NULL, return;);
        ASSERT( self->magic == LAP_MAGIC, return;);
@@ -442,18 +457,18 @@ void irlap_disconnect_indication( struct irlap_cb *self, LAP_REASON reason)
        
        switch( reason) {
        case LAP_RESET_INDICATION:
-               DEBUG( 0, "Sending reset request!\n");
+               DEBUG( 1, __FUNCTION__ "(), Sending reset request!\n");
                irlap_do_event( self, RESET_REQUEST, NULL, NULL);
                break;
-       case LAP_NO_RESPONSE:           
-       case LAP_DISC_INDICATION:
-       case LAP_FOUND_NONE:
+       case LAP_NO_RESPONSE:      /* FALLTROUGH */     
+       case LAP_DISC_INDICATION:  /* FALLTROUGH */
+       case LAP_FOUND_NONE:       /* FALLTROUGH */
        case LAP_MEDIA_BUSY:
                irlmp_link_disconnect_indication( self->notify.instance, 
                                                  self, reason, NULL);
                break;
        default:
-               DEBUG( 0, __FUNCTION__ "(), Reason %d not implemented!\n", 
+               DEBUG( 1, __FUNCTION__ "(), Reason %d not implemented!\n", 
                       reason);
        }
 }
@@ -471,24 +486,48 @@ void irlap_discovery_request( struct irlap_cb *self, DISCOVERY *discovery)
        ASSERT( self != NULL, return;);
        ASSERT( self->magic == LAP_MAGIC, return;);
        ASSERT( discovery != NULL, return;);
+       
+       DEBUG( 4, __FUNCTION__ "(), nslots = %d\n", discovery->nslots);
 
+       ASSERT(( discovery->nslots == 1) || ( discovery->nslots == 6) ||
+              ( discovery->nslots == 8) || ( discovery->nslots == 16), 
+              return;);
+       
        /*
         *  Discovery is only possible in NDM mode
         */ 
        if ( self->state == LAP_NDM) {
                ASSERT( self->discovery_log == NULL, return;);
                self->discovery_log= hashbin_new( HB_LOCAL);
-
-               info.S = 6; /* Number of slots */
+               
+               info.S = discovery->nslots; /* Number of slots */
                info.s = 0; /* Current slot */
-
+               
                self->discovery_cmd = discovery;
                info.discovery = discovery;
                
+               /* Check if the slot timeout is within limits */
+               if ( sysctl_slot_timeout < 2) {
+                       DEBUG( 1, __FUNCTION__ 
+                              "(), to low value for slot timeout!\n");
+                       sysctl_slot_timeout = 2;
+               }
+               /* 
+                * Highest value is actually 8, but we allow higher since
+                * some devices seems to require it.
+                */
+               if ( sysctl_slot_timeout > 16) {
+                       DEBUG( 1, __FUNCTION__ 
+                              "(), to high value for slot timeout!\n");
+                       sysctl_slot_timeout = 16;
+               }
+
+               self->slot_timeout = sysctl_slot_timeout;
+               
                irlap_do_event( self, DISCOVERY_REQUEST, NULL, &info);
        } else { 
                DEBUG( 4, __FUNCTION__ 
-                       "(), discovery only possible in NDM mode\n");
+                      "(), discovery only possible in NDM mode\n");
                irlap_discovery_confirm( self, NULL);
        } 
 }
@@ -506,6 +545,14 @@ void irlap_discovery_confirm( struct irlap_cb *self, hashbin_t *discovery_log)
        
        ASSERT( self->notify.instance != NULL, return;);
        
+       /* 
+        * Check for successful discovery, since we are then allowed to clear 
+        * the media busy condition (irlap p.94). This should allow us to make 
+        * connection attempts much easier.
+        */
+       if (discovery_log && hashbin_get_size(discovery_log) > 0)
+               irda_device_set_media_busy(self->irdev, FALSE);
+       
        /* Inform IrLMP */
        irlmp_link_discovery_confirm( self->notify.instance, discovery_log);
        
@@ -552,7 +599,6 @@ void irlap_status_indication( int quality_of_link)
        default:
                break;
        }
-       /* TODO: layering violation! */
        irlmp_status_indication( quality_of_link, NO_CHANGE);
 }
 
@@ -564,7 +610,7 @@ void irlap_status_indication( int quality_of_link)
  */
 void irlap_reset_indication( struct irlap_cb *self)
 {
-       DEBUG( 0, __FUNCTION__ "()\n");
+       DEBUG( 1, __FUNCTION__ "()\n");
 
        ASSERT( self != NULL, return;);
        ASSERT( self->magic == LAP_MAGIC, return;);
@@ -583,7 +629,7 @@ void irlap_reset_indication( struct irlap_cb *self)
  */
 void irlap_reset_confirm(void)
 {
-       DEBUG( 0, __FUNCTION__ "()\n");
+       DEBUG( 1, __FUNCTION__ "()\n");
 }
 
 /*
@@ -672,7 +718,7 @@ int irlap_validate_ns_received( struct irlap_cb *self, int ns)
 
        /*  ns as expected?  */
        if ( ns == self->vr) {
-               DEBUG( 4, "*** irlap_validate_ns_received: expected!\n");
+               DEBUG( 4, __FUNCTION__ "(), expected!\n");
                return NS_EXPECTED;
        }
        /*
@@ -696,7 +742,7 @@ int irlap_validate_nr_received( struct irlap_cb *self, int nr)
 
        /*  nr as expected?  */
        if ( nr == self->vs) {
-               DEBUG( 4, "*** irlap_validate_nr_received: expected!\n");
+               DEBUG( 4, __FUNCTION__ "(), expected!\n");
                return NR_EXPECTED;
        }
 
@@ -724,7 +770,7 @@ int irlap_validate_nr_received( struct irlap_cb *self, int nr)
  */
 void irlap_initiate_connection_state( struct irlap_cb *self) 
 {
-       DEBUG( 4, "irlap_initiate_connection_state()\n");
+       DEBUG( 4, __FUNCTION__ "()\n");
        
        ASSERT( self != NULL, return;);
        ASSERT( self->magic == LAP_MAGIC, return;);
@@ -818,26 +864,26 @@ void irlap_flush_all_queues( struct irlap_cb *self)
  *    Change the speed of the IrDA port
  *
  */
-void irlap_change_speed( struct irlap_cb *self, int speed)
+void irlap_change_speed(struct irlap_cb *self, int speed)
 {
-       DEBUG( 4, __FUNCTION__ "(), setting speed to %d\n", speed);
+       DEBUG(4, __FUNCTION__ "(), setting speed to %d\n", speed);
 
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == LAP_MAGIC, return;);
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == LAP_MAGIC, return;);
 
-       if ( !self->irdev) {
-               DEBUG( 0, __FUNCTION__ "(), driver missing!\n");
+       if (!self->irdev) {
+               DEBUG( 1, __FUNCTION__ "(), driver missing!\n");
                return;
        }
 
-       irda_device_change_speed( self->irdev, speed);
+       irda_device_change_speed(self->irdev, speed);
 
        self->qos_rx.baud_rate.value = speed;
        self->qos_tx.baud_rate.value = speed;
 }
 
 #ifdef CONFIG_IRDA_COMPRESSION
-void irlap_init_comp_qos_capabilities( struct irlap_cb *self)
+void irlap_init_comp_qos_capabilities(struct irlap_cb *self)
 {
        struct irda_compressor *comp;
        __u8 mask; /* Current bit tested */
@@ -888,8 +934,8 @@ void irlap_init_comp_qos_capabilities( struct irlap_cb *self)
  *    IrLAP itself. Normally, IrLAP will not specify any values, but it can
  *    be used to restrict certain values.
  */
-void irlap_init_qos_capabilities( struct irlap_cb *self, 
-                                 struct qos_info *qos_user)
+void irlap_init_qos_capabilities(struct irlap_cb *self,
+                                struct qos_info *qos_user)
 {
        ASSERT( self != NULL, return;);
        ASSERT( self->magic == LAP_MAGIC, return;);
@@ -911,8 +957,8 @@ void irlap_init_qos_capabilities( struct irlap_cb *self,
         *  allowed to supply these values. We check each parameter since the
         *  user may not have set all of them.
         */
-       if ( qos_user != NULL) {
-               DEBUG( 0, __FUNCTION__ "(), Found user specified QoS!\n");
+       if (qos_user) {
+               DEBUG( 1, __FUNCTION__ "(), Found user specified QoS!\n");
 
                if ( qos_user->baud_rate.bits)
                        self->qos_rx.baud_rate.bits &= qos_user->baud_rate.bits;
@@ -966,6 +1012,7 @@ void irlap_apply_default_connection_parameters( struct irlap_cb *self)
        self->bofs_count = 11;
 
        /* Use these until connection has been made */
+       self->slot_timeout = sysctl_slot_timeout;
        self->final_timeout = FINAL_TIMEOUT;
        self->poll_timeout = POLL_TIMEOUT;
        self->wd_timeout = WD_TIMEOUT;
@@ -974,6 +1021,8 @@ void irlap_apply_default_connection_parameters( struct irlap_cb *self)
        self->qos_tx.additional_bofs.value = 11;
 
        irlap_flush_all_queues( self);
+
+       self->disconnect_pending = FALSE;
 }
 
 /*
@@ -982,8 +1031,8 @@ void irlap_apply_default_connection_parameters( struct irlap_cb *self)
  *    Initialize IrLAP with the negotiated QoS values
  *
  */
-void irlap_apply_connection_parameters( struct irlap_cb *self, 
-                                       struct qos_info *qos) 
+void irlap_apply_connection_parameters(struct irlap_cb *self, 
+                                      struct qos_info *qos) 
 {
        DEBUG( 4, __FUNCTION__ "()\n");
        
@@ -1010,15 +1059,13 @@ void irlap_apply_connection_parameters( struct irlap_cb *self,
         *  TODO: these values should be calculated from the final timer
          *  as well
         */
-       if ( qos->link_disc_time.value == 3)
+       if (qos->link_disc_time.value == 3)
                self->N1 = 0;
        else
-               /* self->N1 = 6; */
                self->N1 = 3000 / qos->max_turn_time.value;
        
        DEBUG( 4, "Setting N1 = %d\n", self->N1);
        
-       /* self->N2 = qos->link_disc_time.value * 2; */
        self->N2 = qos->link_disc_time.value * 1000 / qos->max_turn_time.value;
        DEBUG( 4, "Setting N2 = %d\n", self->N2);
 
@@ -1033,7 +1080,7 @@ void irlap_apply_connection_parameters( struct irlap_cb *self,
 
 #ifdef CONFIG_IRDA_COMPRESSION
        if ( qos->compression.value) {
-               DEBUG( 0, __FUNCTION__ "(), Initializing compression\n");
+               DEBUG( 1, __FUNCTION__ "(), Initializing compression\n");
                irda_set_compression( self, qos->compression.value);
 
                irlap_compressor_init( self, 0);
@@ -1065,7 +1112,7 @@ int irlap_proc_read( char *buf, char **start, off_t offset, int len,
                ASSERT( self != NULL, return -ENODEV;);
                ASSERT( self->magic == LAP_MAGIC, return -EBADR;);
 
-               len += sprintf( buf+len, "IrLAP[%d] <-> %s ",
+               len += sprintf( buf+len, "irlap%d <-> %s ",
                                i++, self->irdev->name);
                len += sprintf( buf+len, "state: %s\n", 
                                irlap_state[ self->state]);
index d2e876be9fdaa5928b9f9aabcfca1943be14da33..9959b64bc14e7d4a445752652d130f9ea9839df0 100644 (file)
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Fri Oct  9 09:18:07 1998
- * Modified at:   Mon Dec 14 11:55:27 1998
+ * Modified at:   Mon Feb  8 01:23:52 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Sources:       ppp.c, isdn_ppp.c
  * 
@@ -81,8 +81,7 @@ void irda_unregister_compressor ( struct compressor *cp)
        if ( !node) {
                DEBUG( 0, __FUNCTION__ "(), compressor not found!\n");
                return;
-       }
-       
+       }       
        kfree( node);
 }
 
@@ -99,7 +98,7 @@ int irda_set_compression( struct irlap_cb *self, int proto)
 
        __u8 options[CILEN_DEFLATE];
 
-       DEBUG( 0, __FUNCTION__ "()\n");
+       DEBUG( 4, __FUNCTION__ "()\n");
 
        ASSERT( self != NULL, return -ENODEV;);
        ASSERT( self->magic == LAP_MAGIC, return -EBADR;);
@@ -180,7 +179,7 @@ void irlap_compressor_init( struct irlap_cb *self, int compress)
        int debug = TRUE;
        __u8 options[CILEN_DEFLATE];
 
-       DEBUG( 0, __FUNCTION__ "()\n");
+       DEBUG(4, __FUNCTION__ "()\n");
 
        ASSERT( self != NULL, return;);
        ASSERT( self->magic == LAP_MAGIC, return;);
@@ -240,8 +239,8 @@ struct sk_buff *irlap_compress_frame( struct irlap_cb *self,
        
        ASSERT( skb != NULL, return NULL;);
        
-       DEBUG( 0, __FUNCTION__ "() skb->len=%d, jiffies=%ld\n", (int) skb->len,
-              jiffies);
+       DEBUG(4, __FUNCTION__ "() skb->len=%d, jiffies=%ld\n", (int) skb->len,
+             jiffies);
 
        ASSERT( self != NULL, return NULL;);
        ASSERT( self->magic == LAP_MAGIC, return NULL;);
@@ -267,7 +266,7 @@ struct sk_buff *irlap_compress_frame( struct irlap_cb *self,
                                                 skb->data, new_skb->data, 
                                                 skb->len, new_skb->len);
        if( count <= 0) {
-               DEBUG( 0, __FUNCTION__ "(), Unable to compress frame!\n");
+               DEBUG(4, __FUNCTION__ "(), Unable to compress frame!\n");
                dev_kfree_skb( new_skb);
 
                /* Tell peer that this frame is not compressed */
@@ -284,8 +283,8 @@ struct sk_buff *irlap_compress_frame( struct irlap_cb *self,
 
        dev_kfree_skb( skb);
        
-       DEBUG( 0, __FUNCTION__ "() new_skb->len=%d\n, jiffies=%ld", 
-              (int) new_skb->len, jiffies);
+       DEBUG(4, __FUNCTION__ "() new_skb->len=%d\n, jiffies=%ld", 
+             (int) new_skb->len, jiffies);
        
        return new_skb;
 }
@@ -336,7 +335,7 @@ struct sk_buff *irlap_decompress_frame( struct irlap_cb *self,
        count = irda_decompress( self->decompressor.state, skb->data, 
                                 skb->len, new_skb->data, new_skb->len);
        if ( count <= 0) {
-               DEBUG( 0, __FUNCTION__ "(), Unable to decompress frame!\n");
+               DEBUG( 4, __FUNCTION__ "(), Unable to decompress frame!\n");
                
                dev_kfree_skb( new_skb);
                return skb;
@@ -344,7 +343,7 @@ struct sk_buff *irlap_decompress_frame( struct irlap_cb *self,
 
        skb_trim( new_skb, count);
        
-       DEBUG( 0, __FUNCTION__ "() new_skb->len=%d\n", (int) new_skb->len);
+       DEBUG( 4, __FUNCTION__ "() new_skb->len=%d\n", (int) new_skb->len);
 
        return new_skb;
 }
index d2afcbd292f703f4ebcf59ea7f2893462303ff4f..6a13b590420661eb1710f9ef2ebc1c45850a3ce0 100644 (file)
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      irlap_event.c
- * Version:       0.1
+ * Version:       0.8
  * Description:   IrLAP state machine implementation
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Aug 16 00:59:29 1997
- * Modified at:   Tue Jan 19 22:58:45 1999
+ * Modified at:   Thu Feb 11 00:38:58 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>,
@@ -71,7 +71,7 @@ static int irlap_state_sclose ( struct irlap_cb *self, IRLAP_EVENT event,
 static int irlap_state_reset_check( struct irlap_cb *, IRLAP_EVENT event, 
                                    struct sk_buff *, struct irlap_info *);
 
-static char *irlap_event[] = {
+static const char *irlap_event[] = {
        "DISCOVERY_REQUEST",
        "CONNECT_REQUEST",
        "CONNECT_RESPONSE",
@@ -103,7 +103,7 @@ static char *irlap_event[] = {
        "BACKOFF_TIMER_EXPIRED",
 };
 
-char *irlap_state[] = {
+const char *irlap_state[] = {
        "LAP_NDM",
        "LAP_QUERY",
        "LAP_REPLY",
@@ -198,53 +198,63 @@ void irlap_start_poll_timer( struct irlap_cb *self, int timeout)
 /*
  * Function irlap_do_event (event, skb, info)
  *
- *    Rushes through the state machine without any delay. If state = XMIT
+ *    Rushes through the state machine without any delay. If state == XMIT
  *    then send queued data frames. 
  */
 void irlap_do_event( struct irlap_cb *self, IRLAP_EVENT event, 
                     struct sk_buff *skb, struct irlap_info *info) 
 {
        int ret;
-       int iter = 0;
        
-       if ( !self || self->magic != LAP_MAGIC) {
-               DEBUG( 0, "irlap_do_event: bad pointer *self\n");
+       if ( !self || self->magic != LAP_MAGIC)
                return;
-       }
-               
-       DEBUG( 4, "irlap_do_event: event = %s, state = %s\n", 
+       
+       DEBUG( 4, __FUNCTION__ "(), event = %s, state = %s\n", 
               irlap_event[ event], irlap_state[ self->state]); 
-
-       /* 
-        *  Do event, this implementation does not deal with pending events. 
-        *  This is because I don't see the need for this. DB
-        */
+       
        ret = (*state[ self->state]) ( self, event, skb, info);
        
        /* 
-        *  Check if we have switched to XMIT state? If so, send queued data 
-        *  frames if any, if -1 is returned it means that we are not allowed 
-        *  to send any more frames.  
+        *  Check if there are any pending events that needs to be executed
         */
-       while (( self->state == LAP_XMIT_P) || ( self->state == LAP_XMIT_S)) { 
-               if ( skb_queue_len( &self->tx_list) > 0) {
+       switch (self->state) {
+       case LAP_XMIT_P: /* FALLTHROUGH */
+       case LAP_XMIT_S:
+               /* 
+                * Check if there are any queued data frames, and do not
+                * try to disconnect link if we send any data frames, since
+                * that will change the state away form XMIT
+                */
+               if (skb_queue_len(&self->tx_list)) {
+                       /* Try to send away all queued data frames */
+                       while ((skb = skb_dequeue(&self->tx_list)) != NULL) {
+                               ret = (*state[ self->state])(self, SEND_I_CMD,
+                                                            skb, NULL);
+                               if ( ret == -EPROTO)
+                                       break; /* Try again later! */
+                       }
+               } else if (self->disconnect_pending) {
+                       DEBUG(0, __FUNCTION__ "(), disconnecting!\n");
+                       self->disconnect_pending = FALSE;
                        
-                       struct sk_buff *skb = skb_dequeue( &self->tx_list); 
-                       ASSERT( skb != NULL, return;);
+                       ret = (*state[self->state])(self, DISCONNECT_REQUEST,
+                                                   NULL, NULL);
+               }
+               break;
+       case LAP_NDM:
+               /* Check if we should try to connect */
+               if (self->connect_pending) {
+                       self->connect_pending = FALSE;
                        
-                       DEBUG( 4, "** Sending queued data frames\n");
-                       ret = (*state[ self->state])( self, SEND_I_CMD, skb,
-                                                     NULL);
-                       if ( ret == -EPROTO)
-                               return; /* Try again later! */
-               } else
-                       return;
-
-               /* Just in case :-) */
-               if (iter++ > 100) {
-                       DEBUG( 0, __FUNCTION__ "(), *** breaking!! ***\n");
-                       return;
+                       ret = (*state[self->state])(self, CONNECT_REQUEST, 
+                                                   NULL, NULL);
                }
+               break;
+/*     case LAP_CONN: */
+/*     case LAP_RESET_WAIT: */
+/*     case LAP_RESET_CHECK: */
+       default:
+               break;
        }
 }
 
@@ -256,10 +266,8 @@ void irlap_do_event( struct irlap_cb *self, IRLAP_EVENT event,
  */
 void irlap_next_state( struct irlap_cb *self, IRLAP_STATE state) 
 {      
-       if ( !self || self->magic != LAP_MAGIC) {
-               DEBUG( 4, "irlap_next_state: I have lost myself!\n");
+       if ( !self || self->magic != LAP_MAGIC)
                return;
-       }
        
        DEBUG( 4, "next LAP state = %s\n", irlap_state[ state]);
 
@@ -308,7 +316,7 @@ static int irlap_state_ndm( struct irlap_cb *self, IRLAP_EVENT event,
                        irlap_send_snrm_frame( self, &self->qos_rx);
                        
                        /* Start Final-bit timer */
-                       irlap_start_final_timer( self, self->final_timeout);
+                       irlap_start_final_timer(self, self->final_timeout);
 
                        self->retry_count = 0;
                        irlap_next_state( self, LAP_SETUP);
@@ -328,7 +336,7 @@ static int irlap_state_ndm( struct irlap_cb *self, IRLAP_EVENT event,
                ASSERT( info != NULL, return -1;);
 
                if ( irda_device_is_media_busy( self->irdev)) {
-                       DEBUG(0, "irlap_discovery_request: media busy!\n"); 
+                       DEBUG(0, __FUNCTION__ "(), media busy!\n"); 
                        /* irlap->log.condition = MEDIA_BUSY; */
                        
                        /* Always switch state before calling upper layers */
@@ -345,7 +353,7 @@ static int irlap_state_ndm( struct irlap_cb *self, IRLAP_EVENT event,
                                                info->discovery);
                self->s++;
 
-               irlap_start_slot_timer( self, SLOT_TIMEOUT);
+               irlap_start_slot_timer( self, self->slot_timeout);
                irlap_next_state( self, LAP_QUERY);
                break;
 
@@ -424,7 +432,7 @@ static int irlap_state_query( struct irlap_cb *self, IRLAP_EVENT event,
                                                        self->s, TRUE,
                                                        self->discovery_cmd);
                        self->s++;
-                       irlap_start_slot_timer( self, SLOT_TIMEOUT);
+                       irlap_start_slot_timer( self, self->slot_timeout);
                        
                        /* Keep state */
                        irlap_next_state( self, LAP_QUERY);
@@ -477,8 +485,8 @@ static int irlap_state_reply( struct irlap_cb *self, IRLAP_EVENT event,
 
        switch( event) {
        case QUERY_TIMER_EXPIRED:
-               DEBUG( 0, __FUNCTION__ "(), QUERY_TIMER_EXPIRED <%ld>\n",
-                      jiffies);
+               DEBUG(2, __FUNCTION__ "(), QUERY_TIMER_EXPIRED <%ld>\n",
+                     jiffies);
                irlap_next_state( self, LAP_NDM);
                break;
        case RECV_DISCOVERY_XID_CMD:
@@ -510,12 +518,12 @@ static int irlap_state_reply( struct irlap_cb *self, IRLAP_EVENT event,
                dev_kfree_skb( skb);
                break;
        default:
-               DEBUG( 0, __FUNCTION__ "(), Unknown event %d, %s\n", event,
-                      irlap_event[event]);
+               DEBUG(1, __FUNCTION__ "(), Unknown event %d, %s\n", event,
+                     irlap_event[event]);
 
-               if ( skb != NULL)
+               if ( skb)
                        dev_kfree_skb( skb);
-
+               
                ret = -1;
                break;
        }
@@ -571,20 +579,20 @@ static int irlap_state_conn( struct irlap_cb *self, IRLAP_EVENT event,
                irlap_next_state( self, LAP_NDM);
 #endif
                break;
-
+               
        case RECV_DISCOVERY_XID_CMD:
                DEBUG( 3, __FUNCTION__ "(), event RECV_DISCOVER_XID_CMD!\n");
                irlap_next_state( self, LAP_NDM);
                break;
-
+               
        case DISCONNECT_REQUEST:
                irlap_send_dm_frame( self);
                irlap_next_state( self, LAP_CONN);
                break;
 
        default:
-               DEBUG( 0, __FUNCTION__ "(), Unknown event %d, %s\n", event, 
-                      irlap_event[event]);
+               DEBUG(1, __FUNCTION__ "(), Unknown event %d, %s\n", event, 
+                     irlap_event[event]);
                ret = -1;
                break;
        }
@@ -682,7 +690,9 @@ static int irlap_state_setup( struct irlap_cb *self, IRLAP_EVENT event,
 
                irlap_apply_connection_parameters( self, &self->qos_tx); 
                self->retry_count = 0;
-               irlap_send_rr_frame( self, CMD_FRAME);
+               
+               /* This frame will just be sent at the old speed */
+               /* irlap_send_rr_frame( self, CMD_FRAME); */
 
                irlap_start_final_timer( self, self->final_timeout/2);
                irlap_next_state( self, LAP_NRM_P);
@@ -724,9 +734,10 @@ static int irlap_state_offline( struct irlap_cb *self, IRLAP_EVENT event,
 /*
  * Function irlap_state_xmit_p (self, event, skb, info)
  * 
- *    XMIT, Only the primary station has right to transmit, and we therefor
- *    do not expect to receive any transmissions from other stations.  
- *
+ *    XMIT, Only the primary station has right to transmit, and we
+ *    therefore do not expect to receive any transmissions from other
+ *    stations.
+ * 
  */
 static int irlap_state_xmit_p( struct irlap_cb *self, IRLAP_EVENT event, 
                               struct sk_buff *skb, struct irlap_info *info) 
@@ -785,6 +796,12 @@ static int irlap_state_xmit_p( struct irlap_cb *self, IRLAP_EVENT event,
                                DEBUG( 4, __FUNCTION__ "(), window <= 1\n");
                                irlap_send_data_primary_poll( self, skb);
                                irlap_next_state( self, LAP_NRM_P);
+                               
+                               /* 
+                                * Make sure state machine does not try to send
+                                * any more frames 
+                                */
+                               ret = -EPROTO;
                        }
 #ifdef CONFIG_IRDA_FAST_RR
                        /* Peer may want to reply immediately */
@@ -817,7 +834,8 @@ static int irlap_state_xmit_p( struct irlap_cb *self, IRLAP_EVENT event,
                irlap_next_state( self, LAP_NRM_P);
                break;
        default:
-               /* DEBUG( 0, "irlap_state_xmit: Unknown event"); */
+               DEBUG(0, __FUNCTION__ "(), Unknown event %s\n", 
+                     irlap_event[event]);
                ret = -EINVAL;
                break;
        }
@@ -834,7 +852,7 @@ static int irlap_state_pclose( struct irlap_cb *self, IRLAP_EVENT event,
 {
        int ret = 0;
 
-       DEBUG( 0, __FUNCTION__ "()\n");
+       DEBUG(1, __FUNCTION__ "()\n");
        
        ASSERT( self != NULL, return -1;);
        ASSERT( self->magic == LAP_MAGIC, return -1;);  
@@ -870,7 +888,7 @@ static int irlap_state_pclose( struct irlap_cb *self, IRLAP_EVENT event,
                }
                break;
        default:
-               DEBUG( 0, __FUNCTION__ "(), Unknown event %d\n", event);
+               DEBUG(1, __FUNCTION__ "(), Unknown event %d\n", event);
                ret = -1;
                break;  
        }
@@ -961,8 +979,8 @@ static int irlap_state_nrm_p( struct irlap_cb *self, IRLAP_EVENT event,
                        /* Keep state */
                        irlap_next_state( self, LAP_NRM_P);
                } else if ( ret == NR_INVALID) {
-                       DEBUG( 0, "irlap_state_nrm_p: received RR with "
-                              "invalid nr !\n");
+                       DEBUG(1, "irlap_state_nrm_p: received RR with "
+                             "invalid nr !\n");
                        del_timer( &self->final_timer);
 
                        irlap_next_state( self, LAP_RESET_WAIT);
@@ -1181,8 +1199,8 @@ static int irlap_state_nrm_p( struct irlap_cb *self, IRLAP_EVENT event,
                        }
                        break;
                }
-               DEBUG( 0, "irlap_state_nrm_p: Not implemented!\n");
-               DEBUG( 0, "event=%s, ns_status=%d, nr_status=%d\n", 
+               DEBUG(1, __FUNCTION__ "(), Not implemented!\n");
+               DEBUG(1, __FUNCTION__ "(), event=%s, ns_status=%d, nr_status=%d\n", 
                       irlap_event[ event], ns_status, nr_status);
                break;
        case RECV_UI_FRAME:
@@ -1257,7 +1275,7 @@ static int irlap_state_nrm_p( struct irlap_cb *self, IRLAP_EVENT event,
                }
                break;
        case RECV_DISC_FRAME: /* FIXME: Check how this is in the standard! */
-               DEBUG( 0, __FUNCTION__ "(), RECV_DISC_FRAME()\n");
+               DEBUG(1, __FUNCTION__ "(), RECV_DISC_FRAME()\n");
 
                /* Always switch state before calling upper layers */
                irlap_next_state( self, LAP_NDM);
@@ -1277,7 +1295,8 @@ static int irlap_state_nrm_p( struct irlap_cb *self, IRLAP_EVENT event,
                
                break;
        default:
-               /* DEBUG( 0, "irlap_state_nrm_p: Unknown event"); */
+               DEBUG(1, __FUNCTION__ "(), Unknown event %s\n", 
+                     irlap_event[event]);
                ret = -1;
                break;
        }
@@ -1322,8 +1341,8 @@ int irlap_state_reset_wait( struct irlap_cb *self, IRLAP_EVENT event,
                irlap_next_state( self, LAP_PCLOSE);
                break;
        default:
-               DEBUG( 0, __FUNCTION__ "(), Unknown event %s\n", 
-                      irlap_event[event]);
+               DEBUG(1, __FUNCTION__ "(), Unknown event %s\n", 
+                     irlap_event[event]);
                ret = -1;
                break;  
        }
@@ -1403,8 +1422,8 @@ int irlap_state_reset( struct irlap_cb *self, IRLAP_EVENT event,
                break;
 
        default:
-               DEBUG( 0, __FUNCTION__ "(), Unknown event %s\n", 
-                      irlap_event[ event]);
+               DEBUG(1, __FUNCTION__ "(), Unknown event %s\n", 
+                     irlap_event[ event]);
                ret = -1;
                break;  
        }
@@ -1468,16 +1487,22 @@ static int irlap_state_xmit_s( struct irlap_cb *self, IRLAP_EVENT event,
                                DEBUG( 4, "(), window <= 1\n");
                                irlap_send_data_secondary_final( self, skb);
                                irlap_next_state( self, LAP_NRM_S);
+
+                               /* 
+                                * Make sure state machine does not try to send
+                                * any more frames 
+                                */
+                               ret = -EPROTO;
                        }
                } else {
-                       DEBUG( 0, __FUNCTION__ "(), Unable to send!\n");
+                       DEBUG(1, __FUNCTION__ "(), Unable to send!\n");
                        skb_queue_head( &self->tx_list, skb);
                        ret = -EPROTO;
                }
                break;
        default:
-               DEBUG( 0, __FUNCTION__ "(), Unknown event %s\n", 
-                      irlap_event[ event]);
+               DEBUG(1, __FUNCTION__ "(), Unknown event %s\n", 
+                     irlap_event[ event]);
                ret = -EINVAL;
                break;
        }
@@ -1543,8 +1568,7 @@ static int irlap_state_nrm_s( struct irlap_cb *self, IRLAP_EVENT event,
                        /* Keep state */
                        irlap_next_state( self, LAP_NRM_S); 
                } else {
-                       DEBUG( 0, __FUNCTION__ "(), "
-                              "invalid nr not implemented!\n");
+                       DEBUG(1, __FUNCTION__ "(), invalid nr not implemented!\n");
                } 
                if ( skb)
                        dev_kfree_skb( skb);
@@ -1731,7 +1755,7 @@ static int irlap_state_nrm_s( struct irlap_cb *self, IRLAP_EVENT event,
                break;
        case RECV_SNRM_CMD:
                del_timer( &self->wd_timer);
-               DEBUG( 0, "irlap_state_nrm_s: received SNRM cmd\n");
+               DEBUG(1, __FUNCTION__ "(), received SNRM cmd\n");
                irlap_next_state( self, LAP_RESET_CHECK);
 
                irlap_reset_indication( self);
@@ -1743,7 +1767,8 @@ static int irlap_state_nrm_s( struct irlap_cb *self, IRLAP_EVENT event,
                 *  Wait until retry_count * n matches negotiated threshold/
                 *  disconnect time (note 2 in IrLAP p. 82)
                 */
-               DEBUG( 0, "retry_count = %d\n", self->retry_count);
+               DEBUG(1, __FUNCTION__ "(), retry_count = %d\n", 
+                     self->retry_count);
 
                if (( self->retry_count < (self->N2/2))  && 
                    ( self->retry_count != self->N1/2)) {
@@ -1800,8 +1825,8 @@ static int irlap_state_nrm_s( struct irlap_cb *self, IRLAP_EVENT event,
                break;
 
        default:
-               DEBUG( 0, __FUNCTION__ "(), Unknown event %d, (%s)\n", 
-                      event, irlap_event[event]);
+               DEBUG(1, __FUNCTION__ "(), Unknown event %d, (%s)\n", 
+                     event, irlap_event[event]);
                ret = -1;
                break;
        }
@@ -1828,7 +1853,7 @@ static int irlap_state_reset_check( struct irlap_cb *self, IRLAP_EVENT event,
 {
        int ret = 0;
 
-       DEBUG( 0, __FUNCTION__ "(), event=%s\n", irlap_event[ event]); 
+       DEBUG(1, __FUNCTION__ "(), event=%s\n", irlap_event[ event]); 
 
        ASSERT( self != NULL, return -ENODEV;);
        ASSERT( self->magic == LAP_MAGIC, return -EBADR;);
@@ -1848,8 +1873,8 @@ static int irlap_state_reset_check( struct irlap_cb *self, IRLAP_EVENT event,
                irlap_start_wd_timer( self, WD_TIMEOUT);
                break;
        default:
-               DEBUG( 0, __FUNCTION__ "(), Unknown event %d, (%s)\n", 
-                      event, irlap_event[event]);
+               DEBUG(1, __FUNCTION__ "(), Unknown event %d, (%s)\n", 
+                     event, irlap_event[event]);
                ret = -1;
                break;
        }
index d00fd185242caa7e8737760cbd0dc69e42034168..d77d765dc89afc05717a29568a3eb1dd6f40089c 100644 (file)
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      irlap_frame.c
- * Version:       0.3
+ * Version:       0.8
  * Description:   Build and transmit IrLAP frames
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Aug 19 10:27:26 1997
- * Modified at:   Tue Jan 19 22:58:13 1999
+ * Modified at:   Sat Feb 20 01:40:14 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, All Rights Resrved.
@@ -26,7 +26,6 @@
 #include <linux/skbuff.h>
 #include <net/sock.h>
 
-#include <linux/skbuff.h>
 #include <linux/if.h>
 #include <linux/if_ether.h>
 #include <linux/netdevice.h>
@@ -49,7 +48,7 @@ extern __u8 *irlmp_hint_to_service( __u8 *hint);
  *    need to do this since it's per packet relevant information.
  *
  */
-__inline__ void irlap_insert_mtt( struct irlap_cb *self, struct sk_buff *skb)
+void irlap_insert_mtt( struct irlap_cb *self, struct sk_buff *skb)
 {
        struct irlap_skb_cb *cb;
 
@@ -75,19 +74,42 @@ __inline__ void irlap_insert_mtt( struct irlap_cb *self, struct sk_buff *skb)
        DEBUG( 4, __FUNCTION__ "(), using %d xbofs\n", cb->xbofs);
 }
 
+/*
+ * Function irlap_queue_xmit (self, skb)
+ *
+ *    A little wrapper for dev_queue_xmit, so we can insert some common
+ *    code into it.
+ */
+void irlap_queue_xmit(struct irlap_cb *self, struct sk_buff *skb)
+{
+       /* Some init stuff */
+       skb->dev = self->netdev;
+       skb->h.raw = skb->nh.raw = skb->mac.raw = skb->data;
+       skb->protocol = htons(ETH_P_IRDA);
+
+       /* 
+        * Insert MTT (min. turn time) into skb, so that the device driver 
+        * knows which MTT to use 
+        */
+       irlap_insert_mtt(self, skb);
+       
+       dev_queue_xmit(skb);
+       self->stats.tx_packets++;
+}
+
 /*
  * Function irlap_send_snrm_cmd (void)
  *
  *    Transmits a connect SNRM command frame
  */
-void irlap_send_snrm_frame( struct irlap_cb *self, struct qos_info *qos) 
+void irlap_send_snrm_frame(struct irlap_cb *self, struct qos_info *qos) 
 {
        struct sk_buff *skb;
        __u8 *frame;
        int len;
        int n;
 
-       DEBUG( 4, "irlap_send_snrm_cmd()\n");
+       DEBUG(4, __FUNCTION__ "()\n");
 
        ASSERT( self != NULL, return;);
        ASSERT( self->magic == LAP_MAGIC, return;);
@@ -95,14 +117,11 @@ void irlap_send_snrm_frame( struct irlap_cb *self, struct qos_info *qos)
        n = 0;
 
        /* Allocate frame */
-       skb = dev_alloc_skb( 64);
-       if (skb == NULL) {
-               DEBUG( 0,"irlap_send_snrm_cmd: "
-                      "Could not allocate an sk_buff of length %d\n", 64);
+       skb = dev_alloc_skb(64);
+       if (!skb)
                return;
-       }
 
-       skb_put( skb, 2); 
+       skb_put(skb, 2); 
        frame = skb->data;
 
        /* Insert address field */
@@ -116,23 +135,20 @@ void irlap_send_snrm_frame( struct irlap_cb *self, struct qos_info *qos)
         *  If we are establishing a connection then insert QoS paramerters 
         */
        if (qos) {
-               skb_put( skb, 9); /* 21 left */
-               memcpy( frame+n, &self->saddr, 4); n += 4;
-               memcpy( frame+n, &self->daddr, 4); n += 4;
+               skb_put(skb, 9); /* 21 left */
+               *((__u32 *)(frame+n)) = cpu_to_le32(self->saddr); n += 4;
+               *((__u32 *)(frame+n)) = cpu_to_le32(self->daddr); n += 4;
+
+/*             memcpy(frame+n, &self->saddr, 4); n += 4; */
+/*             memcpy(frame+n, &self->daddr, 4); n += 4; */
 
                frame[n++] = self->caddr;
                                
-               /* skb_put( skb, 21); */
-               len = irda_insert_qos_negotiation_params( qos, frame+n);
+               len = irda_insert_qos_negotiation_params(qos, frame+n);
                /* Should not be dangerous to do this afterwards */
-               skb_put( skb, len);
+               skb_put(skb, len);
        }
-       skb->dev = self->netdev;
-       skb->h.raw = skb->data;
-       irlap_insert_mtt( self, skb);
-
-       dev_queue_xmit( skb);
-       self->stats.tx_packets++;
+       irlap_queue_xmit(self, skb);
 }
 
 /*
@@ -154,7 +170,8 @@ static void irlap_recv_snrm_cmd( struct irlap_cb *self, struct sk_buff *skb,
        frame = ( struct snrm_frame *) skb->data;
 
        /* Copy peer device address */
-       memcpy( &info->daddr, &frame->saddr, 4);
+       /* memcpy( &info->daddr, &frame->saddr, 4); */
+       info->daddr = le32_to_cpu(frame->saddr);
 
        /* Copy connection address */
        info->caddr = frame->ncaddr;
@@ -168,29 +185,25 @@ static void irlap_recv_snrm_cmd( struct irlap_cb *self, struct sk_buff *skb,
  *    Send UA (Unnumbered Acknowledgement) frame
  *
  */
-void irlap_send_ua_response_frame( struct irlap_cb *self, 
-                                  struct qos_info *qos)
+void irlap_send_ua_response_frame(struct irlap_cb *self, struct qos_info *qos)
 {
        struct sk_buff *skb;
        __u8 *frame;
        int n;
        int len;
        
-       DEBUG( 4, __FUNCTION__ "() <%ld>\n", jiffies);
+       DEBUG(2, __FUNCTION__ "() <%ld>\n", jiffies);
        
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == LAP_MAGIC, return;);
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == LAP_MAGIC, return;);
 
        skb = NULL;
        n = 0;
 
        /* Allocate frame */
-       skb =  dev_alloc_skb( 64);
-       if (skb == NULL) {
-               DEBUG( 0, __FUNCTION__
-                      "Could not allocate an sk_buff of length %d\n", 64);
+       skb =  dev_alloc_skb(64);
+       if (!skb)
                return;
-       }
 
        skb_put( skb, 10);
        frame = skb->data;
@@ -198,21 +211,20 @@ void irlap_send_ua_response_frame( struct irlap_cb *self,
        /* Build UA response */
        frame[n++] = self->caddr;
        frame[n++] = UA_RSP | PF_BIT;
-       memcpy( frame+n, &self->saddr, 4); n += 4;
-       memcpy( frame+n, &self->daddr, 4); n += 4;
+
+       *((__u32 *)(frame+n)) = cpu_to_le32(self->saddr); n += 4;
+       *((__u32 *)(frame+n)) = cpu_to_le32(self->daddr); n += 4;
+
+/*     memcpy( frame+n, &self->saddr, 4); n += 4; */
+/*     memcpy( frame+n, &self->daddr, 4); n += 4; */
        
        /* Should we send QoS negotiation parameters? */
-       if ( qos) {
-               len = irda_insert_qos_negotiation_params( qos, frame+n);
-               skb_put( skb, len);
+       if (qos) {
+               len = irda_insert_qos_negotiation_params(qos, frame+n);
+               skb_put(skb, len);
        }
 
-       skb->dev = self->netdev;
-       skb->h.raw = skb->data;
-       irlap_insert_mtt( self, skb);
-
-       dev_queue_xmit( skb);
-       self->stats.tx_packets++;
+       irlap_queue_xmit(self, skb);
 }
 
 
@@ -230,12 +242,9 @@ void irlap_send_dm_frame( struct irlap_cb *self)
        ASSERT( self != NULL, return;);
        ASSERT( self->magic == LAP_MAGIC, return;);
 
-       skb =  dev_alloc_skb( 32);
-       if (skb == NULL) {
-               DEBUG( 0,"irlap_send_disc_frame: "
-                      "Could not allocate an sk_buff of length %d\n", 64);
+       skb = dev_alloc_skb(32);
+       if (!skb)
                return;
-       }
 
        skb_put( skb, 2);
        frame = skb->data;
@@ -246,13 +255,8 @@ void irlap_send_dm_frame( struct irlap_cb *self)
                frame[0] = self->caddr;
 
        frame[1] = DM_RSP | PF_BIT;
-       
-       skb->dev = self->netdev;
-       skb->h.raw = skb->data;
-       irlap_insert_mtt( self, skb);
 
-       dev_queue_xmit( skb);
-       self->stats.tx_packets++;
+       irlap_queue_xmit(self, skb);    
 }
 
 /*
@@ -261,33 +265,27 @@ void irlap_send_dm_frame( struct irlap_cb *self)
  *    Send disconnect (DISC) frame
  *
  */
-void irlap_send_disc_frame( struct irlap_cb *self) 
+void irlap_send_disc_frame(struct irlap_cb *self) 
 {
        struct sk_buff *skb = NULL;
        __u8 *frame;
        
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == LAP_MAGIC, return;);
+       DEBUG(3, __FUNCTION__ "()\n");
+
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == LAP_MAGIC, return;);
 
-       skb =  dev_alloc_skb( 32);
-       if (skb == NULL) {
-               DEBUG( 0,"irlap_send_disc_frame: "
-                      "Could not allocate an sk_buff of length %d\n", 64);
+       skb = dev_alloc_skb(32);
+       if (!skb)
                return;
-       }
 
-       skb_put( skb, 2);
+       skb_put(skb, 2);
        frame = skb->data;
        
        frame[0] = self->caddr | CMD_FRAME;
        frame[1] = DISC_CMD | PF_BIT;
-       
-       skb->dev = self->netdev;
-       skb->h.raw = skb->data;
-       irlap_insert_mtt( self, skb);
 
-       dev_queue_xmit( skb);
-       self->stats.tx_packets++;
+       irlap_queue_xmit(self, skb);
 }
 
 /*
@@ -309,12 +307,9 @@ void irlap_send_discovery_xid_frame( struct irlap_cb *self, int S, __u8 s,
        ASSERT( self->magic == LAP_MAGIC, return;);
        ASSERT( discovery != NULL, return;);
 
-       skb =  dev_alloc_skb( 64);
-       if (skb == NULL) {
-               DEBUG( 0,"irlap_send_discovery_xid_frame: "
-                      "Could not allocate an sk_buff of length %d\n", 64);
+       skb = dev_alloc_skb(64);
+       if (!skb)
                return;
-       }
 
        skb_put( skb, 14);
        frame = ( struct xid_frame *) skb->data;
@@ -328,12 +323,15 @@ void irlap_send_discovery_xid_frame( struct irlap_cb *self, int S, __u8 s,
        }
        frame->ident = XID_FORMAT;
 
-       memcpy( &frame->saddr, &self->saddr, 4);
+       frame->saddr = cpu_to_le32(self->saddr);
+/*     memcpy( &frame->saddr, &self->saddr, 4); */
 
        if ( command)
-               memcpy( &frame->daddr, &bcast, 4);
+               /* memcpy( &frame->daddr, &bcast, 4); */
+               frame->daddr = cpu_to_le32(bcast);
        else
-               memcpy( &frame->daddr, &self->daddr, 4);        
+               /* memcpy( &frame->daddr, &self->daddr, 4); */
+               frame->daddr = cpu_to_le32(self->daddr);
        
        switch( S) {
        case 1:
@@ -364,7 +362,7 @@ void irlap_send_discovery_xid_frame( struct irlap_cb *self, int S, __u8 s,
        if ( !command || ( frame->slotnr == 0xff)) {
                int i;
 
-               ifdiscovery->hint[0] & HINT_EXTENSION)
+               if (discovery->hint[0] & HINT_EXTENSION)
                        skb_put( skb, 3+discovery->info_len);
                else
                        skb_put( skb, 2+discovery->info_len);
@@ -382,15 +380,9 @@ void irlap_send_discovery_xid_frame( struct irlap_cb *self, int S, __u8 s,
                        discovery->info_len);
 
        } 
-
        ASSERT( self->netdev != NULL, return;);
 
-       skb->dev = self->netdev;
-       skb->h.raw = skb->data;
-       irlap_insert_mtt( self, skb);
-
-       dev_queue_xmit( skb);
-       self->stats.tx_packets++;
+       irlap_queue_xmit(self, skb);
 }
 
 /*
@@ -479,7 +471,8 @@ static void irlap_recv_discovery_xid_cmd( struct irlap_cb *self,
        xid = (struct xid_frame *) skb->data;
        
        /* Copy peer device address */
-       memcpy( &info->daddr, &xid->saddr, 4);
+       /* memcpy( &info->daddr, &xid->saddr, 4); */
+       info->daddr = le32_to_cpu(xid->saddr);
 
        switch ( xid->flags & 0x03) {
        case 0x00:
@@ -567,13 +560,11 @@ void irlap_send_rr_frame( struct irlap_cb *self, int command)
                self->recycle_rr_skb = NULL;
        }
 #endif      
-       if ( !skb) {
+       if (!skb) {
                skb = dev_alloc_skb( 32);
-               if (skb == NULL) {
-                       printk( KERN_WARNING "irlap_send_rr_frame: "
-                               "Could not allocate an skb of length %d\n", 32);
+               if (!skb)
                        return;
-               }
+   
                skb_put( skb, 2);
        }
        ASSERT( skb->len == 2, return;);
@@ -585,14 +576,9 @@ void irlap_send_rr_frame( struct irlap_cb *self, int command)
 
        frame[1] = RR | PF_BIT | (self->vr << 5);
 
-       DEBUG( 4, __FUNCTION__ "(), vr=%d, %ld\n", self->vr, jiffies); 
-
-       skb->dev = self->netdev;
-       skb->h.raw = skb->data;
-       irlap_insert_mtt( self, skb);
+       DEBUG(4, __FUNCTION__ "(), vr=%d, %ld\n", self->vr, jiffies); 
 
-       dev_queue_xmit( skb);
-       self->stats.tx_packets++;
+       irlap_queue_xmit(self, skb);
 }
 
 /*
@@ -613,7 +599,7 @@ static void irlap_recv_rr_frame( struct irlap_cb *self, struct sk_buff *skb,
        frame = skb->data;
        info->nr = frame[1] >> 5;
 
-       DEBUG( 4, __FUNCTION__ "(), nr=%d, %ld\n", info->nr, jiffies);
+       DEBUG(4, __FUNCTION__ "(), nr=%d, %ld\n", info->nr, jiffies);
 
        /*
         *  Make sure the state-machine is in the right state for receiving, 
@@ -660,11 +646,8 @@ void irlap_send_frmr_frame( struct irlap_cb *self, int command)
        ASSERT( self->magic == LAP_MAGIC, return;);
 
        skb = dev_alloc_skb( 32);
-       if (skb == NULL) {
-               printk( KERN_WARNING "irlap_send_frmr_frame: "
-                       "Could not allocate an sk_buff of length %d\n", 32);
+       if (!skb)
                return;
-       }
 
        skb_put( skb, 2);
        frame = skb->data;
@@ -680,12 +663,7 @@ void irlap_send_frmr_frame( struct irlap_cb *self, int command)
 
        DEBUG( 4, __FUNCTION__ "(), vr=%d, %ld\n",self->vr, jiffies); 
 
-       skb->dev = self->netdev;
-       skb->h.raw = skb->data;
-       irlap_insert_mtt( self, skb);
-
-       dev_queue_xmit( skb);
-       self->stats.tx_packets++;
+       irlap_queue_xmit(self, skb);
 }
 
 /*
@@ -716,15 +694,15 @@ static void irlap_recv_rnr_frame( struct irlap_cb *self, struct sk_buff *skb,
  *    Received UA (Unnumbered Acknowledgement) frame
  *
  */
-static void irlap_recv_ua_frame( struct irlap_cb *self, struct sk_buff *skb, 
-                                struct irlap_info *info) 
+static void irlap_recv_ua_frame(struct irlap_cb *self, struct sk_buff *skb, 
+                               struct irlap_info *info) 
 {
-       DEBUG( 4, __FUNCTION__ "()\n"); 
+       DEBUG(4, __FUNCTION__ "(), <%ld>\n", jiffies); 
 
-       ASSERT( skb != NULL, return;);
-       ASSERT( info != NULL, return;);
+       ASSERT(skb != NULL, return;);
+       ASSERT(info != NULL, return;);
 
-       irlap_do_event( self, RECV_UA_RSP, skb, info);
+       irlap_do_event(self, RECV_UA_RSP, skb, info);
 }
 
 /*
@@ -756,7 +734,6 @@ void irlap_send_data_primary( struct irlap_cb *self, struct sk_buff *skb)
                
                /* * Copy buffer */
                tx_skb = skb_clone( skb, GFP_ATOMIC);
-               /* tx_skb = skb_copy( skb, GFP_ATOMIC);  */
                if ( tx_skb == NULL) {
                        dev_kfree_skb( skb);
                        return;
@@ -813,7 +790,6 @@ void irlap_send_data_primary_poll( struct irlap_cb *self, struct sk_buff *skb)
                
                /* Copy buffer */
                tx_skb = skb_clone( skb, GFP_ATOMIC);
-               /* tx_skb = skb_copy( skb, GFP_ATOMIC);  */
                if ( tx_skb == NULL) {
                        dev_kfree_skb( skb);
                        return;
@@ -890,7 +866,6 @@ void irlap_send_data_secondary_final( struct irlap_cb *self,
                skb->data[1] = I_FRAME | (self->vs << 1);
                
                tx_skb = skb_clone( skb, GFP_ATOMIC);
-               /* tx_skb = skb_copy( skb, GFP_ATOMIC); */
                if ( tx_skb == NULL) {
                        dev_kfree_skb( skb);
                        return;
@@ -950,7 +925,6 @@ void irlap_send_data_secondary( struct irlap_cb *self, struct sk_buff *skb)
                skb->data[1] = I_FRAME | (self->vs << 1);
                
                tx_skb = skb_clone( skb, GFP_ATOMIC);
-               /* tx_skb = skb_copy( skb, GFP_ATOMIC); */
                if ( tx_skb == NULL) {
                        dev_kfree_skb( skb);
                        return;
@@ -1006,7 +980,6 @@ void irlap_resend_rejected_frames( struct irlap_cb *self, int command)
                irlap_wait_min_turn_around( self, &self->qos_tx);
 
                tx_skb = skb_clone( skb, GFP_ATOMIC);
-               /* tx_skb = skb_copy( skb, GFP_ATOMIC); */
                if ( tx_skb == NULL) {
                        /* Unlink tx_skb from list */
                        tx_skb->next = tx_skb->prev = NULL;
@@ -1098,12 +1071,7 @@ void irlap_send_ui_frame( struct irlap_cb *self, struct sk_buff *skb,
        frame[0] = self->caddr;
        frame[0] |= (command) ? CMD_FRAME : 0;
 
-       skb->dev = self->netdev;
-       skb->h.raw = skb->data;
-       irlap_insert_mtt( self, skb);
-
-       dev_queue_xmit( skb);
-       self->stats.tx_packets++;
+       irlap_queue_xmit(self, skb);
 }
 
 /*
@@ -1137,16 +1105,11 @@ void irlap_send_i_frame( struct irlap_cb *self, struct sk_buff *skb,
                vs = (frame[1] >> 1) & 0x07;
                pf = (frame[1] >> 4) & 0x01;
                
-               DEBUG( 0, __FUNCTION__ "(), vs=%d, vr=%d, p=%d, %ld\n", 
-                      vs, vr, pf, jiffies);
+               DEBUG(0, __FUNCTION__ "(), vs=%d, vr=%d, p=%d, %ld\n", 
+                     vs, vr, pf, jiffies);
        }
 #endif 
-       skb->dev = self->netdev;
-       skb->h.raw = skb->data;
-       irlap_insert_mtt( self, skb);
-
-       dev_queue_xmit( skb);
-       self->stats.tx_packets++;
+       irlap_queue_xmit(self, skb);
 }
 
 /*
@@ -1170,8 +1133,8 @@ static void irlap_recv_i_frame( struct irlap_cb *self, struct sk_buff *skb,
        info->pf = frame[1] & PF_BIT;      /* Final bit */
        info->ns = (frame[1] >> 1) & 0x07; /* Next to send */
 
-       DEBUG( 4, __FUNCTION__"(), ns=%d, nr=%d, pf=%d, %ld\n", 
-              info->ns, info->nr, info->pf>>4, jiffies); 
+       DEBUG(4, __FUNCTION__"(), ns=%d, nr=%d, pf=%d, %ld\n", 
+             info->ns, info->nr, info->pf>>4, jiffies); 
 
        /*
         *  Make sure the state-machine is in the right state for receiving, 
@@ -1376,7 +1339,7 @@ int irlap_input( struct sk_buff *skb, struct device *netdev,
                irlap_next_state( self, LAP_NDM);
                break;
        case DISC_CMD:
-               DEBUG( 0, "DISC cmd frame received!\n");
+               DEBUG( 2, "DISC cmd frame received!\n");
                irlap_do_event( self, RECV_DISC_FRAME, skb, &info);
                break;
        case TEST_CMD:
index c4f7c2b8dfd9f9915166e257e9c4ede1ff9b9461..e433fcba69557b8569a6ebff7e058efe40055a28 100644 (file)
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 17 20:54:32 1997
- * Modified at:   Sat Jan 16 22:13:20 1999
+ * Modified at:   Sat Feb 20 01:28:39 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, 
 /* Master structure */
 struct irlmp_cb *irlmp = NULL;
 
+/* These can be altered by the sysctl interface */
 int sysctl_discovery = 0;
+int sysctl_discovery_slots = 6;
 char sysctl_devname[65];
 
+char *lmp_reasons[] = {
+       "ERROR, NOT USED",
+       "LM_USER_REQUEST",
+       "LM_LAP_DISCONNECT",
+       "LM_CONNECT_FAILURE",
+       "LM_LAP_RESET",
+       "LM_INIT_DISCONNECT",
+       "ERROR, NOT USED",
+};
+
 __u8 *irlmp_hint_to_service( __u8 *hint);
 #ifdef CONFIG_PROC_FS
 int irlmp_proc_read( char *buf, char **start, off_t offset, int len, 
@@ -61,8 +73,6 @@ int irlmp_proc_read( char *buf, char **start, off_t offset, int len,
  */
 __initfunc(int irlmp_init(void))
 {
-       DEBUG( 4, "--> irlmp_init\n");
-
        /* Initialize the irlmp structure. */
        if ( irlmp == NULL) {
                irlmp = kmalloc( sizeof(struct irlmp_cb), GFP_KERNEL);
@@ -128,7 +138,7 @@ struct lsap_cb *irlmp_open_lsap( __u8 slsap_sel, struct notify_t *notify)
        ASSERT( irlmp != NULL, return NULL;);
        ASSERT( irlmp->magic == LMP_MAGIC, return NULL;);
 
-       DEBUG( 4, "irlmp_open_lsap(), slsap_sel=%02x\n", slsap_sel);
+       DEBUG( 4, __FUNCTION__ "(), slsap_sel=%02x\n", slsap_sel);
 
        /* 
         *  Does the client care which Source LSAP selector it gets? 
@@ -166,6 +176,7 @@ struct lsap_cb *irlmp_open_lsap( __u8 slsap_sel, struct notify_t *notify)
        self->magic = LMP_LSAP_MAGIC;
        self->slsap_sel = slsap_sel;
        self->dlsap_sel = LSAP_ANY;
+       self->connected = FALSE;
 
        init_timer( &self->watchdog_timer);
 
@@ -190,7 +201,7 @@ struct lsap_cb *irlmp_open_lsap( __u8 slsap_sel, struct notify_t *notify)
  */
 static void __irlmp_close_lsap( struct lsap_cb *self)
 {
-       DEBUG( 4, "irlmp_close()\n");
+       DEBUG( 4, __FUNCTION__ "()\n");
 
        ASSERT( self != NULL, return;);
        ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
@@ -205,12 +216,7 @@ static void __irlmp_close_lsap( struct lsap_cb *self)
        ASSERT( irlmp != NULL, return;);
        irlmp->cache.valid = FALSE;
 #endif
-       /*
-        *  Deallocate structure
-        */
        kfree( self);
-
-       DEBUG( 4, "irlmp_close() -->\n");
 }
 
 /*
@@ -243,7 +249,7 @@ void irlmp_close_lsap( struct lsap_cb *self)
                lsap = hashbin_remove( lap->lsaps, self->slsap_sel, NULL);
        }
        if ( lsap == NULL) {
-               DEBUG( 0, __FUNCTION__ 
+               DEBUG( 1, __FUNCTION__ 
                       "(), Looks like somebody has removed me already!\n");
                return;
        }
@@ -285,11 +291,14 @@ void irlmp_register_irlap( struct irlap_cb *irlap, __u32 saddr,
        lap->irlap = irlap;
        lap->magic = LMP_LAP_MAGIC;
        lap->saddr = saddr;
+       lap->daddr = DEV_ADDR_ANY;
        lap->lsaps = hashbin_new( HB_GLOBAL);
        lap->cachelog = hashbin_new( HB_LOCAL);
 
        irlmp_next_lap_state( lap, LAP_STANDBY);
        
+       init_timer(&lap->idle_timer);
+
        /*
         *  Insert into queue of unconnected LSAPs
         */
@@ -309,20 +318,22 @@ void irlmp_register_irlap( struct irlap_cb *irlap, __u32 saddr,
  *    IrLAP layer has been removed!
  *
  */
-void irlmp_unregister_irlap( __u32 saddr)
+void irlmp_unregister_irlap(__u32 saddr)
 {
        struct lap_cb *self;
 
-       DEBUG( 4, __FUNCTION__ "()\n");
+       DEBUG(4, __FUNCTION__ "()\n");
 
-       self = hashbin_remove( irlmp->links, saddr, NULL);
-       if ( self != NULL) {
-               ASSERT( self->magic == LMP_LAP_MAGIC, return;);
+       self = hashbin_remove(irlmp->links, saddr, NULL);
+       if (self) {
+               ASSERT(self->magic == LMP_LAP_MAGIC, return;);
 
-               self->magic = ~LMP_LAP_MAGIC;
-               kfree( self);
+               del_timer(&self->idle_timer);   
+
+               self->magic = 0;
+               kfree(self);
        } else {
-               DEBUG( 0, "irlmp_unregister_irlap(), Didn't find LAP!\n");
+               DEBUG(1, __FUNCTION__ "(), Didn't find LAP layer!\n");
        }
 }
 
@@ -334,98 +345,123 @@ void dump_discoveries( hashbin_t *log)
 
        d = (DISCOVERY *) hashbin_get_first( log);
        while( d != NULL) {
-               DEBUG( 0, "Discovery:\n");
-               DEBUG( 0, "  daddr=%08x\n", d->daddr);
-               DEBUG( 0, "  name=%s\n", d->info);
+               DEBUG( 1, "Discovery:\n");
+               DEBUG( 1, "  daddr=%08x\n", d->daddr);
+               DEBUG( 1, "  name=%s\n", d->info);
 
                d = (DISCOVERY *) hashbin_get_next( log);
        }
 }
 
+static struct lap_cb *irlmp_find_link( __u32 daddr)
+{
+       struct lap_cb *lap;
+       unsigned long flags;
+
+       DEBUG( 1, __FUNCTION__ 
+              "(), client didn't supply saddr, so try to look it up!\n");
+
+       /* 
+        *  Find out which link to connect on, and make sure nothing strange
+        *  happens while we traverse the list
+        */
+       save_flags( flags);
+       cli();
+
+       lap = (struct lap_cb *) hashbin_get_first( irlmp->links);
+       while ( lap != NULL) {
+               ASSERT( lap->magic == LMP_LAP_MAGIC, return NULL;);
+               /* dump_discoveries( lap->cachelog); */
+
+               if ( hashbin_find( lap->cachelog, daddr, NULL)) {
+                       DEBUG( 4, __FUNCTION__
+                              "() found link to connect on!\n");
+                       return lap;
+               }
+               lap = (struct lap_cb *) hashbin_get_next( irlmp->links);
+       }
+       restore_flags(flags);
+
+       return NULL;
+}
+
 /*
  * Function irlmp_connect_request (handle, dlsap, userdata)
  *
  *    Connect with a peer LSAP  
  *
  */
-void irlmp_connect_request( struct lsap_cb *self, __u8 dlsap_sel, __u32 daddr, 
-                           struct qos_info *qos, struct sk_buff *userdata) 
+int irlmp_connect_request(struct lsap_cb *self, __u8 dlsap_sel, 
+                         __u32 saddr, __u32 daddr, 
+                         struct qos_info *qos, struct sk_buff *userdata) 
 {
        struct sk_buff *skb = NULL;
        struct lap_cb *lap;
        struct lsap_cb *lsap;
-       unsigned long flags;
 
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
+       ASSERT( self != NULL, return -1;);
+       ASSERT( self->magic == LMP_LSAP_MAGIC, return -1;);
+       
+       DEBUG( 4, __FUNCTION__ 
+              "(), slsap_sel=%02x, dlsap_sel=%02x, saddr=%08x, daddr=%08x\n", 
+              self->slsap_sel, dlsap_sel, saddr, daddr);
        
-       DEBUG( 4, "irlmp_connect_request(), "
-              "slsap_sel=%02x, dlsap_sel=%02x, daddr=%08x\n", 
-              self->slsap_sel, dlsap_sel, daddr);
-
        if ( self->connected) {
-               DEBUG( 0, __FUNCTION__ "(), Error: already connected!!\n");
+               DEBUG( 1, __FUNCTION__ "(), Error: already connected!!\n");
                
-               return;
+               return -EISCONN;
        }
 
        /* Any userdata? */
        if ( userdata == NULL) {
                skb = dev_alloc_skb( 64);
                if (skb == NULL) {
-                       DEBUG( 0, __FUNCTION__ 
+                       DEBUG( 1, __FUNCTION__ 
                               "(), Could not allocate sk_buff of length %d\n",
                               64);
-                       return;
+                       return -1;
                }
                skb_reserve( skb, LMP_CONTROL_HEADER+LAP_HEADER);
        } else
                skb = userdata;
        
        /* Make room for MUX control header ( 3 bytes) */
-       ASSERT( skb_headroom( skb) >= LMP_CONTROL_HEADER, return;);
+       ASSERT( skb_headroom( skb) >= LMP_CONTROL_HEADER, return -1;);
        skb_push( skb, LMP_CONTROL_HEADER);
 
        self->dlsap_sel = dlsap_sel;
        self->tmp_skb = skb;
        
-       /* 
-        *  Find out which link to connect on, and make sure nothing strange
-        *  happens while we traverse the list
+       /*  
+        * Find the link to where we should try to connect since there may
+        * be more than one IrDA port on this machine. If the client has
+        * passed us the saddr (and already knows which link to use), then
+        * we use that to find the link, if not then we have to look in the
+        * discovery log and check if any of the links has discovered a
+        * device with the given daddr 
         */
-       save_flags( flags);
-       cli();
-
-       lap = (struct lap_cb *) hashbin_get_first( irlmp->links);
-       while ( lap != NULL) {
-               ASSERT( lap->magic == LMP_LAP_MAGIC, return;);
-               /* dump_discoveries( lap->cachelog); */
-
-               if ( hashbin_find( lap->cachelog, daddr, NULL)) {
-                       DEBUG( 4, "irlmp_connect_request() found link to connect on!\n");
-                       self->lap = lap;
-                       break;
-               }
-               lap = (struct lap_cb *) hashbin_get_next( irlmp->links);
-       }
-       restore_flags(flags);
+       if ( saddr)
+               lap = hashbin_find( irlmp->links, saddr, NULL);
+       else
+               lap = irlmp_find_link( daddr);
        
+       if ( lap == NULL) {
+               DEBUG( 1, __FUNCTION__ "(), Unable to find a usable link!\n");
+               
+               return -EHOSTUNREACH;
+       }
+       self->lap = lap;
+
        /* 
         *  Remove LSAP from list of unconnected LSAPs and insert it into the 
         *  list of connected LSAPs for the particular link */
        lsap = hashbin_remove( irlmp->unconnected_lsaps, self->slsap_sel, 
                               NULL);
 
-       /* Check if we found a link to connect on */
-       if ( self->lap == NULL) {
-               DEBUG( 0, __FUNCTION__ "(), Unable to find a usable link!\n");
-               return;
-       }
-
-       ASSERT( lsap != NULL, return;);
-       ASSERT( lsap->magic == LMP_LSAP_MAGIC, return;);
-       ASSERT( lsap->lap != NULL, return;);
-       ASSERT( lsap->lap->magic == LMP_LAP_MAGIC, return;);
+       ASSERT( lsap != NULL, return -1;);
+       ASSERT( lsap->magic == LMP_LSAP_MAGIC, return -1;);
+       ASSERT( lsap->lap != NULL, return -1;);
+       ASSERT( lsap->lap->magic == LMP_LAP_MAGIC, return -1;);
 
        hashbin_insert( self->lap->lsaps, (QUEUE *) self, self->slsap_sel, 
                        NULL);
@@ -435,13 +471,15 @@ void irlmp_connect_request( struct lsap_cb *self, __u8 dlsap_sel, __u32 daddr,
        /*
         *  User supplied qos specifications?
         */
-       if ( qos)
+       if (qos)
                self->qos = *qos;
        
        DEBUG( 4, "*** Connecting SLSAP=%02x, DLSAP= %02x\n",
               self->slsap_sel, self->dlsap_sel);
        
        irlmp_do_lsap_event( self, LM_CONNECT_REQUEST, skb);
+
+       return 0;
 }
 
 /*
@@ -454,7 +492,7 @@ void irlmp_connect_indication( struct lsap_cb *self, struct sk_buff *skb)
 {
        int max_seg_size;
 
-       DEBUG( 4, "irlmp_connect_indication()\n");
+       DEBUG( 4, __FUNCTION__ "()\n");
        
        ASSERT( self != NULL, return;);
        ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
@@ -470,9 +508,8 @@ void irlmp_connect_indication( struct lsap_cb *self, struct sk_buff *skb)
        skb_pull( skb, LMP_CONTROL_HEADER);
 
        if ( self->notify.connect_indication)
-               self->notify.connect_indication( self->notify.instance, self, 
-                                                &self->qos, max_seg_size, 
-                                                skb);
+               self->notify.connect_indication(self->notify.instance, self, 
+                                               &self->qos, max_seg_size, skb);
 }
 
 /*
@@ -483,7 +520,7 @@ void irlmp_connect_indication( struct lsap_cb *self, struct sk_buff *skb)
  */
 void irlmp_connect_response( struct lsap_cb *self, struct sk_buff *userdata) 
 {
-       DEBUG( 4, "irlmp_connect_response()\n");
+       DEBUG( 4, __FUNCTION__ "()\n");
        
        ASSERT( self != NULL, return;);
        ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
@@ -541,14 +578,14 @@ void irlmp_disconnect_request( struct lsap_cb *self, struct sk_buff *userdata)
 {
        struct lsap_cb *lsap;
 
-       DEBUG( 4, "irlmp_disconnect_request()\n");
+       DEBUG( 4, __FUNCTION__ "()\n");
 
        ASSERT( self != NULL, return;);
        ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
 
        /* Already disconnected? */
        if ( !self->connected) {
-               DEBUG( 0, __FUNCTION__ "(), already disconnected!\n");
+               DEBUG( 1, __FUNCTION__ "(), already disconnected!\n");
                return;
        }
 
@@ -596,20 +633,20 @@ void irlmp_disconnect_indication( struct lsap_cb *self, LM_REASON reason,
 {
        struct lsap_cb *lsap;
 
-       DEBUG( 4, __FUNCTION__ "()\n"); 
+       DEBUG( 1, __FUNCTION__ "(), reason=%s\n", lmp_reasons[reason]); 
 
        ASSERT( self != NULL, return;);
        ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
        ASSERT( self->connected == TRUE, return;); 
 
-       DEBUG( 4, __FUNCTION__ "(), slsap_sel=%02x, dlsap_sel=%02x\n", 
+       DEBUG( 3, __FUNCTION__ "(), slsap_sel=%02x, dlsap_sel=%02x\n", 
               self->slsap_sel, self->dlsap_sel);
 
        self->connected = FALSE;
        self->dlsap_sel = LSAP_ANY;
 
        /* 
-        *  Remove assosiation betwen this LSAP and the kink it used 
+        *  Remove association between this LSAP and the link it used 
         */
        ASSERT( self->lap != NULL, return;);
        ASSERT( self->lap->lsaps != NULL, return;);
@@ -622,11 +659,6 @@ void irlmp_disconnect_indication( struct lsap_cb *self, LM_REASON reason,
                        lsap->slsap_sel, NULL);
 
        self->lap = NULL;
-
-       /* FIXME: the reasons should be extracted somewhere else? */
-       if ( userdata) {
-               DEBUG( 4, __FUNCTION__ "(), reason=%02x\n", userdata->data[3]);
-       }
        
        /*
         *  Inform service user
@@ -647,13 +679,18 @@ void irlmp_discovery_request( int nslots)
 {
        struct lap_cb *lap;
 
-       DEBUG( 4, __FUNCTION__ "()\n");
+       DEBUG( 4, __FUNCTION__ "(), nslots=%d\n", nslots);
 
        ASSERT( irlmp != NULL, return;);
 
        if ( !sysctl_discovery)
                return;
 
+       if ((nslots != 1)&&(nslots != 6)&&(nslots != 8)&&(nslots != 16)) {
+               DEBUG( 1, __FUNCTION__ "(), invalid number of slots value!\n");
+               nslots = sysctl_discovery_slots = 8;
+       }
+
        /*
         *  Construct new discovery info to be used by IrLAP,
         *  TODO: no need to do this every time!
@@ -670,6 +707,7 @@ void irlmp_discovery_request( int nslots)
        
        strncpy( irlmp->discovery_cmd.info, sysctl_devname, 31);
        irlmp->discovery_cmd.info_len = strlen( irlmp->discovery_cmd.info);
+       irlmp->discovery_cmd.nslots = nslots;
        
        /*
         * Try to send discovery packets on all links
@@ -678,7 +716,7 @@ void irlmp_discovery_request( int nslots)
        while ( lap != NULL) {
                ASSERT( lap->magic == LMP_LAP_MAGIC, return;);
 
-               DEBUG( 4, "irlmp_discovery_request() sending request!\n");
+               DEBUG( 4, __FUNCTION__ "() sending request!\n");
                irlmp_do_lap_event( lap, LM_LAP_DISCOVERY_REQUEST, NULL);
                
                lap = ( struct lap_cb *) hashbin_get_next( irlmp->links);
@@ -698,8 +736,8 @@ void irlmp_check_services( DISCOVERY *discovery)
        __u8 *service;
        int i = 0;
 
-       printk( KERN_INFO "IrDA Discovered: %s\n", discovery->info);
-       printk( KERN_INFO "    Services: ");
+       DEBUG(1, "IrDA Discovered: %s\n", discovery->info);
+       DEBUG(1, "    Services: ");
 
        service = irlmp_hint_to_service( discovery->hint);
        if (service != NULL) {
@@ -712,7 +750,7 @@ void irlmp_check_services( DISCOVERY *discovery)
                                              service[i], NULL);
                        if ( entry && entry->discovery_callback) {
                                DEBUG( 4, "discovery_callback!\n");
-                                       entry->discovery_callback( discovery);
+                               entry->discovery_callback( discovery);
                        } else {
                                /* 
                                 * Found no clients for dealing with this
@@ -783,11 +821,6 @@ void irlmp_discovery_indication( struct lap_cb *self, DISCOVERY *discovery)
        DEBUG( 4, "discovery->daddr = 0x%08x\n", discovery->daddr); 
        self->daddr = discovery->daddr;
 
-       /*
-        *  Create a new discovery log if neccessary
-        */
-       /* if ( self->cachelog == NULL) */
-/*             self->cachelog = hashbin_new( HB_LOCAL); */
        ASSERT( self->cachelog != NULL, return;);
 
        /*
@@ -858,7 +891,7 @@ void irlmp_data_request( struct lsap_cb *self, struct sk_buff *skb)
  */
 void irlmp_data_indication( struct lsap_cb *self, struct sk_buff *skb) 
 {
-       DEBUG( 4, "irlmp_data_indication()\n"); 
+       DEBUG( 4, __FUNCTION__ "()\n"); 
 
        ASSERT( self != NULL, return;);
        ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
@@ -877,13 +910,11 @@ void irlmp_data_indication( struct lsap_cb *self, struct sk_buff *skb)
  *    
  *
  */
-void irlmp_udata_request( struct lsap_cb *self, struct sk_buff *skb) 
+inline void irlmp_udata_request( struct lsap_cb *self, struct sk_buff *skb) 
 {
        DEBUG( 4, __FUNCTION__ "()\n"); 
 
        ASSERT( skb != NULL, return;);
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
        
        /* Make room for MUX header */
        ASSERT( skb_headroom( skb) >= LMP_HEADER, return;);
@@ -922,7 +953,7 @@ void irlmp_udata_indication( struct lsap_cb *self, struct sk_buff *skb)
  */
 void irlmp_connectionless_data_request( struct sk_buff *skb)
 {
-       DEBUG( 0, __FUNCTION__ "(), Sorry not implemented\n"); 
+       DEBUG( 1, __FUNCTION__ "(), Sorry not implemented\n"); 
 }
 
 /*
@@ -933,12 +964,12 @@ void irlmp_connectionless_data_request( struct sk_buff *skb)
  */
 void irlmp_connectionless_data_indication( struct sk_buff *skb)
 {
-       DEBUG( 0, __FUNCTION__ "()\n"); 
+       DEBUG( 1, __FUNCTION__ "()\n"); 
 }
 
 void irlmp_status_request(void) 
 {
-       DEBUG( 0, "irlmp_status_request(), Not implemented\n");
+       DEBUG( 1, "irlmp_status_request(), Not implemented\n");
 }
 
 void irlmp_status_indication( LINK_STATUS link, LOCK_STATUS lock) 
@@ -952,38 +983,41 @@ void irlmp_status_indication( LINK_STATUS link, LOCK_STATUS lock)
  *    Returns a list of all servics contained in the given hint bits. This
  *    funtion assumes that the hint bits have the size of two bytes only
  */
-__u8 *irlmp_hint_to_service( __u8 *hint)
+__u8 *irlmp_hint_to_service(__u8 *hint)
 {
        __u8 *service;
        int i = 0;
 
-       /* Allocate array to store services in */
+       /* 
+        * Allocate array to store services in. 16 entries should be safe 
+        * since we currently only support 2 hint bytes
+        */
        service = kmalloc( 16, GFP_ATOMIC);
        if ( !service) {
-               DEBUG( 0, "irlmp_hint_to_service: Unable to kmalloc!\n");
+               DEBUG(1, __FUNCTION__ "(), Unable to kmalloc!\n");
                return NULL;
        }
 
        if ( !hint[0]) {
-               printk( "<None>\n");
+               DEBUG(1, "<None>\n");
                return NULL;
        }
        if ( hint[0] & HINT_PNP)
-               printk( "PnP Compatible ");
+               DEBUG(1, "PnP Compatible ");
        if ( hint[0] & HINT_PDA)
-               printk( "PDA/Palmtop ");
+               DEBUG(1, "PDA/Palmtop ");
        if ( hint[0] & HINT_COMPUTER)
-               printk( "Computer ");
+               DEBUG(1, "Computer ");
        if ( hint[0] & HINT_PRINTER) {
-               printk( "Printer\n");
+               DEBUG(1, "Printer ");
                service[i++] = S_PRINTER;
        }
        if ( hint[0] & HINT_MODEM)
-               printk( "Modem ");
+               DEBUG(1, "Modem ");
        if ( hint[0] & HINT_FAX)
-               printk( "Fax ");
+               DEBUG(1, "Fax ");
        if ( hint[0] & HINT_LAN) {
-               printk( "LAN Access\n");                        
+               DEBUG(1, "LAN Access ");                
                service[i++] = S_LAN;
        }
        /* 
@@ -992,22 +1026,22 @@ __u8 *irlmp_hint_to_service( __u8 *hint)
         *  (IrLMP p. 29)
         */
        if ( hint[0] & HINT_EXTENSION) {
-               if ( hint[1] & HINT_TELEPHONY)
-                       printk( "Telephony ");
-               
-               if ( hint[1] & HINT_FILE_SERVER)
-                       printk( "File Server ");
+               if ( hint[1] & HINT_TELEPHONY) {
+                       DEBUG(1, "Telephony ");
+                       service[i++] = S_TELEPHONY;
+               if ( hint[1] & HINT_FILE_SERVER)
+                       DEBUG(1, "File Server ");
                
                if ( hint[1] & HINT_COMM) {
-                       printk( "IrCOMM ");
+                       DEBUG(1, "IrCOMM ");
                        service[i++] = S_COMM;
                }
                if ( hint[1] & HINT_OBEX) {
-                       printk( "IrOBEX ");
+                       DEBUG(1, "IrOBEX ");
                        service[i++] = S_OBEX;
                }
        }
-       printk( "\n");
+       DEBUG(1, "\n");
 
        service[i] = S_END;
        
@@ -1050,7 +1084,7 @@ void irlmp_service_to_hint( int service, __u8 *hint)
                hint[1] |= HINT_OBEX;
                break;
        default:
-               DEBUG( 0, "irlmp_service_to_hint(), Unknown service!\n");
+               DEBUG( 1, __FUNCTION__ "(), Unknown service!\n");
                break;
        }
 }
@@ -1089,7 +1123,7 @@ void irlmp_register_layer( int service, int type, int do_discovery,
        /* Make a new registration */
        entry = kmalloc( sizeof( struct irlmp_registration), GFP_ATOMIC);
        if ( !entry) {
-               DEBUG( 0, "irlmp_register(), Unable to kmalloc!\n");
+               DEBUG( 1, __FUNCTION__ "(), Unable to kmalloc!\n");
                return;
        }
 
@@ -1120,7 +1154,7 @@ void irlmp_unregister_layer( int service, int type)
        }
 
        if ( !entry) {
-               DEBUG( 0, "Unable to find entry to unregister!\n");
+               DEBUG( 1, __FUNCTION__ "Unable to find entry to unregister!\n");
                return;
        }
 
@@ -1164,7 +1198,7 @@ int irlmp_slsap_inuse( __u8 slsap_sel)
        ASSERT( irlmp->magic == LMP_MAGIC, return TRUE;);
        ASSERT( slsap_sel != LSAP_ANY, return TRUE;);
 
-       DEBUG( 4, "irlmp_slsap_inuse()\n");
+       DEBUG( 4, __FUNCTION__ "()\n");
 
        /*
         *  Check if slsap is already in use. To do this we have to loop over
@@ -1208,8 +1242,7 @@ __u8 irlmp_find_free_slsap(void)
       
        lsap_sel = irlmp->free_lsap_sel++;
 
-       DEBUG( 4, "irlmp_find_free_slsap(), picked next free lsap_sel=%02x\n",
-              lsap_sel);
+       DEBUG( 4, __FUNCTION__ "(), next free lsap_sel=%02x\n", lsap_sel);
 
        return lsap_sel;
 }
@@ -1227,21 +1260,25 @@ LM_REASON irlmp_convert_lap_reason( LAP_REASON lap_reason)
 
        switch (lap_reason) {           
        case LAP_DISC_INDICATION: /* Received a disconnect request from peer */
+               DEBUG( 1, __FUNCTION__ "(), LAP_DISC_INDICATION\n");
                reason = LM_USER_REQUEST;
                break;
        case LAP_NO_RESPONSE:    /* To many retransmits without response */
+               DEBUG( 1, __FUNCTION__ "(), LAP_NO_RESPONSE\n");
                reason = LM_LAP_DISCONNECT;
                break;
        case LAP_RESET_INDICATION:
+               DEBUG( 1, __FUNCTION__ "(), LAP_RESET_INDICATION\n");
                reason = LM_LAP_RESET;
                break;
        case LAP_FOUND_NONE:
        case LAP_MEDIA_BUSY:
        case LAP_PRIMARY_CONFLICT:
+               DEBUG( 1, __FUNCTION__ "(), LAP_FOUND_NONE, LAP_MEDIA_BUSY or LAP_PRIMARY_CONFLICT\n");
                reason = LM_CONNECT_FAILURE;
                break;
        default:
-               DEBUG( 0, __FUNCTION__ 
+               DEBUG( 1, __FUNCTION__ 
                       "(), Unknow IrLAP disconnect reason %d!\n", lap_reason);
                reason = LM_LAP_DISCONNECT;
                break;
@@ -1250,6 +1287,26 @@ LM_REASON irlmp_convert_lap_reason( LAP_REASON lap_reason)
        return reason;
 }      
 
+__u32 irlmp_get_saddr(struct lsap_cb *self)
+{
+       DEBUG(0, __FUNCTION__ "()\n");
+
+       ASSERT(self != NULL, return 0;);
+       ASSERT(self->lap != NULL, return 0;);
+
+       return self->lap->saddr;
+}
+
+__u32 irlmp_get_daddr(struct lsap_cb *self)
+{
+       DEBUG(0, __FUNCTION__ "()\n");
+
+       ASSERT(self != NULL, return 0;);
+       ASSERT(self->lap != NULL, return 0;);
+       
+       return self->lap->daddr;
+}
+
 #ifdef CONFIG_PROC_FS
 /*
  * Function irlmp_proc_read (buf, start, offset, len, unused)
@@ -1295,8 +1352,7 @@ int irlmp_proc_read( char *buf, char **start, off_t offset, int len,
                len += sprintf( buf+len, "lap state: %s, ", 
                                irlmp_state[ lap->lap_state]);
 
-               len += sprintf( buf+len, 
-                               "saddr: %#08x, daddr: %#08x, ",
+               len += sprintf( buf+len, "saddr: %#08x, daddr: %#08x, ",
                                lap->saddr, lap->daddr); 
                len += sprintf( buf+len, "\n");
 
index a1f5379588271b953617f0d9cc88176e687a8a0e..957176f94c580be29c48afbcd73ba7e304af8132 100644 (file)
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      irlmp_event.c
- * Version:       0.1
+ * Version:       0.8
  * Description:   An IrDA LMP event driver for Linux
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Sat Jan 16 22:22:29 1999
+ * Modified at:   Thu Feb 11 01:24:21 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, 
 #include <net/irda/irlmp_frame.h>
 #include <net/irda/irlmp_event.h>
 
-char *irlmp_state[] = {
+const char *irlmp_state[] = {
        "LAP_STANDBY",
        "LAP_U_CONNECT",
        "LAP_ACTIVE",
 };
 
-char *irlsap_state[] = {
+const char *irlsap_state[] = {
        "LSAP_DISCONNECTED",
        "LSAP_CONNECT",
        "LSAP_CONNECT_PEND",
@@ -47,7 +47,7 @@ char *irlsap_state[] = {
        "LSAP_SETUP_PEND",
 };
 
-static char *irlmp_event[] = {
+static const char *irlmp_event[] = {
        "LM_CONNECT_REQUEST",
        "LM_CONNECT_CONFIRM",
        "LM_CONNECT_RESPONSE",
@@ -71,6 +71,7 @@ static char *irlmp_event[] = {
        "LM_LAP_DISCONNECT_REQUEST",
        "LM_LAP_DISCOVERY_REQUEST",
        "LM_LAP_DISCOVERY_CONFIRM",
+       "LM_LAP_IDLE_TIMEOUT",
 };
 
 /* LAP Connection control proto declarations */
@@ -150,7 +151,7 @@ void irlmp_discovery_timer_expired( unsigned long data)
        
        DEBUG( 4, "IrLMP, discovery timer expired!\n");
        
-       irlmp_discovery_request( 8);
+       irlmp_discovery_request( sysctl_discovery_slots);
 
        /* Restart timer */
        irlmp_start_discovery_timer( irlmp, 300);
@@ -168,6 +169,18 @@ void irlmp_watchdog_timer_expired( unsigned long data)
        irlmp_do_lsap_event( self, LM_WATCHDOG_TIMEOUT, NULL);
 }
 
+void irlmp_idle_timer_expired(unsigned long data)
+{
+       struct lap_cb *self = (struct lap_cb *) data;
+       
+       DEBUG( 0, __FUNCTION__ "()\n");
+
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == LMP_LAP_MAGIC, return;);
+
+       irlmp_do_lap_event( self, LM_LAP_IDLE_TIMEOUT, NULL);
+}
+
 /*********************************************************************
  *
  *    LAP connection control states
@@ -207,10 +220,10 @@ static void irlmp_state_standby( struct lap_cb *self, IRLMP_EVENT event,
                irlap_connect_response( self->irlap, skb);
                break;
        case LM_LAP_CONNECT_REQUEST:
-               DEBUG( 4, "irlmp_state_standby() LS_CONNECT_REQUEST\n");
+               DEBUG(4, __FUNCTION__ "() LS_CONNECT_REQUEST\n");
 
                /* FIXME: need to set users requested QoS */
-               irlap_connect_request( self->irlap, self->daddr, NULL, 0);
+               irlap_connect_request(self->irlap, self->daddr, NULL, 0);
 
                irlmp_next_lap_state( self, LAP_U_CONNECT);
                break;
@@ -221,7 +234,7 @@ static void irlmp_state_standby( struct lap_cb *self, IRLMP_EVENT event,
                irlmp_next_lap_state( self, LAP_STANDBY);
                break;
        default:
-               DEBUG( 4, "irlmp_state_standby: Unknown event\n");
+               DEBUG(4, __FUNCTION__ "(), Unknown event\n");
                break;
        }
 }
@@ -239,7 +252,7 @@ static void irlmp_state_u_connect( struct lap_cb *self, IRLMP_EVENT event,
        struct lsap_cb *lsap;
        struct lsap_cb *lsap_current;
        
-       DEBUG( 4, __FUNCTION__ "()\n"); 
+       DEBUG(2, __FUNCTION__ "(), event=%s\n", irlmp_event[ event]);
 
        switch( event) {
        case LM_LAP_CONNECT_CONFIRM:
@@ -253,7 +266,7 @@ static void irlmp_state_u_connect( struct lap_cb *self, IRLMP_EVENT event,
                }               
                break;
        case LM_LAP_DISCONNECT_INDICATION:
-               DEBUG( 4, __FUNCTION__ "(), IRLAP_DISCONNECT_INDICATION\n");
+               DEBUG(2, __FUNCTION__ "(), IRLAP_DISCONNECT_INDICATION\n");
        
                irlmp_next_lap_state( self, LAP_STANDBY);
 
@@ -312,25 +325,31 @@ static void irlmp_state_active( struct lap_cb *self, IRLMP_EVENT event,
                 */
                lsap = ( struct lsap_cb *) hashbin_get_first( self->lsaps);
                while ( lsap != NULL) {
-                       irlmp_do_lsap_event( lsap, LM_LAP_CONNECT_CONFIRM, 
-                                            skb); 
-                       lsap = (struct lsap_cb*) hashbin_get_next(self->lsaps);
+                       irlmp_do_lsap_event(lsap, LM_LAP_CONNECT_CONFIRM, skb);
+                       lsap = (struct lsap_cb*) hashbin_get_next(self->lsaps);
                }
-               
                /* Keep state */
                break;
        case LM_LAP_DISCONNECT_REQUEST:
                DEBUG( 4, __FUNCTION__ "(), LM_LAP_DISCONNECT_REQUEST\n");
 
                /*
-                *  Need to find out if we should close IrLAP or not
+                *  Need to find out if we should close IrLAP or not. If there
+                *  is only one LSAP connection left on this link, that LSAP 
+                *  must be the one that tries to close IrLAP. It will be 
+                *  removed later and moved to the list of unconnected LSAPs
                 */
-               if ( hashbin_get_size( self->lsaps) == 0) {
-                       DEBUG( 0, __FUNCTION__ 
-                              "(), no more LSAPs so time to disconnect IrLAP\n");
-                       irlmp_next_lap_state( self, LAP_STANDBY);
-               
-                       irlap_disconnect_request( self->irlap);
+               if (hashbin_get_size(self->lsaps) == 1)
+                       irlmp_start_idle_timer(self, LM_IDLE_TIMEOUT);
+
+               break;
+       case LM_LAP_IDLE_TIMEOUT:
+               if (hashbin_get_size(self->lsaps) == 0) {
+                       DEBUG(0, __FUNCTION__ 
+                             "(), no more LSAPs so time to close IrLAP\n");
+                       irlmp_next_lap_state(self, LAP_STANDBY);
+                       
+                       irlap_disconnect_request(self->irlap);
                }
                break;
        case LM_LAP_DISCONNECT_INDICATION:
@@ -395,7 +414,6 @@ static void irlmp_state_disconnected( struct lsap_cb *self, IRLMP_EVENT event,
        case LM_CONNECT_INDICATION:
                irlmp_next_lsap_state( self, LSAP_CONNECT_PEND);
 
-
                /* 
                 *  Bind this LSAP to the IrLAP link where the connect was
                 *  received 
@@ -415,8 +433,7 @@ static void irlmp_state_disconnected( struct lsap_cb *self, IRLMP_EVENT event,
                irlmp_do_lap_event( self->lap, LM_LAP_CONNECT_REQUEST, skb);
                break;
        default:
-               /* DEBUG( 4, "irlmp_state_disconnected: Unknown event %d\n",
-                  event); */
+               DEBUG( 4, __FUNCTION__ "(), Unknown event %d\n", event);
                break;
        }
 }
@@ -448,7 +465,7 @@ static void irlmp_state_connect( struct lsap_cb *self, IRLMP_EVENT event,
                irlmp_next_lsap_state( self, LSAP_DATA_TRANSFER_READY);
                break;
        default:
-               DEBUG( 4, "irlmp_state_connect: Unknown event\n");
+               DEBUG( 4, __FUNCTION__ "(), Unknown event\n");
                break;
        }
 }
@@ -489,8 +506,7 @@ static void irlmp_state_connect_pend( struct lsap_cb *self, IRLMP_EVENT event,
                break;
                
        default:
-               DEBUG( 4, "irlmp_state_connect_pend: Unknown event %d\n", 
-                      event);
+               DEBUG( 4, __FUNCTION__ "Unknown event %d\n", event);
                break;  
        }       
 }
@@ -571,12 +587,13 @@ static void irlmp_state_dtr( struct lsap_cb *self, IRLMP_EVENT event,
                ASSERT( self->lap != NULL, return;);
                ASSERT( self->lap->magic == LMP_LAP_MAGIC, return;);
        
-               reason = irlmp_convert_lap_reason( self->lap->reason);
+               ASSERT(skb != NULL, return;);
+               ASSERT(skb->len > 3, return;);
+               reason = skb->data[3];
 
                 /* Try to close the LAP connection */
                DEBUG( 4, __FUNCTION__ "(), trying to close IrLAP\n");
-               irlmp_do_lap_event( self->lap, LM_LAP_DISCONNECT_REQUEST, 
-                                   NULL);
+               irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
 
                irlmp_disconnect_indication( self, reason, skb);
 
@@ -602,7 +619,7 @@ static void irlmp_state_setup( struct lsap_cb *self, IRLMP_EVENT event,
        ASSERT( self != NULL, return;);
        ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
 
-       DEBUG( 4, "irlmp_state_setup()\n");
+       DEBUG( 4, __FUNCTION__ "()\n");
 
        switch( event) {
        case LM_CONNECT_CONFIRM:
@@ -622,10 +639,21 @@ static void irlmp_state_setup( struct lsap_cb *self, IRLMP_EVENT event,
                ASSERT( self->lap != NULL, return;);
                ASSERT( self->lap->magic == LMP_LAP_MAGIC, return;);
                
-               reason = irlmp_convert_lap_reason( self->lap->reason);
-               
+               ASSERT(skb != NULL, return;);
+               ASSERT(skb->len > 3, return;);
+               reason = skb->data[3];
+
                irlmp_disconnect_indication( self, reason, skb);
                break;
+       case LM_WATCHDOG_TIMEOUT:
+               DEBUG( 0, __FUNCTION__ "() WATCHDOG_TIMEOUT!\n");
+               
+               ASSERT( self->lap != NULL, return;);
+               irlmp_do_lap_event( self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
+               irlmp_next_lsap_state( self, LSAP_DISCONNECTED);
+               
+               irlmp_disconnect_indication( self, LM_CONNECT_FAILURE, NULL);
+               break;
        default:
                DEBUG( 4, __FUNCTION__ "(), Unknown event %d\n", event);
                break;  
@@ -643,6 +671,7 @@ static void irlmp_state_setup( struct lsap_cb *self, IRLMP_EVENT event,
 static void irlmp_state_setup_pend( struct lsap_cb *self, IRLMP_EVENT event, 
                                    struct sk_buff *skb) 
 {
+       LM_REASON reason;
 
        DEBUG( 4, __FUNCTION__ "()\n"); 
 
@@ -656,18 +685,23 @@ static void irlmp_state_setup_pend( struct lsap_cb *self, IRLMP_EVENT event,
                                    self->tmp_skb);
                irlmp_next_lsap_state( self, LSAP_SETUP);
                break;
-       case LM_DISCONNECT_INDICATION:
-               del_timer( &self->watchdog_timer);
-
-               irlmp_next_lsap_state( self, LSAP_DISCONNECTED);
-               break;
        case LM_WATCHDOG_TIMEOUT:
                DEBUG( 0, __FUNCTION__ "() WATCHDOG_TIMEOUT!\n");
 
-               /* FIXME: should we do a disconnect_indication? */
                ASSERT( self->lap != NULL, return;);
-               irlmp_do_lap_event( self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
+               irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
+               irlmp_next_lsap_state( self, LSAP_DISCONNECTED);
+
+               irlmp_disconnect_indication( self, LM_CONNECT_FAILURE, NULL);
+               break;
+       case LM_LAP_DISCONNECT_INDICATION: /* LS_Disconnect.indication */
+               del_timer( &self->watchdog_timer);
+
                irlmp_next_lsap_state( self, LSAP_DISCONNECTED);
+               
+               reason = irlmp_convert_lap_reason( self->lap->reason);
+               
+               irlmp_disconnect_indication( self, reason, NULL);
                break;
        default:
                DEBUG( 4, __FUNCTION__ "(), Unknown event %d\n", event);
index 9d5ac0c35cc612ae2d12a5e04b80ce9a9ab04e88..bf993d4902c4833a33d4c33a624fa1451d0816e1 100644 (file)
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Aug 19 02:09:59 1997
- * Modified at:   Sat Jan 16 22:14:04 1999
+ * Modified at:   Thu Feb 18 08:48:28 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>
@@ -196,15 +196,15 @@ void irlmp_link_data_indication( struct lap_cb *self, int reliable,
  *    IrLAP has disconnected 
  *
  */
-void irlmp_link_disconnect_indication( struct lap_cb *lap, 
-                                      struct irlap_cb *irlap, 
-                                      LAP_REASON reason, 
-                                      struct sk_buff *userdata)
+void irlmp_link_disconnect_indication(struct lap_cb *lap, 
+                                     struct irlap_cb *irlap, 
+                                     LAP_REASON reason, 
+                                     struct sk_buff *userdata)
 {
-       DEBUG( 4, __FUNCTION__ "()\n");
+       DEBUG(2, __FUNCTION__ "()\n");
 
-       ASSERT( lap != NULL, return;);
-       ASSERT( lap->magic == LMP_LAP_MAGIC, return;);
+       ASSERT(lap != NULL, return;);
+       ASSERT(lap->magic == LMP_LAP_MAGIC, return;);
 
        lap->reason = reason;
 
@@ -213,7 +213,7 @@ void irlmp_link_disconnect_indication( struct lap_cb *lap,
        /*
         *  Inform station state machine
         */
-       irlmp_do_lap_event( lap, LM_LAP_DISCONNECT_INDICATION, NULL);
+       irlmp_do_lap_event(lap, LM_LAP_DISCONNECT_INDICATION, NULL);
 }
 
 /*
@@ -222,7 +222,8 @@ void irlmp_link_disconnect_indication( struct lap_cb *lap,
  *    Incoming LAP connection!
  *
  */
-void irlmp_link_connect_indication( struct lap_cb *self, struct qos_info *qos,
+void irlmp_link_connect_indication( struct lap_cb *self, __u32 saddr, 
+                                   __u32 daddr, struct qos_info *qos,
                                    struct sk_buff *skb) 
 {
        DEBUG( 4, __FUNCTION__ "()\n");
@@ -230,6 +231,10 @@ void irlmp_link_connect_indication( struct lap_cb *self, struct qos_info *qos,
        /* Copy QoS settings for this session */
        self->qos = qos;
 
+       /* Update destination device address */
+       self->daddr = daddr;
+       ASSERT(self->saddr == saddr, return;);
+
        irlmp_do_lap_event( self, LM_LAP_CONNECT_INDICATION, skb);
 }
 
index c98985cfbfe081efd7a9b8744506d029c137a645..bb3081a9c21501691348843edecd048db097dd73 100644 (file)
@@ -1,6 +1,6 @@
 /*********************************************************************
  *
- * Filename:      irlpt.c
+ * Filename:      irlpt_cli.c
  * Version:       
  * Description:   
  * Status:        Experimental.
@@ -49,18 +49,21 @@ static void irlpt_client_close(struct irlpt_cb *self);
 
 static void irlpt_client_discovery_indication( DISCOVERY *);
 
-static void irlpt_client_connect_confirm( void *instance, void *sap, 
+static void irlpt_client_connect_confirm( void *instance, 
+                                         void *sap, 
                                          struct qos_info *qos, 
                                          int max_seg_size, 
                                          struct sk_buff *skb);
-static void irlpt_client_disconnect_indication( void *instance, void *sap, 
+static void irlpt_client_disconnect_indication( void *instance, 
+                                               void *sap, 
                                                LM_REASON reason,
                                                struct sk_buff *userdata);
+static void irlpt_client_expired(unsigned long data);
 
 #if 0
 static char *rcsid = "$Id: irlpt_client.c,v 1.10 1998/11/10 22:50:57 dagb Exp $";
 #endif
-static char *version = "IrLPT, $Revision: 1.10 $/$Date: 1998/11/10 22:50:57 $ (Thomas Davis)";
+static char *version = "IrLPT client, v2 (Thomas Davis)";
 
 struct file_operations client_fops = {
        irlpt_seek,    /* seek */
@@ -102,6 +105,9 @@ static int irlpt_client_proc_read( char *buf, char **start, off_t offset,
        while( self) {
                ASSERT( self != NULL, return len;);
                ASSERT( self->magic == IRLPT_MAGIC, return len;);
+               if (self->in_use == FALSE) {
+                       break;
+               }
 
                len += sprintf(buf+len, "ifname: %s\n", self->ifname);
                len += sprintf(buf+len, "minor: %d\n", self->ir_dev.minor);
@@ -130,19 +136,20 @@ static int irlpt_client_proc_read( char *buf, char **start, off_t offset,
                        break;
                }
                
-               len += sprintf(buf+len, "service_type: %s\n", 
-                              irlpt_service_type[index]);
-               len += sprintf(buf+len, "port_type: %s\n", 
+               len += sprintf(buf+len, "service_type: %s, port type: %s\n", 
+                              irlpt_service_type[index],
                               irlpt_port_type[ self->porttype]);
-               len += sprintf(buf+len, "daddr: 0x%08x\n", self->daddr);
-               len += sprintf(buf+len, "fsm_state: %s\n", 
-                              irlpt_client_fsm_state[self->state]);
-               len += sprintf(buf+len, "retries: %d\n", self->open_retries);
-               len += sprintf(buf+len, "dlsap: %d\n", self->dlsap_sel);
 
-               len += sprintf(buf+len, "count: %d\n", self->count);
-               len += sprintf(buf+len, "rx_queue: %d\n", 
-                              skb_queue_len(&self->rx_queue));
+               len += sprintf(buf+len, "saddr: 0x%08x, daddr: 0x%08x\n", 
+                              self->saddr, self->daddr);
+               len += sprintf(buf+len, 
+                              "retries: %d, count: %d, queued packets: %d\n", 
+                              self->open_retries,
+                              self->count, self->pkt_count);
+               len += sprintf(buf+len, "slsap: %d, dlsap: %d\n", 
+                              self->slsap_sel, self->dlsap_sel);
+               len += sprintf(buf+len, "fsm state: %s\n", 
+                              irlpt_client_fsm_state[self->state]);
                len += sprintf(buf+len, "\n\n");
                
                self = (struct irlpt_cb *) hashbin_get_next( irlpt_clients);
@@ -163,7 +170,7 @@ extern struct proc_dir_entry proc_irda;
 #endif /* CONFIG_PROC_FS */
 
 /*
- * Function irlpt_init (dev)
+ * Function irlpt_client_init (dev)
  *
  *   Initializes the irlpt control structure
  *
@@ -176,7 +183,8 @@ __initfunc(int irlpt_client_init(void))
 
        irlpt_clients = hashbin_new( HB_LOCAL); 
        if ( irlpt_clients == NULL) {
-               printk( KERN_WARNING "IrLPT: Can't allocate hashbin!\n");
+               printk( KERN_WARNING 
+                       "IrLPT client: Can't allocate hashbin!\n");
                return -ENOMEM;
        }
 
@@ -195,9 +203,7 @@ __initfunc(int irlpt_client_init(void))
 
 #ifdef MODULE
 /*
- * Function irlpt_cleanup (void)
- *
- *
+ * Function irlpt_client_cleanup (void)
  *
  */
 static void irlpt_client_cleanup(void)
@@ -207,7 +213,7 @@ static void irlpt_client_cleanup(void)
        irlmp_unregister_layer( S_PRINTER, CLIENT);
 
        /*
-        *  Delete hashbin and close all irlan client instances in it
+        *  Delete hashbin and close all irlpt client instances in it
         */
        hashbin_delete( irlpt_clients, (FREE_FUNC) irlpt_client_close);
 
@@ -221,9 +227,7 @@ static void irlpt_client_cleanup(void)
 
 
 /*
- * Function irlpt_open (void)
- *
- *    This is the entry-point which starts all the fun! Currently this
+ * Function irlpt_client_open (void)
  *
  */
 static struct irlpt_cb *irlpt_client_open( __u32 daddr)
@@ -232,15 +236,24 @@ static struct irlpt_cb *irlpt_client_open( __u32 daddr)
 
        DEBUG( irlpt_client_debug, "--> "__FUNCTION__ "\n");
 
-       self = kmalloc(sizeof(struct irlpt_cb), GFP_ATOMIC);
-       if (self == NULL)
-               return NULL;
+       self = (struct irlpt_cb *) hashbin_find(irlpt_clients, daddr, NULL);
+
+       if (self == NULL) {
+               self = kmalloc(sizeof(struct irlpt_cb), GFP_ATOMIC);
+               if (self == NULL)
+                       return NULL;
+
+               memset(self, 0, sizeof(struct irlpt_cb));
 
-       memset(self, 0, sizeof(struct irlpt_cb));
+               ASSERT( self != NULL, return NULL;);
 
-       ASSERT( self != NULL, return NULL;);
+               sprintf(self->ifname, "irlpt%d", 
+                       hashbin_get_size(irlpt_clients));
+
+               hashbin_insert( irlpt_clients, (QUEUE *) self, daddr, NULL);
+
+       }
 
-       sprintf(self->ifname, "irlpt%d", hashbin_get_size(irlpt_clients));
        self->ir_dev.minor = MISC_DYNAMIC_MINOR;
        self->ir_dev.name = self->ifname;
        self->ir_dev.fops = &client_fops;
@@ -251,14 +264,13 @@ static struct irlpt_cb *irlpt_client_open( __u32 daddr)
        self->in_use = TRUE;
        self->servicetype = IRLPT_THREE_WIRE_RAW;
        self->porttype = IRLPT_SERIAL;
+       self->do_event = irlpt_client_do_event;
 
        skb_queue_head_init(&self->rx_queue);
 
        irlpt_client_next_state( self, IRLPT_CLIENT_IDLE);
 
-       hashbin_insert( irlpt_clients, (QUEUE *) self, daddr, NULL);
-
-       /*      MOD_INC_USE_COUNT; */
+       MOD_INC_USE_COUNT;
 
        DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
 
@@ -280,17 +292,15 @@ static void irlpt_client_close( struct irlpt_cb *self)
        ASSERT( self->magic == IRLPT_MAGIC, return;);
 
        while (( skb = skb_dequeue(&self->rx_queue)) != NULL) {
-               DEBUG(3, "irlpt_client_close: freeing SKB\n");
+               DEBUG(irlpt_client_debug, 
+                     __FUNCTION__ ": freeing SKB\n");
                 dev_kfree_skb( skb);
        }
 
        misc_deregister(&self->ir_dev);
+       self->in_use = FALSE;
 
-       self->magic = ~IRLPT_MAGIC;
-
-       kfree( self);
-
-       /* MOD_DEC_USE_COUNT; */
+       MOD_DEC_USE_COUNT;
 
        DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
 }
@@ -306,49 +316,51 @@ static void irlpt_client_discovery_indication( DISCOVERY *discovery)
 {
        struct irlpt_info info;
        struct irlpt_cb *self;
-       __u32 daddr;
+       __u32 daddr; /* address of remote printer */
+       __u32 saddr; /* address of local link where it was discovered */
 
        DEBUG( irlpt_client_debug, "--> " __FUNCTION__ "\n");
 
        ASSERT( irlpt_clients != NULL, return;);
        ASSERT( discovery != NULL, return;);
 
-       daddr = discovery->daddr;
+       daddr = info.daddr = discovery->daddr;
+       saddr = info.saddr = discovery->saddr;
 
        /*
         *  Check if an instance is already dealing with this device
         *  (daddr)
         */
        self = (struct irlpt_cb *) hashbin_find( irlpt_clients, daddr, NULL);
-       if ( self != NULL) {
-               ASSERT( self->magic == IRLPT_MAGIC, return;);
-               if ( self->state == IRLPT_CLIENT_IDLE) {
-                       irlpt_client_do_event( self, 
-                                              IRLPT_DISCOVERY_INDICATION, 
-                                              NULL, &info);
+       if (self == NULL || self->in_use == FALSE) {
+               DEBUG( irlpt_client_debug, __FUNCTION__ 
+                      ": daddr 0x%08x not found or was closed\n", daddr);
+               /*
+                * We have no instance for daddr, so time to start a new 
+                * instance. First we must find a free entry in master array
+                */
+               if (( self = irlpt_client_open( daddr)) == NULL) {
+                       DEBUG(irlpt_client_debug, __FUNCTION__ 
+                             ": failed!\n");
+                       return;
                }
-               return;
-       }
-    
-
-       /*
-        * We have no instance for daddr, so time to start a new instance.
-        * First we must find a free entry in master array
-        */
-       if (( self = irlpt_client_open( daddr)) == NULL) {
-               DEBUG(irlpt_client_debug, __FUNCTION__ 
-                     ":irlpt_client_open failed!\n");
        }
 
        ASSERT(self != NULL, return;);
        ASSERT(self->magic == IRLPT_MAGIC, return;);
 
-       self->daddr = info.daddr = daddr;
+       self->daddr = daddr;
+       self->saddr = saddr;
+       self->timeout = irlpt_client_expired;
+
+       irda_start_timer( &self->lpt_timer, 5000, (unsigned long) self, 
+                         self->timeout);
        
-       if (self->state == IRLPT_CLIENT_IDLE) {
-               irlpt_client_do_event( self, IRLPT_DISCOVERY_INDICATION, 
-                                      NULL, &info);
-       }
+#if 0
+       /* changed to wake up when we get connected; that way,
+          if the connection drops, we can easily kill the link. */
+       wake_up_interruptible( &self->write_wait);
+#endif
 
        DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
 }
@@ -357,7 +369,8 @@ static void irlpt_client_discovery_indication( DISCOVERY *discovery)
  * Function irlpt_disconnect_indication (handle)
  *
  */
-static void irlpt_client_disconnect_indication( void *instance, void *sap, 
+static void irlpt_client_disconnect_indication( void *instance,
+                                               void *sap, 
                                                LM_REASON reason,
                                                struct sk_buff *skb)
 {
@@ -373,8 +386,8 @@ static void irlpt_client_disconnect_indication( void *instance, void *sap,
 
        info.daddr = self->daddr;
 
-        DEBUG( irlpt_client_debug, __FUNCTION__ 
-              ": reason=%d (%s), peersap=%d\n",
+        DEBUG( irlpt_client_debug, 
+              __FUNCTION__ ": reason=%d (%s), peersap=%d\n",
               reason, irlpt_reasons[reason], self->dlsap_sel);
 
        self->connected = IRLPT_DISCONNECTED;
@@ -413,6 +426,7 @@ static void irlpt_client_connect_confirm( void *instance, void *sap,
 
        info.daddr = self->daddr;
 
+#if 0
        /*
         *  Check if we have got some QoS parameters back! This should be the
         *  negotiated QoS for the link.
@@ -421,6 +435,7 @@ static void irlpt_client_connect_confirm( void *instance, void *sap,
                DEBUG( irlpt_client_debug, __FUNCTION__ ": Frame Size: %d\n",
                       qos->data_size.value);
        }
+#endif
 
        self->irlap_data_size = (qos->data_size.value - IRLPT_MAX_HEADER);
        self->connected = TRUE;
@@ -489,7 +504,6 @@ static void irlpt_client_data_indication( void *instance, void *sap,
  *    Fixed to match changes in iriap.h, DB.
  *
  */
-
 void irlpt_client_get_value_confirm(__u16 obj_id, struct ias_value *value, 
                                    void *priv)
 {
@@ -505,10 +519,13 @@ void irlpt_client_get_value_confirm(__u16 obj_id, struct ias_value *value,
        ASSERT( self != NULL, return;);
        ASSERT( self->magic == IRLPT_MAGIC, return;);
 
-       /* can't stop here..  if we get a bad obj, must tell the state
-          machine that!
-       ASSERT( type == IAS_INTEGER, return;);
-       */
+       /* Check if request succeeded */
+       if ( !value) {
+               DEBUG( 0, __FUNCTION__ "(), got NULL value!\n");
+               irlpt_client_do_event( self, IAS_PROVIDER_NOT_AVAIL, NULL, 
+                                      &info);
+               return;
+       }
 
        if ( value->type == IAS_INTEGER && value->t.integer != -1) {
                info.dlsap_sel = value->t.integer;
@@ -518,11 +535,10 @@ void irlpt_client_get_value_confirm(__u16 obj_id, struct ias_value *value,
                       ": obj_id = %d, value = %d\n", 
                       obj_id, value->t.integer);
 
-               irlpt_client_do_event( self, IAS_PROVIDER_AVAIL, 
-                                      NULL, &info);
+               irlpt_client_do_event( self, IAS_PROVIDER_AVAIL, NULL, &info);
        } else
-               irlpt_client_do_event( self, IAS_PROVIDER_NOT_AVAIL, 
-                                      NULL, &info);
+               irlpt_client_do_event( self, IAS_PROVIDER_NOT_AVAIL, NULL, 
+                                      &info);
 
        DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
 }
@@ -536,9 +552,12 @@ void irlpt_client_connect_request( struct irlpt_cb *self)
        ASSERT( self != NULL, return;);
        ASSERT( self->magic == IRLPT_MAGIC, return;);
 
+       irda_notify_init( &lpt_notify);
+
        lpt_notify.connect_confirm = irlpt_client_connect_confirm;
        lpt_notify.disconnect_indication = irlpt_client_disconnect_indication;
        lpt_notify.data_indication = irlpt_client_data_indication;
+       strcpy( lpt_notify.name, "IrLPT client");
        lpt_notify.instance = self;
 
        self->lsap = irlmp_open_lsap( LSAP_ANY, &lpt_notify);
@@ -549,17 +568,51 @@ void irlpt_client_connect_request( struct irlpt_cb *self)
                DEBUG( irlpt_client_debug, __FUNCTION__ 
                       ": issue THREE_WIRE_RAW connect\n");
                irlmp_connect_request( self->lsap, self->dlsap_sel, 
-                                      self->daddr, NULL, NULL);
+                                      self->saddr, self->daddr, NULL, NULL);
        }
 
        DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
 }
 
+static void irlpt_client_expired(unsigned long data)
+{
+       struct irlpt_cb *self = (struct irlpt_cb *) data;
+       struct sk_buff *skb;
+
+       DEBUG( irlpt_client_debug, "--> " __FUNCTION__ "\n");
+
+       DEBUG( irlpt_client_debug, __FUNCTION__
+              ": removing irlpt_cb!\n");
+
+       ASSERT(self != NULL, return; );
+       ASSERT(self->magic == IRLPT_MAGIC, return;);
+
+       if (self->state == IRLPT_CLIENT_CONN) {
+               skb = dev_alloc_skb(64);
+               if (skb == NULL) {
+                       DEBUG( 0, __FUNCTION__ "(: Could not allocate an "
+                              "sk_buff of length %d\n", 64);
+                       return;
+               }
+
+               skb_reserve( skb, LMP_CONTROL_HEADER+LAP_HEADER);
+               irlmp_disconnect_request(self->lsap, skb);
+               DEBUG(irlpt_client_debug, __FUNCTION__
+                     ": irlmp_close_slap(self->lsap)\n");
+               irlmp_close_lsap(self->lsap);
+       }
+
+       irlpt_client_close(self);
+
+       DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
+}
 
 #ifdef MODULE
 
 MODULE_AUTHOR("Thomas Davis <ratbert@radiks.net>");
-MODULE_DESCRIPTION("The Linux IrDA/IrLPT protocol");
+MODULE_DESCRIPTION("The Linux IrDA/IrLPT client protocol");
+MODULE_PARM(irlpt_client_debug,"1i");
+MODULE_PARM(irlpt_client_fsm_debug,"1i");
 
 /*
  * Function init_module (void)
@@ -570,11 +623,11 @@ MODULE_DESCRIPTION("The Linux IrDA/IrLPT protocol");
 int init_module(void)
 {
 
-        DEBUG( irlpt_client_debug, "--> irlpt client: init_module\n");
+        DEBUG( irlpt_client_debug, "--> IrLPT client: init_module\n");
 
         irlpt_client_init();
 
-        DEBUG( irlpt_client_debug, "irlpt client: init_module -->\n");
+        DEBUG( irlpt_client_debug, "IrLPT client: init_module -->\n");
 
         return 0;
 }
@@ -587,13 +640,13 @@ int init_module(void)
  */
 void cleanup_module(void)
 {
-        DEBUG( irlpt_client_debug, "--> irlpt client: cleanup_module\n");
+        DEBUG( irlpt_client_debug, "--> IrLPT client: cleanup_module\n");
         /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
 
         /* Free some memory */
         irlpt_client_cleanup();
 
-        DEBUG( irlpt_client_debug, "irlpt client: cleanup_module -->\n");
+        DEBUG( irlpt_client_debug, "IrLPT client: cleanup_module -->\n");
 }
 
 #endif /* MODULE */
index 6362756a20b53a1222a7e43ba9cb2d8da26b0ded..75598742aa88538a6de2d9f9d69363c1e2a55702 100644 (file)
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Jan 12 11:06:00 1999
- * Modified at:   Tue Jan 12 11:14:22 1999
+ * Modified at:   Tue Jan 26 12:02:31 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998, Thomas Davis, <ratbert@radiks.net>
 static char *rcsid = "$Id: irlpt_client_fsm.c,v 1.3 1998/10/05 05:46:44 ratbert Exp $";
 #endif
 
-static int irlpt_client_state_idle  ( struct irlpt_cb *self, IRLPT_EVENT event,
+static int irlpt_client_state_idle  ( struct irlpt_cb *self, 
+                                     IRLPT_EVENT event,
                                      struct sk_buff *skb, 
                                      struct irlpt_info *info);
-static int irlpt_client_state_query ( struct irlpt_cb *self, IRLPT_EVENT event,
+static int irlpt_client_state_query ( struct irlpt_cb *self, 
+                                     IRLPT_EVENT event,
                                      struct sk_buff *skb, 
                                      struct irlpt_info *info);
 static int irlpt_client_state_ready  ( struct irlpt_cb *self, 
                                       IRLPT_EVENT event, 
                                       struct sk_buff *skb, 
                                       struct irlpt_info *info);
-static int irlpt_client_state_waiti ( struct irlpt_cb *self, IRLPT_EVENT event,
+static int irlpt_client_state_waiti ( struct irlpt_cb *self, 
+                                     IRLPT_EVENT event,
                                      struct sk_buff *skb, 
                                      struct irlpt_info *info);
-static int irlpt_client_state_waitr ( struct irlpt_cb *self, IRLPT_EVENT event,
-                                     struct sk_buff *skb, 
-                                     struct irlpt_info *info);
-static int irlpt_client_state_conn  ( struct irlpt_cb *self, IRLPT_EVENT event,
+static int irlpt_client_state_conn  ( struct irlpt_cb *self, 
+                                     IRLPT_EVENT event,
                                      struct sk_buff *skb, 
                                      struct irlpt_info *info);
 
-int irlpt_client_fsm_debug = 3;
+int irlpt_client_fsm_debug = 4;
 
-int (*irlpt_client_state[])( struct irlpt_cb *self, IRLPT_EVENT event, 
-                                   struct sk_buff *skb, 
-                                   struct irlpt_info *info) = 
+int (*irlpt_client_state[])( struct irlpt_cb *self, 
+                            IRLPT_EVENT event, 
+                            struct sk_buff *skb, 
+                            struct irlpt_info *info) = 
 { 
        irlpt_client_state_idle,
        irlpt_client_state_query,
        irlpt_client_state_ready,
        irlpt_client_state_waiti,
-       irlpt_client_state_waitr,
        irlpt_client_state_conn,
 };
 
-void irlpt_client_do_event( struct irlpt_cb *self, IRLPT_EVENT event, 
-                                  struct sk_buff *skb, 
-                                  struct irlpt_info *info) 
+void irlpt_client_do_event( struct irlpt_cb *self, 
+                           IRLPT_EVENT event, 
+                           struct sk_buff *skb, 
+                           struct irlpt_info *info) 
 {
-       DEBUG( irlpt_client_fsm_debug,"--> "  __FUNCTION__ "\n");
+       DEBUG( irlpt_client_fsm_debug, "--> "  __FUNCTION__ "\n");
 
        ASSERT( self != NULL, return;);
        ASSERT( self->magic == IRLPT_MAGIC, return;);
 
-       DEBUG( irlpt_client_fsm_debug, __FUNCTION__ ": STATE = %s, EVENT = %s\n", 
+       DEBUG( irlpt_client_fsm_debug, 
+              __FUNCTION__ ": STATE = %s, EVENT = %s\n", 
               irlpt_server_fsm_state[self->state], irlpt_fsm_event[event]);
 
        (*irlpt_client_state[ self->state]) ( self, event, skb, info);
@@ -86,9 +89,10 @@ void irlpt_client_do_event( struct irlpt_cb *self, IRLPT_EVENT event,
        DEBUG( irlpt_client_fsm_debug, __FUNCTION__ " -->\n");
 }
 
-void irlpt_client_next_state( struct irlpt_cb *self, IRLPT_CLIENT_STATE state) 
+void irlpt_client_next_state( struct irlpt_cb *self, 
+                             IRLPT_CLIENT_STATE state) 
 {
-       DEBUG( irlpt_client_fsm_debug,"--> "  __FUNCTION__ ":\n");
+       DEBUG( irlpt_client_fsm_debug, "--> "  __FUNCTION__ ":\n");
 
        ASSERT( self != NULL, return;);
        ASSERT( self->magic == IRLPT_MAGIC, return;);
@@ -102,16 +106,17 @@ void irlpt_client_next_state( struct irlpt_cb *self, IRLPT_CLIENT_STATE state)
 }
 
 /*
- * Function client_state_idle (event, skb, info)
+ * Function irlpt_client_state_idle (self, event, skb, info)
  *
  *    IDLE, We are waiting for an indication that there is a provider
  *    available.
  */
-static int irlpt_client_state_idle( struct irlpt_cb *self, IRLPT_EVENT event, 
+static int irlpt_client_state_idle( struct irlpt_cb *self, 
+                                   IRLPT_EVENT event, 
                                    struct sk_buff *skb, 
                                    struct irlpt_info *info) 
 {
-       DEBUG( irlpt_client_fsm_debug,"--> "  __FUNCTION__ ":\n");
+       DEBUG( irlpt_client_fsm_debug, "--> "  __FUNCTION__ ":\n");
 
        ASSERT( self != NULL, return -1;);
        ASSERT( self->magic == IRLPT_MAGIC, return -1;);
@@ -120,11 +125,13 @@ static int irlpt_client_state_idle( struct irlpt_cb *self, IRLPT_EVENT event,
        case IRLPT_DISCOVERY_INDICATION:
                /* Get some values from peer IAS */
                DEBUG( irlpt_client_fsm_debug, __FUNCTION__ 
-                      ": IRLPT_DISCOVERY_INDICATION, sending getvaluebyclass command..\n");
-               iriap_getvaluebyclass_request( info->daddr, 
-                                       "IrLPT", "IrDA:IrLMP:LsapSel",
-                                       irlpt_client_get_value_confirm,
-                                       (void *) self);
+                      ": IRLPT_DISCOVERY_INDICATION, "
+                      "sending getvaluebyclass command..\n");
+               iriap_getvaluebyclass_request( 
+                       "IrLPT", "IrDA:IrLMP:LsapSel",
+                       info->saddr, info->daddr,
+                       irlpt_client_get_value_confirm,
+                       (void *) self);
                irlpt_client_next_state( self, IRLPT_CLIENT_QUERY);
                break;
 
@@ -145,36 +152,53 @@ static int irlpt_client_state_idle( struct irlpt_cb *self, IRLPT_EVENT event,
 }
 
 /*
- * Function client_state_query
+ * Function irlpt_client_state_query
  *
  *    QUERY, We have queryed the remote IAS and is ready to connect
  *    to provider, just waiting for the confirm.
  *
  */
-static int irlpt_client_state_query( struct irlpt_cb *self, IRLPT_EVENT event, 
+static int irlpt_client_state_query( struct irlpt_cb *self, 
+                                    IRLPT_EVENT event, 
                                     struct sk_buff *skb, 
                                     struct irlpt_info *info) 
 {
-       DEBUG( irlpt_client_fsm_debug,"--> "  __FUNCTION__ ":\n");
+       DEBUG( irlpt_client_fsm_debug, "--> "  __FUNCTION__ ":\n");
 
        ASSERT( self != NULL, return -1;);
        ASSERT( self->magic == IRLPT_MAGIC, return -1;);
 
        switch( event) {
        case IAS_PROVIDER_AVAIL:
-               DEBUG( irlpt_client_fsm_debug, __FUNCTION__ ": IAS_PROVIDER_AVAIL\n");
+               DEBUG( irlpt_client_fsm_debug, 
+                      __FUNCTION__ ": IAS_PROVIDER_AVAIL\n");
                self->open_retries = 0;
                irlpt_client_next_state( self, IRLPT_CLIENT_READY);
-               irlpt_client_do_event( self, IRLPT_CONNECT_REQUEST, NULL, NULL);
+               irlpt_client_do_event( self, IRLPT_CONNECT_REQUEST, 
+                                      NULL, NULL);
                break;
 
        case IAS_PROVIDER_NOT_AVAIL:
-               DEBUG( irlpt_client_fsm_debug, __FUNCTION__ ": IAS_PROVIDER_NOT_AVAIL\n");
+               DEBUG( irlpt_client_fsm_debug, 
+                      __FUNCTION__ ": IAS_PROVIDER_NOT_AVAIL\n");
                irlpt_client_next_state( self, IRLPT_CLIENT_IDLE);
+               DEBUG(irlpt_client_fsm_debug, __FUNCTION__
+                     ": waking any sleepers..\n");
+               wake_up_interruptible(&self->read_wait);
                break;
 
+       case LMP_DISCONNECT:
+       case LAP_DISCONNECT:
+               DEBUG( irlpt_client_fsm_debug, __FUNCTION__ 
+                      ": LMP_DISCONNECT or LAP_DISCONNECT\n");
+               irlpt_client_next_state( self, IRLPT_CLIENT_IDLE);
+               DEBUG(irlpt_client_fsm_debug, __FUNCTION__
+                     ": waking any sleepers..\n");
+               wake_up_interruptible(&self->read_wait);
+               break;
        default:
-               DEBUG( irlpt_client_fsm_debug, __FUNCTION__ ": Unknown event %d (%s)\n",
+               DEBUG( irlpt_client_fsm_debug, 
+                      __FUNCTION__ ": Unknown event %d (%s)\n",
                       event, irlpt_fsm_event[event]);
                break;
        }
@@ -189,11 +213,12 @@ static int irlpt_client_state_query( struct irlpt_cb *self, IRLPT_EVENT event,
 }
 
 /*
- * Function client_state_info 
+ * Function irlpt_client_state_info 
  *
  *    INFO, We have issued a GetInfo command and is awaiting a reply.
  */
-static int irlpt_client_state_ready( struct irlpt_cb *self, IRLPT_EVENT event,
+static int irlpt_client_state_ready( struct irlpt_cb *self, 
+                                    IRLPT_EVENT event,
                                     struct sk_buff *skb, 
                                     struct irlpt_info *info) 
 {
@@ -204,8 +229,8 @@ static int irlpt_client_state_ready( struct irlpt_cb *self, IRLPT_EVENT event,
 
        switch( event) {
        case IRLPT_CONNECT_REQUEST:
-               DEBUG( irlpt_client_fsm_debug, __FUNCTION__ 
-                      ": IRLPT_CONNECT_REQUEST\n");
+               DEBUG( irlpt_client_fsm_debug, 
+                      __FUNCTION__ ": IRLPT_CONNECT_REQUEST\n");
                irlpt_client_connect_request(self);
                irlpt_client_next_state( self, IRLPT_CLIENT_WAITI);
                break;
@@ -213,6 +238,9 @@ static int irlpt_client_state_ready( struct irlpt_cb *self, IRLPT_EVENT event,
        case LAP_DISCONNECT:
                DEBUG( irlpt_client_fsm_debug, __FUNCTION__ 
                       ": LMP_DISCONNECT or LAP_DISCONNECT\n");
+               DEBUG(irlpt_client_fsm_debug, __FUNCTION__
+                     ": waking any sleepers..\n");
+               wake_up_interruptible(&self->read_wait);
                irlpt_client_next_state( self, IRLPT_CLIENT_IDLE);
                break;
        default:
@@ -233,11 +261,12 @@ static int irlpt_client_state_ready( struct irlpt_cb *self, IRLPT_EVENT event,
 
 
 /*
- * Function client_state_waiti 
+ * Function irlpt_client_state_waiti 
  *
  *
  */
-static int irlpt_client_state_waiti( struct irlpt_cb *self, IRLPT_EVENT event, 
+static int irlpt_client_state_waiti( struct irlpt_cb *self, 
+                                    IRLPT_EVENT event, 
                                     struct sk_buff *skb, 
                                     struct irlpt_info *info) 
 {
@@ -250,10 +279,17 @@ static int irlpt_client_state_waiti( struct irlpt_cb *self, IRLPT_EVENT event,
        case LMP_CONNECT:
                DEBUG( irlpt_client_fsm_debug, __FUNCTION__ ": LMP_CONNECT\n");
                irlpt_client_next_state(self, IRLPT_CLIENT_CONN);
+               DEBUG(irlpt_client_fsm_debug, __FUNCTION__
+                     ": waking any sleepers..\n");
+               wake_up_interruptible(&self->read_wait);
                break;
        case LAP_DISCONNECT:
        case LMP_DISCONNECT:
-               DEBUG( irlpt_client_fsm_debug, __FUNCTION__ ": LMP_DISCONNECT\n");
+               DEBUG( irlpt_client_fsm_debug, 
+                      __FUNCTION__ ": LMP_DISCONNECT\n");
+               DEBUG(irlpt_client_fsm_debug, __FUNCTION__
+                     ": waking any sleepers..\n");
+               wake_up_interruptible(&self->read_wait);
                irlpt_client_next_state( self, IRLPT_CLIENT_IDLE);
                break;
 
@@ -274,63 +310,18 @@ static int irlpt_client_state_waiti( struct irlpt_cb *self, IRLPT_EVENT event,
 }
 
 /*
- * Function client_state_waitr 
- *
- *
- */
-static int irlpt_client_state_waitr( struct irlpt_cb *self, IRLPT_EVENT event,
-                                    struct sk_buff *skb, 
-                                    struct irlpt_info *info) 
-{
-       DEBUG( irlpt_client_fsm_debug,"--> "  __FUNCTION__ ":\n");
-
-       ASSERT( self != NULL, return -1;);
-       ASSERT( self->magic == IRLPT_MAGIC, return -1;);
-
-       switch( event) {
-       case LMP_CONNECT:
-               DEBUG( irlpt_client_fsm_debug, __FUNCTION__ ": LMP_CONNECT\n");
-               irlpt_client_next_state(self, IRLPT_CLIENT_CONN);
-               break;
-
-       case LMP_DISCONNECT:
-               DEBUG( irlpt_client_fsm_debug, __FUNCTION__ ": LMP_DISCONNECT\n");
-               irlpt_client_next_state( self, IRLPT_CLIENT_IDLE);
-               break;
-
-       case LAP_DISCONNECT:
-               DEBUG( irlpt_client_fsm_debug, __FUNCTION__ ": LAP_DISCONNECT\n");
-               irlpt_client_next_state( self, IRLPT_CLIENT_IDLE);
-               break;
-
-       default:
-               DEBUG( irlpt_client_fsm_debug, __FUNCTION__ 
-                      ": Unknown event %d, (%s)\n",
-                      event, irlpt_fsm_event[event]);
-               break;
-       }
-
-       if ( skb) {
-               dev_kfree_skb( skb);
-       }
-
-       DEBUG( irlpt_client_fsm_debug, __FUNCTION__ " -->\n");
-
-       return 0;
-}
-
-/*
- * Function client_state_conn (event, skb, info)
+ * Function irlpt_client_state_conn (self, event, skb, info)
  *
  *    CONN, We have connected to a provider but has not issued any
  *    commands yet.
  *
  */
-static int irlpt_client_state_conn( struct irlpt_cb *self, IRLPT_EVENT event, 
+static int irlpt_client_state_conn( struct irlpt_cb *self, 
+                                   IRLPT_EVENT event, 
                                    struct sk_buff *skb, 
                                    struct irlpt_info *info) 
 {
-       DEBUG( irlpt_client_fsm_debug,"--> "  __FUNCTION__ ":\n");
+       DEBUG( irlpt_client_fsm_debug, "--> " __FUNCTION__ ":\n");
 
        ASSERT( self != NULL, return -1;);
        ASSERT( self->magic == IRLPT_MAGIC, return -1;);
@@ -346,6 +337,10 @@ static int irlpt_client_state_conn( struct irlpt_cb *self, IRLPT_EVENT event,
        case LAP_DISCONNECT:
                DEBUG( irlpt_client_fsm_debug, __FUNCTION__ 
                       ": LMP_DISCONNECT/LAP_DISCONNECT\n");
+               DEBUG(irlpt_client_fsm_debug, __FUNCTION__
+                     ": waking any sleepers..\n");
+               wake_up_interruptible(&self->read_wait);
+               irlpt_client_next_state( self, IRLPT_CLIENT_IDLE);
                irlpt_client_next_state( self, IRLPT_CLIENT_IDLE);
                break;
 
index 886eb30a02d109657b8a54d810b06ff7214dd31e..b4512736a6da0fe07782b9f7547c1f3cddade6c4 100644 (file)
@@ -68,7 +68,7 @@ char *irlpt_connected[] = {
 
 char *irlpt_reasons[] = {
        "SERVICE_CLOSE",     /* Service has closed the connection */
-       "DISC_INDICATION",   /* Received disconnect request from peer entity*/
+       "DISC_INDICATION",   /* Received disconnect request from peer entity*/
        "NO_RESPONSE",       /* To many retransmits without response */
        "DEADLOCK_DETECTED", /* To many retransmits _with_ response */
        "FOUND_NONE",        /* No devices were discovered */
@@ -81,7 +81,6 @@ char *irlpt_client_fsm_state[] = {
        "IRLPT_CLIENT_QUERY",
        "IRLPT_CLIENT_READY",
        "IRLPT_CLIENT_WAITI",
-       "IRLPT_CLIENT_WAITR",
        "IRLPT_CLIENT_CONN"
 };
 
@@ -108,9 +107,8 @@ char *irlpt_fsm_event[] = {
 hashbin_t *irlpt_clients = NULL;
 struct irlpt_cb *irlpt_server = NULL;
 int irlpt_common_debug = 4;  /* want to change this? please don't! 
-                               use irlpt_common_debug=3 on the command line! */
-
-static struct wait_queue *irlpt_wait;
+                               use irlpt_common_debug=3 on the 
+                               command line! */
 
 #if 0
 static char *rcsid = "$Id: irlpt_common.c,v 1.6 1998/11/10 22:50:58 dagb Exp $";
@@ -152,7 +150,6 @@ ssize_t irlpt_read( struct file *file, char *buffer, size_t count, loff_t
        char *ptr = buffer;
        struct irlpt_cb *self;
        struct sk_buff *skb = NULL;
-       struct wait_queue wait = { current, NULL };
 
        DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
 
@@ -170,11 +167,12 @@ ssize_t irlpt_read( struct file *file, char *buffer, size_t count, loff_t
                switch (self->eof) {
                case LM_USER_REQUEST:
                        self->eof = FALSE;
-                       DEBUG(3, "irlpt_read: returning 0\n");
+                       DEBUG(irlpt_common_debug, 
+                             __FUNCTION__ ": returning 0\n");
                        return 0;
                case LM_LAP_DISCONNECT:
                        self->eof = FALSE;
-                       return -EIO;
+                       return 0;
                case LM_LAP_RESET:
                        self->eof = FALSE;
                        return -ECONNRESET;
@@ -208,11 +206,7 @@ ssize_t irlpt_read( struct file *file, char *buffer, size_t count, loff_t
                               len, count, self->eof);
 
                        if (!signal_pending(current) && !self->eof) {
-                               add_wait_queue(&irlpt_wait, &wait);
-                               current->state = TASK_INTERRUPTIBLE;
-                               schedule();
-                               current->state = TASK_RUNNING;
-                               remove_wait_queue(&irlpt_wait, &wait);
+                               interruptible_sleep_on(&self->read_wait);
                        } else
                                break;
                }
@@ -228,7 +222,6 @@ ssize_t irlpt_write(struct file *file, const char *buffer,
 {
        struct irlpt_cb *self;
        struct sk_buff *skb;
-       struct wait_queue wait = { current, NULL };
 
        DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
 
@@ -240,26 +233,25 @@ ssize_t irlpt_write(struct file *file, const char *buffer,
        DEBUG( irlpt_common_debug, __FUNCTION__ 
               ": count = %d\n", count);
 
-       if (self->state != IRLPT_CLIENT_CONN) {
+       DEBUG( irlpt_common_debug, __FUNCTION__ 
+              ": pkt_count = %d\n", self->pkt_count);
+       if (self->pkt_count > 8) {
                DEBUG( irlpt_common_debug, __FUNCTION__ 
-                      ": state != IRLPT_CONN (possible link problems?)\n");
-               return -ENOLINK;
+                      ": too many outstanding buffers, going to sleep\n");
+               interruptible_sleep_on(&self->write_wait);
        }
 
        DEBUG( irlpt_common_debug, __FUNCTION__ 
               ": pkt_count = %d\n", self->pkt_count);
-       if (self->pkt_count > 8) {
+
+       if (self->state != IRLPT_CLIENT_CONN) {
                DEBUG( irlpt_common_debug, __FUNCTION__ 
-                      ": too many outstanding buffers, going to sleep\n");
-               add_wait_queue(&self->write_wait, &wait);
-               current->state = TASK_INTERRUPTIBLE;
-               schedule();
-               current->state = TASK_RUNNING;
-               remove_wait_queue(&self->write_wait, &wait);
+                      ": state != IRLPT_CONN (possible link problems?)\n");
+               return -ENOLINK;
        }
 
        DEBUG( irlpt_common_debug, __FUNCTION__ 
-              ":count = %d, irlap_data_size = %d, IRLPT_MAX_HEADER = %d\n",
+              ": count = %d, irlap_data_size = %d, IRLPT_MAX_HEADER = %d\n",
                count, self->irlap_data_size, IRLPT_MAX_HEADER);
 
        if (count > (self->irlap_data_size - IRLPT_MAX_HEADER)) {
@@ -272,7 +264,8 @@ ssize_t irlpt_write(struct file *file, const char *buffer,
 
        skb = dev_alloc_skb(count + IRLPT_MAX_HEADER);
        if ( skb == NULL) {
-               printk( KERN_INFO __FUNCTION__ ": couldn't allocate skbuff!\n");
+               printk( KERN_INFO 
+                       __FUNCTION__ ": couldn't allocate skbuff!\n");
                return 0;
        }
 
@@ -292,6 +285,9 @@ ssize_t irlpt_write(struct file *file, const char *buffer,
 
        irlmp_data_request(self->lsap, skb);
 
+       irda_start_timer( &self->lpt_timer, 5000, (unsigned long) self, 
+                         self->timeout);
+
        DEBUG(irlpt_common_debug, __FUNCTION__ " -->\n");
 
        return(count);
@@ -305,60 +301,13 @@ loff_t irlpt_seek( struct file *file, loff_t offset, int count)
        return -ESPIPE;
 }
 
-#if 0
-
 /*
- * Function irlpt_select (inode, filp, mode, table)
- *
- *    Implementation for the select() call
- *
- */
-int irlpt_select( struct inode *inode, struct file *filp, int mode, 
-                        select_table *table)
-{
-       struct irlpt_cb *self;
-
-       DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
-       
-       self = irlpt_find_handle(MINOR( inode->i_rdev));
-
-       ASSERT( self != NULL, return -1;);
-       ASSERT( self->magic == IRLPT_MAGIC, return -1;);
-
-       switch (mode) {
-       case SEL_IN:
-               if ( skb_queue_len( &self->rx_queue))
-                       return 1; /* Readable */
-               select_wait( &self->read_wait, table);
-               break;
-       case SEL_OUT:
-               if ( self->connected)
-                       return 1;
-               select_wait( &self->write_wait, table);
-               break;
-       case SEL_EX:
-               if ( self->connected)
-                       return 1;
-               select_wait( &self->ex_wait, table);
-               break;
-       default:
-               break;
-       }
-
-       DEBUG(irlpt_common_debug, __FUNCTION__ " -->\n");
-
-       return 0;
-}
-
-#else
-
-/*
- * Function irobex_poll (file, wait)
+ * Function irlpt_poll (file, wait)
  *
  *    
  *
  */
-static u_int irlpt_poll(struct file *file, poll_table *wait)
+u_int irlpt_poll(struct file *file, poll_table *wait)
 {
        DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
 
@@ -367,8 +316,6 @@ static u_int irlpt_poll(struct file *file, poll_table *wait)
        return 0;
 }
 
-#endif
-
 /*
  * Function open_irlpt (inode, file)
  *
@@ -378,6 +325,7 @@ static u_int irlpt_poll(struct file *file, poll_table *wait)
 int irlpt_open(struct inode *inode, struct file *file)
 {
        struct irlpt_cb *self;
+       struct irlpt_info info;
 
        DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
 
@@ -386,22 +334,6 @@ int irlpt_open(struct inode *inode, struct file *file)
        ASSERT( self != NULL, return -1;);
        ASSERT( self->magic == IRLPT_MAGIC, return -1;);
 
-#if 0
-       if (self->state == IRLPT_IDLE) {
-               DEBUG( irlpt_common_debug, __FUNCTION__ 
-                      ": state == IRLPT_IDLE! (no device found yet)\n");
-               return -ENODEV;
-       }
-
-       if (self->state == IRLPT_QUERY ||
-           self->state == IRLPT_READY ||
-           self->state == IRLPT_WAITI) {
-               DEBUG( irlpt_common_debug, __FUNCTION__ ": state == IRLPT_QUERY, " 
-                      "IRLPT_READY or IRLPT_WAITI (link problems)!\n");
-               return -EBUSY;
-       }
-#endif
-
        if (self->count++) {
                DEBUG( irlpt_common_debug, __FUNCTION__ 
                       ": count not zero; actual = %d\n", self->count);
@@ -409,6 +341,35 @@ int irlpt_open(struct inode *inode, struct file *file)
                return -EBUSY;
        }
 
+       self->eof = FALSE;
+
+       /* ok, now, if it's idle, try to get some information
+          about the remote end, and sleep till we get totally connected.. */
+
+       if ((self->servicetype != IRLPT_SERVER_MODE) && 
+           self->state != IRLPT_CLIENT_CONN) {
+               DEBUG(irlpt_common_debug, __FUNCTION__
+                     ": self->state != IRLPT_CLIENT_CONN\n");
+
+               info.daddr = self->daddr;
+               info.saddr = self->saddr;
+
+               if (self->do_event != NULL) {
+                       DEBUG(irlpt_common_debug, __FUNCTION__ 
+                             ": doing a discovery..\n");
+                       self->do_event( self, 
+                                       IRLPT_DISCOVERY_INDICATION, 
+                                       NULL, &info);
+                       DEBUG(irlpt_common_debug, __FUNCTION__ 
+                             ": sleeping until connected.\n");
+                       interruptible_sleep_on(&self->read_wait);
+               }
+       }
+
+       /* at this point, if it's a client, we have a connection.
+        * if it's the server, it's waiting for a connection.
+        */
+
        DEBUG(irlpt_common_debug, __FUNCTION__ " -->\n");
 
        return 0;
@@ -420,9 +381,12 @@ int irlpt_open(struct inode *inode, struct file *file)
  *
  *
  */
-int irlpt_close(struct inode *inode, struct file *file)
+int irlpt_close(struct inode *inode, 
+               struct file *file)
 {
        struct irlpt_cb *self;
+       struct sk_buff *skb;
+       struct irlpt_info info;
 
        DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
 
@@ -433,12 +397,42 @@ int irlpt_close(struct inode *inode, struct file *file)
        ASSERT( self != NULL, return -1;);
        ASSERT( self->magic == IRLPT_MAGIC, return -1;);
 
-       DEBUG(irlpt_common_debug, __FUNCTION__ ": self->count=%d\n", self->count);
+       DEBUG(irlpt_common_debug, 
+             __FUNCTION__ ": self->count=%d\n", self->count);
+
        if (self->count > 0)
                self->count--;
 
-       DEBUG(irlpt_common_debug, __FUNCTION__ " -->\n");
+       while (self->pkt_count > 0) {
+               interruptible_sleep_on(&self->write_wait);
+       }
+
+       /* all done, tear down the connection and wait for the next open */
+       if ((self->servicetype != IRLPT_SERVER_MODE) &&
+           self->state == IRLPT_CLIENT_CONN) {
+               skb = dev_alloc_skb(64);
+               if (skb == NULL) {
+                       DEBUG( 0, __FUNCTION__ "(: Could not allocate an "
+                              "sk_buff of length %d\n", 64);
+                       return 0;
+               }
+
+               skb_reserve( skb, LMP_CONTROL_HEADER+LAP_HEADER);
+               irlmp_disconnect_request(self->lsap, skb);
+               DEBUG(irlpt_common_debug, __FUNCTION__
+                     ": irlmp_close_slap(self->lsap)\n");
+               irlmp_close_lsap(self->lsap);
+       }
+
+       info.daddr = self->daddr;
 
+       if (self->do_event != NULL) {
+               DEBUG(irlpt_common_debug, __FUNCTION__ 
+                     ": closing connection..\n");
+               self->do_event( self, LMP_DISCONNECT, NULL, &info);
+       }
+
+       DEBUG(irlpt_common_debug, __FUNCTION__ " -->\n");
        return 0;
 }
 
@@ -486,6 +480,10 @@ void irlpt_flow_control(struct sk_buff *skb)
 
 #ifdef MODULE
 
+MODULE_AUTHOR("Thomas Davis <ratbert@radiks.net>");
+MODULE_DESCRIPTION("The Linux IrDA/IrLPT common");
+MODULE_PARM(irlpt_common_debug,"1i");
+
 /*
  * Function init_module (void)
  *
index b7d6f1bb9bda57d7aa39acc18268553ab28af572..a365ef5b43166bc5e5ae6673efb9e71ddae5f32a 100644 (file)
@@ -49,31 +49,34 @@ static int irlpt_server_proc_read(char *buf, char **start, off_t offset,
 
 int irlpt_server_init(void);
 static void irlpt_server_cleanup(void);
-static void irlpt_server_disconnect_indication( void *instance, void *sap, 
+static void irlpt_server_disconnect_indication( void *instance, 
+                                               void *sap, 
                                                LM_REASON reason,
                                                struct sk_buff *skb);
-static void irlpt_server_connect_confirm( void *instance, void *sap, 
+static void irlpt_server_connect_confirm( void *instance, 
+                                         void *sap, 
                                          struct qos_info *qos,  
                                          int max_seg_size,
                                          struct sk_buff *skb);
-static void irlpt_server_connect_indication( void *instance, void *sap, 
+static void irlpt_server_connect_indication( void *instance, 
+                                            void *sap, 
                                             struct qos_info *qos, 
                                             int max_seg_size,
                                             struct sk_buff *skb);
-static void irlpt_server_data_indication( void *instance, void *sap, 
+static void irlpt_server_data_indication( void *instance, 
+                                         void *sap, 
                                          struct sk_buff *skb);
 static void register_irlpt_server(void);
 static void deregister_irlpt_server(void);
 
-static struct wait_queue *irlpt_server_wait;
-
 int irlpt_server_lsap = LSAP_IRLPT;
 int irlpt_server_debug = 4;
 
 #if 0
 static char *rcsid = "$Id: irlpt_server.c,v 1.9 1998/10/22 12:02:22 dagb Exp $";
 #endif
-static char *version = "IrLPT server, $Revision: 1.9 $/$Date: 1998/10/22 12:02:22 $ (Thomas Davis)";
+
+static char *version = "IrLPT server, v2 (Thomas Davis)";
 
 struct file_operations irlpt_fops = {
        irlpt_seek,     /* seek */
@@ -96,7 +99,7 @@ struct file_operations irlpt_fops = {
 #ifdef CONFIG_PROC_FS
 
 /*
- * Function proc_irlpt_read (buf, start, offset, len, unused)
+ * Function irlpt_server_proc_read (buf, start, offset, len, unused)
  *
  *
  *
@@ -137,21 +140,19 @@ static int irlpt_server_proc_read(char *buf, char **start, off_t offset,
                        break;
                }
 
-               len += sprintf(buf+len, "servicetype: %s\n", 
-                              irlpt_service_type[index]);
-               len += sprintf(buf+len, "porttype: %s\n", 
+               len += sprintf(buf+len, "servicetype: %s, porttype: %s\n",
+                              irlpt_service_type[index],
                               irlpt_port_type[irlpt_server->porttype]);
-               len += sprintf(buf+len, "daddr: %d\n", 
-                              irlpt_server->daddr);
-               len += sprintf(buf+len, "state: %s\n", 
-                              irlpt_server_fsm_state[irlpt_server->state]);
-               len += sprintf(buf+len, "retries: %d\n", 
-                              irlpt_server->open_retries);
-               len += sprintf(buf+len, "peersap: %d\n", 
+               len += sprintf(buf+len, "saddr: 0x%08x, daddr: 0x%08x\n", 
+                              irlpt_server->saddr, irlpt_server->daddr);
+               len += sprintf(buf+len, "slsap: 0x%08x, dlsap: 0x%08x\n", 
+                              irlpt_server->slsap_sel, 
                               irlpt_server->dlsap_sel);
-               len += sprintf(buf+len, "count: %d\n", 
+               len += sprintf(buf+len, "retries: %d, count: %d\n", 
+                              irlpt_server->open_retries,
                               irlpt_server->count);
-               len += sprintf(buf+len, "rx_queue: %d\n", 
+               len += sprintf(buf+len, "fsm state: %s, rx queue depth: %d\n", 
+                              irlpt_server_fsm_state[irlpt_server->state],
                               skb_queue_len(&irlpt_server->rx_queue));
                len += sprintf(buf+len, "\n");
        }
@@ -258,11 +259,14 @@ static void irlpt_server_cleanup(void)
  * Function irlpt_disconnect_indication (handle)
  *
  */
-static void irlpt_server_disconnect_indication( void *instance, void *sap, 
+static void irlpt_server_disconnect_indication( void *instance, 
+                                               void *sap, 
                                                LM_REASON reason,
                                                struct sk_buff *userdata)
 {
+#if 0
        struct irlpt_info info;
+#endif
        struct irlpt_cb *self;
 
        DEBUG( irlpt_server_debug, "--> " __FUNCTION__ "\n");
@@ -272,17 +276,22 @@ static void irlpt_server_disconnect_indication( void *instance, void *sap,
        ASSERT( self != NULL, return;);
        ASSERT( self->magic == IRLPT_MAGIC, return;);
 
+#if 0
        info.daddr = self->daddr;
+#endif
 
-       DEBUG( irlpt_server_debug, __FUNCTION__ ": reason=%d (%s), dlsap_sel=%d\n",
+       DEBUG( irlpt_server_debug, 
+              __FUNCTION__ ": reason=%d (%s), dlsap_sel=%d\n",
               reason, irlpt_reasons[reason], self->dlsap_sel);
 
        self->connected = IRLPT_DISCONNECTED;
        self->eof = reason;
 
-        wake_up_interruptible(&irlpt_server_wait);
+        wake_up_interruptible(&self->read_wait);
+       wake_up_interruptible(&self->write_wait);
+       wake_up_interruptible(&self->ex_wait);
 
-       DEBUG( irlpt_server_debug, __FUNCTION__ ": skb_queue_len=%d\n",
+       DEBUG( irlpt_server_debug, __FUNCTION__ ": rx queue length: %d\n",
               skb_queue_len(&irlpt_server->rx_queue));
 
        irlpt_server_do_event( self, LMP_DISCONNECT, NULL, NULL);
@@ -298,12 +307,12 @@ static void irlpt_server_disconnect_indication( void *instance, void *sap,
  *
  *    LSAP connection confirmed!
  */
-static void irlpt_server_connect_confirm( void *instance, void *sap, 
+static void irlpt_server_connect_confirm( void *instance, 
+                                         void *sap, 
                                          struct qos_info *qos,
                                          int max_seg_size,
                                          struct sk_buff *skb)
 {
-       struct irlpt_info info;
        struct irlpt_cb *self;
 
        DEBUG( irlpt_server_debug, "--> " __FUNCTION__ "\n");
@@ -312,21 +321,6 @@ static void irlpt_server_connect_confirm( void *instance, void *sap,
        ASSERT( self != NULL, return;);
        ASSERT( self->magic == IRLPT_MAGIC, return;);
 
-       info.daddr = self->daddr;
-
-       /*
-        *  Check if we have got some QoS parameters back! This should be the
-        *  negotiated QoS for the link.
-        */
-       if ( qos) {
-               DEBUG( irlpt_server_debug, __FUNCTION__ 
-                      ": IrLPT Negotiated BAUD_RATE: %02x\n", 
-                      qos->baud_rate.bits);                    
-               DEBUG( irlpt_server_debug, __FUNCTION__ 
-                      ": IrLPT Negotiated BAUD_RATE: %d bps.\n", 
-                      qos->baud_rate.value);
-       }
-
        self->connected = TRUE;
 
        irlpt_server_do_event( self, LMP_CONNECT, NULL, NULL);
@@ -338,19 +332,20 @@ static void irlpt_server_connect_confirm( void *instance, void *sap,
  * Function irlpt_connect_indication (handle)
  *
  */
-static void irlpt_server_connect_indication( void *instance, void *sap, 
+static void irlpt_server_connect_indication( void *instance, 
+                                            void *sap, 
                                             struct qos_info *qos, 
                                             int max_seg_size,
                                             struct sk_buff *skb)
 {
        struct irlpt_cb *self;
        struct irlpt_info info;
-       struct lsap_cb *lsap;
 
        DEBUG( irlpt_server_debug, "--> " __FUNCTION__ "\n");
 
        self = ( struct irlpt_cb *) instance;
-       lsap = (struct lsap_cb *) sap;
+
+       info.lsap  = (struct lsap_cb *) sap;
        
        ASSERT( self != NULL, return;);
        ASSERT( self->magic == IRLPT_MAGIC, return;);
@@ -358,8 +353,6 @@ static void irlpt_server_connect_indication( void *instance, void *sap,
        self->connected = IRLPT_CONNECTED;
        self->eof = FALSE;
 
-       info.lsap = lsap;
-
        irlpt_server_do_event( self, LMP_CONNECT, NULL, &info);
 
        if (skb) {
@@ -370,12 +363,13 @@ static void irlpt_server_connect_indication( void *instance, void *sap,
 }
 
 /*
- * Function irlpt_data_indication (handle, skb)
+ * Function irlpt_server_data_indication (handle, skb)
  *
  *    This function gets the data that is received on the data channel
  *
  */
-static void irlpt_server_data_indication( void *instance, void *sap, 
+static void irlpt_server_data_indication( void *instance, 
+                                         void *sap, 
                                          struct sk_buff *skb) 
 {
 
@@ -397,7 +391,7 @@ static void irlpt_server_data_indication( void *instance, void *sap,
 #endif
        
        skb_queue_tail(&self->rx_queue, skb);
-        wake_up_interruptible(&irlpt_server_wait);
+        wake_up_interruptible(&self->read_wait);
 
        DEBUG( irlpt_server_debug, __FUNCTION__ " -->\n");
 }
@@ -419,9 +413,8 @@ static void register_irlpt_server(void)
        /*
         *  First register control TSAP
         */
-
        if ( !irlpt_server || irlpt_server->magic != IRLPT_MAGIC) {
-               DEBUG( 0, "irlpt_register_server:, unable to obtain handle!\n");
+               DEBUG( 0, __FUNCTION__ ": unable to obtain handle!\n");
                return;
        }
 
@@ -432,12 +425,13 @@ static void register_irlpt_server(void)
        notify.disconnect_indication = irlpt_server_disconnect_indication;
        notify.data_indication = irlpt_server_data_indication;
        notify.instance = irlpt_server;
-       strcpy(notify.name, "IrLPT");
+       strcpy(notify.name, "IrLPT server");
 
        irlpt_server->lsap = irlmp_open_lsap( irlpt_server_lsap, &notify);
 
        irlpt_server->connected = IRLPT_WAITING;
        irlpt_server->service_LSAP = irlpt_server_lsap;
+       irlpt_server->slsap_sel = irlpt_server_lsap;
 
        /* 
         *  Register with LM-IAS
@@ -461,35 +455,9 @@ static void register_irlpt_server(void)
  */
 static void deregister_irlpt_server(void)
 {
-#if 0
-       struct notify_t notify;
-#endif
        DEBUG( irlpt_server_debug, "--> " __FUNCTION__ "\n");
 
-#if 0
-       /*
-        *  First register control TSAP
-        */
-
-       if ( !irlpt_server || irlpt_server->magic != IRLPT_MAGIC) {
-               DEBUG( 0, "irlpt_register_server:, unable to obtain handle!\n");
-               return;
-       }
-
-       irda_notify_init(&notify);
-
-       notify.connect_confirm = irlpt_server_connect_confirm;
-       notify.connect_indication = irlpt_server_connect_indication;
-       notify.disconnect_indication = irlpt_server_disconnect_indication;
-       notify.data_indication = irlpt_server_data_indication;
-       notify.instance = irlpt_server;
-       strcpy(notify.name, "IrLPT");
-
-       irlpt_server->lsap = irlmp_open_lsap( irlpt_server_lsap, &notify);
-
-       irlpt_server->connected = IRLPT_WAITING;
-       irlpt_server->service_LSAP = irlpt_server_lsap;
-#endif
+       irlpt_server->connected = IRLPT_DISCONNECTED;
 
        /* 
         *  de-Register with LM-IAS
@@ -504,7 +472,9 @@ static void deregister_irlpt_server(void)
 #ifdef MODULE
 
 MODULE_AUTHOR("Thomas Davis <ratbert@radiks.net>");
-MODULE_DESCRIPTION("The Linux IrDA/IrLPT protocol");
+MODULE_DESCRIPTION("The Linux IrDA/IrLPT server protocol");
+MODULE_PARM(irlpt_server_debug,"1i");
+MODULE_PARM(irlpt_server_fsm_debug, "1i");
 
 /*
  * Function init_module (void)
@@ -515,11 +485,11 @@ MODULE_DESCRIPTION("The Linux IrDA/IrLPT protocol");
 int init_module(void)
 {
 
-        DEBUG( irlpt_server_debug, "--> irlpt server: init_module\n");
+        DEBUG( irlpt_server_debug, "--> IrLPT server: init_module\n");
 
         irlpt_server_init();
 
-        DEBUG( irlpt_server_debug, "irlpt server: init_module -->\n");
+        DEBUG( irlpt_server_debug, "IrLPT server: init_module -->\n");
 
         return 0;
 }
@@ -532,14 +502,14 @@ int init_module(void)
  */
 void cleanup_module(void)
 {
-       DEBUG( irlpt_server_debug, "--> " __FUNCTION__ "\n");
-        DEBUG( 3, "--> irlpt server: cleanup_module\n");
+        DEBUG( irlpt_server_debug, "--> IrLPT server: cleanup_module\n");
+
         /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
 
         /* Free some memory */
         irlpt_server_cleanup();
 
-        DEBUG( irlpt_server_debug, "irlpt server: cleanup_module -->\n");
+        DEBUG( irlpt_server_debug, "IrLPT server: cleanup_module -->\n");
 }
 
 #endif /* MODULE */
index 3640a96777b9a1e2bd273b2ba73283ce771ca4aa..d37d98b7cbb94148af355dec753254de67e66a35 100644 (file)
@@ -4,8 +4,10 @@
  * Version:       0.1
  * Sources:       irlan_event.c
  * 
- *     Copyright (c) 1997, Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
- *     Copyright (c) 1998, Thomas Davis, <ratbert@radiks.net>, All Rights Reserved.
+ *     Copyright (c) 1997, Dag Brattli <dagb@cs.uit.no>, 
+ *             All Rights Reserved.
+ *     Copyright (c) 1998, Thomas Davis, <ratbert@radiks.net>, 
+ *             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 
@@ -38,9 +40,10 @@ static int irlpt_server_state_conn  ( struct irlpt_cb *self,
 static char *rcsid = "$Id: irlpt_server_fsm.c,v 1.4 1998/10/05 05:46:45 ratbert Exp $";
 #endif
 
-int irlpt_server_fsm_debug = 3;
+int irlpt_server_fsm_debug = 4; /* don't change this! */
 
-static int (*irlpt_server_state[])( struct irlpt_cb *self, IRLPT_EVENT event, 
+static int (*irlpt_server_state[])( struct irlpt_cb *self, 
+                                   IRLPT_EVENT event, 
                                    struct sk_buff *skb,
                                    struct irlpt_info *info) = 
 { 
@@ -48,10 +51,13 @@ static int (*irlpt_server_state[])( struct irlpt_cb *self, IRLPT_EVENT event,
        irlpt_server_state_conn,
 };
 
-void irlpt_server_do_event( struct irlpt_cb *self, IRLPT_EVENT event, 
-                           struct sk_buff *skb, struct irlpt_info *info) 
+void irlpt_server_do_event( struct irlpt_cb *self, 
+                           IRLPT_EVENT event, 
+                           struct sk_buff *skb, 
+                           struct irlpt_info *info) 
 {
-       DEBUG( irlpt_server_fsm_debug, __FUNCTION__ ": STATE = %s, EVENT = %s\n", 
+       DEBUG( irlpt_server_fsm_debug, 
+              __FUNCTION__ ": STATE = %s, EVENT = %s\n", 
               irlpt_server_fsm_state[self->state], irlpt_fsm_event[event]);
 
        ASSERT( self != NULL, return;);
@@ -62,7 +68,8 @@ void irlpt_server_do_event( struct irlpt_cb *self, IRLPT_EVENT event,
        DEBUG( irlpt_server_fsm_debug, __FUNCTION__ " -->\n");
 }
 
-void irlpt_server_next_state( struct irlpt_cb *self, IRLPT_CLIENT_STATE state) 
+void irlpt_server_next_state( struct irlpt_cb *self, 
+                             IRLPT_CLIENT_STATE state) 
 {
 
        DEBUG( irlpt_server_fsm_debug, __FUNCTION__ ": NEXT STATE = %s\n", 
@@ -82,7 +89,8 @@ void irlpt_server_next_state( struct irlpt_cb *self, IRLPT_CLIENT_STATE state)
  *    IDLE, We are waiting for an indication that there is a provider
  *    available.
  */
-static int irlpt_server_state_idle( struct irlpt_cb *self, IRLPT_EVENT event, 
+static int irlpt_server_state_idle( struct irlpt_cb *self, 
+                                   IRLPT_EVENT event, 
                                    struct sk_buff *skb, 
                                    struct irlpt_info *info) 
 {
@@ -96,10 +104,12 @@ static int irlpt_server_state_idle( struct irlpt_cb *self, IRLPT_EVENT event,
        switch( event) {
        case LMP_CONNECT:
                DEBUG( irlpt_server_fsm_debug, __FUNCTION__ 
-                      ": LM_CONNECT, remote lsap=%d\n", 
-                      info->dlsap_sel);
+                      ": LM_CONNECT, remote lsap: 0x%08x\n",
+                      info->lsap->dlsap_sel);
 
-               self->dlsap_sel = info->dlsap_sel;
+               self->dlsap_sel = info->lsap->dlsap_sel;
+               self->daddr = info->daddr;
+               self->saddr = info->saddr;
 
                r_skb = dev_alloc_skb(64);
                if (r_skb == NULL) { 
@@ -107,12 +117,9 @@ static int irlpt_server_state_idle( struct irlpt_cb *self, IRLPT_EVENT event,
                                ": can't allocate sk_buff of length 64\n");
                        return 0;
                }
-               ALLOC_SKB_MAGIC(r_skb);
                skb_reserve( r_skb, LMP_MAX_HEADER);
-               skb->len = 0;
                irlmp_connect_response( self->lsap, r_skb);
                irlpt_server_next_state( self, IRLPT_SERVER_CONN);
-
                break;
 
        default:
index c009d685877e288b298ea6e991c7c022a5502c9b..fede19a63385db97aa7937b17434dbee091ee52c 100644 (file)
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Dec 15 13:55:39 1997
- * Modified at:   Tue Jan 19 23:34:18 1999
+ * Modified at:   Thu Feb 18 08:51:50 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997 Dag Brattli, All Rights Reserved.
 
 #include <linux/config.h>
 #include <linux/module.h> 
+
 #include <linux/init.h>
-#include <asm/segment.h>
 #include <linux/poll.h>
+#include <asm/segment.h>
+
+#include <linux/proc_fs.h>
 
 #include <net/irda/irda.h>
+#include <net/irda/irmod.h>
+#include <net/irda/irlap.h>
+#ifdef CONFIG_IRDA_COMPRESSION
+#include <net/irda/irlap_comp.h>
+#endif /* CONFIG_IRDA_COMPRESSION */
 #include <net/irda/irlmp.h>
 #include <net/irda/iriap.h>
+#include <net/irda/irias_object.h>
 #include <net/irda/irttp.h>
+#include <net/irda/irda_device.h>
+#include <net/irda/wrapper.h>
+#include <net/irda/timer.h>
+
+extern struct proc_dir_entry proc_irda;
 
 struct irda_cb irda; /* One global instance */
 
@@ -57,15 +71,15 @@ extern int irvtd_init(void);
 extern int irlpt_client_init(void);
 extern int irlpt_server_init(void);
 
-static int irda_open( struct inode * inode, struct file *file);
-static int irda_ioctl( struct inode *inode, struct file *filp, 
-                        unsigned int cmd, unsigned long arg);
-static int irda_close( struct inode *inode, struct file *file);
-static ssize_t irda_read( struct file *file, char *buffer, size_t count, 
-                           loff_t *noidea);
-static ssize_t irda_write( struct file *file, const char *buffer,
-                            size_t count, loff_t *noidea);
-static u_int irda_poll( struct file *file, poll_table *wait);
+static int irda_open(struct inode * inode, struct file *file);
+static int irda_ioctl(struct inode *inode, struct file *filp, 
+                     unsigned int cmd, unsigned long arg);
+static int irda_close(struct inode *inode, struct file *file);
+static ssize_t irda_read(struct file *file, char *buffer, size_t count, 
+                        loff_t *noidea);
+static ssize_t irda_write(struct file *file, const char *buffer,
+                         size_t count, loff_t *noidea);
+static u_int irda_poll(struct file *file, poll_table *wait);
 
 static struct file_operations irda_fops = {
        NULL,          /* seek */
@@ -82,13 +96,95 @@ static struct file_operations irda_fops = {
        NULL,          /* fasync */
 };
 
+/* IrTTP */
+EXPORT_SYMBOL(irttp_open_tsap);
+EXPORT_SYMBOL(irttp_close_tsap);
+EXPORT_SYMBOL(irttp_connect_response);
+EXPORT_SYMBOL(irttp_data_request);
+EXPORT_SYMBOL(irttp_disconnect_request);
+EXPORT_SYMBOL(irttp_flow_request);
+EXPORT_SYMBOL(irttp_connect_request);
+EXPORT_SYMBOL(irttp_udata_request);
+
+/* Main IrDA module */
+#ifdef CONFIG_IRDA_DEBUG
+EXPORT_SYMBOL(irda_debug);
+#endif
+EXPORT_SYMBOL(irda_notify_init);
+EXPORT_SYMBOL(irmanager_notify);
+EXPORT_SYMBOL(irda_lock);
+EXPORT_SYMBOL(proc_irda);
+
+/* IrIAP/IrIAS */
+EXPORT_SYMBOL(iriap_getvaluebyclass_request);
+EXPORT_SYMBOL(irias_object_change_attribute);
+EXPORT_SYMBOL(irias_add_integer_attrib);
+EXPORT_SYMBOL(irias_add_octseq_attrib);
+EXPORT_SYMBOL(irias_add_string_attrib);
+EXPORT_SYMBOL(irias_insert_object);
+EXPORT_SYMBOL(irias_new_object);
+EXPORT_SYMBOL(irias_delete_object);
+EXPORT_SYMBOL(irias_find_object);
+EXPORT_SYMBOL(irias_find_attrib);
+EXPORT_SYMBOL(irias_new_integer_value);
+EXPORT_SYMBOL(irias_new_string_value);
+EXPORT_SYMBOL(irias_new_octseq_value);
+
+/* IrLMP */
+EXPORT_SYMBOL(irlmp_discovery_request);
+EXPORT_SYMBOL(irlmp_register_layer);
+EXPORT_SYMBOL(irlmp_unregister_layer);
+EXPORT_SYMBOL(irlmp_data_request);
+EXPORT_SYMBOL(irlmp_open_lsap);
+EXPORT_SYMBOL(irlmp_close_lsap);
+EXPORT_SYMBOL(irlmp_connect_request);
+EXPORT_SYMBOL(irlmp_connect_response);
+EXPORT_SYMBOL(irlmp_disconnect_request);
+EXPORT_SYMBOL(irlmp_get_daddr);
+EXPORT_SYMBOL(irlmp_get_saddr);
+EXPORT_SYMBOL(lmp_reasons);
+
+/* Queue */
+EXPORT_SYMBOL(hashbin_find);
+EXPORT_SYMBOL(hashbin_new);
+EXPORT_SYMBOL(hashbin_insert);
+EXPORT_SYMBOL(hashbin_delete);
+EXPORT_SYMBOL(hashbin_remove);
+EXPORT_SYMBOL(hashbin_get_next);
+EXPORT_SYMBOL(hashbin_get_first);
+
+/* IrLAP */
+#ifdef CONFIG_IRDA_COMPRESSION
+EXPORT_SYMBOL(irda_unregister_compressor);
+EXPORT_SYMBOL(irda_register_compressor);
+#endif /* CONFIG_IRDA_COMPRESSION */
+EXPORT_SYMBOL(irda_init_max_qos_capabilies);
+EXPORT_SYMBOL(irda_qos_bits_to_value);
+EXPORT_SYMBOL(irda_device_open);
+EXPORT_SYMBOL(irda_device_close);
+EXPORT_SYMBOL(irda_device_setup);
+EXPORT_SYMBOL(irda_device_set_media_busy);
+EXPORT_SYMBOL(irda_device_txqueue_empty);
+EXPORT_SYMBOL(async_wrap_skb);
+EXPORT_SYMBOL(async_unwrap_char);
+EXPORT_SYMBOL(irda_start_timer);
+EXPORT_SYMBOL(irda_get_mtt);
+EXPORT_SYMBOL(setup_dma);
+
+#ifdef CONFIG_IRTTY
+EXPORT_SYMBOL(irtty_set_dtr_rts);
+EXPORT_SYMBOL(irtty_register_dongle);
+EXPORT_SYMBOL(irtty_unregister_dongle);
+#endif
+
 __initfunc(int irda_init(void))
 {
-        printk( KERN_INFO "Linux Support for the IrDA (tm) protocols (Dag Brattli)\n");
+        printk(KERN_INFO "Linux-2.2 Support for the IrDA (tm) Protocols (Dag Brattli)\n");
 
-       irda_device_init();
-       irlap_init();
        irlmp_init();
+       irlap_init();
+       irda_device_init();
+
        iriap_init();
        irttp_init();
        
@@ -113,12 +209,6 @@ __initfunc(int irda_init(void))
 #ifdef CONFIG_IRLAN
        irlan_init();
 #endif
-#ifdef CONFIG_IRLAN_CLIENT
-       irlan_client_init();
-#endif
-#ifdef CONFIG_IRLAN_SERVER
-       irlan_server_init();
-#endif
 #ifdef CONFIG_IROBEX
        irobex_init();
 #endif
@@ -135,9 +225,21 @@ __initfunc(int irda_init(void))
        irlpt_server_init();
 #endif
 
+#ifdef CONFIG_IRDA_COMPRESSION
+#ifdef CONFIG_IRDA_DEFLATE
+       irda_deflate_init();
+#endif /* CONFIG_IRDA_DEFLATE */
+#endif /* CONFIG_IRDA_COMPRESSION */
+
        return 0;
 }
 
+/* 
+ * FIXME:
+ * This function should have been wrapped with #ifdef MODULE, but then
+ * irda_proto_cleanup() must be moved from af_irda.c to this file since
+ * that function must also be wrapped if this one is.
+ */
 void irda_cleanup(void)
 {
        misc_deregister( &irda.dev);
@@ -168,10 +270,12 @@ void irda_cleanup(void)
  *    Lock variable. Returns false if the lock is already set.
  *    
  */
-inline int irda_lock( int *lock) {
-       if ( test_and_set_bit( 0, (void *) lock))  {
-             printk("Trying to lock, already locked variable!\n");
-            return FALSE;
+inline int irda_lock(int *lock) 
+{
+       if (test_and_set_bit( 0, (void *) lock))  {
+               DEBUG(3, __FUNCTION__ 
+                     "(), Trying to lock, already locked variable!\n");
+               return FALSE;
         }  
        return TRUE;
 }
@@ -182,8 +286,9 @@ inline int irda_lock( int *lock) {
  *    Unlock variable. Returns false if lock is already unlocked
  *
  */
-inline int irda_unlock( int *lock) {
-       if ( !test_and_clear_bit( 0, (void *) lock))  {
+inline int irda_unlock(int *lock) 
+{
+       if (!test_and_clear_bit(0, (void *) lock))  {
                printk("Trying to unlock already unlocked variable!\n");
                return FALSE;
         }
@@ -198,7 +303,6 @@ inline int irda_unlock( int *lock) {
  */
 void irda_notify_init( struct notify_t *notify)
 {
-
        notify->data_indication = NULL;
        notify->udata_indication = NULL;
        notify->connect_confirm = NULL;
@@ -402,9 +506,19 @@ static u_int irda_poll( struct file *file, poll_table *wait)
 }
 
 #ifdef MODULE
+#ifdef CONFIG_PROC_FS
+void irda_proc_modcount(struct inode *inode, int fill)
+{
+       if (fill)
+               MOD_INC_USE_COUNT;
+       else
+               MOD_DEC_USE_COUNT;
+}
+#endif /* CONFIG_PROC_FS */
 
 MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
 MODULE_DESCRIPTION("The Linux IrDA protocol subsystem"); 
+MODULE_PARM(irda_debug, "1l");
 
 /*
  * Function init_module (void)
index 8b289182d2b51514dcb3d831dc821cd529c0d5a2..6916be460c18271bc3191857203d2db37332afa2 100644 (file)
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      irobex.c
- * Version:       0.3
+ * Version:       0.4
  * Description:   Kernel side of the IrOBEX layer
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Jun 25 21:21:07 1998
- * Modified at:   Sat Jan 16 22:18:03 1999
+ * Modified at:   Mon Feb  8 09:05:01 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
@@ -46,6 +46,8 @@
  */
 struct irobex_cb *irobex;
 
+extern char *lmp_reasons[];
+
 char *irobex_state[] = {
        "OBEX_IDLE",
        "OBEX_DISCOVER",
@@ -54,10 +56,29 @@ char *irobex_state[] = {
        "OBEX_DATA",
 };
 
-static int irobex_dev_open( struct inode * inode, struct file *file);
+static void   irobex_cleanup(void);
+/* static struct irobex_cb *irobex_open(void); */
+/* static void   irobex_close( struct irobex_cb *self); */
+
+static void irobex_data_indication( void *instance, void *sap, 
+                                   struct sk_buff *skb);
+static void irobex_disconnect_indication( void *instance, void *sap, 
+                                         LM_REASON reason, 
+                                         struct sk_buff *skb);
+static void irobex_disconnect_request( struct irobex_cb *self);
+static int irobex_connect_request(struct irobex_cb *self);
+static void irobex_connect_confirm( void *instance, void *sap, 
+                                   struct qos_info *qos,
+                                   int max_sdu_size, struct sk_buff *skb);
+static void irobex_discovery_indication( DISCOVERY *discovery);
+static void irobex_flow_indication( void *instance, void *sap, 
+                                   LOCAL_FLOW flow);
+static void irobex_get_value_confirm(__u16 obj_id, struct ias_value *value, 
+                                    void *priv);
+static void irobex_register_server( struct irobex_cb *self);
 static int irobex_ioctl( struct inode *inode, struct file *filp, 
                         unsigned int cmd, unsigned long arg);
-
+static int irobex_dev_open( struct inode * inode, struct file *file);
 static int irobex_dev_close( struct inode *inode, struct file *file);
 static ssize_t irobex_read( struct file *file, char *buffer, size_t count, 
                            loff_t *noidea);
@@ -105,6 +126,7 @@ struct proc_dir_entry proc_irobex = {
  */
 __initfunc(int irobex_init(void))
 {
+       struct irmanager_event mgr_event;
        struct irobex_cb *self;
 
        self = kmalloc(sizeof(struct irobex_cb), GFP_ATOMIC);
@@ -134,6 +156,10 @@ __initfunc(int irobex_init(void))
                
        irlmp_register_layer( S_OBEX, CLIENT | SERVER, TRUE, 
                              irobex_discovery_indication);
+
+/*     mgr_event.event = EVENT_IROBEX_INIT; */
+/*     sprintf( mgr_event.devname, "%s", self->devname); */
+/*     irmanager_notify( &mgr_event); */
        
        return 0;
 }
@@ -145,7 +171,7 @@ __initfunc(int irobex_init(void))
  *
  */
 #ifdef MODULE
-void irobex_cleanup(void)
+static void irobex_cleanup(void)
 {
        struct sk_buff *skb;
        struct irobex_cb *self;
@@ -163,6 +189,7 @@ void irobex_cleanup(void)
        irlmp_unregister_layer( S_OBEX, CLIENT | SERVER);
 
        if ( self->tsap) {
+               irttp_disconnect_request(self->tsap, NULL, P_NORMAL);
                irttp_close_tsap( self->tsap);
                self->tsap = NULL;
        }
@@ -207,8 +234,7 @@ static ssize_t irobex_read( struct file *file, char *buffer, size_t count,
   
        DEBUG( 4, __FUNCTION__ ": count=%d, skb_len=%d, state=%s, eof=%d\n", 
               count, skb_queue_len( &self->rx_queue), 
-              irobex_state[self->state], 
-              self->eof);
+              irobex_state[self->state], self->eof);
 
        if ( self->state != OBEX_DATA) {
                DEBUG( 0, __FUNCTION__ "(), link not connected yet!\n");
@@ -446,8 +472,8 @@ static int irobex_ioctl( struct inode *inode, struct file *filp,
 
        self = irobex;
        
-       ASSERT( self != NULL, return -ENOTTY;);
-       ASSERT( self->magic = IROBEX_MAGIC, return -ENOTTY;);
+       ASSERT(self != NULL, return -ENOTTY;);
+       ASSERT(self->magic == IROBEX_MAGIC, return -ENOTTY;);
        
        if ( _IOC_TYPE(cmd) != IROBEX_IOC_MAGIC) 
                return -EINVAL;
@@ -464,107 +490,11 @@ static int irobex_ioctl( struct inode *inode, struct file *filp,
        switch ( cmd) {
        case IROBEX_IOCSCONNECT:
                DEBUG( 4, __FUNCTION__ "(): IROBEX_IOCSCONNECT!\n");
-               
-               /* Already connected? */
-               if ( self->state == OBEX_DATA) {
-                       DEBUG( 0, __FUNCTION__ "(), already connected!\n");
-                       return 0;
-               }
-               
-               /* Timeout after 15 secs. */
-               irobex_start_watchdog_timer( self, 1000);
-
-               /*
-                * If we have discovered a remote device we
-                * check if the discovery is still fresh. If not, we don't
-                * trust the address.
-                */
-               if ( self->daddr && ((jiffies - self->time_discovered) > 500))
-                       self->daddr = 0;
-
-               /* 
-                * Try to discover remote remote device if it has not been 
-                * discovered yet. 
-                */
-               if ( !self->daddr) {
-                       self->state = OBEX_DISCOVER;
-                       
-                       irlmp_discovery_request( 8);
-                       
-                       /* Wait for discovery to complete */
-                       interruptible_sleep_on( &self->write_wait);
-                       del_timer( &self->watchdog_timer);
-               }
-               
-               /* Give up if we are unable to discover any remote devices */
-               if ( !self->daddr) {
-                       DEBUG( 0, __FUNCTION__ 
-                              "(), Unable to discover any devices!\n");
-                       return -ENOTTY;
-               }
-               
-               /* Need to find remote destination TSAP selector? */
-               if ( !self->dtsap_sel) {
-                       DEBUG( 0, __FUNCTION__ "() : Quering remote IAS!\n");
-                       
-                       self->state = OBEX_QUERY;
-                       
-                       /* Timeout after 5 secs. */
-                       irobex_start_watchdog_timer( self, 500);
-                       iriap_getvaluebyclass_request( 
-                               self->daddr,
-                               "OBEX", 
-                               "IrDA:TinyTP:LsapSel",
-                               irobex_get_value_confirm,
-                               self);
-                       
-                       interruptible_sleep_on( &self->write_wait);
-                       del_timer( &self->watchdog_timer);
-               }       
-               
-               if ( !self->dtsap_sel) {
-                       DEBUG( 0, __FUNCTION__ 
-                              "(), Unable to query remote LM-IAS!\n");
-                       return -ENOTTY;
-               }
-
-               self->state = OBEX_CONN;
-               
-               /* Timeout after 5 secs. */
-               irobex_start_watchdog_timer( self, 500);
-
-               irttp_connect_request( self->tsap, self->dtsap_sel, 
-                                      self->daddr, NULL, SAR_DISABLE, 
-                                      NULL);
-               
-               /* Go to sleep and wait for connection!  */
-               interruptible_sleep_on( &self->write_wait);
-               del_timer( &self->watchdog_timer);
-               
-               if ( self->state != OBEX_DATA) {
-                       DEBUG( 0, __FUNCTION__ 
-                              "(), Unable to connect to remote device!\n");
-                       return -ENOTTY;
-               }
-               
+               return irobex_connect_request( self);           
                break;
        case IROBEX_IOCSDISCONNECT:
                DEBUG( 4, __FUNCTION__ "(): IROBEX_IOCSDISCONNECT!\n");
-
-               if ( self->state != OBEX_DATA)
-                       return 0;
-
-               irttp_disconnect_request( self->tsap, NULL, P_NORMAL);
-
-               /* Reset values for this instance */
-               self->state = OBEX_IDLE;
-               self->eof = LM_USER_REQUEST;
-               self->daddr = 0;
-               self->dtsap_sel = 0;
-               self->rx_flow = FLOW_START;
-               self->tx_flow = FLOW_START;
-               
-               wake_up_interruptible( &self->read_wait);
+               irobex_disconnect_request( self);
                break;
        default:
                return -EINVAL;
@@ -631,6 +561,7 @@ static int irobex_dev_close( struct inode *inode, struct file *file)
 
        /* Close TSAP is its still there */
        if ( self->tsap) {
+               irttp_disconnect_request(self->tsap, NULL, P_NORMAL);
                irttp_close_tsap( self->tsap);
                self->tsap = NULL;
        }
@@ -658,11 +589,11 @@ static int irobex_dev_close( struct inode *inode, struct file *file)
  *    device it is, and which services it has.
  *
  */
-void irobex_discovery_indication( DISCOVERY *discovery) 
+static void irobex_discovery_indication( DISCOVERY *discovery)
 {
        struct irobex_cb *self;
        
-       DEBUG( 4, __FUNCTION__ "()\n");
+       DEBUG( 0, __FUNCTION__ "()\n");
        
        self = irobex;
 
@@ -671,6 +602,7 @@ void irobex_discovery_indication( DISCOVERY *discovery)
 
        /* Remember address and time if was discovered */
        self->daddr = discovery->daddr;
+       self->saddr = discovery->saddr;
        self->time_discovered = jiffies;
        
        /* Wake up process if its waiting for device to be discovered */
@@ -678,18 +610,37 @@ void irobex_discovery_indication( DISCOVERY *discovery)
                wake_up_interruptible( &self->write_wait);
 }
 
+static void irobex_disconnect_request( struct irobex_cb *self)
+{
+       if ( self->state != OBEX_DATA)
+               return;
+       
+       irttp_disconnect_request( self->tsap, NULL, P_NORMAL);
+       
+       /* Reset values for this instance */
+       self->state = OBEX_IDLE;
+       self->eof = LM_USER_REQUEST;
+       self->daddr = 0;
+       self->dtsap_sel = 0;
+       self->rx_flow = FLOW_START;
+       self->tx_flow = FLOW_START;
+               
+       wake_up_interruptible( &self->read_wait);
+}
+
 /*
  * Function irobex_disconnect_indication (handle, reason, priv)
  *
  *    Link has been disconnected
  *
  */
-void irobex_disconnect_indication( void *instance, void *sap, 
-                                  LM_REASON reason, struct sk_buff *userdata)
+static void irobex_disconnect_indication( void *instance, void *sap, 
+                                         LM_REASON reason, 
+                                         struct sk_buff *userdata)
 {
        struct irobex_cb *self;
        
-       DEBUG( 4, __FUNCTION__ "(), reason=%d\n", reason);
+       DEBUG( 0, __FUNCTION__ "(), reason=%s\n", lmp_reasons[reason]);
        
        self = ( struct irobex_cb *) instance;
        
@@ -712,14 +663,105 @@ void irobex_disconnect_indication( void *instance, void *sap,
                dev_kfree_skb( userdata);
 }
 
+int irobex_connect_request(struct irobex_cb *self)
+{
+       int count = 0;
+
+       /* Already connected? */
+       if ( self->state == OBEX_DATA) {
+               DEBUG( 0, __FUNCTION__ "(), already connected!\n");
+               return 0;
+       }
+       
+       /* Timeout after 15 secs. */
+       irobex_start_watchdog_timer( self, 1000);
+       
+       /*
+        * If we have discovered a remote device we
+        * check if the discovery is still fresh. If not, we don't
+        * trust the address.
+        */
+       if ( self->daddr && ((jiffies - self->time_discovered) > 1000)) {
+               DEBUG( 0, __FUNCTION__ "(), daddr is old <%d>!\n",
+                      jiffies - self->time_discovered);
+               self->daddr = 0;
+       }
+       
+       /* 
+        * Try to discover remote remote device if it has not been 
+        * discovered yet. 
+        */
+       if ( !self->daddr) {
+               self->state = OBEX_DISCOVER;
+               
+               irlmp_discovery_request( 8);
+               
+               /* Wait for discovery to complete */
+               interruptible_sleep_on( &self->write_wait);
+               del_timer( &self->watchdog_timer);
+       }
+       
+       /* Give up if we are unable to discover any remote devices */
+       if ( !self->daddr) {
+               DEBUG( 0, __FUNCTION__ 
+                      "(), Unable to discover any devices!\n");
+               return -EHOSTUNREACH;
+       }
+       
+       /* Need to find remote destination TSAP selector? */
+       while ( !self->dtsap_sel) {
+               DEBUG( 0, __FUNCTION__ "() : Quering remote IAS!\n");
+               
+               self->state = OBEX_QUERY;
+               
+               /* Timeout after 5 secs. */
+               irobex_start_watchdog_timer( self, 500);
+               iriap_getvaluebyclass_request( 
+                       "OBEX", "IrDA:TinyTP:LsapSel",
+                       self->saddr, self->daddr,
+                       irobex_get_value_confirm,
+                       self);
+               
+               interruptible_sleep_on( &self->write_wait);
+               del_timer( &self->watchdog_timer);
+               
+               /* Give up after a few tries */
+               if (( count++ > 2) && !self->dtsap_sel) {
+                       DEBUG( 0, __FUNCTION__ 
+                              "(), Unable to query remote LM-IAS!\n");
+                       return -ETIMEDOUT;
+               }
+       }
+       self->state = OBEX_CONN;
+       
+       /* Timeout after 5 secs. */
+       irobex_start_watchdog_timer( self, 500);
+       
+       irttp_connect_request( self->tsap, self->dtsap_sel, 
+                              self->saddr, self->daddr, NULL, SAR_DISABLE, 
+                              NULL);
+       
+       /* Go to sleep and wait for connection!  */
+       interruptible_sleep_on( &self->write_wait);
+       del_timer( &self->watchdog_timer);
+       
+       if ( self->state != OBEX_DATA) {
+               DEBUG( 0, __FUNCTION__ 
+                      "(), Unable to connect to remote device!\n");
+               return -ETIMEDOUT;
+       }
+       return 0;
+}
+
 /*
  * Function irobex_connect_confirm (instance, sap, qos, userdata)
  *
  *    Connection to peer IrOBEX layer established
  *
  */
-void irobex_connect_confirm( void *instance, void *sap, struct qos_info *qos,
-                            int max_sdu_size, struct sk_buff *userdata)
+static void irobex_connect_confirm( void *instance, void *sap, 
+                                   struct qos_info *qos,
+                                   int max_sdu_size, struct sk_buff *userdata)
 {
        struct irobex_cb *self;
        
@@ -834,7 +876,8 @@ void irobex_connect_indication( void *instance, void *sap,
  *    This function gets the data that is received on the data channel
  *
  */
-void irobex_data_indication( void *instance, void *sap, struct sk_buff *skb) 
+static void irobex_data_indication( void *instance, void *sap, 
+                                   struct sk_buff *skb) 
 {
 
        struct irobex_cb *self;
@@ -876,7 +919,8 @@ void irobex_data_indication( void *instance, void *sap, struct sk_buff *skb)
  *    
  *
  */
-void irobex_flow_indication( void *instance, void *sap, LOCAL_FLOW flow) 
+static void irobex_flow_indication( void *instance, void *sap, 
+                                   LOCAL_FLOW flow) 
 {
        struct irobex_cb *self;
 
@@ -908,8 +952,8 @@ void irobex_flow_indication( void *instance, void *sap, LOCAL_FLOW flow)
  *    Got results from previous GetValueByClass request
  *
  */
-void irobex_get_value_confirm( __u16 obj_id, struct ias_value *value, 
-                              void *priv)
+static void irobex_get_value_confirm( __u16 obj_id, struct ias_value *value, 
+                                     void *priv)
 {
        struct irobex_cb *self;
        
@@ -919,7 +963,14 @@ void irobex_get_value_confirm( __u16 obj_id, struct ias_value *value,
        self = ( struct irobex_cb *) priv;
        
        if ( !self || self->magic != IROBEX_MAGIC) {
-               DEBUG( 0, "irobex_get_value_confirm: bad magic!\n");
+               DEBUG( 0, __FUNCTION__ "(), bad magic!\n");
+               return;
+       }
+
+       /* Check if request succeeded */
+       if ( !value) {
+               DEBUG( 0, __FUNCTION__ "(), got NULL value!\n");
+
                return;
        }
 
@@ -996,7 +1047,7 @@ void irobex_provider_confirm( struct irobex_cb *self, __u8 dlsap)
  *    must register both a TSAP for control and data
  * 
  */
-void irobex_register_server( struct irobex_cb *self)
+static void irobex_register_server( struct irobex_cb *self)
 {
        struct notify_t notify;
        struct ias_object *obj;
index bc6a3ace5c0136b89aa6577ed902b2e9f0e41b9d..977dd36a37b8aafd2bdb14455624aebadf34005f 100644 (file)
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Thomas Davis, <ratbert@radiks.net>
  * Created at:    Sat Feb 21 21:33:24 1998
- * Modified at:   Tue Dec 15 09:21:50 1998
+ * Modified at:   Thu Feb 11 15:23:23 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998, Thomas Davis, <ratbert@radiks.net>, 
 #include <net/irda/irlap.h>
 #include <net/irda/irlmp.h>
 
-static int proc_irda_21x_lookup(struct inode * dir, struct dentry *dentry);
+static int proc_irda_lookup(struct inode * dir, struct dentry *dentry);
 
 static int proc_irda_readdir(struct file *filp, void *dirent, 
                             filldir_t filldir);
 
-extern int irda_device_proc_read( char *buf, char **start, off_t offset, 
-                                 int len, int unused);
-extern int irlap_proc_read( char *buf, char **start, off_t offset, int len, 
-                           int unused);
-extern int irlmp_proc_read( char *buf, char **start, off_t offset, int len, 
-                           int unused);
-extern int irttp_proc_read( char *buf, char **start, off_t offset, int len, 
-                           int unused);
-extern int irias_proc_read( char *buf, char **start, off_t offset, int len,
-                           int unused);
+extern int irda_device_proc_read(char *buf, char **start, off_t offset, 
+                                int len, int unused);
+extern int irlap_proc_read(char *buf, char **start, off_t offset, int len, 
+                          int unused);
+extern int irlmp_proc_read(char *buf, char **start, off_t offset, int len, 
+                          int unused);
+extern int irttp_proc_read(char *buf, char **start, off_t offset, int len, 
+                          int unused);
+extern int irias_proc_read(char *buf, char **start, off_t offset, int len,
+                          int unused);
 
-static int proc_discovery_read( char *buf, char **start, off_t offset, int len,
-                               int unused);
-
-/* int proc_irda_readdir(struct inode *inode, struct file *filp, void *dirent,  */
-/*                   filldir_t filldir); */
+static int proc_discovery_read(char *buf, char **start, off_t offset, int len,
+                              int unused);
 
 enum irda_directory_inos {
        PROC_IRDA_LAP = 1,
@@ -82,7 +79,7 @@ static struct file_operations proc_irda_dir_operations = {
 struct inode_operations proc_irda_dir_inode_operations = {
         &proc_irda_dir_operations,   /* default net directory file-ops */
         NULL,                   /* create */
-       proc_irda_21x_lookup, 
+       proc_irda_lookup, 
         NULL,                   /* link */
         NULL,                   /* unlink */
         NULL,                   /* symlink */
@@ -186,13 +183,14 @@ static struct dentry_operations proc_dentry_operations =
  *
  */
 void irda_proc_register(void) {
-       proc_net_register( &proc_irda);
-       proc_register( &proc_irda, &proc_lap);
-       proc_register( &proc_irda, &proc_lmp);
-       proc_register( &proc_irda, &proc_ttp);
-       proc_register( &proc_irda, &proc_ias);
-       proc_register( &proc_irda, &proc_irda_device); 
-       proc_register( &proc_irda, &proc_discovery);
+       proc_net_register(&proc_irda);
+       proc_irda.fill_inode = &irda_proc_modcount;
+       proc_register(&proc_irda, &proc_lap);
+       proc_register(&proc_irda, &proc_lmp);
+       proc_register(&proc_irda, &proc_ttp);
+       proc_register(&proc_irda, &proc_ias);
+       proc_register(&proc_irda, &proc_irda_device); 
+       proc_register(&proc_irda, &proc_discovery);
 }
 
 /*
@@ -202,22 +200,22 @@ void irda_proc_register(void) {
  *
  */
 void irda_proc_unregister(void) {
-       proc_unregister( &proc_irda, proc_discovery.low_ino);
+       proc_unregister(&proc_irda, proc_discovery.low_ino);
        proc_unregister(&proc_irda, proc_irda_device.low_ino);
-       proc_unregister( &proc_irda, proc_ias.low_ino);
-       proc_unregister( &proc_irda, proc_ttp.low_ino);
-       proc_unregister( &proc_irda, proc_lmp.low_ino);
-       proc_unregister( &proc_irda, proc_lap.low_ino);
-       proc_unregister( proc_net, proc_irda.low_ino);
+       proc_unregister(&proc_irda, proc_ias.low_ino);
+       proc_unregister(&proc_irda, proc_ttp.low_ino);
+       proc_unregister(&proc_irda, proc_lmp.low_ino);
+       proc_unregister(&proc_irda, proc_lap.low_ino);
+       proc_unregister(proc_net, proc_irda.low_ino);
 }
 
 /*
- * Function proc_irda_21x_lookup (dir, dentry)
+ * Function proc_irda_lookup (dir, dentry)
  *
- *    This is a copy of proc_lookup from the linux-2.1.x 
+ *    This is a copy of proc_lookup from the linux-2.2.x kernel
  *
  */
-int proc_irda_21x_lookup(struct inode * dir, struct dentry *dentry)
+int proc_irda_lookup(struct inode * dir, struct dentry *dentry)
 {
        struct inode *inode;
        struct proc_dir_entry * de;
@@ -261,8 +259,8 @@ out:
  *    to the irda module
  * 
  */
-static int proc_irda_readdir( struct file *filp, void *dirent, 
-                             filldir_t filldir)
+static int proc_irda_readdir(struct file *filp, void *dirent, 
+                            filldir_t filldir)
 {
        struct proc_dir_entry * de;
        unsigned int ino;
@@ -319,8 +317,8 @@ static int proc_irda_readdir( struct file *filp, void *dirent,
  *    Print discovery information in /proc file system
  *
  */
-int proc_discovery_read( char *buf, char **start, off_t offset, int len, 
-                        int unused)
+int proc_discovery_read(char *buf, char **start, off_t offset, int len, 
+                       int unused)
 {
        DISCOVERY *discovery;
        struct lap_cb *lap;
index 3d23c8aef568ceafac773063f7756c9c52fb734c..8137c49a247e8f64febf672c6f3d19fe08fbf96d 100644 (file)
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Jun  9 13:29:31 1998
- * Modified at:   Wed Jan 13 21:21:22 1999
+ * Modified at:   Mon Feb  8 09:05:51 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (C) 1998, Aage Kvalnes <aage@cs.uit.no>
@@ -55,6 +55,8 @@ hashbin_t *hashbin_new( int type)
         * Allocate new hashbin
         */
        hashbin = kmalloc( sizeof(hashbin_t), GFP_ATOMIC);
+       if (!hashbin)
+               return NULL;
 
        /*
         * Initialize structure
@@ -205,13 +207,12 @@ void hashbin_unlock( hashbin_t* hashbin, __u32 hashv, char* name,
  *    Insert an entry into the hashbin
  *
  */
-void hashbin_insert( hashbin_t* hashbin, QUEUE* entry, __u32 hashv, 
-                    char* name)
+void hashbin_insert( hashbin_t* hashbin, QUEUE* entry, __u32 hashv, char* name)
 {
        unsigned long flags = 0;
        int bin;
 
-       DEBUG( 4, "hashbin_insert()\n");
+       DEBUG( 4, __FUNCTION__"()\n");
 
        ASSERT( hashbin != NULL, return;);
        ASSERT( hashbin->magic == HB_MAGIC, return;);
@@ -583,7 +584,7 @@ inline void enqueue_last( QUEUE **queue, QUEUE* element)
 void enqueue_first(QUEUE **queue, QUEUE* element)
 {
        
-       DEBUG( 4, "enqueue_first()\n");
+       DEBUG( 4, __FUNCTION__ "()\n");
 
        /*
         * Check if queue is empty.
index e8a3f99103880b949b5cef005a1a761ab62dfafb..7565138e94766490bf94c6c471d43729bb9626c0 100644 (file)
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun May 24 22:12:06 1998
- * Modified at:   Thu Jan  7 10:35:02 1999
+ * Modified at:   Mon Jan 25 13:55:54 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997 Dag Brattli, All Rights Reserved.
 #include <net/irda/irda.h>
 
 #define NET_IRDA 412 /* Random number */
-enum { DISCOVERY=1, DEVNAME, COMPRESSION, DEBUG };
+enum { DISCOVERY=1, DEVNAME, COMPRESSION, DEBUG, SLOTS, SLOT_TIMEOUT };
 
 extern int sysctl_discovery;
+extern int sysctl_discovery_slots;
+extern int sysctl_slot_timeout;
 int sysctl_compression = 0;
 extern char sysctl_devname[];
 
@@ -53,6 +55,10 @@ static ctl_table irda_table[] = {
        { DEBUG, "debug", &irda_debug,
          sizeof(int), 0644, NULL, &proc_dointvec },
 #endif
+       { SLOTS, "discovery_slots", &sysctl_discovery_slots,
+         sizeof(int), 0644, NULL, &proc_dointvec },
+       { SLOT_TIMEOUT, "slot_timeout", &sysctl_slot_timeout,
+         sizeof(int), 0644, NULL, &proc_dointvec },
        { 0 }
 };
 
index 3da804e7deb25567fde665e1231015e9eb9b6773..100b6b9581dbd6de81d6704155745651726a12ca 100644 (file)
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      irttp.c
- * Version:       0.4
+ * Version:       1.0
  * Description:   Tiny Transport Protocol (TTP) implementation
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Aug 31 20:14:31 1997
- * Modified at:   Tue Jan 19 23:56:58 1999
+ * Modified at:   Sat Feb 20 01:30:39 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, 
 
 struct irttp_cb *irttp = NULL;
 
-static void __irttp_close_tsap( struct tsap_cb *self);
+static void __irttp_close_tsap(struct tsap_cb *self);
 
-static void irttp_data_indication( void *instance, void *sap, 
+static void irttp_data_indication(void *instance, void *sap, 
+                                 struct sk_buff *skb);
+static void irttp_udata_indication(void *instance, void *sap, 
                                   struct sk_buff *skb);
-static void irttp_udata_indication( void *instance, void *sap, 
-                                   struct sk_buff *skb);
-static void irttp_disconnect_indication( void *instance, void *sap,  
-                                        LM_REASON reason,
-                                        struct sk_buff *);
-static void irttp_connect_indication( void *instance, void *sap, 
-                                     struct qos_info *qos, int max_sdu_size,
-                                     struct sk_buff *skb);
-
-static void irttp_run_tx_queue( struct tsap_cb *self);
-static void irttp_run_rx_queue( struct tsap_cb *self);
-
-static void irttp_flush_queues( struct tsap_cb *self);
-static void irttp_fragment_skb( struct tsap_cb *self, struct sk_buff *skb);
-static struct sk_buff *irttp_reassemble_skb( struct tsap_cb *self);
-static void irttp_start_todo_timer( struct tsap_cb *self, int timeout);
+static void irttp_disconnect_indication(void *instance, void *sap,  
+                                       LM_REASON reason,
+                                       struct sk_buff *);
+static void irttp_connect_indication(void *instance, void *sap, 
+                                    struct qos_info *qos, int max_sdu_size,
+                                    struct sk_buff *skb);
+
+static void irttp_run_tx_queue(struct tsap_cb *self);
+static void irttp_run_rx_queue(struct tsap_cb *self);
+
+static void irttp_flush_queues(struct tsap_cb *self);
+static void irttp_fragment_skb(struct tsap_cb *self, struct sk_buff *skb);
+static struct sk_buff *irttp_reassemble_skb(struct tsap_cb *self);
+static void irttp_start_todo_timer(struct tsap_cb *self, int timeout);
 
 /*
  * Function irttp_init (void)
@@ -64,21 +64,19 @@ static void irttp_start_todo_timer( struct tsap_cb *self, int timeout);
  */
 __initfunc(int irttp_init(void))
 {
-       DEBUG( 4, "--> irttp_init\n");
-
        /* Initialize the irttp structure. */
-       if ( irttp == NULL) {
-               irttp = kmalloc( sizeof(struct irttp_cb), GFP_KERNEL);
-               if ( irttp == NULL)
+       if (irttp == NULL) {
+               irttp = kmalloc(sizeof(struct irttp_cb), GFP_KERNEL);
+               if (irttp == NULL)
                        return -ENOMEM;
        }
-       memset( irttp, 0, sizeof(struct irttp_cb));
-
+       memset(irttp, 0, sizeof(struct irttp_cb));
+       
        irttp->magic = TTP_MAGIC;
 
-       irttp->tsaps = hashbin_new( HB_LOCAL);
-       if ( !irttp->tsaps) {
-               printk( KERN_WARNING "IrDA: Can't allocate IrTTP hashbin!\n");
+       irttp->tsaps = hashbin_new(HB_LOCAL);
+       if (!irttp->tsaps) {
+               printk(KERN_WARNING "IrDA: Can't allocate IrTTP hashbin!\n");
                return -ENOMEM;
        }
        
@@ -91,69 +89,69 @@ __initfunc(int irttp_init(void))
  *    Called by module destruction/cleanup code
  *
  */
+#ifdef MODULE
 void irttp_cleanup(void) 
 {
-       DEBUG( 4, "irttp_cleanup\n");
-       
        /* Check for main structure */
-       ASSERT( irttp != NULL, return;);
-       ASSERT( irttp->magic == TTP_MAGIC, return;);
+       ASSERT(irttp != NULL, return;);
+       ASSERT(irttp->magic == TTP_MAGIC, return;);
        
        /*
         *  Delete hashbin and close all TSAP instances in it
         */
-       hashbin_delete( irttp->tsaps, (FREE_FUNC) __irttp_close_tsap);
+       hashbin_delete(irttp->tsaps, (FREE_FUNC) __irttp_close_tsap);
 
-       irttp->magic = ~TTP_MAGIC;
+       irttp->magic = 0;
        
        /* De-allocate main structure */
-       kfree( irttp);
+       kfree(irttp);
 
        irttp = NULL;
 }
+#endif
 
 /*
  * Function irttp_open_tsap (stsap, notify)
  *
  *    Create TSAP connection endpoint,
  */
-struct tsap_cb *irttp_open_tsap( __u8 stsap_sel, int credit, 
-                                struct notify_t *notify) 
+struct tsap_cb *irttp_open_tsap(__u8 stsap_sel, int credit, 
+                               struct notify_t *notify) 
 {
        struct notify_t ttp_notify;
        struct tsap_cb *self;
        struct lsap_cb *lsap;
 
-       ASSERT( irttp != NULL, return NULL;);
-       ASSERT( irttp->magic == TTP_MAGIC, return NULL;);
+       ASSERT(irttp != NULL, return NULL;);
+       ASSERT(irttp->magic == TTP_MAGIC, return NULL;);
 
-       self = kmalloc( sizeof(struct tsap_cb), GFP_ATOMIC);
-       if ( self == NULL) {
-               printk( KERN_ERR "IrTTP: Can't allocate memory for "
+       self = kmalloc(sizeof(struct tsap_cb), GFP_ATOMIC);
+       if (self == NULL) {
+               printk(KERN_ERR "IrTTP: Can't allocate memory for "
                        "TSAP control block!\n");
                return NULL;
        }
-       memset( self, 0, sizeof(struct tsap_cb));
+       memset(self, 0, sizeof(struct tsap_cb));
 
-       init_timer( &self->todo_timer);
+       init_timer(&self->todo_timer);
 
        /* Initialize callbacks for IrLMP to use */
 
-       irda_notify_init( &ttp_notify);
+       irda_notify_init(&ttp_notify);
        ttp_notify.connect_confirm = irttp_connect_confirm;
        ttp_notify.connect_indication = irttp_connect_indication;
        ttp_notify.disconnect_indication = irttp_disconnect_indication;
        ttp_notify.data_indication = irttp_data_indication;
        ttp_notify.udata_indication = irttp_udata_indication;
        ttp_notify.instance = self;
-       strncpy( ttp_notify.name, notify->name, NOTIFY_MAX_NAME);
+       strncpy(ttp_notify.name, notify->name, NOTIFY_MAX_NAME);
 
        /*
         *  Create LSAP at IrLMP layer
         */
-       lsap = irlmp_open_lsap( stsap_sel, &ttp_notify);
-       if ( lsap == NULL) {
-               printk( KERN_ERR "IrTTP, Unable to get LSAP!!\n");
+       lsap = irlmp_open_lsap(stsap_sel, &ttp_notify);
+       if (lsap == NULL) {
+               printk(KERN_ERR "IrTTP, Unable to get LSAP!!\n");
                return NULL;
        }
        
@@ -163,22 +161,23 @@ struct tsap_cb *irttp_open_tsap( __u8 stsap_sel, int credit,
         *  the stsap_sel we have might not be valid anymore
         */
        self->stsap_sel = lsap->slsap_sel;
-       DEBUG( 4, __FUNCTION__ "(), stsap_sel=%02x\n", self->stsap_sel);
+       DEBUG(4, __FUNCTION__ "(), stsap_sel=%02x\n", self->stsap_sel);
 
        self->notify = *notify;
        self->lsap = lsap;
        self->magic = TTP_TSAP_MAGIC;
+       self->connected = FALSE;
 
-       skb_queue_head_init( &self->rx_queue);
-       skb_queue_head_init( &self->tx_queue);
-       skb_queue_head_init( &self->rx_fragments);
+       skb_queue_head_init(&self->rx_queue);
+       skb_queue_head_init(&self->tx_queue);
+       skb_queue_head_init(&self->rx_fragments);
 
        /*
         *  Insert ourself into the hashbin
         */
-       hashbin_insert( irttp->tsaps, (QUEUE *) self, self->stsap_sel, NULL);
+       hashbin_insert(irttp->tsaps, (QUEUE *) self, self->stsap_sel, NULL);
 
-       if ( credit > TTP_MAX_QUEUE)
+       if (credit > TTP_MAX_QUEUE)
                self->initial_credit = TTP_MAX_QUEUE;
        else
                self->initial_credit = credit;
@@ -193,27 +192,22 @@ struct tsap_cb *irttp_open_tsap( __u8 stsap_sel, int credit,
  *    deallocation of the TSAP, and resetting of the TSAPs values;
  *
  */
-static void __irttp_close_tsap( struct tsap_cb *self)
+static void __irttp_close_tsap(struct tsap_cb *self)
 {
-       DEBUG( 4, __FUNCTION__ "()\n");
+       DEBUG(4, __FUNCTION__ "()\n");
 
        /* First make sure we're connected. */
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
 
-       irttp_flush_queues( self);
+       irttp_flush_queues(self);
 
-       del_timer( &self->todo_timer);
+       del_timer(&self->todo_timer);
 
        self->connected = FALSE;
        self->magic = ~TTP_TSAP_MAGIC;
 
-       /*
-        *  Deallocate structure
-        */
-       kfree( self);
-
-       DEBUG( 4, "irttp_close_tsap() -->\n");
+       kfree(self);
 }
 
 /*
@@ -223,24 +217,41 @@ static void __irttp_close_tsap( struct tsap_cb *self)
  *    associated with this TSAP
  *
  */
-void irttp_close_tsap( struct tsap_cb *self)
+int irttp_close_tsap(struct tsap_cb *self)
 {
        struct tsap_cb *tsap;
 
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
+       DEBUG(4, __FUNCTION__ "()\n");
+
+       ASSERT(self != NULL, return -1;);
+       ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
+
+       /* Make sure tsap has been disconnected */
+       if (self->connected) {
+               /* Check if disconnect is not pending */
+               if (!self->disconnect_pend) {
+                       DEBUG(0, __FUNCTION__ "(), TSAP still connected!\n");
+                       irttp_disconnect_request(self, NULL, P_NORMAL);
+               }
+               self->close_pend = TRUE;
+               irttp_start_todo_timer(self, 100);
 
-       tsap = hashbin_remove( irttp->tsaps, self->stsap_sel, NULL);
+               return 0; /* Will be back! */
+       }
+       
+       tsap = hashbin_remove(irttp->tsaps, self->stsap_sel, NULL);
 
-       ASSERT( tsap == self, return;);
+       ASSERT(tsap == self, return -1;);
 
        /* Close corresponding LSAP */
-       if ( self->lsap) {
-               irlmp_close_lsap( self->lsap);
+       if (self->lsap) {
+               irlmp_close_lsap(self->lsap);
                self->lsap = NULL;
        }
 
-       __irttp_close_tsap( self);
+       __irttp_close_tsap(self);
+
+       return 0;
 }
 
 /*
@@ -249,26 +260,26 @@ void irttp_close_tsap( struct tsap_cb *self)
  *    Send unreliable data on this TSAP
  *
  */
-int irttp_udata_request( struct tsap_cb *self, struct sk_buff *skb) 
+int irttp_udata_request(struct tsap_cb *self, struct sk_buff *skb) 
 {
-       ASSERT( self != NULL, return -1;);
-       ASSERT( self->magic == TTP_TSAP_MAGIC, return -1;);
-       ASSERT( skb != NULL, return -1;);
+       ASSERT(self != NULL, return -1;);
+       ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
+       ASSERT(skb != NULL, return -1;);
 
-       DEBUG( 4, __FUNCTION__ "()\n");
+       DEBUG(4, __FUNCTION__ "()\n");
 
        /* Check that nothing bad happens */
-       if (( skb->len == 0) || ( !self->connected)) {
-               DEBUG( 0, __FUNCTION__ "(), No data, or not connected\n");
+       if ((skb->len == 0) || (!self->connected)) {
+               DEBUG(1, __FUNCTION__ "(), No data, or not connected\n");
                return -1;
        }
        
-       if ( skb->len > self->max_seg_size) {
-               DEBUG( 0, __FUNCTION__ "(), UData is to large for IrLAP!\n");
+       if (skb->len > self->max_seg_size) {
+               DEBUG(1, __FUNCTION__ "(), UData is to large for IrLAP!\n");
                return -1;
        }
                    
-       irlmp_udata_request( self->lsap, skb);
+       irlmp_udata_request(self->lsap, skb);
        self->stats.tx_packets++;
 
        return 0;
@@ -280,19 +291,19 @@ int irttp_udata_request( struct tsap_cb *self, struct sk_buff *skb)
  *    Queue frame for transmission. If SAR is enabled, fragement the frame 
  *    and queue the fragments for transmission
  */
-int irttp_data_request( struct tsap_cb *self, struct sk_buff *skb) 
+int irttp_data_request(struct tsap_cb *self, struct sk_buff *skb) 
 {
        __u8 *frame;
 
-       DEBUG( 4, __FUNCTION__ "()\n");
+       DEBUG(4, __FUNCTION__ "()\n");
 
-       ASSERT( self != NULL, return -1;);
-       ASSERT( self->magic == TTP_TSAP_MAGIC, return -1;);
-       ASSERT( skb != NULL, return -1;);
+       ASSERT(self != NULL, return -1;);
+       ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);
+       ASSERT(skb != NULL, return -1;);
 
        /* Check that nothing bad happens */
-       if (( skb->len == 0) || ( !self->connected)) {
-               DEBUG( 4, __FUNCTION__ "(), No data, or not connected\n");
+       if ((skb->len == 0) || (!self->connected)) {
+               DEBUG(4, __FUNCTION__ "(), No data, or not connected\n");
                return -1;
        }
 
@@ -300,10 +311,8 @@ int irttp_data_request( struct tsap_cb *self, struct sk_buff *skb)
         *  Check if SAR is disabled, and the frame is larger than what fits
         *  inside an IrLAP frame
         */
-       if (( self->tx_max_sdu_size == 0) && 
-           ( skb->len > self->max_seg_size)) 
-       {
-               DEBUG( 0, __FUNCTION__ 
+       if ((self->tx_max_sdu_size == 0) && (skb->len > self->max_seg_size)) {
+               DEBUG(1, __FUNCTION__ 
                       "(), SAR disabled, and data is to large for IrLAP!\n");
                return -1;
        }
@@ -312,34 +321,33 @@ int irttp_data_request( struct tsap_cb *self, struct sk_buff *skb)
         *  Check if SAR is enabled, and the frame is larger than the 
         *  TxMaxSduSize 
         */
-       if (( self->tx_max_sdu_size != 0) && 
+       if ((self->tx_max_sdu_size != 0) && 
            (skb->len > self->tx_max_sdu_size))
        {
-               DEBUG( 0, __FUNCTION__ "(), SAR enabled, "
+               DEBUG(1, __FUNCTION__ "(), SAR enabled, "
                       "but data is larger than TxMaxSduSize!\n");
                return -1;
        }
        /* 
         *  Check if transmit queue is full
         */
-       if ( skb_queue_len( &self->tx_queue) >= TTP_MAX_QUEUE) {
+       if (skb_queue_len(&self->tx_queue) >= TTP_MAX_QUEUE) {
                /*
                 *  Give it a chance to empty itself
                 */
-               irttp_run_tx_queue( self);
+               irttp_run_tx_queue(self);
                
                return -1;
        }
        
        /* Queue frame, or queue frame segments */
-       if (( self->tx_max_sdu_size == 0) || 
-           ( skb->len < self->max_seg_size)) {
+       if ((self->tx_max_sdu_size == 0) || (skb->len < self->max_seg_size)) {
                /* Queue frame */
-               frame = skb_push( skb, TTP_HEADER);
+               frame = skb_push(skb, TTP_HEADER);
                frame[0] = 0x00; /* Clear more bit */
                
-               DEBUG( 4, __FUNCTION__ "(), queueing original skb\n");
-               skb_queue_tail( &self->tx_queue, skb);
+               DEBUG(4, __FUNCTION__ "(), queueing original skb\n");
+               skb_queue_tail(&self->tx_queue, skb);
        } else {
                /*
                 *  Fragment the frame, this function will also queue the
@@ -347,25 +355,24 @@ int irttp_data_request( struct tsap_cb *self, struct sk_buff *skb)
                 *  queue may be overfilled by all the segments for a little
                 *  while
                 */
-               irttp_fragment_skb( self, skb);
+               irttp_fragment_skb(self, skb);
        }
 
        /* Check if we can accept more data from client */
-       if (( !self->tx_sdu_busy) && 
-           ( skb_queue_len( &self->tx_queue) > HIGH_THRESHOLD)) {
+       if ((!self->tx_sdu_busy) && 
+           (skb_queue_len(&self->tx_queue) > HIGH_THRESHOLD)) {
                
                /* Tx queue filling up, so stop client */
                self->tx_sdu_busy = TRUE;
                
-               if ( self->notify.flow_indication) {
-                       self->notify.flow_indication( self->notify.instance, 
-                                                     self, 
-                                                     FLOW_STOP);
+               if (self->notify.flow_indication) {
+                       self->notify.flow_indication(
+                               self->notify.instance, self, FLOW_STOP);
                }
        }
        
        /* Try to make some progress */
-       irttp_run_tx_queue( self);
+       irttp_run_tx_queue(self);
        
        return 0;
 }
@@ -376,40 +383,40 @@ int irttp_data_request( struct tsap_cb *self, struct sk_buff *skb)
  *    If possible, transmit a frame queued for transmission.
  *
  */
-static void irttp_run_tx_queue( struct tsap_cb *self) 
+static void irttp_run_tx_queue(struct tsap_cb *self) 
 {
        struct sk_buff *skb = NULL;
        unsigned long flags;
        __u8 *frame;
        int n;
 
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
-
-       if ( irda_lock( &self->tx_queue_lock) == FALSE)
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
+       
+       if (irda_lock(&self->tx_queue_lock) == FALSE)
                return;
 
-       while (( self->send_credit > 0) && !skb_queue_empty( &self->tx_queue)){
+       while ((self->send_credit > 0) && !skb_queue_empty(&self->tx_queue)){
 
-               skb = skb_dequeue( &self->tx_queue);
-               ASSERT( skb != NULL, return;);
+               skb = skb_dequeue(&self->tx_queue);
+               ASSERT(skb != NULL, return;);
                
                /* Make room for TTP header */
-               ASSERT( skb_headroom( skb) >= TTP_HEADER, return;);
+               ASSERT(skb_headroom(skb) >= TTP_HEADER, return;);
                                
                /*
                 *  Since we can transmit and receive frames concurrently, 
                 *  the code below is a critical region and we must assure that
                 *  nobody messes with the credits while we update them.
                 */
-               save_flags( flags); 
+               save_flags(flags); 
                cli();
 
                n = self->avail_credit;
                self->avail_credit = 0;
                
                /* Only space for 127 credits in frame */
-               if ( n > 127) {
+               if (n > 127) {
                        self->avail_credit = n-127;
                        n = 127;
                }
@@ -418,7 +425,7 @@ static void irttp_run_tx_queue( struct tsap_cb *self)
 
                restore_flags(flags);
 
-               DEBUG( 4, "irttp_xmit: Giving away %d credits\n", n);
+               DEBUG(4, "irttp_xmit: Giving away %d credits\n", n);
                
                /* 
                 *  More bit must be set by the data_request() or fragment() 
@@ -426,38 +433,27 @@ static void irttp_run_tx_queue( struct tsap_cb *self)
                 */
                frame = skb->data;
 
-               DEBUG( 4, __FUNCTION__ "(), More=%s\n", frame[0] & 0x80 ? 
+               DEBUG(4, __FUNCTION__ "(), More=%s\n", frame[0] & 0x80 ? 
                       "TRUE" : "FALSE" );
 
                frame[0] |= (__u8) (n & 0x7f);
                
-               irlmp_data_request( self->lsap, skb);
+               irlmp_data_request(self->lsap, skb);
                self->stats.tx_packets++;
 
                /* Check if we can accept more frames from client */
-               if (( self->tx_sdu_busy) && 
-                   ( skb_queue_len( &self->tx_queue) < LOW_THRESHOLD)) { 
+               if ((self->tx_sdu_busy) && 
+                   (skb_queue_len(&self->tx_queue) < LOW_THRESHOLD)) { 
                        self->tx_sdu_busy = FALSE;
                        
-                       if ( self->notify.flow_indication)
-                               self->notify.flow_indication( self->notify.instance, 
-                                                             self, 
-                                                             FLOW_START);
+                       if (self->notify.flow_indication)
+                               self->notify.flow_indication(
+                                     self->notify.instance, self, FLOW_START);
                }
        }
        
        /* Reset lock */
        self->tx_queue_lock = 0;
-
-       /* Check if there is any disconnect request pending */
-       if ( self->disconnect_pend) {
-               if ( self->disconnect_skb) {
-                       irttp_disconnect_request( self, self->disconnect_skb,
-                                                 P_NORMAL);
-                       self->disconnect_skb = NULL;
-               } else
-                       irttp_disconnect_request( self, NULL, P_NORMAL);
-       }
 }
 
 /*
@@ -466,42 +462,39 @@ static void irttp_run_tx_queue( struct tsap_cb *self)
  *    Send a dataless flowdata TTP-PDU and give available credit to peer
  *    TSAP
  */
-void irttp_give_credit( struct tsap_cb *self) 
+void irttp_give_credit(struct tsap_cb *self) 
 {
        struct sk_buff *tx_skb = NULL;
        unsigned long flags;
        int n;
 
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == TTP_TSAP_MAGIC, return;);        
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == TTP_TSAP_MAGIC, return;); 
 
-       DEBUG( 4, "irttp_give_credit() send=%d,avail=%d,remote=%d\n", 
+       DEBUG(4, __FUNCTION__ "() send=%d,avail=%d,remote=%d\n", 
               self->send_credit, self->avail_credit, self->remote_credit);
        
        /* Give credit to peer */
-       tx_skb = dev_alloc_skb( 64);
-       if ( tx_skb == NULL) {
-               DEBUG( 0, "irttp_give_credit: "
-                      "Could not allocate an sk_buff of length %d\n", 64);
+       tx_skb = dev_alloc_skb(64);
+       if (!tx_skb)
                return;
-       }
 
        /* Reserve space for LMP, and LAP header */
-       skb_reserve( tx_skb, LMP_HEADER+LAP_HEADER);
+       skb_reserve(tx_skb, LMP_HEADER+LAP_HEADER);
 
        /*
         *  Since we can transmit and receive frames concurrently, 
         *  the code below is a critical region and we must assure that
         *  nobody messes with the credits while we update them.
         */
-       save_flags( flags);
+       save_flags(flags);
        cli();
 
        n = self->avail_credit;
        self->avail_credit = 0;
        
        /* Only space for 127 credits in frame */
-       if ( n > 127) {
+       if (n > 127) {
                self->avail_credit = n - 127;
                n = 127;
        }
@@ -509,10 +502,10 @@ void irttp_give_credit( struct tsap_cb *self)
 
        restore_flags(flags);
 
-       skb_put( tx_skb, 1);
-       tx_skb->data[0] = (__u8) ( n & 0x7f);
+       skb_put(tx_skb, 1);
+       tx_skb->data[0] = (__u8) (n & 0x7f);
        
-       irlmp_data_request( self->lsap, tx_skb);
+       irlmp_data_request(self->lsap, tx_skb);
        self->stats.tx_packets++;
 }
 
@@ -522,22 +515,21 @@ void irttp_give_credit( struct tsap_cb *self)
  *    
  *
  */
-void irttp_udata_indication( void *instance, void *sap, struct sk_buff *skb) 
+void irttp_udata_indication(void *instance, void *sap, struct sk_buff *skb) 
 {
        struct tsap_cb *self;
 
-       DEBUG( 4, __FUNCTION__ "()\n");
+       DEBUG(4, __FUNCTION__ "()\n");
 
        self = (struct tsap_cb *) instance;
 
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
-       ASSERT( skb != NULL, return;);
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
+       ASSERT(skb != NULL, return;);
 
        /* Just pass data to layer above */
-       if ( self->notify.udata_indication) {
-               self->notify.udata_indication( self->notify.instance, self, 
-                                              skb);
+       if (self->notify.udata_indication) {
+               self->notify.udata_indication(self->notify.instance, self, skb);
        }
        self->stats.rx_packets++;
 }
@@ -548,7 +540,7 @@ void irttp_udata_indication( void *instance, void *sap, struct sk_buff *skb)
  *    Receive segment from IrLMP. 
  *
  */
-void irttp_data_indication( void *instance, void *sap, struct sk_buff *skb)
+void irttp_data_indication(void *instance, void *sap, struct sk_buff *skb)
 {
        struct tsap_cb *self;
        int more;
@@ -557,16 +549,16 @@ void irttp_data_indication( void *instance, void *sap, struct sk_buff *skb)
        
        self = (struct tsap_cb *) instance;
 
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
-       ASSERT( skb != NULL, return;);
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
+       ASSERT(skb != NULL, return;);
 
        frame = skb->data;
        
        n = frame[0] & 0x7f;     /* Extract the credits */
        more = frame[0] & 0x80;
 
-       DEBUG( 4, __FUNCTION__"(), got %d credits, TSAP sel=%02x\n", 
+       DEBUG(4, __FUNCTION__"(), got %d credits, TSAP sel=%02x\n", 
               n, self->stsap_sel);
 
        self->stats.rx_packets++;
@@ -575,7 +567,7 @@ void irttp_data_indication( void *instance, void *sap, struct sk_buff *skb)
         *  Data or dataless frame? Dataless frames only contain the 
         *  TTP_HEADER
         */
-       if ( skb->len == 1) {
+       if (skb->len == 1) {
                /* Dataless flowdata TTP-PDU */
                self->send_credit += n;
        } else {
@@ -587,27 +579,27 @@ void irttp_data_indication( void *instance, void *sap, struct sk_buff *skb)
                 *  We don't remove the TTP header, since we must preserve the
                 *  more bit, so the defragment routing knows what to do
                 */
-               skb_queue_tail( &self->rx_queue, skb);
+               skb_queue_tail(&self->rx_queue, skb);
        } 
 
-       irttp_run_rx_queue( self);
+       irttp_run_rx_queue(self);
 
        /* 
         *  Give avay some credits to peer? 
         */
-       if (( skb_queue_empty( &self->tx_queue)) && 
-           ( self->remote_credit < LOW_THRESHOLD) && 
-           ( self->avail_credit > 0)) 
+       if ((skb_queue_empty(&self->tx_queue)) && 
+           (self->remote_credit < LOW_THRESHOLD) && 
+           (self->avail_credit > 0)) 
        {
                /* Schedule to start immediately after this thread */
-               irttp_start_todo_timer( self, 0);
+               irttp_start_todo_timer(self, 0);
        }
 
        /* If peer has given us some credites and we didn't have anyone
          * from before, the we need to shedule the tx queue? 
         */
-       if ( self->send_credit == n)
-               irttp_start_todo_timer( self, 0);
+       if (self->send_credit == n)
+               irttp_start_todo_timer(self, 0);
 }
 
 /*
@@ -617,26 +609,26 @@ void irttp_data_indication( void *instance, void *sap, struct sk_buff *skb)
  *    delivering frames if the receive queues are starting to get full, or 
  *    to tell IrTTP to start delivering frames again.
  */
-void irttp_flow_request( struct tsap_cb *self, LOCAL_FLOW flow)
+void irttp_flow_request(struct tsap_cb *self, LOCAL_FLOW flow)
 {
-       DEBUG( 0, __FUNCTION__ "()\n");
+       DEBUG(1, __FUNCTION__ "()\n");
 
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
 
-       switch ( flow) {
+       switch (flow) {
        case FLOW_STOP:
-               DEBUG( 0, __FUNCTION__ "(), flow stop\n");
+               DEBUG(1, __FUNCTION__ "(), flow stop\n");
                self->rx_sdu_busy = TRUE;
                break;
        case FLOW_START:
-               DEBUG( 0, __FUNCTION__ "(), flow start\n");
+               DEBUG(1, __FUNCTION__ "(), flow start\n");
                self->rx_sdu_busy = FALSE;
                
-               irttp_run_rx_queue( self);
+               irttp_run_rx_queue(self);
                break;
        default:
-               DEBUG( 0, __FUNCTION__ "(), Unknown flow command!\n");
+               DEBUG(1, __FUNCTION__ "(), Unknown flow command!\n");
        }
 }
        
@@ -646,37 +638,35 @@ void irttp_flow_request( struct tsap_cb *self, LOCAL_FLOW flow)
  *    Try to connect to remote destination TSAP selector
  *
  */
-void irttp_connect_request( struct tsap_cb *self, __u8 dtsap_sel, __u32 daddr,
-                           struct qos_info *qos, int max_sdu_size, 
-                           struct sk_buff *userdata) 
+void irttp_connect_request(struct tsap_cb *self, __u8 dtsap_sel, 
+                          __u32 saddr, __u32 daddr,
+                          struct qos_info *qos, int max_sdu_size, 
+                          struct sk_buff *userdata) 
 {
        struct sk_buff *skb;
        __u8 *frame;
        __u8 n;
        
-       DEBUG( 4, __FUNCTION__ "(), max_sdu_size=%d\n", max_sdu_size); 
+       DEBUG(4, __FUNCTION__ "(), max_sdu_size=%d\n", max_sdu_size); 
        
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
 
        /* Any userdata supplied? */
-       if ( userdata == NULL) {
-               skb = dev_alloc_skb( 64);
-               if (skb == NULL) {
-                       DEBUG( 0, __FUNCTION__ "Could not allocate an "
-                              "sk_buff of length %d\n", 64);
+       if (userdata == NULL) {
+               skb = dev_alloc_skb(64);
+               if (!skb) 
                        return;
-               }
                
                /* Reserve space for MUX_CONTROL and LAP header */
-               skb_reserve( skb, (TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER));
+               skb_reserve(skb, (TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER));
        } else {
                skb = userdata;
                /*  
                 *  Check that the client has reserved enough space for 
                 *  headers
                 */
-               ASSERT( skb_headroom( userdata) >= 
+               ASSERT(skb_headroom(userdata) >= 
                        (TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER), return;);
        }
 
@@ -696,7 +686,7 @@ void irttp_connect_request( struct tsap_cb *self, __u8 dtsap_sel, __u32 daddr,
        /*
         *  Give away max 127 credits for now
         */
-       if ( n > 127) {
+       if (n > 127) {
                self->avail_credit=n-127;
                n = 127;
        }
@@ -704,29 +694,29 @@ void irttp_connect_request( struct tsap_cb *self, __u8 dtsap_sel, __u32 daddr,
        self->remote_credit = n;
 
        /* SAR enabled? */
-       if ( max_sdu_size > 0) {
-               ASSERT( skb_headroom( skb) >= 
+       if (max_sdu_size > 0) {
+               ASSERT(skb_headroom(skb) >= 
                        (TTP_HEADER_WITH_SAR+LMP_CONTROL_HEADER+LAP_HEADER), 
                        return;);
 
                /* Insert SAR parameters */
-               frame = skb_push( skb, TTP_HEADER_WITH_SAR);
+               frame = skb_push(skb, TTP_HEADER_WITH_SAR);
                
                frame[0] = TTP_PARAMETERS | n; 
                frame[1] = 0x04; /* Length */
                frame[2] = 0x01; /* MaxSduSize */
                frame[3] = 0x02; /* Value length */
-               *((__u16 *) (frame+4))= htons( max_sdu_size); /* Big endian! */
+               *((__u16 *) (frame+4))= htons(max_sdu_size); /* Big endian! */
        } else {
                /* Insert plain TTP header */
-               frame = skb_push( skb, TTP_HEADER);
+               frame = skb_push(skb, TTP_HEADER);
                
                /* Insert initial credit in frame */
                frame[0] = n & 0x7f;
        }
 
        /* Connect with IrLMP. No QoS parameters for now */
-       irlmp_connect_request( self->lsap, dtsap_sel, daddr, qos, skb);
+       irlmp_connect_request(self->lsap, dtsap_sel, saddr, daddr, qos, skb);
 }
 
 /*
@@ -735,24 +725,21 @@ void irttp_connect_request( struct tsap_cb *self, __u8 dtsap_sel, __u32 daddr,
  *    Sevice user confirms TSAP connection with peer. 
  *
  */
-void irttp_connect_confirm( void *instance, void *sap, struct qos_info *qos,
-                           int max_seg_size, struct sk_buff *skb) 
+void irttp_connect_confirm(void *instance, void *sap, struct qos_info *qos,
+                          int max_seg_size, struct sk_buff *skb) 
 {
        struct tsap_cb *self;
        __u8 *frame;
        __u8 n;
        int parameters;
 
-       DEBUG( 4, __FUNCTION__ "()\n");
+       DEBUG(4, __FUNCTION__ "()\n");
        
        self = (struct tsap_cb *) instance;
 
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
-       ASSERT( skb != NULL, return;);
-
-       /* FIXME: just remove this when we know its working */
-       ASSERT( max_seg_size == qos->data_size.value, return;);
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
+       ASSERT(skb != NULL, return;);
 
        self->max_seg_size = max_seg_size-LMP_HEADER-LAP_HEADER;
 
@@ -760,40 +747,40 @@ void irttp_connect_confirm( void *instance, void *sap, struct qos_info *qos,
         *  Check if we have got some QoS parameters back! This should be the
         *  negotiated QoS for the link.
         */
-       if ( qos) {
-               DEBUG( 4, "IrTTP, Negotiated BAUD_RATE: %02x\n", 
+       if (qos) {
+               DEBUG(4, "IrTTP, Negotiated BAUD_RATE: %02x\n", 
                       qos->baud_rate.bits);                    
-               DEBUG( 4, "IrTTP, Negotiated BAUD_RATE: %d bps.\n", 
+               DEBUG(4, "IrTTP, Negotiated BAUD_RATE: %d bps.\n", 
                       qos->baud_rate.value);
        }
 
        frame = skb->data;
        n = frame[0] & 0x7f;
        
-       DEBUG( 4, __FUNCTION__ "(), Initial send_credit=%d\n", n);
+       DEBUG(4, __FUNCTION__ "(), Initial send_credit=%d\n", n);
        
        self->send_credit = n;
        self->tx_max_sdu_size = 0;
        self->connected = TRUE;
 
        parameters = frame[0] & 0x80;   
-       if ( parameters) {
-               DEBUG( 4, __FUNCTION__ "(), Contains parameters!\n");
+       if (parameters) {
+               DEBUG(4, __FUNCTION__ "(), Contains parameters!\n");
                
                self->tx_max_sdu_size = ntohs(*(__u16 *)(frame+4));
-               DEBUG( 4, __FUNCTION__ "(), RxMaxSduSize=%d\n", 
+               DEBUG(4, __FUNCTION__ "(), RxMaxSduSize=%d\n", 
                       self->tx_max_sdu_size);
        }
        
-       DEBUG( 4, "irttp_connect_confirm() send=%d,avail=%d,remote=%d\n", 
-              self->send_credit, self->avail_credit, self->remote_credit);
+       DEBUG(4, __FUNCTION__ "() send=%d,avail=%d,remote=%d\n", 
+             self->send_credit, self->avail_credit, self->remote_credit);
 
-       skb_pull( skb, TTP_HEADER);
+       skb_pull(skb, TTP_HEADER);
 
-       if ( self->notify.connect_confirm) {
-               self->notify.connect_confirm( self->notify.instance, self, 
-                                             qos, self->tx_max_sdu_size, 
-                                             skb);
+       if (self->notify.connect_confirm) {
+               self->notify.connect_confirm(self->notify.instance, self, 
+                                            qos, self->tx_max_sdu_size, 
+                                            skb);
        }
 }
 
@@ -803,32 +790,33 @@ void irttp_connect_confirm( void *instance, void *sap, struct qos_info *qos,
  *    Some other device is connecting to this TSAP
  *
  */
-void irttp_connect_indication( void *instance, void *sap, 
-                              struct qos_info *qos, int max_seg_size, 
-                              struct sk_buff *skb) 
+void irttp_connect_indication(void *instance, void *sap, 
+                             struct qos_info *qos, int max_seg_size, 
+                             struct sk_buff *skb) 
 {
        struct tsap_cb *self;
+       struct lsap_cb *lsap;
        __u8 *frame;
        int parameters;
        int n;
 
        self = (struct tsap_cb *) instance;
 
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
-       ASSERT( skb != NULL, return;);
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
+       ASSERT(skb != NULL, return;);
+
+       lsap = (struct lsap_cb *) sap;
 
        /* FIXME: just remove this when we know its working */
-       ASSERT( max_seg_size == qos->data_size.value, return;);
+       ASSERT(max_seg_size == qos->data_size.value, return;);
 
        self->max_seg_size = max_seg_size-LMP_HEADER-LAP_HEADER;
 
-       DEBUG( 4, "irttp_connect_indication(), TSAP sel=%02x\n", 
-              self->stsap_sel);
+       DEBUG(4, __FUNCTION__ "(), TSAP sel=%02x\n", self->stsap_sel);
 
-       /* FIXME: Need to update dtsap_sel if its equal to LSAP_ANY */
-/*     if ( self->dtsap_sel == LSAP_ANY) */
-/*             self->dtsap_sel = lsap->dlsap_sel; */
+       /* Need to update dtsap_sel if its equal to LSAP_ANY */
+       self->dtsap_sel = lsap->dlsap_sel;
 
        frame = skb->data;
        n = frame[0] & 0x7f;
@@ -837,22 +825,22 @@ void irttp_connect_indication( void *instance, void *sap,
        self->tx_max_sdu_size = 0;
        
        parameters = frame[0] & 0x80;   
-       if ( parameters) {
-               DEBUG( 4, __FUNCTION__ "(), Contains parameters!\n");
+       if (parameters) {
+               DEBUG(4, __FUNCTION__ "(), Contains parameters!\n");
                
                self->tx_max_sdu_size = ntohs(*(__u16 *)(frame+4));
-               DEBUG( 4, __FUNCTION__ "(), MaxSduSize=%d\n", 
-                      self->tx_max_sdu_size);
+               DEBUG(4, __FUNCTION__ "(), MaxSduSize=%d\n", 
+                     self->tx_max_sdu_size);
        }
 
-       DEBUG( 4, "irttp_connect_indication: initial send_credit=%d\n", n);
+       DEBUG(4, __FUNCTION__ "(), initial send_credit=%d\n", n);
 
-       skb_pull( skb, 1);
+       skb_pull(skb, 1);
 
-       if ( self->notify.connect_indication) {
-               self->notify.connect_indication( self->notify.instance, self, 
-                                                qos, self->rx_max_sdu_size, 
-                                                skb);
+       if (self->notify.connect_indication) {
+               self->notify.connect_indication(self->notify.instance, self, 
+                                               qos, self->rx_max_sdu_size, 
+                                               skb);
        }
 }
 
@@ -863,37 +851,34 @@ void irttp_connect_indication( void *instance, void *sap,
  *    IrLMP!
  * 
  */
-void irttp_connect_response( struct tsap_cb *self, int max_sdu_size, 
-                            struct sk_buff *userdata)
+void irttp_connect_response(struct tsap_cb *self, int max_sdu_size, 
+                           struct sk_buff *userdata)
 {
        struct sk_buff *skb;
        __u8 *frame;
        __u8 n;
 
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
 
-       DEBUG( 4, __FUNCTION__ "(), Source TSAP selector=%02x\n", 
-              self->stsap_sel);
+       DEBUG(4, __FUNCTION__ "(), Source TSAP selector=%02x\n", 
+             self->stsap_sel);
        
        /* Any userdata supplied? */
-       if ( userdata == NULL) {
-               skb = dev_alloc_skb( 64);
-               if (skb == NULL) {
-                       DEBUG( 0, __FUNCTION__ "Could not allocate an "
-                              "sk_buff of length %d\n", 64);
+       if (userdata == NULL) {
+               skb = dev_alloc_skb(64);
+               if (!skb)
                        return;
-               }
 
                /* Reserve space for MUX_CONTROL and LAP header */
-               skb_reserve( skb, (TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER));
+               skb_reserve(skb, (TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER));
        } else {
                skb = userdata;
                /*  
                 *  Check that the client has reserved enough space for 
                 *  headers
                 */
-               ASSERT( skb_headroom( skb) >= 
+               ASSERT(skb_headroom(skb) >= 
                        (TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER), return;);
        }
        
@@ -906,7 +891,7 @@ void irttp_connect_response( struct tsap_cb *self, int max_sdu_size,
        n = self->initial_credit;
 
        /* Frame has only space for max 127 credits (7 bits) */
-       if ( n > 127) {
+       if (n > 127) {
                self->avail_credit = n - 127;
                n = 127;
        }
@@ -915,117 +900,112 @@ void irttp_connect_response( struct tsap_cb *self, int max_sdu_size,
        self->connected = TRUE;
 
        /* SAR enabled? */
-       if ( max_sdu_size > 0) {
-               ASSERT( skb_headroom( skb) >= 
-                       (TTP_HEADER_WITH_SAR+LMP_CONTROL_HEADER+LAP_HEADER), 
-                       return;);
+       if (max_sdu_size > 0) {
+               ASSERT(skb_headroom(skb) >= 
+                      (TTP_HEADER_WITH_SAR+LMP_CONTROL_HEADER+LAP_HEADER), 
+                      return;);
                
                /* Insert TTP header with SAR parameters */
-               frame = skb_push( skb, TTP_HEADER_WITH_SAR);
+               frame = skb_push(skb, TTP_HEADER_WITH_SAR);
                
                frame[0] = TTP_PARAMETERS | n;
                frame[1] = 0x04; /* Length */
                frame[2] = 0x01; /* MaxSduSize */
                frame[3] = 0x02; /* Value length */
-               *((__u16 *) (frame+4))= htons( max_sdu_size);
+               *((__u16 *) (frame+4))= htons(max_sdu_size);
        } else {
                /* Insert TTP header */
-               frame = skb_push( skb, TTP_HEADER);
+               frame = skb_push(skb, TTP_HEADER);
                
                frame[0] = n & 0x7f;
        }
         
-       irlmp_connect_response( self->lsap, skb);
+       irlmp_connect_response(self->lsap, skb);
 }
 
 /*
- * Function irttp_disconnect_request ( self)
+ * Function irttp_disconnect_request (self)
  *
  *    Close this connection please! If priority is high, the queued data 
  *    segments, if any, will be deallocated first
  *
  */
-void irttp_disconnect_request( struct tsap_cb *self, struct sk_buff *userdata, 
-                              int priority)
+void irttp_disconnect_request(struct tsap_cb *self, struct sk_buff *userdata, 
+                             int priority)
 {
        struct sk_buff *skb;
 
-       DEBUG( 4, __FUNCTION__ "()\n");
+       DEBUG(2, __FUNCTION__ "()\n");
 
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
 
        /* Already disconnected? */
-       if ( !self->connected) {
-               DEBUG( 4, __FUNCTION__ "(), already disconnected!\n");
+       if (!self->connected) {
+               DEBUG(4, __FUNCTION__ "(), already disconnected!\n");
                return;
        }
 
        /* Disconnect already pending? */
-       if ( self->disconnect_pend) {
-               DEBUG( 0, __FUNCTION__ "(), disconnect already pending\n");
-               if ( userdata) {
-                       dev_kfree_skb( userdata);
+       if (self->disconnect_pend) {
+               DEBUG(1, __FUNCTION__ "(), disconnect already pending\n");
+               if (userdata) {
+                       dev_kfree_skb(userdata);
                }
 
                /* Try to make some progress */
-               irttp_run_rx_queue( self);
+               irttp_run_rx_queue(self);
                return;
        }
 
        /*
         *  Check if there is still data segments in the transmit queue
         */
-       if ( skb_queue_len( &self->tx_queue) > 0) {
-               if ( priority == P_HIGH) {
-                       DEBUG( 0, __FUNCTION__  "High priority!!()\n" );
+       if (skb_queue_len(&self->tx_queue) > 0) {
+               if (priority == P_HIGH) {
+                       DEBUG(1, __FUNCTION__  "High priority!!()\n" );
                        
                        /* 
                         *  No need to send the queued data, if we are 
                         *  disconnecting right now since the data will
                         *  not have any usable connection to be sent on
                         */
-                       irttp_flush_queues( self);
-               } else if ( priority == P_NORMAL) {
+                       irttp_flush_queues(self);
+               } else if (priority == P_NORMAL) {
                        /* 
                         *  Must delay disconnect til after all data segments
                         *  have been sent an the tx_queue is empty
                         */
-                       if ( userdata)
+                       if (userdata)
                                self->disconnect_skb = userdata;
                        else
                                self->disconnect_skb = NULL;
 
                        self->disconnect_pend = TRUE;
 
-                       irttp_run_tx_queue( self);
-                       /*  
-                        *  irttp_xmit will call us again when the tx_queue
-                        *  is empty
-                        */
+                       irttp_run_tx_queue(self);
+
+                       irttp_start_todo_timer(self, 100);
                        return;
                }
        }
-       DEBUG( 0, __FUNCTION__ "(), Disconnecting ...\n");
+       DEBUG(1, __FUNCTION__ "(), Disconnecting ...\n");
 
        self->connected = FALSE;
        
-       if ( !userdata) {
-               skb = dev_alloc_skb( 64);
-               if (skb == NULL) {
-                       DEBUG( 0, __FUNCTION__ "(), Could not allocate an "
-                              "sk_buff of length %d\n", 64);
+       if (!userdata) {
+               skb = dev_alloc_skb(64);
+               if (!skb)
                        return;
-               }
-
+               
                /* 
                 *  Reserve space for MUX and LAP header 
                 */
-               skb_reserve( skb, LMP_CONTROL_HEADER+LAP_HEADER);
-
+               skb_reserve(skb, LMP_CONTROL_HEADER+LAP_HEADER);
+               
                userdata = skb;
        }
-       irlmp_disconnect_request( self->lsap, userdata);
+       irlmp_disconnect_request(self->lsap, userdata);
 }
 
 /*
@@ -1034,26 +1014,26 @@ void irttp_disconnect_request( struct tsap_cb *self, struct sk_buff *userdata,
  *    Disconnect indication, TSAP disconnected by peer?
  *
  */
-void irttp_disconnect_indication( void *instance, void *sap, LM_REASON reason, 
-                                 struct sk_buff *userdata) 
+void irttp_disconnect_indication(void *instance, void *sap, LM_REASON reason, 
+                                struct sk_buff *userdata) 
 {
        struct tsap_cb *self;
 
-       DEBUG( 4, "irttp_disconnect_indication()\n");
+       DEBUG(4, __FUNCTION__ "()\n");
 
-       self = ( struct tsap_cb *) instance;
+       self = (struct tsap_cb *) instance;
        
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
        
        self->connected = FALSE;
        
        /* 
         *  Use callback to notify layer above 
         */
-       if ( self->notify.disconnect_indication)
-               self->notify.disconnect_indication( self->notify.instance, 
-                                                   self, reason, userdata);
+       if (self->notify.disconnect_indication)
+               self->notify.disconnect_indication(self->notify.instance, 
+                                                  self, reason, userdata);
 }
 
 /*
@@ -1062,43 +1042,43 @@ void irttp_disconnect_indication( void *instance, void *sap, LM_REASON reason,
  *     Check if we have any frames to be transmitted, or if we have any
  *     available credit to give away.
  */
-void irttp_run_rx_queue( struct tsap_cb *self) 
+void irttp_run_rx_queue(struct tsap_cb *self) 
 {
        struct sk_buff *skb;
        __u8 *frame;
        int more = 0;
        void *instance;
 
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
 
        instance = self->notify.instance;
-       ASSERT( instance != NULL, return;);
+       ASSERT(instance != NULL, return;);
 
-       DEBUG( 4, "irttp_do_events() send=%d,avail=%d,remote=%d\n", 
+       DEBUG(4, __FUNCTION__ "() send=%d,avail=%d,remote=%d\n", 
               self->send_credit, self->avail_credit, self->remote_credit);
 
-       if ( irda_lock( &self->rx_queue_lock) == FALSE)
+       if (irda_lock(&self->rx_queue_lock) == FALSE)
                return;
        
        /*
         *  Process receive queue
         */
-       while (( !skb_queue_empty( &self->rx_queue)) &&  !self->rx_sdu_busy) {
+       while ((!skb_queue_empty(&self->rx_queue)) &&  !self->rx_sdu_busy) {
 
-               skb = skb_dequeue( &self->rx_queue);
-               if ( !skb)
+               skb = skb_dequeue(&self->rx_queue);
+               if (!skb)
                        break; /* Should not happend, but ...  */
                
                self->avail_credit++;
 
                frame = skb->data;
                more = frame[0] & 0x80;
-               DEBUG( 4, __FUNCTION__ "(), More=%s\n", more ? "TRUE" : 
+               DEBUG(4, __FUNCTION__ "(), More=%s\n", more ? "TRUE" : 
                       "FALSE");
 
                /* Remove TTP header */
-               skb_pull( skb, TTP_HEADER);
+               skb_pull(skb, TTP_HEADER);
 
                /* Add the length of the remaining data */
                self->rx_sdu_size += skb->len;
@@ -1110,52 +1090,52 @@ void irttp_run_rx_queue( struct tsap_cb *self)
                 * implements byte streams without any message boundaries
                 */
                if ((self->no_defrag) || (self->rx_max_sdu_size == 0)) {
-                       self->notify.data_indication( instance, self, skb);
+                       self->notify.data_indication(instance, self, skb);
                        self->rx_sdu_size = 0;
-
+                       
                        continue;
                }
 
                /* Check if this is a fragment, and not the last fragment */
-               if ( more) {
+               if (more) {
                        /*  
                         *  Queue the fragment if we still are within the 
                         *  limits of the maximum size of the rx_sdu
                         */
-                       if ( self->rx_sdu_size <= self->rx_max_sdu_size) {
-                               DEBUG( 4, __FUNCTION__ 
+                       if (self->rx_sdu_size <= self->rx_max_sdu_size) {
+                               DEBUG(4, __FUNCTION__ 
                                       "(), queueing fragment\n");
 
-                               skb_queue_tail( &self->rx_fragments, skb);
+                               skb_queue_tail(&self->rx_fragments, skb);
                        } else {
-                               DEBUG( 0, __FUNCTION__ "(), Error!\n");
+                               DEBUG(1, __FUNCTION__ "(), Error!\n");
                        }
                } else {
                        /*
                         *  This is the last fragment, so time to reassemble!
                         */
-                       if ( self->rx_sdu_size <= self->rx_max_sdu_size) {
+                       if (self->rx_sdu_size <= self->rx_max_sdu_size) {
 
                                /* A little optimizing. Only queue the 
                                 * fragment if there is other fragments. Since
                                 * if this is the last and only fragment, 
                                 * there is no need to reassemble 
                                 */
-                               if ( !skb_queue_empty( &self->rx_fragments)) {
+                               if (!skb_queue_empty(&self->rx_fragments)) {
 
-                                       DEBUG( 4, __FUNCTION__ 
+                                       DEBUG(4, __FUNCTION__ 
                                               "(), queueing fragment\n");
-                                       skb_queue_tail( &self->rx_fragments, 
+                                       skb_queue_tail(&self->rx_fragments, 
                                                        skb);
 
-                                       skb = irttp_reassemble_skb( self);
+                                       skb = irttp_reassemble_skb(self);
                                }
-                               self->notify.data_indication( instance, self, 
-                                                             skb);
+                               self->notify.data_indication(instance, self, 
+                                                            skb);
                        } else {
-                               DEBUG( 0, __FUNCTION__ 
+                               DEBUG(1, __FUNCTION__ 
                                       "(), Truncated frame\n");
-                               self->notify.data_indication( 
+                               self->notify.data_indication(
                                        self->notify.instance, self, skb);
                        }
                        self->rx_sdu_size = 0;
@@ -1170,28 +1150,26 @@ void irttp_run_rx_queue( struct tsap_cb *self)
  *
  *     Flushes (removes all frames) in transitt-buffer (tx_list)
  */
-void irttp_flush_queues( struct tsap_cb *self)
+void irttp_flush_queues(struct tsap_cb *self)
 {
        struct sk_buff* skb;
        
-       DEBUG( 4, __FUNCTION__ "()\n");
+       DEBUG(4, __FUNCTION__ "()\n");
 
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
        
        /* Deallocate frames waiting to be sent */
-       while (( skb = skb_dequeue( &self->tx_queue)) != NULL) {
-               dev_kfree_skb( skb);
-       }
+       while ((skb = skb_dequeue(&self->tx_queue)) != NULL)
+               dev_kfree_skb(skb);
+       
        /* Deallocate received frames */
-       while (( skb = skb_dequeue( &self->rx_queue)) != NULL) {
-               dev_kfree_skb( skb);
-       }
-       /* Deallocate received fragments */
-       while (( skb = skb_dequeue( &self->rx_fragments)) != NULL) {
-               dev_kfree_skb( skb);
-       }
+       while ((skb = skb_dequeue(&self->rx_queue)) != NULL)
+               dev_kfree_skb(skb);
        
+       /* Deallocate received fragments */
+       while ((skb = skb_dequeue(&self->rx_fragments)) != NULL)
+               dev_kfree_skb(skb);
 }
 
 /*
@@ -1201,40 +1179,38 @@ void irttp_flush_queues( struct tsap_cb *self)
  *    queue
  *
  */
-static struct sk_buff *irttp_reassemble_skb( struct tsap_cb *self)
+static struct sk_buff *irttp_reassemble_skb(struct tsap_cb *self)
 {
        struct sk_buff *skb, *frag;
        int n = 0;  /* Fragment index */
+       
+       ASSERT(self != NULL, return NULL;);
+       ASSERT(self->magic == TTP_TSAP_MAGIC, return NULL;);
 
-       ASSERT( self != NULL, return NULL;);
-       ASSERT( self->magic == TTP_TSAP_MAGIC, return NULL;);
-
-       DEBUG( 4, __FUNCTION__ "(), self->rx_sdu_size=%d\n", 
-              self->rx_sdu_size);
+       DEBUG(4, __FUNCTION__ "(), self->rx_sdu_size=%d\n", 
+             self->rx_sdu_size);
 
-       skb = dev_alloc_skb( self->rx_sdu_size);
-       if ( !skb) {
-               DEBUG( 0, __FUNCTION__ "(), unable to allocate skb\n");
+       skb = dev_alloc_skb(self->rx_sdu_size);
+       if (!skb)
                return NULL;
-       }
 
-       skb_put( skb, self->rx_sdu_size);
+       skb_put(skb, self->rx_sdu_size);
 
        /*
         *  Copy all fragments to a new buffer
         */
-       while (( frag = skb_dequeue( &self->rx_fragments)) != NULL) {
-               memcpy( skb->data+n, frag->data, frag->len);
+       while ((frag = skb_dequeue(&self->rx_fragments)) != NULL) {
+               memcpy(skb->data+n, frag->data, frag->len);
                n += frag->len;
                
-               dev_kfree_skb( frag);
+               dev_kfree_skb(frag);
        }
-       DEBUG( 4, __FUNCTION__ "(), frame len=%d\n", n);
+       DEBUG(4, __FUNCTION__ "(), frame len=%d\n", n);
        /* Set the new length */
 
-       DEBUG( 4, __FUNCTION__ "(), rx_sdu_size=%d\n", self->rx_sdu_size);
-       ASSERT( n <= self->rx_sdu_size, return NULL;);
-       skb_trim( skb, n);
+       DEBUG(4, __FUNCTION__ "(), rx_sdu_size=%d\n", self->rx_sdu_size);
+       ASSERT(n <= self->rx_sdu_size, return NULL;);
+       skb_trim(skb, n);
 
        self->rx_sdu_size = 0;
 
@@ -1247,60 +1223,57 @@ static struct sk_buff *irttp_reassemble_skb( struct tsap_cb *self)
  *    Fragments a frame and queues all the fragments for transmission
  *
  */
-static void irttp_fragment_skb( struct tsap_cb *self, struct sk_buff *skb)
+static void irttp_fragment_skb(struct tsap_cb *self, struct sk_buff *skb)
 {
        struct sk_buff *frag;
        __u8 *frame;
 
-       DEBUG( 4, __FUNCTION__ "()\n");
+       DEBUG(4, __FUNCTION__ "()\n");
 
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
-       ASSERT( skb != NULL, return;);
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
+       ASSERT(skb != NULL, return;);
 
        /*
         *  Split frame into a number of segments
         */
-       while ( skb->len > 0) {
+       while (skb->len > 0) {
                /*
                 *  Instead of making the last segment, we just
                 *  queue what is left of the original skb
                 */
-               if ( skb->len < self->max_seg_size) {
-                       DEBUG( 4, __FUNCTION__ 
+               if (skb->len < self->max_seg_size) {
+                       DEBUG(4, __FUNCTION__ 
                               "(), queuing last segment\n");
 
-                       frame = skb_push( skb, TTP_HEADER);
+                       frame = skb_push(skb, TTP_HEADER);
                        frame[0] = 0x00; /* Clear more bit */
-                       skb_queue_tail( &self->tx_queue, skb);
+                       skb_queue_tail(&self->tx_queue, skb);
                        
                        return;
                }
                
                /* Make new segment */
-               frag = dev_alloc_skb( self->max_seg_size+
-                                        TTP_HEADER+LMP_HEADER+
-                                        LAP_HEADER);
-               if ( frag == NULL) {
-                       DEBUG( 0, __FUNCTION__ 
-                              "(), Couldn't allocate skbuff!\n");
+               frag = dev_alloc_skb(self->max_seg_size+
+                                     TTP_HEADER+LMP_HEADER+
+                                     LAP_HEADER);
+               if (!frag)
                        return;
-               }
 
-               skb_reserve( frag, LMP_HEADER+LAP_HEADER);
+               skb_reserve(frag, LMP_HEADER+LAP_HEADER);
 
                /*
                 *  Copy data from the original skb into this fragment. We
                 *  first insert the TTP header with the more bit set
                 */
-               frame = skb_put( frag, self->max_seg_size+TTP_HEADER);
+               frame = skb_put(frag, self->max_seg_size+TTP_HEADER);
                frame[0] = TTP_MORE;
-               memcpy( frag->data+1, skb->data, self->max_seg_size);
+               memcpy(frag->data+1, skb->data, self->max_seg_size);
                
                /* Hide the copied data from the original skb */
-               skb_pull( skb, self->max_seg_size);
+               skb_pull(skb, self->max_seg_size);
                
-               skb_queue_tail( &self->tx_queue, frag);
+               skb_queue_tail(&self->tx_queue, frag);
        }
 }
 
@@ -1310,31 +1283,51 @@ static void irttp_fragment_skb( struct tsap_cb *self, struct sk_buff *skb)
  *    Todo timer has expired!
  *
  */
-static void irttp_todo_expired( unsigned long data)
+static void irttp_todo_expired(unsigned long data)
 {
-       struct tsap_cb *self = ( struct tsap_cb *) data;
+       struct tsap_cb *self = (struct tsap_cb *) data;
 
-       DEBUG( 4, __FUNCTION__ "()\n");
+       DEBUG(4, __FUNCTION__ "()\n");
        
        /* Check that we still exist */
-       if ( !self || self->magic != TTP_TSAP_MAGIC) {
+       if (!self || self->magic != TTP_TSAP_MAGIC) {
                return;
        }
 
-       irttp_run_rx_queue( self);
-       irttp_run_tx_queue( self);
+       irttp_run_rx_queue(self);
+       irttp_run_tx_queue(self);
 
        /*  Give avay some credits to peer?  */
-       if (( skb_queue_empty( &self->tx_queue)) && 
-           ( self->remote_credit < LOW_THRESHOLD) && 
-           ( self->avail_credit > 0)) 
+       if ((skb_queue_empty(&self->tx_queue)) && 
+           (self->remote_credit < LOW_THRESHOLD) && 
+           (self->avail_credit > 0)) 
        {
-               DEBUG( 4, "irttp_do_events: sending credit!\n");
-               irttp_give_credit( self);
+               DEBUG(4, __FUNCTION__ "(), sending credit!\n");
+               irttp_give_credit(self);
        }
-       
-       /* Rearm! */
-       /* irttp_start_todo_timer( self, 50); */
+
+       /* Check if time for disconnect */
+       if (self->disconnect_pend) {
+               /* Check if it's possible to disconnect yet */
+               if (skb_queue_empty(&self->tx_queue)) {
+                       if (self->disconnect_skb) {
+                               irttp_disconnect_request(
+                                       self, self->disconnect_skb, P_NORMAL);
+                               self->disconnect_skb = NULL;
+                       } else
+                               irttp_disconnect_request(self, NULL, P_NORMAL);
+               } else {
+                       /* Try again later */
+                       irttp_start_todo_timer(self, 100);
+                       
+                       /* No reason to try and close now */
+                       return;
+               }
+       }
+
+       /* Check if it's closing time */
+       if (self->close_pend)
+               irttp_close_tsap(self);
 }
 
 /*
@@ -1343,18 +1336,18 @@ static void irttp_todo_expired( unsigned long data)
  *    Start todo timer. 
  *
  */
-static void irttp_start_todo_timer( struct tsap_cb *self, int timeout)
+static void irttp_start_todo_timer(struct tsap_cb *self, int timeout)
 {
-       ASSERT( self != NULL, return;);
-       ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
+       ASSERT(self != NULL, return;);
+       ASSERT(self->magic == TTP_TSAP_MAGIC, return;);
 
-       del_timer( &self->todo_timer);
+       del_timer(&self->todo_timer);
        
        self->todo_timer.data     = (unsigned long) self;
        self->todo_timer.function = &irttp_todo_expired;
        self->todo_timer.expires  = jiffies + timeout;
        
-       add_timer( &self->todo_timer);
+       add_timer(&self->todo_timer);
 }
 
 #ifdef CONFIG_PROC_FS
@@ -1363,65 +1356,64 @@ static void irttp_start_todo_timer( struct tsap_cb *self, int timeout)
  *
  *    Give some info to the /proc file system
  */
-int irttp_proc_read( char *buf, char **start, off_t offset, int len, 
-                    int unused)
+int irttp_proc_read(char *buf, char **start, off_t offset, int len, int unused)
 {
        struct tsap_cb *self;
        unsigned long flags;
        int i = 0;
        
-       ASSERT( irttp != NULL, return 0;);
+       ASSERT(irttp != NULL, return 0;);
        
        len = 0;
        
        save_flags(flags);
        cli();
 
-       self = ( struct tsap_cb *) hashbin_get_first( irttp->tsaps);
-       while ( self != NULL) {
-               if ( !self || self->magic != TTP_TSAP_MAGIC) {
-                       DEBUG( 0, "irttp_proc_read: bad ptr self\n");
+       self = (struct tsap_cb *) hashbin_get_first(irttp->tsaps);
+       while (self != NULL) {
+               if (!self || self->magic != TTP_TSAP_MAGIC) {
+                       DEBUG(1, "irttp_proc_read: bad ptr self\n");
                        return len;
                }
 
-               len += sprintf( buf+len, "TSAP %d, ", i++);
-               len += sprintf( buf+len, "stsap_sel: %02x, ", 
+               len += sprintf(buf+len, "TSAP %d, ", i++);
+               len += sprintf(buf+len, "stsap_sel: %02x, ", 
                                self->stsap_sel);
-               len += sprintf( buf+len, "dtsap_sel: %02x\n", 
+               len += sprintf(buf+len, "dtsap_sel: %02x\n", 
                                self->dtsap_sel);
-               len += sprintf( buf+len, "  connected: %s, ",
+               len += sprintf(buf+len, "  connected: %s, ",
                                self->connected? "TRUE":"FALSE");
-               len += sprintf( buf+len, "avail credit: %d, ",
+               len += sprintf(buf+len, "avail credit: %d, ",
                                self->avail_credit);
-               len += sprintf( buf+len, "remote credit: %d, ",
+               len += sprintf(buf+len, "remote credit: %d, ",
                                self->remote_credit);
-               len += sprintf( buf+len, "send credit: %d\n",
+               len += sprintf(buf+len, "send credit: %d\n",
                                self->send_credit);
-               len += sprintf( buf+len, "  tx packets: %d, ",
+               len += sprintf(buf+len, "  tx packets: %d, ",
                                self->stats.tx_packets);
-               len += sprintf( buf+len, "rx packets: %d, ",
+               len += sprintf(buf+len, "rx packets: %d, ",
                                self->stats.rx_packets);
-               len += sprintf( buf+len, "tx_queue len: %d ", 
-                               skb_queue_len( &self->tx_queue));
-               len += sprintf( buf+len, "rx_queue len: %d\n", 
-                               skb_queue_len( &self->rx_queue));
-               len += sprintf( buf+len, "  tx_sdu_busy: %s, ",
+               len += sprintf(buf+len, "tx_queue len: %d ", 
+                               skb_queue_len(&self->tx_queue));
+               len += sprintf(buf+len, "rx_queue len: %d\n", 
+                               skb_queue_len(&self->rx_queue));
+               len += sprintf(buf+len, "  tx_sdu_busy: %s, ",
                                self->tx_sdu_busy? "TRUE":"FALSE");
-               len += sprintf( buf+len, "rx_sdu_busy: %s\n",
+               len += sprintf(buf+len, "rx_sdu_busy: %s\n",
                                self->rx_sdu_busy? "TRUE":"FALSE");
-               len += sprintf( buf+len, "  max_seg_size: %d, ",
+               len += sprintf(buf+len, "  max_seg_size: %d, ",
                                self->max_seg_size);
-               len += sprintf( buf+len, "tx_max_sdu_size: %d, ",
+               len += sprintf(buf+len, "tx_max_sdu_size: %d, ",
                                self->tx_max_sdu_size);
-               len += sprintf( buf+len, "rx_max_sdu_size: %d\n",
+               len += sprintf(buf+len, "rx_max_sdu_size: %d\n",
                                self->rx_max_sdu_size);
 
-               len += sprintf( buf+len, "  Used by (%s)\n", 
+               len += sprintf(buf+len, "  Used by (%s)\n", 
                                self->notify.name);
 
-               len += sprintf( buf+len, "\n");
+               len += sprintf(buf+len, "\n");
                
-               self = ( struct tsap_cb *) hashbin_get_next( irttp->tsaps);
+               self = (struct tsap_cb *) hashbin_get_next(irttp->tsaps);
        }
        restore_flags(flags);
 
index 215666aa0768e46071de341a4028e5dffa88c335..015d7559f59269f080104c8a6cd663d464b5a1d9 100644 (file)
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      qos.c
- * Version:       0.1
+ * Version:       0.8
  * Description:   IrLAP QoS negotiation
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Sep  9 00:00:26 1997
- * Modified at:   Sat Dec 12 12:21:42 1998
+ * Modified at:   Mon Feb  1 09:56:21 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
@@ -109,8 +109,8 @@ void irda_init_max_qos_capabilies( struct qos_info *qos)
  *    We just set the QoS capabilities for the peer station
  *
  */
-void irda_qos_negotiate( struct qos_info *qos_rx, struct qos_info *qos_tx, 
-                        struct sk_buff *skb) 
+void irda_qos_negotiate(struct qos_info *qos_rx, struct qos_info *qos_tx, 
+                       struct sk_buff *skb) 
 {
        int n=0;
 #ifdef CONFIG_IRDA_COMPRESSION
@@ -162,7 +162,7 @@ void irda_qos_negotiate( struct qos_info *qos_rx, struct qos_info *qos_tx,
                        break;
                }
 
-               switch( code) {
+               switch(code) {
                case PI_BAUD_RATE:
                        /* 
                         *  Stations must agree on baud rate, so calculate
@@ -178,7 +178,8 @@ void irda_qos_negotiate( struct qos_info *qos_rx, struct qos_info *qos_tx,
                        /*
                         *  Negotiated independently for each station
                         */
-                       DEBUG( 4, "MAX_TURN_TIME: %02x\n", byte);
+                       DEBUG(4, __FUNCTION__ "(), MAX_TURN_TIME: %02x\n", 
+                             byte);
                        qos_tx->max_turn_time.bits = byte;
                        break;
                case PI_DATA_SIZE:
@@ -268,7 +269,7 @@ void irda_qos_negotiate( struct qos_info *qos_rx, struct qos_info *qos_tx,
  *    Insert QoS negotiaion pararameters into frame
  *
  */
-int irda_insert_qos_negotiation_params( struct qos_info *qos, __u8 *frame)
+int irda_insert_qos_negotiation_params(struct qos_info *qos, __u8 *frame)
 {
        int n;
        __u16_host_order word;
index 95c18f13ff7f129a85bbc1385a1d3696c18ee7e6..ed3929a728ea82e6ef1c38faab6816ea8402d747 100644 (file)
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Aug 16 00:59:29 1997
- * Modified at:   Wed Dec  9 01:34:59 1998
+ * Modified at:   Thu Feb  4 10:49:38 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
@@ -100,11 +100,16 @@ inline void irlmp_start_watchdog_timer( struct lsap_cb *self, int timeout)
                          irlmp_watchdog_timer_expired);
 }
 
-inline void irlmp_start_discovery_timer( struct irlmp_cb *self, int timeout) 
+inline void irlmp_start_discovery_timer(struct irlmp_cb *self, int timeout) 
 {
-       irda_start_timer( &self->discovery_timer, timeout, 
-                         (unsigned long) self,
-                         irlmp_discovery_timer_expired);
+       irda_start_timer(&self->discovery_timer, timeout, (unsigned long) self,
+                        irlmp_discovery_timer_expired);
+}
+
+inline void irlmp_start_idle_timer(struct lap_cb *self, int timeout) 
+{
+       irda_start_timer(&self->idle_timer, timeout, (unsigned long) self,
+                        irlmp_idle_timer_expired);
 }
 
 /*
index fdebb5788e70dcda6ef5461d8a7cca26d1fc2682..680bced96e2b43624226209b1cbd46844cb7d3ce 100644 (file)
@@ -1,12 +1,12 @@
 /*********************************************************************
  *                
  * Filename:      wrapper.c
- * Version:       
- * Description:   IrDA Wrapper layer
+ * Version:       1.0
+ * Description:   SIR wrapper layer
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Sat Jan 16 22:05:45 1999
+ * Modified at:   Tue Feb 16 17:27:23 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, 
@@ -36,7 +36,7 @@
 
 #define MIN_LENGTH 14
 
-__inline__ static int stuff_byte( __u8 byte, __u8 *buf);
+inline static int stuff_byte( __u8 byte, __u8 *buf);
 
 /*
  * Function async_wrap (skb, *tx_buff)
@@ -54,8 +54,6 @@ int async_wrap_skb( struct sk_buff *skb, __u8 *tx_buff, int buffsize)
                __u8 bytes[2];
        } fcs;
 
-
-       DEBUG( 6, __FUNCTION__ "()\n"); 
        ASSERT( skb != NULL, return 0;);
 
        /* Initialize variables */
@@ -63,7 +61,7 @@ int async_wrap_skb( struct sk_buff *skb, __u8 *tx_buff, int buffsize)
        n = 0;
 
        if ( skb->len > 2048) {
-               DEBUG( 0,"async_xmit: Warning size=%d of sk_buff to big!\n", 
+               DEBUG( 0, __FUNCTION__ "Warning size=%d of sk_buff to big!\n", 
                       (int) skb->len);
 
                return 0;
@@ -119,15 +117,12 @@ int async_wrap_skb( struct sk_buff *skb, __u8 *tx_buff, int buffsize)
  *    Got a frame, make a copy of it, and pass it up the stack!
  *
  */
-static __inline__ void async_bump( struct irda_device *idev, __u8 *buf, 
-                                  int len)
+static inline void async_bump( struct irda_device *idev, __u8 *buf, int len)
 {
                struct sk_buff *skb;
  
-       skb = dev_alloc_skb( len+1);
-       if (skb == NULL)  {
-               printk( KERN_INFO __FUNCTION__ "() memory squeeze, " 
-                       "dropping frame.\n");
+       skb = dev_alloc_skb(len+1);
+       if (!skb)  {
                idev->stats.rx_dropped++;
                return;
        }
@@ -141,7 +136,6 @@ static __inline__ void async_bump( struct irda_device *idev, __u8 *buf,
        skb_put( skb, len-2);
        memcpy( skb->data, buf, len-2); 
        
-       idev->rx_buff.len = 0;
        /* 
         *  Feed it to IrLAP layer 
         */
@@ -150,11 +144,11 @@ static __inline__ void async_bump( struct irda_device *idev, __u8 *buf,
        skb->mac.raw  = skb->data;
        skb->protocol = htons(ETH_P_IRDA);
 
-       netif_rx( skb);
+       netif_rx(skb);
        idev->stats.rx_packets++;
        idev->stats.rx_bytes += skb->len;       
 }
+
 /*
  * Function async_unwrap (skb)
  *
@@ -166,16 +160,25 @@ void async_unwrap_char( struct irda_device *idev, __u8 byte)
        /* State machine for receiving frames */           
        switch( idev->rx_buff.state) {
        case OUTSIDE_FRAME:
-               if ( byte == BOF) {
+               switch( byte) {
+               case BOF:
                        idev->rx_buff.state = BEGIN_FRAME;
                        idev->rx_buff.in_frame = TRUE;
-               } else if ( byte == EOF) {
+                       break;
+               case XBOF:
+                       idev->xbofs++;
+                       break;
+               case EOF:
                        irda_device_set_media_busy( idev, TRUE);
+                       break;
+               default:
+                       break;
                }
                break;
        case BEGIN_FRAME:
                switch ( byte) {
                case BOF:
+                       
                        /* Continue */
                        break;
                case CE:
@@ -191,13 +194,10 @@ void async_unwrap_char( struct irda_device *idev, __u8 byte)
                        break;
                default:
                        /* Got first byte of frame */
-                       if ( idev->rx_buff.len < idev->rx_buff.truesize)  {
-                               idev->rx_buff.data[ idev->rx_buff.len++] = byte;
+                       idev->rx_buff.data[ idev->rx_buff.len++] = byte;
                        
-                               idev->rx_buff.fcs = IR_FCS( INIT_FCS, byte);
-                               idev->rx_buff.state = INSIDE_FRAME;
-                       } else 
-                               printk( "Rx buffer overflow\n");
+                       idev->rx_buff.fcs = IR_FCS( INIT_FCS, byte);
+                       idev->rx_buff.state = INSIDE_FRAME;
                        break;
                }
                break;
@@ -205,7 +205,6 @@ void async_unwrap_char( struct irda_device *idev, __u8 byte)
                switch ( byte) {
                case BOF:
                        /* New frame? */
-                       DEBUG( 4, "New frame?\n");
                        idev->rx_buff.state = BEGIN_FRAME;
                        idev->rx_buff.len = 0;
                        irda_device_set_media_busy( idev, TRUE);
@@ -215,7 +214,6 @@ void async_unwrap_char( struct irda_device *idev, __u8 byte)
                        break;
                case EOF:
                        /* Abort frame */
-                       DEBUG( 0, "Abort frame (2)\n");
                        idev->rx_buff.state = OUTSIDE_FRAME;
                        idev->rx_buff.len = 0;
                        break;
@@ -228,10 +226,15 @@ void async_unwrap_char( struct irda_device *idev, __u8 byte)
                        if ( idev->rx_buff.len < idev->rx_buff.truesize)  {
                                idev->rx_buff.data[ idev->rx_buff.len++] = byte;
                        
-                               idev->rx_buff.fcs = IR_FCS( idev->rx_buff.fcs, byte);
+                               idev->rx_buff.fcs = IR_FCS(idev->rx_buff.fcs,
+                                                          byte);
                                idev->rx_buff.state = INSIDE_FRAME;
-                       } else 
-                               printk( "Rx buffer overflow\n");
+                       } else {
+                               DEBUG( 1, __FUNCTION__ 
+                                      "(), Rx buffer overflow, aborting\n");
+                               idev->rx_buff.state = OUTSIDE_FRAME;
+                               idev->rx_buff.len = 0;
+                       }
                        break;
                }
                break;
@@ -258,6 +261,7 @@ void async_unwrap_char( struct irda_device *idev, __u8 byte)
                        if ( idev->rx_buff.fcs == GOOD_FCS) {
                                async_bump( idev, idev->rx_buff.data, 
                                            idev->rx_buff.len);
+                               idev->rx_buff.len = 0;
                        } else {
                                /* Wrong CRC, discard frame!  */
                                irda_device_set_media_busy( idev, TRUE); 
@@ -272,9 +276,14 @@ void async_unwrap_char( struct irda_device *idev, __u8 byte)
                        if ( idev->rx_buff.len < idev->rx_buff.truesize)  {
                                idev->rx_buff.data[ idev->rx_buff.len++] = byte;
                                
-                               idev->rx_buff.fcs = IR_FCS( idev->rx_buff.fcs, byte);
-                       } else 
-                               printk( "Rx buffer overflow\n");
+                               idev->rx_buff.fcs = IR_FCS( idev->rx_buff.fcs,
+                                                           byte);
+                       } else {
+                               DEBUG( 1, __FUNCTION__ 
+                                      "(), Rx buffer overflow, aborting\n");
+                               idev->rx_buff.state = OUTSIDE_FRAME;
+                               idev->rx_buff.len = 0;
+                       }
                        break;
                }
                break;
@@ -288,11 +297,11 @@ void async_unwrap_char( struct irda_device *idev, __u8 byte)
  *    buf. The buffer must at all times be able to have two bytes inserted.
  * 
  */
-__inline__ static int stuff_byte( __u8 byte, __u8 *buf) 
+inline static int stuff_byte( __u8 byte, __u8 *buf) 
 {
        switch ( byte) {
-       case BOF:
-       case EOF:
+       case BOF: /* FALLTHROUGH */
+       case EOF: /* FALLTHROUGH */
        case CE:
                /* Insert transparently coded */
                buf[0] = CE;               /* Send link escape */
@@ -308,3 +317,5 @@ __inline__ static int stuff_byte( __u8 byte, __u8 *buf)
 }
         
 
+
+