From 777720deee62bdd4ce7563e67976f45098540529 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:18:20 -0500 Subject: [PATCH] Linux 2.2.3pre3 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 --- CREDITS | 16 + Documentation/Configure.help | 9 + Documentation/sound/CMI8330 | 86 ++ Documentation/sound/VIBRA16 | 80 ++ MAINTAINERS | 6 + arch/i386/defconfig | 2 +- arch/i386/kernel/bios32.c | 132 +- drivers/char/Config.in | 2 + drivers/char/Makefile | 8 + drivers/char/dtlk.c | 722 ++++++++++ drivers/char/ftape/zftape/zftape-init.c | 2 - drivers/char/mem.c | 2 - drivers/char/misc.c | 3 + drivers/char/radio-aimslab.c | 33 +- drivers/char/radio-aztech.c | 28 +- drivers/net/Makefile | 1 + drivers/net/cosa.c | 214 ++- drivers/net/cosa.h | 11 +- drivers/net/irda/Config.in | 1 + drivers/net/irda/Makefile | 8 + drivers/net/irda/actisys.c | 91 +- drivers/net/irda/esi.c | 36 +- drivers/net/irda/girbil.c | 276 ++++ drivers/net/irda/irport.c | 3 +- drivers/net/irda/irtty.c | 106 +- drivers/net/irda/pc87108.c | 15 +- drivers/net/irda/tekram.c | 92 +- drivers/net/irda/uircc.c | 20 +- drivers/net/irda/w83977af_ir.c | 10 +- drivers/net/ne.c | 1 + drivers/net/plip.c | 4 +- drivers/net/sk_g16.c | 2 +- drivers/pci/pci.c | 25 +- drivers/sbus/char/flash.c | 2 - drivers/sbus/char/vfc_dev.c | 2 - drivers/scsi/ChangeLog.ncr53c8xx | 24 +- drivers/scsi/README.ncr53c8xx | 27 +- drivers/scsi/README.st | 13 +- drivers/scsi/ncr53c8xx.c | 178 +-- drivers/scsi/ncr53c8xx.h | 3 +- drivers/scsi/st.c | 9 +- drivers/sound/Config.in | 7 +- drivers/sound/ad1848.c | 185 ++- drivers/sound/ad1848_mixer.h | 64 +- drivers/sound/es1370.c | 5 +- drivers/sound/es1371.c | 4 - drivers/sound/lowlevel/awe_compat.h | 23 +- drivers/sound/lowlevel/awe_wave.c | 68 +- drivers/sound/mad16.c | 2 +- drivers/sound/sb.h | 18 +- drivers/sound/sb_card.c | 8 +- drivers/sound/sb_common.c | 47 +- drivers/sound/sb_mixer.c | 1 + drivers/sound/sequencer.c | 6 +- drivers/sound/sonicvibes.c | 2 - drivers/sound/sound_core.c | 1 - drivers/sound/soundcard.c | 27 +- drivers/sound/trix.c | 2 +- drivers/video/atyfb.c | 2 - drivers/video/fbmem.c | 2 - drivers/video/igafb.c | 2 - drivers/video/sbusfb.c | 2 - fs/Config.in | 8 +- fs/affs/inode.c | 1 - fs/affs/super.c | 1 - fs/dquot.c | 5 +- fs/fat/mmap.c | 2 - fs/isofs/file.c | 1 - fs/ncpfs/mmap.c | 2 - fs/smbfs/cache.c | 5 +- include/linux/awe_voice.h | 6 +- include/linux/dtlk.h | 104 ++ include/linux/miscdevice.h | 2 +- include/linux/pci.h | 20 +- include/net/br.h | 4 +- include/net/irda/dongle.h | 3 +- include/net/irda/ircomm_common.h | 1 + include/net/irda/irda.h | 4 +- include/net/irda/irda_device.h | 17 +- include/net/irda/iriap.h | 26 +- include/net/irda/irias_object.h | 32 +- .../net/irda/{irlan_cli.h => irlan_client.h} | 37 +- include/net/irda/irlan_common.h | 151 ++- include/net/irda/irlan_eth.h | 10 +- include/net/irda/irlan_event.h | 29 +- include/net/irda/irlan_filter.h | 33 + .../irda/{irlan_srv.h => irlan_provider.h} | 39 +- include/net/irda/irlap.h | 14 +- include/net/irda/irlap_event.h | 4 +- include/net/irda/irlmp.h | 31 +- include/net/irda/irlmp_event.h | 9 +- include/net/irda/irlmp_frame.h | 6 +- include/net/irda/irlpt_cli.h | 8 +- include/net/irda/irlpt_cli_fsm.h | 12 +- include/net/irda/irlpt_common.h | 19 +- include/net/irda/irlpt_server.h | 2 +- include/net/irda/irlpt_server_fsm.h | 21 +- include/net/irda/irmod.h | 40 +- include/net/irda/irobex.h | 30 +- include/net/irda/irttp.h | 82 +- include/net/irda/irtty.h | 6 +- include/net/irda/pc87108.h | 6 +- include/net/irda/timer.h | 17 +- include/net/irda/wrapper.h | 9 +- mm/filemap.c | 2 - mm/mmap.c | 2 + mm/swapfile.c | 4 +- net/Makefile | 2 +- net/ax25/af_ax25.c | 2 +- net/bridge/br.c | 49 +- net/bridge/br_tree.c | 24 + net/core/scm.c | 1 - net/core/skbuff.c | 2 +- net/core/sock.c | 2 +- net/econet/econet.c | 1 - net/ipv4/Config.in | 1 - net/ipv4/arp.c | 13 + net/ipv4/icmp.c | 2 +- net/ipv4/tcp.c | 5 +- net/ipv4/tcp_input.c | 6 +- net/ipv4/tcp_ipv4.c | 2 +- net/ipv4/tcp_output.c | 15 +- net/ipv6/tcp_ipv6.c | 3 +- net/irda/Makefile | 8 +- net/irda/af_irda.c | 570 ++------ net/irda/ircomm/attach.c | 66 +- net/irda/ircomm/ircomm_common.c | 121 +- net/irda/irda_device.c | 166 +-- net/irda/iriap.c | 245 ++-- net/irda/iriap_event.c | 11 +- net/irda/irlan/Config.in | 6 - net/irda/irlan/Makefile | 33 +- net/irda/irlan/irlan_cli.c | 676 ---------- net/irda/irlan/irlan_cli_event.c | 494 ------- net/irda/irlan/irlan_client.c | 617 +++++++++ net/irda/irlan/irlan_client_event.c | 532 ++++++++ net/irda/irlan/irlan_common.c | 1194 +++++++++++------ net/irda/irlan/irlan_eth.c | 244 +--- net/irda/irlan/irlan_event.c | 20 +- net/irda/irlan/irlan_filter.c | 235 ++++ net/irda/irlan/irlan_provider.c | 431 ++++++ net/irda/irlan/irlan_provider_event.c | 240 ++++ net/irda/irlan/irlan_srv.c | 915 ------------- net/irda/irlan/irlan_srv_event.c | 268 ---- net/irda/irlap.c | 191 ++- net/irda/irlap_comp.c | 23 +- net/irda/irlap_event.c | 187 +-- net/irda/irlap_frame.c | 243 ++-- net/irda/irlmp.c | 308 +++-- net/irda/irlmp_event.c | 116 +- net/irda/irlmp_frame.c | 25 +- net/irda/irlpt/irlpt_cli.c | 215 +-- net/irda/irlpt/irlpt_cli_fsm.c | 177 ++- net/irda/irlpt/irlpt_common.c | 190 ++- net/irda/irlpt/irlpt_srvr.c | 140 +- net/irda/irlpt/irlpt_srvr_fsm.c | 37 +- net/irda/irmod.c | 168 ++- net/irda/irobex/irobex.c | 291 ++-- net/irda/irproc.c | 74 +- net/irda/irqueue.c | 11 +- net/irda/irsysctl.c | 10 +- net/irda/irttp.c | 896 ++++++------- net/irda/qos.c | 15 +- net/irda/timer.c | 15 +- net/irda/wrapper.c | 81 +- 165 files changed, 8075 insertions(+), 6210 deletions(-) create mode 100644 Documentation/sound/CMI8330 create mode 100644 Documentation/sound/VIBRA16 create mode 100644 drivers/char/dtlk.c create mode 100644 drivers/net/irda/girbil.c create mode 100644 include/linux/dtlk.h rename include/net/irda/{irlan_cli.h => irlan_client.h} (51%) create mode 100644 include/net/irda/irlan_filter.h rename include/net/irda/{irlan_srv.h => irlan_provider.h} (54%) delete mode 100644 net/irda/irlan/irlan_cli.c delete mode 100644 net/irda/irlan/irlan_cli_event.c create mode 100644 net/irda/irlan/irlan_client.c create mode 100644 net/irda/irlan/irlan_client_event.c create mode 100644 net/irda/irlan/irlan_filter.c create mode 100644 net/irda/irlan/irlan_provider.c create mode 100644 net/irda/irlan/irlan_provider_event.c delete mode 100644 net/irda/irlan/irlan_srv.c delete mode 100644 net/irda/irlan/irlan_srv_event.c diff --git a/CREDITS b/CREDITS index 3984ee2778bd..f98666c4378a 100644 --- 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 diff --git a/Documentation/Configure.help b/Documentation/Configure.help index 5368897871ec..cf504364cb61 100644 --- a/Documentation/Configure.help +++ b/Documentation/Configure.help @@ -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 index 000000000000..43b1c5a72b5d --- /dev/null +++ b/Documentation/sound/CMI8330 @@ -0,0 +1,86 @@ +How to enable CMI 8330 soundchip on Linux +------------------------------------------ +Stefan Laudat + +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: + + + +(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) + + + + 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 index 000000000000..0a0aff9d7531 --- /dev/null +++ b/Documentation/sound/VIBRA16 @@ -0,0 +1,80 @@ +Sound Blaster 16X Vibra addendum +-------------------------------- +by Marius Ilioaea + Stefan Laudat + +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: + + + +(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) + + + + 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! ;) + + diff --git a/MAINTAINERS b/MAINTAINERS index 137de4bcd958..b743736c09a1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -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 diff --git a/arch/i386/defconfig b/arch/i386/defconfig index 696de8ddcb84..6ecccdf8cbf7 100644 --- a/arch/i386/defconfig +++ b/arch/i386/defconfig @@ -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 diff --git a/arch/i386/kernel/bios32.c b/arch/i386/kernel/bios32.c index e7383e55b213..9bf2fdce2ba6 100644 --- a/arch/i386/kernel/bios32.c +++ b/arch/i386/kernel/bios32.c @@ -14,7 +14,7 @@ * Hannover, Germany * hm@ix.de * - * Copyright 1997, 1998 Martin Mares + * Copyright 1997--1999 Martin Mares * * For more information, please consult the following manuals (look at * http://www.pcisig.com/ for how to get them): @@ -71,6 +71,10 @@ * 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 @@ -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; ivendor == 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; } diff --git a/drivers/char/Config.in b/drivers/char/Config.in index c0760b8877df..f5facd8dd661 100644 --- a/drivers/char/Config.in +++ b/drivers/char/Config.in @@ -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 diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 6a627847b29a..78fb870a761b 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -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 index 000000000000..0b928dc6041b --- /dev/null +++ b/drivers/char/dtlk.c @@ -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 + * Current maintainer: Jim Van Zandt + */ + +/* 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 +#endif + +#ifdef MODULE +#include +#include +#else +#define MOD_INC_USE_COUNT +#define MOD_DEC_USE_COUNT +#endif + +#define KERNEL +#include + +#include +#include +#include /* for verify_area */ +#include /* for -EBUSY */ +#include /* for check_region, request_region */ +#include /* for loops_per_sec */ +#include /* for put_user_byte */ +#include /* for inb_p, outb_p, inb, outb, etc. */ +#include /* for get_user, etc. */ +#include /* for wait_queue */ +#include /* for __init */ +#include /* for POLLIN, etc. */ +#include /* 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 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; +} diff --git a/drivers/char/ftape/zftape/zftape-init.c b/drivers/char/ftape/zftape/zftape-init.c index 1b50349391ec..10ac9929223a 100644 --- a/drivers/char/ftape/zftape/zftape-init.c +++ b/drivers/char/ftape/zftape/zftape-init.c @@ -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; diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 6eaa07d23e71..588856d3c4e9 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -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; } diff --git a/drivers/char/misc.c b/drivers/char/misc.c index 563d16050ad0..04409a84ee10 100644 --- a/drivers/char/misc.c +++ b/drivers/char/misc.c @@ -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 diff --git a/drivers/char/radio-aimslab.c b/drivers/char/radio-aimslab.c index 4ebbe2475580..f0a9a1c1734e 100644 --- a/drivers/char/radio-aimslab.c +++ b/drivers/char/radio-aimslab.c @@ -3,6 +3,11 @@ * Coverted to new API by Alan Cox * Various bugfixes and enhancements by Russell Kroll * + * History: + * 1999-02-24 Russell Kroll + * 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))) diff --git a/drivers/char/radio-aztech.c b/drivers/char/radio-aztech.c index 39d56a86fcf4..f9f1d94c82a8 100644 --- a/drivers/char/radio-aztech.c +++ b/drivers/char/radio-aztech.c @@ -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 . Based on original tuner code by: * * Quay Ly * Donald Song @@ -14,6 +12,11 @@ * 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 + * 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; diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 8786bf6483c6..4eb7d49c51ac 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -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 diff --git a/drivers/net/cosa.c b/drivers/net/cosa.c index 5c76aa0d414a..69f8bb0d8406 100644 --- a/drivers/net/cosa.c +++ b/drivers/net/cosa.c @@ -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 @@ -27,7 +27,7 @@ * Masaryk University (http://www.ics.muni.cz/). The hardware is * developed by Jiri Novotny . 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 \n"); + printk(KERN_INFO "cosa v1.04 (c) 1997-8 Jan Kasprzak \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<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<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: diff --git a/drivers/net/cosa.h b/drivers/net/cosa.h index 09f2e243d284..7b5a39018e86 100644 --- a/drivers/net/cosa.h +++ b/drivers/net/cosa.h @@ -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 @@ -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__ */ diff --git a/drivers/net/irda/Config.in b/drivers/net/irda/Config.in index c40b6f5c801b..64f6c327e911 100644 --- a/drivers/net/irda/Config.in +++ b/drivers/net/irda/Config.in @@ -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 diff --git a/drivers/net/irda/Makefile b/drivers/net/irda/Makefile index 05880d5e1f16..6a1571004312 100644 --- a/drivers/net/irda/Makefile +++ b/drivers/net/irda/Makefile @@ -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: diff --git a/drivers/net/irda/actisys.c b/drivers/net/irda/actisys.c index 97fb5fa27919..513b9ba30bd6 100644 --- a/drivers/net/irda/actisys.c +++ b/drivers/net/irda/actisys.c @@ -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 * 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 * * 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 "); +MODULE_DESCRIPTION("ACTiSYS IR-220L and IR-220L+ dongle driver"); /* * Function init_module (void) diff --git a/drivers/net/irda/esi.c b/drivers/net/irda/esi.c index a93e167aacbb..8bdf796ef730 100644 --- a/drivers/net/irda/esi.c +++ b/drivers/net/irda/esi.c @@ -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, * 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 * 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 index 000000000000..f74186b6ae4c --- /dev/null +++ b/drivers/net/irda/girbil.c @@ -0,0 +1,276 @@ +/********************************************************************* + * + * Filename: girbil.c + * Version: 1.0 + * Description: Implementation for the Greenwich GIrBIL dongle + * Status: Experimental. + * Author: Dag Brattli + * Created at: Sat Feb 6 21:02:33 1999 + * Modified at: Tue Feb 9 15:36:36 1999 + * Modified by: Dag Brattli + * + * 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 +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +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 "); +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 */ diff --git a/drivers/net/irda/irport.c b/drivers/net/irda/irport.c index ae8bcb27ba7c..616a8d3d9500 100644 --- a/drivers/net/irda/irport.c +++ b/drivers/net/irda/irport.c @@ -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"); diff --git a/drivers/net/irda/irtty.c b/drivers/net/irda/irtty.c index 09853b5b6974..f4c39035ffb7 100644 --- a/drivers/net/irda/irtty.c +++ b/drivers/net/irda/irtty.c @@ -1,12 +1,12 @@ /********************************************************************* * * Filename: irtty.c - * Version: 1.0 + * Version: 1.1 * Description: IrDA line discipline implementation * Status: Experimental. * Author: Dag Brattli * 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 * Sources: slip.c by Laurence Culhane, * Fred N. van Kempen, @@ -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 "); +MODULE_DESCRIPTION("IrDA TTY device driver"); + /* * Function init_module (void) * diff --git a/drivers/net/irda/pc87108.c b/drivers/net/irda/pc87108.c index faf9eea3376d..ea35883a5563 100644 --- a/drivers/net/irda/pc87108.c +++ b/drivers/net/irda/pc87108.c @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * 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 * * Copyright (c) 1998 Dag Brattli @@ -50,7 +50,6 @@ #include #include #include -#include #include #include @@ -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) diff --git a/drivers/net/irda/tekram.c b/drivers/net/irda/tekram.c index bdada4afab5e..40a1e46bf2b8 100644 --- a/drivers/net/irda/tekram.c +++ b/drivers/net/irda/tekram.c @@ -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 * 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 * * 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 "); +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 */ diff --git a/drivers/net/irda/uircc.c b/drivers/net/irda/uircc.c index 05da78a001ff..e182049eabc8 100644 --- a/drivers/net/irda/uircc.c +++ b/drivers/net/irda/uircc.c @@ -7,7 +7,7 @@ * Status: Experimental. * Author: Dag Brattli * 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 * * 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); diff --git a/drivers/net/irda/w83977af_ir.c b/drivers/net/irda/w83977af_ir.c index 5a7995ef7ead..7e634e0fe41d 100644 --- a/drivers/net/irda/w83977af_ir.c +++ b/drivers/net/irda/w83977af_ir.c @@ -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 * * 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) diff --git a/drivers/net/ne.c b/drivers/net/ne.c index 36b9123e8aa2..9bbf753c5ae9 100644 --- a/drivers/net/ne.c +++ b/drivers/net/ne.c @@ -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 diff --git a/drivers/net/plip.c b/drivers/net/plip.c index c41da18669e4..4bf73f81e225 100644 --- a/drivers/net/plip.c +++ b/drivers/net/plip.c @@ -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; diff --git a/drivers/net/sk_g16.c b/drivers/net/sk_g16.c index ac6736cabfb4..244df754479c 100644 --- a/drivers/net/sk_g16.c +++ b/drivers/net/sk_g16.c @@ -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) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 599253933317..4e1e3465d330 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -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 + * Copyright 1997 -- 1999 Martin Mares */ #include @@ -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) { diff --git a/drivers/sbus/char/flash.c b/drivers/sbus/char/flash.c index cea0c5131aac..2160b75a4a1b 100644 --- a/drivers/sbus/char/flash.c +++ b/drivers/sbus/char/flash.c @@ -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; } diff --git a/drivers/sbus/char/vfc_dev.c b/drivers/sbus/char/vfc_dev.c index 48661f34b0af..9ebc20c71898 100644 --- a/drivers/sbus/char/vfc_dev.c +++ b/drivers/sbus/char/vfc_dev.c @@ -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; } diff --git a/drivers/scsi/ChangeLog.ncr53c8xx b/drivers/scsi/ChangeLog.ncr53c8xx index 0f9c85de5bc5..2ecad6f2b39b 100644 --- a/drivers/scsi/ChangeLog.ncr53c8xx +++ b/drivers/scsi/ChangeLog.ncr53c8xx @@ -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). diff --git a/drivers/scsi/README.ncr53c8xx b/drivers/scsi/README.ncr53c8xx index 47bbe19ba6bf..38babc5f1099 100644 --- a/drivers/scsi/README.ncr53c8xx +++ b/drivers/scsi/README.ncr53c8xx @@ -4,7 +4,7 @@ Written by Gerard Roudier 21 Rue Carnot 95170 DEUIL LA BARRE - FRANCE -22 November 1998 +14 February 1999 =============================================================================== 1. Introduction @@ -39,6 +39,7 @@ Written by Gerard Roudier 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 diff --git a/drivers/scsi/README.st b/drivers/scsi/README.st index c50bd2793945..da8099937ccf 100644 --- a/drivers/scsi/README.st +++ b/drivers/scsi/README.st @@ -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 diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c index d6cbbcded52b..ccd54869fd3f 100644 --- a/drivers/scsi/ncr53c8xx.c +++ b/drivers/scsi/ncr53c8xx.c @@ -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 diff --git a/drivers/scsi/ncr53c8xx.h b/drivers/scsi/ncr53c8xx.h index b9a3b1156f9a..6ba860aa34c1 100644 --- a/drivers/scsi/ncr53c8xx.h +++ b/drivers/scsi/ncr53c8xx.h @@ -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 diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 8ffabde7ecc2..c53e2e7908a2 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -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) diff --git a/drivers/sound/Config.in b/drivers/sound/Config.in index 435c2168a671..634bb1820162 100644 --- a/drivers/sound/Config.in +++ b/drivers/sound/Config.in @@ -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 diff --git a/drivers/sound/ad1848.c b/drivers/sound/ad1848.c index 709d7f2edf4e..c80c9517c269 100644 --- a/drivers/sound/ad1848.c +++ b/drivers/sound/ad1848.c @@ -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; diff --git a/drivers/sound/ad1848_mixer.h b/drivers/sound/ad1848_mixer.h index 5768420a9746..fdd06e49978c 100644 --- a/drivers/sound/ad1848_mixer.h +++ b/drivers/sound/ad1848_mixer.h @@ -24,7 +24,10 @@ * 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 | \ @@ -47,16 +50,27 @@ 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 */ diff --git a/drivers/sound/es1370.c b/drivers/sound/es1370.c index 37d1fc38fb1e..dd73886db389 100644 --- a/drivers/sound/es1370.c +++ b/drivers/sound/es1370.c @@ -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; } diff --git a/drivers/sound/es1371.c b/drivers/sound/es1371.c index e52f47d149d9..69aa867aaa8d 100644 --- a/drivers/sound/es1371.c +++ b/drivers/sound/es1371.c @@ -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; } diff --git a/drivers/sound/lowlevel/awe_compat.h b/drivers/sound/lowlevel/awe_compat.h index 0ad4fb0622dc..9f9c57039ed2 100644 --- a/drivers/sound/lowlevel/awe_compat.h +++ b/drivers/sound/lowlevel/awe_compat.h @@ -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 */ diff --git a/drivers/sound/lowlevel/awe_wave.c b/drivers/sound/lowlevel/awe_wave.c index 1c2472049b90..8fd5431e6cbb 100644 --- a/drivers/sound/lowlevel/awe_wave.c +++ b/drivers/sound/lowlevel/awe_wave.c @@ -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 -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 "); 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; diff --git a/drivers/sound/mad16.c b/drivers/sound/mad16.c index 41533aedaf24..649c9861f510 100644 --- a/drivers/sound/mad16.c +++ b/drivers/sound/mad16.c @@ -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 diff --git a/drivers/sound/sb.h b/drivers/sound/sb.h index fd8fdcbd3ed4..a47d7099fd65 100644 --- a/drivers/sound/sb.h +++ b/drivers/sound/sb.h @@ -47,11 +47,13 @@ #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); diff --git a/drivers/sound/sb_card.c b/drivers/sound/sb_card.c index 5b6315a24ce0..e2630f0b751c 100644 --- a/drivers/sound/sb_card.c +++ b/drivers/sound/sb_card.c @@ -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); diff --git a/drivers/sound/sb_common.c b/drivers/sound/sb_common.c index 907250981448..ab85fd3fb508 100644 --- a/drivers/sound/sb_common.c +++ b/drivers/sound/sb_common.c @@ -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; diff --git a/drivers/sound/sb_mixer.c b/drivers/sound/sb_mixer.c index 97ce1b39de59..4f10108b928f 100644 --- a/drivers/sound/sb_mixer.c +++ b/drivers/sound/sb_mixer.c @@ -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: diff --git a/drivers/sound/sequencer.c b/drivers/sound/sequencer.c index 44207cb6276b..af40a2117455 100644 --- a/drivers/sound/sequencer.c +++ b/drivers/sound/sequencer.c @@ -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; diff --git a/drivers/sound/sonicvibes.c b/drivers/sound/sonicvibes.c index b1899e143944..0ecb00c62ad0 100644 --- a/drivers/sound/sonicvibes.c +++ b/drivers/sound/sonicvibes.c @@ -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; } diff --git a/drivers/sound/sound_core.c b/drivers/sound/sound_core.c index 115b9e33dd04..9bc08fbd03cf 100644 --- a/drivers/sound/sound_core.c +++ b/drivers/sound/sound_core.c @@ -39,7 +39,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/sound/soundcard.c b/drivers/sound/soundcard.c index cf3b70feacab..6731180b4025 100644 --- a/drivers/sound/soundcard.c +++ b/drivers/sound/soundcard.c @@ -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"); diff --git a/drivers/sound/trix.c b/drivers/sound/trix.c index 1a6b79c769d4..70b4af6d381b 100644 --- a/drivers/sound/trix.c +++ b/drivers/sound/trix.c @@ -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 diff --git a/drivers/video/atyfb.c b/drivers/video/atyfb.c index 613b5f20c4d5..c3b95d7cc6b1 100644 --- a/drivers/video/atyfb.c +++ b/drivers/video/atyfb.c @@ -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) { diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 56f0ac7904bd..f6e92fa478f9 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -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; } diff --git a/drivers/video/igafb.c b/drivers/video/igafb.c index e3a86c86852a..d6173e77e7d6 100644 --- a/drivers/video/igafb.c +++ b/drivers/video/igafb.c @@ -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) { diff --git a/drivers/video/sbusfb.c b/drivers/video/sbusfb.c index 88ecf574321d..bc5bafa951fd 100644 --- a/drivers/video/sbusfb.c +++ b/drivers/video/sbusfb.c @@ -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; diff --git a/fs/Config.in b/fs/Config.in index 74b4601b7a5f..3b8d32fb3468 100644 --- a/fs/Config.in +++ b/fs/Config.in @@ -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 diff --git a/fs/affs/inode.c b/fs/affs/inode.c index c23e3b1b94b9..9b05ec062ae1 100644 --- a/fs/affs/inode.c +++ b/fs/affs/inode.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include diff --git a/fs/affs/super.c b/fs/affs/super.c index 464b6df8aea3..0c2a838f5ee3 100644 --- a/fs/affs/super.c +++ b/fs/affs/super.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include diff --git a/fs/dquot.c b/fs/dquot.c index 8b7d07295a69..25f008e27704 100644 --- a/fs/dquot.c +++ b/fs/dquot.c @@ -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. diff --git a/fs/fat/mmap.c b/fs/fat/mmap.c index 4cda79196571..0494ad013605 100644 --- a/fs/fat/mmap.c +++ b/fs/fat/mmap.c @@ -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; } diff --git a/fs/isofs/file.c b/fs/isofs/file.c index 0a508c90bc0d..e2b4405d92eb 100644 --- a/fs/isofs/file.c +++ b/fs/isofs/file.c @@ -16,7 +16,6 @@ #include #include #include -#include /* * We have mostly NULLs here: the current defaults are OK for diff --git a/fs/ncpfs/mmap.c b/fs/ncpfs/mmap.c index 2c7610d0b80a..6b321e6c984a 100644 --- a/fs/ncpfs/mmap.c +++ b/fs/ncpfs/mmap.c @@ -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; } diff --git a/fs/smbfs/cache.c b/fs/smbfs/cache.c index 292493dacb18..36f1650ac32b 100644 --- a/fs/smbfs/cache.c +++ b/fs/smbfs/cache.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include @@ -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; } diff --git a/include/linux/awe_voice.h b/include/linux/awe_voice.h index 95fc207da025..aed60f5c2052 100644 --- a/include/linux/awe_voice.h +++ b/include/linux/awe_voice.h @@ -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 index 000000000000..07a6b82bc065 --- /dev/null +++ b/include/linux/dtlk.h @@ -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 */ +}; diff --git a/include/linux/miscdevice.h b/include/linux/miscdevice.h index 0f1f90a83103..d4718b3113f2 100644 --- a/include/linux/miscdevice.h +++ b/include/linux/miscdevice.h @@ -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); diff --git a/include/linux/pci.h b/include/linux/pci.h index 96bafde00063..eb3feb9a64d6 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -3,7 +3,7 @@ * * PCI defines and function prototypes * Copyright 1994, Drew Eckhardt - * Copyright 1997, 1998 Martin Mares + * Copyright 1997--1999 Martin Mares * * 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 */ @@ -101,7 +101,9 @@ #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 */ @@ -182,6 +184,12 @@ #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 @@ -356,6 +364,7 @@ #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 @@ -949,6 +958,9 @@ #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 @@ -1031,6 +1043,7 @@ #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); diff --git a/include/net/br.h b/include/net/br.h index c0b69e54aa51..1210b4e3ecec 100644 --- a/include/net/br.h +++ b/include/net/br.h @@ -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; diff --git a/include/net/irda/dongle.h b/include/net/irda/dongle.h index 8498f41767a4..d8983c009d2c 100644 --- a/include/net/irda/dongle.h +++ b/include/net/irda/dongle.h @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * 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 * * 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 { diff --git a/include/net/irda/ircomm_common.h b/include/net/irda/ircomm_common.h index a092d98082cd..9ef035889554 100644 --- a/include/net/irda/ircomm_common.h +++ b/include/net/irda/ircomm_common.h @@ -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 */ diff --git a/include/net/irda/irda.h b/include/net/irda/irda.h index 22458aa0ba0e..30835b9a9419 100644 --- a/include/net/irda/irda.h +++ b/include/net/irda/irda.h @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * 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 * * 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) \ diff --git a/include/net/irda/irda_device.h b/include/net/irda/irda_device.h index d8e546bb5ada..7439f5ffb49a 100644 --- a/include/net/irda/irda_device.h +++ b/include/net/irda/irda_device.h @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Haris Zukanovic * 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 * * Copyright (c) 1998 Haris Zukanovic, @@ -35,11 +35,13 @@ #include #include -#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 */ diff --git a/include/net/irda/iriap.h b/include/net/irda/iriap.h index 495da351e704..df214129d247 100644 --- a/include/net/irda/iriap.h +++ b/include/net/irda/iriap.h @@ -1,12 +1,12 @@ /********************************************************************* * * Filename: iriap.h - * Version: + * Version: 0.5 * Description: Information Access Protocol (IAP) * Status: Experimental. * Author: Dag Brattli * 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 * * Copyright (c) 1997 Dag Brattli , All Rights Reserved. @@ -55,23 +55,13 @@ 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 + + diff --git a/include/net/irda/irias_object.h b/include/net/irda/irias_object.h index efacac8548a5..4a76018b6ff8 100644 --- a/include/net/irda/irias_object.h +++ b/include/net/irda/irias_object.h @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * 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 * * 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 /* LM-IAS Attribute types */ #define IAS_MISSING 0 @@ -38,12 +38,10 @@ */ 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_client.h similarity index 51% rename from include/net/irda/irlan_cli.h rename to include/net/irda/irlan_client.h index fb677af20cd3..547868c6a26b 100644 --- a/include/net/irda/irlan_cli.h +++ b/include/net/irda/irlan_client.h @@ -1,12 +1,12 @@ /********************************************************************* * - * Filename: client.h + * Filename: irlan_client.h * Version: 0.3 * Description: IrDA LAN access layer * Status: Experimental. * Author: Dag Brattli * Created at: Sun Aug 31 20:14:37 1997 - * Modified at: Mon Oct 19 12:37:20 1998 + * Modified at: Wed Feb 3 14:29:49 1999 * Modified by: Dag Brattli * * Copyright (c) 1998 Dag Brattli , All Rights Reserved. @@ -30,36 +30,15 @@ #include #include -int irlan_client_init(void); -void irlan_client_cleanup(void); +#include -void irlan_discovery_indication( DISCOVERY*); -void irlan_client_disconnect_indication( void *instance, void *sap, - LM_REASON reason, struct sk_buff *); +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_data_indication( void *instance, void *sap, - struct sk_buff *skb); +void irlan_client_open_ctrl_tsap( struct irlan_cb *self); -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_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 diff --git a/include/net/irda/irlan_common.h b/include/net/irda/irlan_common.h index 33ba52377333..a07fdfd2f365 100644 --- a/include/net/irda/irlan_common.h +++ b/include/net/irda/irlan_common.h @@ -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 * 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 * * Copyright (c) 1998 Dag Brattli , All Rights Reserved. @@ -30,10 +30,11 @@ #include #include -#include "irqueue.h" -#include "irttp.h" +#include +#include -#define IRLAN_MTU 1518 +#define IRLAN_MTU 1518 +#define IRLAN_TIMEOUT 1000 /* Command packet types */ #define CMD_GET_PROVIDER_INFO 0 @@ -61,23 +62,23 @@ #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 @@ -87,36 +88,51 @@ #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; diff --git a/include/net/irda/irlan_eth.h b/include/net/irda/irlan_eth.h index 72f14ff75a80..4cc2b12a875c 100644 --- a/include/net/irda/irlan_eth.h +++ b/include/net/irda/irlan_eth.h @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * 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 * * Copyright (c) 1998 Dag Brattli, All Rights Reserved. @@ -25,12 +25,8 @@ #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); diff --git a/include/net/irda/irlan_event.h b/include/net/irda/irlan_event.h index d3a062af0f2d..b9baac9eb8b6 100644 --- a/include/net/irda/irlan_event.h +++ b/include/net/irda/irlan_event.h @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * 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 * * Copyright (c) 1997 Dag Brattli , 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 index 000000000000..b68eec161b47 --- /dev/null +++ b/include/net/irda/irlan_filter.h @@ -0,0 +1,33 @@ +/********************************************************************* + * + * Filename: irlan_filter.h + * Version: + * Description: + * Status: Experimental. + * Author: Dag Brattli + * Created at: Fri Jan 29 15:24:08 1999 + * Modified at: Sun Feb 7 23:35:31 1999 + * Modified by: Dag Brattli + * + * 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_srv.h b/include/net/irda/irlan_provider.h similarity index 54% rename from include/net/irda/irlan_srv.h rename to include/net/irda/irlan_provider.h index c187302e2556..a95b490955de 100644 --- a/include/net/irda/irlan_srv.h +++ b/include/net/irda/irlan_provider.h @@ -1,12 +1,12 @@ /********************************************************************* * - * Filename: server.h + * Filename: irlan_provider.h * Version: 0.1 * Description: IrDA LAN access layer * Status: Experimental. * Author: Dag Brattli * Created at: Sun Aug 31 20:14:37 1997 - * Modified at: Fri Oct 16 11:25:37 1998 + * Modified at: Sat Jan 30 16:22:24 1999 * Modified by: Dag Brattli * * Copyright (c) 1998 Dag Brattli , All Rights Reserved. @@ -32,31 +32,26 @@ #include -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_provider_ctrl_disconnect_indication(void *instance, void *sap, + LM_REASON reason, + struct sk_buff *skb); -void irlan_server_disconnect_indication( void *instance, void *sap, - LM_REASON reason, +void irlan_provider_ctrl_data_indication(void *instance, void *sap, 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_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 *); -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, +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_server_send_reply( struct irlan_cb *self, int command, - int ret_code); -void irlan_server_register(void); +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/irlap.h b/include/net/irda/irlap.h index 524d2b79907b..dd958b86b51d 100644 --- a/include/net/irda/irlap.h +++ b/include/net/irda/irlap.h @@ -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 * 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 * * Copyright (c) 1998 Dag Brattli , 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 */ diff --git a/include/net/irda/irlap_event.h b/include/net/irda/irlap_event.h index bf4128939623..db77cf5d9367 100644 --- a/include/net/irda/irlap_event.h +++ b/include/net/irda/irlap_event.h @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * 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 * * Copyright (c) 1998 Dag Brattli , 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); diff --git a/include/net/irda/irlmp.h b/include/net/irda/irlmp.h index a10a08fe1b14..82690a34aed5 100644 --- a/include/net/irda/irlmp.h +++ b/include/net/irda/irlmp.h @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * 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 * * Copyright (c) 1998 Dag Brattli , All Rights Reserved. @@ -28,17 +28,19 @@ #include #include -#include "irmod.h" -#include "qos.h" -#include "irlap.h" -#include "irlmp_event.h" -#include "irqueue.h" +#include +#include +#include +#include +#include /* 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 diff --git a/include/net/irda/irlmp_event.h b/include/net/irda/irlmp_event.h index 1ffb6faa5537..88076a970928 100644 --- a/include/net/irda/irlmp_event.h +++ b/include/net/irda/irlmp_event.h @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * 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 * * Copyright (c) 1997 Dag Brattli , 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); diff --git a/include/net/irda/irlmp_frame.h b/include/net/irda/irlmp_frame.h index 64960f31dcc4..84e5136c7464 100644 --- a/include/net/irda/irlmp_frame.h +++ b/include/net/irda/irlmp_frame.h @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * 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 * * Copyright (c) 1997 Dag Brattli , 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); diff --git a/include/net/irda/irlpt_cli.h b/include/net/irda/irlpt_cli.h index 1a54c68ebddf..cd0807dd2a84 100644 --- a/include/net/irda/irlpt_cli.h +++ b/include/net/irda/irlpt_cli.h @@ -1,6 +1,6 @@ /********************************************************************* * - * Filename: irlpt_client.h + * Filename: irlpt_cli.h * Version: 0.1 * Description: * Status: Experimental. @@ -35,8 +35,10 @@ */ 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); diff --git a/include/net/irda/irlpt_cli_fsm.h b/include/net/irda/irlpt_cli_fsm.h index 4013c2f4dec2..b6fd153a5dbe 100644 --- a/include/net/irda/irlpt_cli_fsm.h +++ b/include/net/irda/irlpt_cli_fsm.h @@ -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 , All Rights Reserved. - * Copyright (c) 1998, Thomas Davis, , All Rights Reserved. + * Copyright (c) 1997 Dag Brattli , + * All Rights Reserved. + * Copyright (c) 1998, Thomas Davis, , + * 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. * ********************************************************************/ diff --git a/include/net/irda/irlpt_common.h b/include/net/irda/irlpt_common.h index 0e51b017a8d5..83a9c307cc8f 100644 --- a/include/net/irda/irlpt_common.h +++ b/include/net/irda/irlpt_common.h @@ -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; diff --git a/include/net/irda/irlpt_server.h b/include/net/irda/irlpt_server.h index 7984a331ddae..44e310f9571c 100644 --- a/include/net/irda/irlpt_server.h +++ b/include/net/irda/irlpt_server.h @@ -1,6 +1,6 @@ /********************************************************************* * - * Filename: server.h + * Filename: irlpt_server.h * Version: 0.1 * Description: * Status: Experimental. diff --git a/include/net/irda/irlpt_server_fsm.h b/include/net/irda/irlpt_server_fsm.h index 8f23226c3300..c7ee3f871560 100644 --- a/include/net/irda/irlpt_server_fsm.h +++ b/include/net/irda/irlpt_server_fsm.h @@ -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 , All Rights Reserved. - * Copyright (c) 1998, Thomas Davis, , All Rights Reserved. + * Copyright (c) 1997 Dag Brattli , + * All Rights Reserved. + * Copyright (c) 1998, Thomas Davis, , + * 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. * ********************************************************************/ @@ -23,8 +25,11 @@ #include #include -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 diff --git a/include/net/irda/irmod.h b/include/net/irda/irmod.h index a2f5925723f0..52d49330affe 100644 --- a/include/net/irda/irmod.h +++ b/include/net/irda/irmod.h @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * 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 * * 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 diff --git a/include/net/irda/irobex.h b/include/net/irda/irobex.h index 8f69707d01a6..b07da06abe82 100644 --- a/include/net/irda/irobex.h +++ b/include/net/irda/irobex.h @@ -1,12 +1,12 @@ /********************************************************************* * * Filename: irobex.h - * Version: + * Version: 0.8 * Description: * Status: Experimental. * Author: Dag Brattli * 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 * * Copyright (c) 1998 Dag Brattli, All Rights Reserved. @@ -28,7 +28,6 @@ #include #include #include -/* #include */ #include #include @@ -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); diff --git a/include/net/irda/irttp.h b/include/net/irda/irttp.h index 02a486dd54c3..4b75d8fa654f 100644 --- a/include/net/irda/irttp.h +++ b/include/net/irda/irttp.h @@ -1,12 +1,12 @@ /********************************************************************* * * Filename: irttp.h - * Version: 0.3 + * Version: 1.0 * Description: Tiny Transport Protocol (TTP) definitions * Status: Experimental. * Author: Dag Brattli * 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 * * Copyright (c) 1998 Dag Brattli , All Rights Reserved. @@ -33,21 +33,21 @@ #include #include -#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 @@ -56,13 +56,13 @@ * 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 */ diff --git a/include/net/irda/irtty.h b/include/net/irda/irtty.h index 313a32d9b3eb..920909600e54 100644 --- a/include/net/irda/irtty.h +++ b/include/net/irda/irtty.h @@ -1,12 +1,12 @@ /********************************************************************* * * Filename: irtty.h - * Version: 0.1 + * Version: 1.0 * Description: * Status: Experimental. * Author: Dag Brattli * 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 * * 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 diff --git a/include/net/irda/pc87108.h b/include/net/irda/pc87108.h index ed47bdc1b94a..8be4feea1a2b 100644 --- a/include/net/irda/pc87108.h +++ b/include/net/irda/pc87108.h @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * 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 * * Copyright (c) 1998 Dag Brattli @@ -148,8 +148,8 @@ #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 diff --git a/include/net/irda/timer.h b/include/net/irda/timer.h index 35a5be2604af..39719b5e3a6e 100644 --- a/include/net/irda/timer.h +++ b/include/net/irda/timer.h @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * 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 * * Copyright (c) 1997, 1998 Dag Brattli , @@ -26,11 +26,11 @@ #ifndef TIMER_H #define TIMER_H -#include "irda.h" -#include "irmod.h" -#include "irlap.h" -#include "irlmp.h" -#include "irda_device.h" +#include +#include +#include +#include +#include /* * 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); diff --git a/include/net/irda/wrapper.h b/include/net/irda/wrapper.h index 838713f31fbc..ca21ebec5123 100644 --- a/include/net/irda/wrapper.h +++ b/include/net/irda/wrapper.h @@ -1,12 +1,12 @@ /********************************************************************* * * Filename: wrapper.h - * Version: + * Version: 1.0 * Description: IrDA Wrapper layer * Status: Experimental. * Author: Dag Brattli * 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 * * Copyright (c) 1998 Dag Brattli , All Rights Reserved. @@ -28,7 +28,7 @@ #include #include -#include "irda_device.h" +#include #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, diff --git a/mm/filemap.c b/mm/filemap.c index 7bdb5d57a8e1..9caf66fca814 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -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; } diff --git a/mm/mmap.c b/mm/mmap.c index 9a9146754699..b5a4817df886 100644 --- 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++; } /* diff --git a/mm/swapfile.c b/mm/swapfile.c index dd66701b53d7..42ca4900aeed 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -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); diff --git a/net/Makefile b/net/Makefile index 6e0971c7af42..d6869098d4ff 100644 --- a/net/Makefile +++ b/net/Makefile @@ -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 diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index f9392fe34527..a2ad7111f929 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -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); diff --git a/net/bridge/br.c b/net/bridge/br.c index 9a18af09a96a..996aeb7180b3 100644 --- a/net/bridge/br.c +++ b/net/bridge/br.c @@ -6,7 +6,7 @@ * More hacks to be able to switch protocols on and off by Christoph Lameter * * 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 #include #include -#include #include #include #include @@ -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); diff --git a/net/bridge/br_tree.c b/net/bridge/br_tree.c index 0936a0f8b6b0..c1ed82f10875 100644 --- a/net/bridge/br_tree.c +++ b/net/bridge/br_tree.c @@ -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; +} diff --git a/net/core/scm.c b/net/core/scm.c index c28da7ebbd76..48c7b79d8a2b 100644 --- a/net/core/scm.c +++ b/net/core/scm.c @@ -27,7 +27,6 @@ #include #include -#include #include #include #include diff --git a/net/core/skbuff.c b/net/core/skbuff.c index b40bc8f82f06..b76364371fb4 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -4,7 +4,7 @@ * Authors: Alan Cox * Florian La Roche * - * 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. diff --git a/net/core/sock.c b/net/core/sock.c index 381ee8be416e..fd9c6f9424a7 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -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, * Fred N. van Kempen, diff --git a/net/econet/econet.c b/net/econet/econet.c index 8a3a72ae7eaa..8930109b37a0 100644 --- a/net/econet/econet.c +++ b/net/econet/econet.c @@ -44,7 +44,6 @@ #include #include #include -#include static struct proto_ops econet_ops; static struct sock *econet_sklist; diff --git a/net/ipv4/Config.in b/net/ipv4/Config.in index 8e4b3945eafa..43334d5bd089 100644 --- a/net/ipv4/Config.in +++ b/net/ipv4/Config.in @@ -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 diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index efb16cc473da..0af02ef51c45 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -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: /* diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 544dd8937ce5..c21eed8faa19 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -3,7 +3,7 @@ * * Alan Cox, * - * 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 diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 8378c2b03e90..98b83adab205 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -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, * Fred N. van Kempen, @@ -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); } diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index c93a874db5f5..3a2d39807298 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -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, * Fred N. van Kempen, @@ -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)))); } diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index b8b23eb38439..0522d872eca8 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -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 * diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 03c96e99c870..83a05302eb60 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -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, * Fred N. van Kempen, @@ -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. */ diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 00d9b099e741..81871e5ea09c 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $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; } diff --git a/net/irda/Makefile b/net/irda/Makefile index 4af71d35f667..495614172cbb 100644 --- a/net/irda/Makefile +++ b/net/irda/Makefile @@ -10,13 +10,19 @@ 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 diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c index 85c191b29a5e..67e102a240e0 100644 --- a/net/irda/af_irda.c +++ b/net/irda/af_irda.c @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * 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 * Sources: af_netroom.c, af_ax25.x * @@ -23,11 +23,17 @@ * ********************************************************************/ +#include #include #include #include +#include +#include +#include + +#include + #include -#include #include #include @@ -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( ¬ify); - tsap = irttp_open_tsap( LSAP_ANY, DEFAULT_INITIAL_CREDIT, ¬ify); - - 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; diff --git a/net/irda/ircomm/attach.c b/net/irda/ircomm/attach.c index 1e5e373ee88d..7ec8e469ec56 100644 --- a/net/irda/ircomm/attach.c +++ b/net/irda/ircomm/attach.c @@ -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, - ¬ify ); + self->tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT, + ¬ify); 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; } diff --git a/net/irda/ircomm/ircomm_common.c b/net/irda/ircomm/ircomm_common.c index cfda567ceb67..d6004ed00e77 100644 --- a/net/irda/ircomm/ircomm_common.c +++ b/net/irda/ircomm/ircomm_common.c @@ -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 */ diff --git a/net/irda/irda_device.c b/net/irda/irda_device.c index 65a8605a7daf..00698944d42e 100644 --- a/net/irda/irda_device.c +++ b/net/irda/irda_device.c @@ -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 * 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 * * Copyright (c) 1998 Dag Brattli, All Rights Reserved. @@ -30,10 +30,15 @@ #include #include #include +#include -#include +#include +#include +#include #include +#include + #include #include #include @@ -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); diff --git a/net/irda/iriap.c b/net/irda/iriap.c index f23d3faafe35..5f626abd27aa 100644 --- a/net/irda/iriap.c +++ b/net/irda/iriap.c @@ -1,12 +1,12 @@ /********************************************************************* * * Filename: iriap.c - * Version: 0.1 + * Version: 0.8 * Description: Information Access Protocol (IAP) * Status: Experimental. * Author: Dag Brattli * 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 * * Copyright (c) 1998 Dag Brattli , @@ -33,18 +33,35 @@ #include #include +#include #include #include #include #include +/* 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; diff --git a/net/irda/iriap_event.c b/net/irda/iriap_event.c index c0ba0058e224..ccba78ecefc2 100644 --- a/net/irda/iriap_event.c +++ b/net/irda/iriap_event.c @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * 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 * * Copyright (c) 1997 Dag Brattli , 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; } } diff --git a/net/irda/irlan/Config.in b/net/irda/irlan/Config.in index a9a7b84f2ab0..7951d90abc91 100644 --- a/net/irda/irlan/Config.in +++ b/net/irda/irlan/Config.in @@ -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 diff --git a/net/irda/irlan/Makefile b/net/irda/irlan/Makefile index d5b37b9d8b44..6d4cb8433132 100644 --- a/net/irda/irlan/Makefile +++ b/net/irda/irlan/Makefile @@ -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 index 700f25e9ca52..000000000000 --- a/net/irda/irlan/irlan_cli.c +++ /dev/null @@ -1,676 +0,0 @@ -/********************************************************************* - * - * Filename: irlan_cli.c - * Version: 0.8 - * Description: IrDA LAN Access Protocol Client - * Status: Experimental. - * Author: Dag Brattli - * Created at: Sun Aug 31 20:14:37 1997 - * Modified at: Mon Jan 18 13:24:26 1999 - * Modified by: Dag Brattli - * Sources: skeleton.c by Donald Becker - * slip.c by Laurence Culhane, - * Fred N. van Kempen, - * - * 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 - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -/* - * 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( ¬ify_ctrl); - irda_notify_init( ¬ify_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, - ¬ify_ctrl); - self->tsap_data = irttp_open_tsap( LSAP_ANY, - DEFAULT_INITIAL_CREDIT, - ¬ify_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; iname, 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 "); -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 index 2f01a4b4a783..000000000000 --- a/net/irda/irlan/irlan_cli_event.c +++ /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 - * Created at: Sun Aug 31 20:14:37 1997 - * Modified at: Wed Dec 9 02:36:49 1998 - * Modified by: Dag Brattli - * - * 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 - -#include -#include -#include -#include -#include - -#include -#include -#include - -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 index 000000000000..78e33c46ca64 --- /dev/null +++ b/net/irda/irlan/irlan_client.c @@ -0,0 +1,617 @@ +/********************************************************************* + * + * Filename: irlan_client.c + * Version: 0.9 + * Description: IrDA LAN Access Protocol (IrLAN) Client + * Status: Experimental. + * Author: Dag Brattli + * Created at: Sun Aug 31 20:14:37 1997 + * Modified at: Wed Feb 17 23:29:34 1999 + * Modified by: Dag Brattli + * Sources: skeleton.c by Donald Becker + * slip.c by Laurence Culhane, + * Fred N. van Kempen, + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#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(¬ify); + + /* 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, ¬ify); + 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; imagic == 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 index 000000000000..ec666c3d2c45 --- /dev/null +++ b/net/irda/irlan/irlan_client_event.c @@ -0,0 +1,532 @@ +/********************************************************************* + * + * Filename: irlan_client_event.c + * Version: 0.9 + * Description: IrLAN client state machine + * Status: Experimental. + * Author: Dag Brattli + * Created at: Sun Aug 31 20:14:37 1997 + * Modified at: Thu Feb 4 16:08:07 1999 + * Modified by: Dag Brattli + * + * 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 + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +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; +} + + + + + + + + + + + + + diff --git a/net/irda/irlan/irlan_common.c b/net/irda/irlan/irlan_common.c index 90be583f5b9d..1ff3b5a5215b 100644 --- a/net/irda/irlan/irlan_common.c +++ b/net/irda/irlan/irlan_common.c @@ -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 * 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 * * Copyright (c) 1997 Dag Brattli , All Rights Reserved. @@ -44,17 +44,59 @@ #include #include +#include +#include +#include +#include -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 or irlan */ + if (!eth) { + /* Get the first free irlan 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(¬ify); + + 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, ¬ify); + 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 "); 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 */ - diff --git a/net/irda/irlan/irlan_eth.c b/net/irda/irlan/irlan_eth.c index c84aa0aa9165..d09df36524f9 100644 --- a/net/irda/irlan/irlan_eth.c +++ b/net/irda/irlan/irlan_eth.c @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * 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 * Sources: skeleton.c by Donald Becker * slip.c by Laurence Culhane, @@ -34,159 +34,51 @@ #include #include -/* - * 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; } diff --git a/net/irda/irlan/irlan_event.c b/net/irda/irlan/irlan_event.c index 96fbccb58ef9..d54e7cc122c0 100644 --- a/net/irda/irlan/irlan_event.c +++ b/net/irda/irlan/irlan_event.c @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * 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 * * 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 index 000000000000..5419b321c31a --- /dev/null +++ b/net/irda/irlan/irlan_filter.c @@ -0,0 +1,235 @@ +/********************************************************************* + * + * Filename: irlan_filter.c + * Version: + * Description: + * Status: Experimental. + * Author: Dag Brattli + * Created at: Fri Jan 29 11:16:38 1999 + * Modified at: Sun Feb 7 23:48:07 1999 + * Modified by: Dag Brattli + * + * 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 + +#include + +/* + * 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 index 000000000000..eb8f035c921d --- /dev/null +++ b/net/irda/irlan/irlan_provider.c @@ -0,0 +1,431 @@ +/********************************************************************* + * + * Filename: irlan_provider.c + * Version: 0.9 + * Description: IrDA LAN Access Protocol Implementation + * Status: Experimental. + * Author: Dag Brattli + * Created at: Sun Aug 31 20:14:37 1997 + * Modified at: Thu Feb 4 16:08:33 1999 + * Modified by: Dag Brattli + * Sources: skeleton.c by Donald Becker + * slip.c by Laurence Culhane, + * Fred N. van Kempen, + * + * 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 +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/* + * 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; imagic == 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(¬ify); + 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, ¬ify); + 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 index 000000000000..c8dc9b44cccd --- /dev/null +++ b/net/irda/irlan/irlan_provider_event.c @@ -0,0 +1,240 @@ +/********************************************************************* + * + * Filename: irlan_provider_event.c + * Version: 0.9 + * Description: IrLAN provider state machine) + * Status: Experimental. + * Author: Dag Brattli + * Created at: Sun Aug 31 20:14:37 1997 + * Modified at: Wed Feb 3 21:43:06 1999 + * Modified by: Dag Brattli + * + * 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 +#include +#include +#include + +#include +#include + +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 index df4c6f954263..000000000000 --- a/net/irda/irlan/irlan_srv.c +++ /dev/null @@ -1,915 +0,0 @@ -/********************************************************************* - * - * Filename: irlan_srv.c - * Version: 0.1 - * Description: IrDA LAN Access Protocol Implementation - * Status: Experimental. - * Author: Dag Brattli - * Created at: Sun Aug 31 20:14:37 1997 - * Modified at: Mon Dec 14 19:10:49 1998 - * Modified by: Dag Brattli - * Sources: skeleton.c by Donald Becker - * slip.c by Laurence Culhane, - * Fred N. van Kempen, - * - * 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 - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -/* - * 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 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( ¬ify); - 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, ¬ify); - if ( tsap == NULL) { - DEBUG( 0, __FUNCTION__ "(), Got no handle!!\n"); - return; - } - self->tsap_ctrl = tsap; - - /* - * Now register data TSAP - */ - irda_notify_init( ¬ify); - 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, ¬ify); - 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 "); -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 index 6ad8d2f46bff..000000000000 --- a/net/irda/irlan/irlan_srv_event.c +++ /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 - * Created at: Sun Aug 31 20:14:37 1997 - * Modified at: Wed Dec 9 02:39:05 1998 - * Modified by: Dag Brattli - * - * 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 -#include -#include -#include - -#include -#include - -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; -} - - - - - - - - - - diff --git a/net/irda/irlap.c b/net/irda/irlap.c index 633d29220219..c14191276cd9 100644 --- a/net/irda/irlap.c +++ b/net/irda/irlap.c @@ -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 * 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 * * Copyright (c) 1998 Dag Brattli , @@ -43,12 +43,23 @@ #include 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]); diff --git a/net/irda/irlap_comp.c b/net/irda/irlap_comp.c index d2e876be9fda..9959b64bc14e 100644 --- a/net/irda/irlap_comp.c +++ b/net/irda/irlap_comp.c @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * 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 * 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; } diff --git a/net/irda/irlap_event.c b/net/irda/irlap_event.c index d2afcbd292f7..6a13b5904206 100644 --- a/net/irda/irlap_event.c +++ b/net/irda/irlap_event.c @@ -1,12 +1,12 @@ /********************************************************************* * * Filename: irlap_event.c - * Version: 0.1 + * Version: 0.8 * Description: IrLAP state machine implementation * Status: Experimental. * Author: Dag Brattli * 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 * * Copyright (c) 1998 Dag Brattli , @@ -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; } diff --git a/net/irda/irlap_frame.c b/net/irda/irlap_frame.c index d00fd185242c..d77d765dc89a 100644 --- a/net/irda/irlap_frame.c +++ b/net/irda/irlap_frame.c @@ -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 * 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 * * Copyright (c) 1998 Dag Brattli , All Rights Resrved. @@ -26,7 +26,6 @@ #include #include -#include #include #include #include @@ -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; - if( discovery->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: diff --git a/net/irda/irlmp.c b/net/irda/irlmp.c index c4f7c2b8dfd9..e433fcba6955 100644 --- a/net/irda/irlmp.c +++ b/net/irda/irlmp.c @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * 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 * * Copyright (c) 1998 Dag Brattli , @@ -44,9 +44,21 @@ /* 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( "\n"); + DEBUG(1, "\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"); diff --git a/net/irda/irlmp_event.c b/net/irda/irlmp_event.c index a1f537958827..957176f94c58 100644 --- a/net/irda/irlmp_event.c +++ b/net/irda/irlmp_event.c @@ -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 * 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 * * Copyright (c) 1998 Dag Brattli , @@ -32,13 +32,13 @@ #include #include -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); diff --git a/net/irda/irlmp_frame.c b/net/irda/irlmp_frame.c index 9d5ac0c35cc6..bf993d4902c4 100644 --- a/net/irda/irlmp_frame.c +++ b/net/irda/irlmp_frame.c @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * 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 * * Copyright (c) 1998 Dag Brattli @@ -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); } diff --git a/net/irda/irlpt/irlpt_cli.c b/net/irda/irlpt/irlpt_cli.c index c98985cfbfe0..bb3081a9c215 100644 --- a/net/irda/irlpt/irlpt_cli.c +++ b/net/irda/irlpt/irlpt_cli.c @@ -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 "); -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 */ diff --git a/net/irda/irlpt/irlpt_cli_fsm.c b/net/irda/irlpt/irlpt_cli_fsm.c index 6362756a20b5..75598742aa88 100644 --- a/net/irda/irlpt/irlpt_cli_fsm.c +++ b/net/irda/irlpt/irlpt_cli_fsm.c @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * 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 * * Copyright (c) 1998, Thomas Davis, @@ -35,50 +35,53 @@ 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; diff --git a/net/irda/irlpt/irlpt_common.c b/net/irda/irlpt/irlpt_common.c index 886eb30a02d1..b4512736a6da 100644 --- a/net/irda/irlpt/irlpt_common.c +++ b/net/irda/irlpt/irlpt_common.c @@ -68,7 +68,7 @@ char *irlpt_connected[] = { char *irlpt_reasons[] = { "SERVICE_CLOSE", /* Service has closed the connection */ - "DISC_INDICATION", /* Received a 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 "); +MODULE_DESCRIPTION("The Linux IrDA/IrLPT common"); +MODULE_PARM(irlpt_common_debug,"1i"); + /* * Function init_module (void) * diff --git a/net/irda/irlpt/irlpt_srvr.c b/net/irda/irlpt/irlpt_srvr.c index b7d6f1bb9bda..a365ef5b4316 100644 --- a/net/irda/irlpt/irlpt_srvr.c +++ b/net/irda/irlpt/irlpt_srvr.c @@ -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, ¬ify); 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(¬ify); - - 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, ¬ify); - - 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 "); -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 */ diff --git a/net/irda/irlpt/irlpt_srvr_fsm.c b/net/irda/irlpt/irlpt_srvr_fsm.c index 3640a96777b9..d37d98b7cbb9 100644 --- a/net/irda/irlpt/irlpt_srvr_fsm.c +++ b/net/irda/irlpt/irlpt_srvr_fsm.c @@ -4,8 +4,10 @@ * Version: 0.1 * Sources: irlan_event.c * - * Copyright (c) 1997, Dag Brattli , All Rights Reserved. - * Copyright (c) 1998, Thomas Davis, , All Rights Reserved. + * Copyright (c) 1997, Dag Brattli , + * All Rights Reserved. + * Copyright (c) 1998, Thomas Davis, , + * 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: diff --git a/net/irda/irmod.c b/net/irda/irmod.c index c009d685877e..fede19a63385 100644 --- a/net/irda/irmod.c +++ b/net/irda/irmod.c @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * 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 * * Copyright (c) 1997 Dag Brattli, All Rights Reserved. @@ -24,14 +24,28 @@ #include #include + #include -#include #include +#include + +#include #include +#include +#include +#ifdef CONFIG_IRDA_COMPRESSION +#include +#endif /* CONFIG_IRDA_COMPRESSION */ #include #include +#include #include +#include +#include +#include + +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 "); MODULE_DESCRIPTION("The Linux IrDA protocol subsystem"); +MODULE_PARM(irda_debug, "1l"); /* * Function init_module (void) diff --git a/net/irda/irobex/irobex.c b/net/irda/irobex/irobex.c index 8b289182d2b5..6916be460c18 100644 --- a/net/irda/irobex/irobex.c +++ b/net/irda/irobex/irobex.c @@ -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 * 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 * * 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; diff --git a/net/irda/irproc.c b/net/irda/irproc.c index bc6a3ace5c01..977dd36a37b8 100644 --- a/net/irda/irproc.c +++ b/net/irda/irproc.c @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Thomas Davis, * 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 * * Copyright (c) 1998, Thomas Davis, , @@ -31,27 +31,24 @@ #include #include -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; diff --git a/net/irda/irqueue.c b/net/irda/irqueue.c index 3d23c8aef568..8137c49a247e 100644 --- a/net/irda/irqueue.c +++ b/net/irda/irqueue.c @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * 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 * * Copyright (C) 1998, Aage Kvalnes @@ -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. diff --git a/net/irda/irsysctl.c b/net/irda/irsysctl.c index e8a3f9910388..7565138e9476 100644 --- a/net/irda/irsysctl.c +++ b/net/irda/irsysctl.c @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * 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 * * Copyright (c) 1997 Dag Brattli, All Rights Reserved. @@ -31,9 +31,11 @@ #include #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 } }; diff --git a/net/irda/irttp.c b/net/irda/irttp.c index 3da804e7deb2..100b6b9581db 100644 --- a/net/irda/irttp.c +++ b/net/irda/irttp.c @@ -1,12 +1,12 @@ /********************************************************************* * * Filename: irttp.c - * Version: 0.4 + * Version: 1.0 * Description: Tiny Transport Protocol (TTP) implementation * Status: Experimental. * Author: Dag Brattli * 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 * * Copyright (c) 1998 Dag Brattli , @@ -35,26 +35,26 @@ 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); diff --git a/net/irda/qos.c b/net/irda/qos.c index 215666aa0768..015d7559f592 100644 --- a/net/irda/qos.c +++ b/net/irda/qos.c @@ -1,12 +1,12 @@ /********************************************************************* * * Filename: qos.c - * Version: 0.1 + * Version: 0.8 * Description: IrLAP QoS negotiation * Status: Experimental. * Author: Dag Brattli * 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 * * Copyright (c) 1998 Dag Brattli , 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; diff --git a/net/irda/timer.c b/net/irda/timer.c index 95c18f13ff7f..ed3929a728ea 100644 --- a/net/irda/timer.c +++ b/net/irda/timer.c @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * 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 * * Copyright (c) 1997 Dag Brattli , 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); } /* diff --git a/net/irda/wrapper.c b/net/irda/wrapper.c index fdebb5788e70..680bced96e2b 100644 --- a/net/irda/wrapper.c +++ b/net/irda/wrapper.c @@ -1,12 +1,12 @@ /********************************************************************* * * Filename: wrapper.c - * Version: - * Description: IrDA Wrapper layer + * Version: 1.0 + * Description: SIR wrapper layer * Status: Experimental. * Author: Dag Brattli * 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 * * Copyright (c) 1998 Dag Brattli , @@ -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) } + + -- 2.39.5