From 089fdcc45f022cfa374fcfbe36881d3e1880bc6f Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:19:02 -0500 Subject: [PATCH] Import 2.2.10pre2 --- README | 6 +- arch/i386/lib/checksum.S | 2 +- arch/sparc64/kernel/setup.c | 4 +- drivers/block/loop.c | 2 + drivers/block/ns87415.c | 17 + drivers/char/bttv.c | 40 ++ drivers/char/bttv.h | 9 + drivers/misc/parport_pc.c | 4 +- drivers/net/cosa.c | 4 + drivers/net/eexpress.c | 24 +- drivers/net/irda/Config.in | 32 +- drivers/net/irda/Makefile | 24 + drivers/net/irda/actisys.c | 147 ++--- drivers/net/irda/esi.c | 72 +- drivers/net/irda/girbil.c | 75 +-- drivers/net/irda/irport.c | 343 ++++++++-- drivers/net/irda/irtty.c | 167 ++--- drivers/net/irda/litelink.c | 209 ++++++ drivers/net/irda/pc87108.c | 43 +- drivers/net/irda/tekram.c | 87 +-- drivers/net/irda/toshoboe.c | 901 ++++++++++++++++++++++++++ drivers/net/irda/uircc.c | 18 +- drivers/net/irda/w83977af_ir.c | 531 ++++++++------- drivers/net/sunhme.c | 2 +- drivers/video/cgsixfb.c | 25 +- fs/ext2/file.c | 49 +- fs/smbfs/inode.c | 2 - include/net/irda/crc.h | 15 +- include/net/irda/dongle.h | 8 +- include/net/irda/ircomm_common.h | 13 +- include/net/irda/irda.h | 10 +- include/net/irda/irda_device.h | 58 +- include/net/irda/iriap.h | 8 +- include/net/irda/irlan_common.h | 41 +- include/net/irda/irlan_provider.h | 10 +- include/net/irda/irlap.h | 18 +- include/net/irda/irlmp.h | 6 +- include/net/irda/irlpt_common.h | 3 +- include/net/irda/irport.h | 14 +- include/net/irda/irttp.h | 14 +- include/net/irda/irtty.h | 27 +- include/net/irda/toshoboe.h | 165 +++++ include/net/irda/w83977af_ir.h | 27 +- include/net/irda/wrapper.h | 18 +- net/ipv4/ip_options.c | 1 - net/ipv6/icmp.c | 4 +- net/irda/af_irda.c | 299 ++++++++- net/irda/crc.c | 8 +- net/irda/discovery.c | 47 +- net/irda/ircomm/ircomm_common.c | 215 +++--- net/irda/ircomm/irvtd_driver.c | 28 +- net/irda/irda_device.c | 278 +++++++- net/irda/iriap.c | 80 +-- net/irda/iriap_event.c | 8 +- net/irda/irlan/irlan_client.c | 76 +-- net/irda/irlan/irlan_client_event.c | 12 +- net/irda/irlan/irlan_common.c | 151 +++-- net/irda/irlan/irlan_eth.c | 112 ++-- net/irda/irlan/irlan_event.c | 16 +- net/irda/irlan/irlan_filter.c | 23 +- net/irda/irlan/irlan_provider.c | 121 +++- net/irda/irlan/irlan_provider_event.c | 14 +- net/irda/irlap_comp.c | 8 +- net/irda/irlap_event.c | 96 +-- net/irda/irlap_frame.c | 12 +- net/irda/irlmp.c | 136 ++-- net/irda/irlmp_frame.c | 52 +- net/irda/irlpt/irlpt_cli.c | 24 +- net/irda/irlpt/irlpt_cli_fsm.c | 12 +- net/irda/irlpt/irlpt_common.c | 12 +- net/irda/irlpt/irlpt_srvr.c | 29 +- net/irda/irmod.c | 30 +- net/irda/irproc.c | 47 +- net/irda/irsysctl.c | 8 +- net/irda/irttp.c | 74 ++- net/irda/qos.c | 11 +- net/irda/wrapper.c | 332 +++++----- 77 files changed, 3971 insertions(+), 1699 deletions(-) create mode 100644 drivers/net/irda/litelink.c create mode 100644 drivers/net/irda/toshoboe.c create mode 100644 include/net/irda/toshoboe.h diff --git a/README b/README index b1bac81558f5..2bd186f4db13 100644 --- a/README +++ b/README @@ -32,11 +32,11 @@ DOCUMENTATION: - There is a lot of documentation available both in electronic form on the Internet and in books, both Linux-specific and pertaining to general UNIX questions. I'd recommend looking into the documentation - subdirectories on any Linux ftp site for the LDP (Linux Documentation + subdirectories on any Linux FTP site for the LDP (Linux Documentation Project) books. This README is not meant to be documentation on the system: there are much better sources available. - - There are various readme's in the kernel Documentation/ subdirectory: + - There are various README files in the Documentation/ subdirectory: these typically contain kernel-specific installation notes for some drivers for example. See ./Documentation/00-INDEX for a list of what is contained in each file. Please read the Changes file, as it @@ -219,7 +219,7 @@ IF SOMETHING GOES WRONG: isn't anyone listed there, then the second best thing is to mail them to me (torvalds@transmeta.com), and possibly to any other relevant mailing-list or to the newsgroup. The mailing-lists are - useful especially for SCSI and NETworking problems, as I can't test + useful especially for SCSI and networking problems, as I can't test either of those personally anyway. - In all bug-reports, *please* tell what kernel you are talking about, diff --git a/arch/i386/lib/checksum.S b/arch/i386/lib/checksum.S index 46527a85de12..af10dc7c9ce5 100644 --- a/arch/i386/lib/checksum.S +++ b/arch/i386/lib/checksum.S @@ -369,7 +369,7 @@ DST( movb %cl, (%edi) ) #define ROUND1(x) \ SRC(movl x(%esi), %ebx ) ; \ - addl %ebx, %eax\n ; \ + addl %ebx, %eax ; \ DST(movl %ebx, x(%edi) ) ; #define ROUND(x) \ diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c index caa1d99ef100..b09df0576413 100644 --- a/arch/sparc64/kernel/setup.c +++ b/arch/sparc64/kernel/setup.c @@ -1,4 +1,4 @@ -/* $Id: setup.c,v 1.43 1999/04/12 08:08:24 davem Exp $ +/* $Id: setup.c,v 1.43.2.1 1999/05/28 02:18:13 davem Exp $ * linux/arch/sparc64/kernel/setup.c * * Copyright (C) 1995,1996 David S. Miller (davem@caip.rutgers.edu) @@ -550,7 +550,9 @@ __initfunc(void setup_arch(char **cmdline_p, ic_servaddr = sv; if (gw) ic_gateway = gw; +#if defined(CONFIG_IP_PNP_BOOTP) || defined(CONFIG_IP_PNP_RARP) ic_proto_enabled = 0; +#endif } } #endif diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 56cf5fb13a54..26ffb26cac3d 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -504,6 +504,8 @@ static int loop_set_status(struct loop_device *lo, struct loop_info *arg) if ((unsigned int) info.lo_encrypt_key_size > LO_KEY_SIZE) return -EINVAL; type = info.lo_encrypt_type; + if (info.lo_encrypt_key_size == 0 && type == LO_CRYPT_XOR) + return -EINVAL; if (type >= MAX_LO_CRYPT || xfer_funcs[type] == NULL) return -EINVAL; err = loop_release_xfer(lo); diff --git a/drivers/block/ns87415.c b/drivers/block/ns87415.c index 3275c017132d..a89b0e9c5e1f 100644 --- a/drivers/block/ns87415.c +++ b/drivers/block/ns87415.c @@ -49,8 +49,25 @@ static void ns87415_prepare_drive (ide_drive_t *drive, unsigned int use_dma) new = use_dma ? ((new & ~other) | bit) : (new & ~bit); if (new != *old) { + unsigned char stat; + + /* + * Don't change DMA engine settings while Write Buffers + * are busy. + */ + (void) pci_read_config_byte(dev, 0x43, &stat); + while (stat & 0x03) { + udelay(1); + (void) pci_read_config_byte(dev, 0x43, &stat); + } + *old = new; (void) pci_write_config_dword(dev, 0x40, new); + + /* + * And let things settle... + */ + udelay(10); } __restore_flags(flags); /* local CPU only */ diff --git a/drivers/char/bttv.c b/drivers/char/bttv.c index 12ac86673fce..a3292e409c86 100644 --- a/drivers/char/bttv.c +++ b/drivers/char/bttv.c @@ -543,6 +543,8 @@ static struct tvcard tvcards[] = { 3, 1, 0, 2,15, { 2, 3, 1, 1}, { 0, 0, 0, 0, 0}}, /* Pixelview PlayTV (bt878) */ { 3, 4, 0, 2, 0x01e000, { 2, 0, 1, 1}, {0x01c000, 0, 0x018000, 0x014000, 0x002000, 0 }}, + /* "Leadtek WinView 601", */ + { 3, 1, 0, 2, 0x8300f8, { 2, 3, 1, 1,0}, {0x4fa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007}}, }; #define TVCARDS (sizeof(tvcards)/sizeof(tvcard)) @@ -2036,6 +2038,41 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg) I2CWrite(&(btv->i2c), I2C_TDA9850, TDA9850_CON3, con3, 1); } + + /* PT2254A programming Jon Tombs, jon@gte.esi.us.es */ + if (btv->type == BTTV_WINVIEW_601) { + int bits_out, loops, vol, data; + + /* 32 levels logarithmic */ + vol = 32 - ((v.volume>>11)); + /* units */ + bits_out = (PT2254_DBS_IN_2>>(vol%5)); + /* tens */ + bits_out |= (PT2254_DBS_IN_10>>(vol/5)); + bits_out |= PT2254_L_CHANEL | PT2254_R_CHANEL; + data = btread(BT848_GPIO_DATA); + data &= ~(WINVIEW_PT2254_CLK| WINVIEW_PT2254_DATA| + WINVIEW_PT2254_STROBE); + for (loops = 17; loops >= 0 ; loops--) { + if (bits_out & (1<have_msp3400) { i2c_control_device(&(btv->i2c), @@ -3033,6 +3070,9 @@ static void idcard(int i) case BTTV_VHX: strcpy(btv->video_dev.name,"BT848(Aimslab-VHX)"); break; + case BTTV_WINVIEW_601: + strcpy(btv->video_dev.name,"BT848(Leadtek WinView 601)"); + break; } printk("%s\n",btv->video_dev.name); audio(btv, AUDIO_MUTE); diff --git a/drivers/char/bttv.h b/drivers/char/bttv.h index 479384783b48..41024d7aad17 100644 --- a/drivers/char/bttv.h +++ b/drivers/char/bttv.h @@ -210,6 +210,7 @@ struct bttv #define BTTV_VHX 0x0e #define BTTV_ZOLTRIX 0x0f #define BTTV_PIXVIEWPLAYTV 0x10 +#define BTTV_WINVIEW_601 0x11 #define AUDIO_TUNER 0x00 #define AUDIO_RADIO 0x01 @@ -260,4 +261,12 @@ struct bttv #define TEA6300_FA 0x04 /* fader control */ #define TEA6300_SW 0x05 /* mute and source switch */ +#define PT2254_L_CHANEL 0x10 +#define PT2254_R_CHANEL 0x08 +#define PT2254_DBS_IN_2 0x400 +#define PT2254_DBS_IN_10 0x20000 +#define WINVIEW_PT2254_CLK 0x40 +#define WINVIEW_PT2254_DATA 0x20 +#define WINVIEW_PT2254_STROBE 0x80 + #endif diff --git a/drivers/misc/parport_pc.c b/drivers/misc/parport_pc.c index 33f873e7d2de..f73b1c44490e 100644 --- a/drivers/misc/parport_pc.c +++ b/drivers/misc/parport_pc.c @@ -371,12 +371,12 @@ static int parport_SPP_supported(struct parport *pb) * copy. Some ports _do_ allow reads, so bypass the software * copy here. In addition, some bits aren't writable. */ r = inb (pb->base+CONTROL); - if ((r & 0x3f) == w) { + if ((r & 0xf) == w) { w = 0xe; parport_pc_write_control (pb, w); r = inb (pb->base+CONTROL); parport_pc_write_control (pb, 0xc); - if ((r & 0x3f) == w) + if ((r & 0xf) == w) return PARPORT_MODE_PCSPP; } diff --git a/drivers/net/cosa.c b/drivers/net/cosa.c index 69f8bb0d8406..bc4084f8611f 100644 --- a/drivers/net/cosa.c +++ b/drivers/net/cosa.c @@ -2,6 +2,9 @@ /* * Copyright (C) 1995-1997 Jan "Yenya" Kasprzak + * + * 5/25/1999 : Marcelo Tosatti + * fixed a deadlock in cosa_sppp_open * * 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 @@ -598,6 +601,7 @@ static int cosa_sppp_open(struct device *d) if (chan->usage != 0) { printk(KERN_WARNING "%s: sppp_open called with usage count %d\n", chan->name, chan->usage); + spin_unlock_irqrestore(&chan->cosa->lock, flags); return -EBUSY; } chan->setup_rx = sppp_setup_rx; diff --git a/drivers/net/eexpress.c b/drivers/net/eexpress.c index d94e0efd6e6a..51af63aa4f2f 100644 --- a/drivers/net/eexpress.c +++ b/drivers/net/eexpress.c @@ -81,7 +81,20 @@ * ftp's, which is significantly better than I get in DOS, so the overhead of * stopping and restarting the CU with each transmit is not prohibitive in * practice. + * + * Update by David Woodhouse 11/5/99: + * + * I've seen "CU wedged" messages in 16-bit mode, on the Alpha architecture. + * I assume that this is because 16-bit accesses are actually handled as two + * 8-bit accesses. */ + +#ifdef __alpha__ +#define LOCKUP16 1 +#endif +#ifndef LOCKUP16 +#define LOCKUP16 0 +#endif #include #include @@ -297,7 +310,7 @@ static inline void clear_loopback(struct device *dev) outb(inb(dev->base_addr + Config) & ~2, dev->base_addr + Config); } -static inline short int SHADOW(short int addr) +static inline unsigned short int SHADOW(short int addr) { addr &= 0x1f; if (addr > 0xf) addr += 0x3ff0; @@ -400,7 +413,10 @@ static int eexp_close(struct device *dev) outb(0,ioaddr+SIGNAL_CA); free_irq(irq,dev); outb(i586_RST,ioaddr+EEPROM_Ctrl); - release_region(ioaddr,16); + release_region(ioaddr, EEXP_IO_EXTENT); + release_region(ioaddr+0x4000, 16); + release_region(ioaddr+0x8000, 16); + release_region(ioaddr+0xc000, 16); MOD_DEC_USE_COUNT; return 0; @@ -887,7 +903,7 @@ static void eexp_hw_tx_pio(struct device *dev, unsigned short *buf, struct net_local *lp = (struct net_local *)dev->priv; unsigned short ioaddr = dev->base_addr; - if (lp->width) { + if (LOCKUP16 || lp->width) { /* Stop the CU so that there is no chance that it jumps off to a bogus address while we are writing the pointer to the next transmit packet in 8-bit mode -- @@ -927,7 +943,7 @@ static void eexp_hw_tx_pio(struct device *dev, unsigned short *buf, if (lp->tx_head != lp->tx_reap) dev->tbusy = 0; - if (lp->width) { + if (LOCKUP16 || lp->width) { /* Restart the CU so that the packet can actually be transmitted. (Zoltan Szilagyi 10-12-96) */ scb_command(dev, SCB_CUresume); diff --git a/drivers/net/irda/Config.in b/drivers/net/irda/Config.in index 64f6c327e911..1a7831e83506 100644 --- a/drivers/net/irda/Config.in +++ b/drivers/net/irda/Config.in @@ -1,18 +1,24 @@ mainmenu_option next_comment comment 'Infrared-port device drivers' -dep_tristate 'IrTTY (uses serial driver)' CONFIG_IRTTY_SIR $CONFIG_IRDA -if [ "$CONFIG_IRTTY_SIR" != "n" ]; then - comment ' Dongle support' - bool ' Serial dongle support' CONFIG_DONGLE - if [ "$CONFIG_DONGLE" != "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 +comment 'SIR device drivers' +dep_tristate 'IrTTY (uses Linux serial driver)' CONFIG_IRTTY_SIR $CONFIG_IRDA +dep_tristate 'IrPORT (IrDA serial driver)' CONFIG_IRPORT_SIR $CONFIG_IRDA + +comment 'FIR device drivers' +dep_tristate 'NSC PC87108' CONFIG_NSC_FIR $CONFIG_IRDA +dep_tristate 'Winbond W83977AF (IR)' CONFIG_WINBOND_FIR $CONFIG_IRDA +dep_tristate 'Sharp UIRCC' CONFIG_SHARP_FIR $CONFIG_IRDA +dep_tristate 'Toshiba Type-O IR Port' CONFIG_TOSHIBA_FIR $CONFIG_IRDA + +comment 'Dongle support' +bool 'Serial dongle support' CONFIG_DONGLE +if [ "$CONFIG_DONGLE" != "n" ]; then + dep_tristate ' ESI JetEye PC dongle' CONFIG_ESI_DONGLE $CONFIG_IRDA + dep_tristate ' ACTiSYS IR-220L and IR220L+ dongle' CONFIG_ACTISYS_DONGLE $CONFIG_IRDA + dep_tristate ' Tekram IrMate 210B dongle' CONFIG_TEKRAM_DONGLE $CONFIG_IRDA + dep_tristate ' Greenwich GIrBIL dongle' CONFIG_GIRBIL_DONGLE $CONFIG_IRDA + dep_tristate ' Parallax LiteLink dongle' CONFIG_LITELINK_DONGLE $CONFIG_IRDA fi -dep_tristate ' NSC PC87108' CONFIG_NSC_FIR $CONFIG_IRDA -dep_tristate ' Winbond W83977AF (IR)' CONFIG_WINBOND_FIR $CONFIG_IRDA -dep_tristate ' Sharp UIRCC' CONFIG_SHARP_FIR $CONFIG_IRDA + endmenu diff --git a/drivers/net/irda/Makefile b/drivers/net/irda/Makefile index 6a7920a6e1c5..bd691dcae7fc 100644 --- a/drivers/net/irda/Makefile +++ b/drivers/net/irda/Makefile @@ -20,6 +20,14 @@ else endif endif +ifeq ($(CONFIG_IRPORT_SIR),y) +L_OBJS += irport.o +else + ifeq ($(CONFIG_IRPORT_SIR),m) + M_OBJS += irport.o + endif +endif + ifeq ($(CONFIG_NSC_FIR),y) L_OBJS += pc87108.o else @@ -44,6 +52,14 @@ else endif endif +ifeq ($(CONFIG_TOSHIBA_FIR),y) +L_OBJS += toshoboe.o +else + ifeq ($(CONFIG_TOSHIBA_FIR),m) + M_OBJS += toshoboe.o + endif +endif + ifeq ($(CONFIG_ESI_DONGLE),y) L_OBJS += esi.o else @@ -76,6 +92,14 @@ else endif endif +ifeq ($(CONFIG_LITELINK_DONGLE),y) +L_OBJS += litelink.o +else + ifeq ($(CONFIG_LITELINK_DONGLE),m) + M_OBJS += litelink.o + endif +endif + include $(TOPDIR)/Rules.make clean: diff --git a/drivers/net/irda/actisys.c b/drivers/net/irda/actisys.c index 46ce2badfb85..11fde80062e4 100644 --- a/drivers/net/irda/actisys.c +++ b/drivers/net/irda/actisys.c @@ -1,16 +1,16 @@ /********************************************************************* * * Filename: actisys.c - * Version: 0.5 + * Version: 0.8 * 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 Apr 12 11:56:35 1999 + * Modified at: Mon May 10 15:12:54 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli, All Rights Reserved. + * Copyright (c) 1998-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 @@ -36,15 +36,14 @@ #include #include #include -#include #include -static void actisys_reset( struct irda_device *dev, int unused); -static void actisys_open( struct irda_device *idev, int type); -static void actisys_close( struct irda_device *dev); +static void actisys_reset(struct irda_device *dev, int unused); +static void actisys_open(struct irda_device *idev, int type); +static void actisys_close(struct irda_device *dev); static void actisys_change_speed( struct irda_device *dev, int baudrate); -static void actisys_reset( struct irda_device *dev, int unused); -static void actisys_init_qos( struct irda_device *idev, struct qos_info *qos); +static void actisys_reset(struct irda_device *dev, int unused); +static void actisys_init_qos(struct irda_device *idev, struct qos_info *qos); /* These are the baudrates supported */ static int baud_rates[] = { 9600, 19200, 57600, 115200, 38400}; @@ -58,17 +57,37 @@ static struct dongle dongle = { actisys_init_qos, }; -__initfunc(void actisys_init(void)) +static struct dongle dongle_plus = { + ACTISYS_PLUS_DONGLE, + actisys_open, + actisys_close, + actisys_reset, + actisys_change_speed, + actisys_init_qos, +}; + +__initfunc(int actisys_init(void)) { - irtty_register_dongle(&dongle); + int ret; + + ret = irda_device_register_dongle(&dongle); + if (ret < 0) + return ret; + ret = irda_device_register_dongle(&dongle_plus); + if (ret < 0) { + irda_device_unregister_dongle(&dongle); + return ret; + } + return 0; } void actisys_cleanup(void) { - irtty_unregister_dongle(&dongle); + irda_device_unregister_dongle(&dongle); + irda_device_unregister_dongle(&dongle_plus); } -static void actisys_open( struct irda_device *idev, int type) +static void actisys_open(struct irda_device *idev, int type) { strcat(idev->description, " <-> actisys"); @@ -78,8 +97,11 @@ static void actisys_open( struct irda_device *idev, int type) MOD_INC_USE_COUNT; } -static void actisys_close( struct irda_device *dev) +static void actisys_close(struct irda_device *idev) { + /* Power off dongle */ + irda_device_set_dtr_rts(idev, FALSE, FALSE); + MOD_DEC_USE_COUNT; } @@ -90,25 +112,16 @@ static void actisys_close( struct irda_device *dev) * 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) +static void actisys_change_speed(struct irda_device *idev, int baudrate) { - struct irtty_cb *self; - struct tty_struct *tty; - struct termios old_termios; - int cflag; int current_baudrate; int index = 0; - DEBUG( 4, __FUNCTION__ "()\n"); + DEBUG(4, __FUNCTION__ "()\n"); - ASSERT( idev != NULL, return;); - ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;); - - self = (struct irtty_cb *) idev->priv; + ASSERT(idev != NULL, return;); + ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); - ASSERT( self != NULL, return;); - ASSERT( self->magic == IRTTY_MAGIC, return;); - current_baudrate = idev->qos.baud_rate.value; /* Find the correct baudrate index for the currently used baudrate */ @@ -117,69 +130,34 @@ static void actisys_change_speed( struct irda_device *idev, int baudrate) DEBUG( 4, __FUNCTION__ "(), index=%d\n", index); - if ( !self->tty) - return; - - tty = self->tty; - /* Cycle through avaiable baudrates until we reach the correct one */ - while ( current_baudrate != baudrate) { - DEBUG( 4, __FUNCTION__ "(), current baudrate = %d\n", - baud_rates[index]); + while (current_baudrate != baudrate) { + DEBUG(4, __FUNCTION__ "(), current baudrate = %d\n", + baud_rates[index]); /* Set DTR, clear RTS */ - irtty_set_dtr_rts(tty, TRUE, FALSE); + irda_device_set_dtr_rts(idev, TRUE, FALSE); /* Wait at a few ms */ current->state = TASK_INTERRUPTIBLE; schedule_timeout(2); /* Set DTR, Set RTS */ - irtty_set_dtr_rts(tty, TRUE, TRUE); + irda_device_set_dtr_rts(idev, TRUE, TRUE); /* Wait at a few ms again */ current->state = TASK_INTERRUPTIBLE; - schedule_timeout( 2); + schedule_timeout(2); /* Go to next baudrate */ - if ( idev->io.dongle_id == ACTISYS_DONGLE) + if (idev->io.dongle_id == ACTISYS_DONGLE) index = (index+1) % 4; /* IR-220L */ else index = (index+1) % 5; /* IR-220L+ */ current_baudrate = 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); - cflag = tty->termios->c_cflag; - - cflag &= ~CBAUD; - - switch ( baudrate) { - case 9600: - default: - cflag |= B9600; - break; - case 19200: - cflag |= B19200; - break; - case 38400: - cflag |= B38400; - break; - case 57600: - cflag |= B57600; - break; - case 115200: - cflag |= B115200; - break; - } - - /* Change speed of serial port */ - tty->termios->c_cflag = cflag; - tty->driver.set_termios( tty, &old_termios); + DEBUG(4, __FUNCTION__ "(), current baudrate = %d\n",baud_rates[index]); } /* @@ -191,32 +169,20 @@ static void actisys_change_speed( struct irda_device *idev, int baudrate) * 1. Clear DTR for a few ms. * */ -static void actisys_reset( struct irda_device *idev, int unused) +static void actisys_reset(struct irda_device *idev, int unused) { - struct irtty_cb *self; - struct tty_struct *tty; - - ASSERT( idev != NULL, return;); - ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;); - - self = (struct irtty_cb *) idev->priv; + ASSERT(idev != NULL, return;); + ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); - ASSERT( self != NULL, return;); - ASSERT( self->magic == IRTTY_MAGIC, return;); - - tty = self->tty; - if ( !tty) - return; - /* Clear DTR */ - irtty_set_dtr_rts(tty, FALSE, TRUE); + irda_device_set_dtr_rts(idev, FALSE, TRUE); /* Sleep 10-20 ms*/ current->state = TASK_INTERRUPTIBLE; schedule_timeout(2); /* Go back to normal mode */ - irtty_set_dtr_rts(tty, TRUE, TRUE); + irda_device_set_dtr_rts(idev, TRUE, TRUE); idev->qos.baud_rate.value = 9600; } @@ -227,12 +193,12 @@ static void actisys_reset( struct irda_device *idev, int unused) * Initialize QoS capabilities * */ -static void actisys_init_qos( struct irda_device *idev, struct qos_info *qos) +static void actisys_init_qos(struct irda_device *idev, struct qos_info *qos) { qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200; /* Remove support for 38400 if this is not a 220L+ dongle */ - if ( idev->io.dongle_id == ACTISYS_DONGLE) + if (idev->io.dongle_id == ACTISYS_DONGLE) qos->baud_rate.bits &= ~IR_38400; qos->min_turn_time.bits &= 0x40; /* Needs 0.01 ms */ @@ -251,8 +217,7 @@ MODULE_DESCRIPTION("ACTiSYS IR-220L and IR-220L+ dongle driver"); */ int init_module(void) { - actisys_init(); - return(0); + return actisys_init(); } /* diff --git a/drivers/net/irda/esi.c b/drivers/net/irda/esi.c index 5395d2829688..b12885846bc7 100644 --- a/drivers/net/irda/esi.c +++ b/drivers/net/irda/esi.c @@ -1,17 +1,17 @@ /********************************************************************* * * Filename: esi.c - * Version: 1.2 + * Version: 1.4 * 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 Apr 12 11:55:30 1999 + * Modified at: Mon May 10 15:13:12 1999 * Modified by: Dag Brattli * Sources: esi.c * + * Copyright (c) 1998-1999, Dag Brattli, * Copyright (c) 1998, Thomas Davis, , - * Copyright (c) 1998, Dag Brattli, * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -41,11 +41,11 @@ #include #include -static void esi_open( struct irda_device *idev, int type); -static void esi_close( struct irda_device *driver); -static void esi_change_speed( struct irda_device *idev, int baud); -static void esi_reset( struct irda_device *idev, int unused); -static void esi_qos_init( struct irda_device *idev, struct qos_info *qos); +static void esi_open(struct irda_device *idev, int type); +static void esi_close(struct irda_device *driver); +static void esi_change_speed(struct irda_device *idev, int baud); +static void esi_reset(struct irda_device *idev, int unused); +static void esi_qos_init(struct irda_device *idev, struct qos_info *qos); static struct dongle dongle = { ESI_DONGLE, @@ -58,17 +58,17 @@ static struct dongle dongle = { __initfunc(int esi_init(void)) { - return irtty_register_dongle(&dongle); + return irda_device_register_dongle(&dongle); } void esi_cleanup(void) { - irtty_unregister_dongle( &dongle); + irda_device_unregister_dongle(&dongle); } -static void esi_open( struct irda_device *idev, int type) +static void esi_open(struct irda_device *idev, int type) { - strcat( idev->description, " <-> esi"); + strcat(idev->description, " <-> esi"); idev->io.dongle_id = type; idev->flags |= IFF_DONGLE; @@ -76,8 +76,11 @@ static void esi_open( struct irda_device *idev, int type) MOD_INC_USE_COUNT; } -static void esi_close( struct irda_device *driver) -{ +static void esi_close(struct irda_device *idev) +{ + /* Power off dongle */ + irda_device_set_dtr_rts(idev, FALSE, FALSE); + MOD_DEC_USE_COUNT; } @@ -87,54 +90,30 @@ static void esi_close( struct irda_device *driver) * Set the speed for the Extended Systems JetEye PC ESI-9680 type dongle * */ -static void esi_change_speed( struct irda_device *idev, int baud) +static void esi_change_speed(struct irda_device *idev, int baud) { - struct irtty_cb *self; - struct tty_struct *tty; int dtr, rts; - struct termios old_termios; - int cflag; - - 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; + ASSERT(idev != NULL, return;); + ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); - old_termios = *(tty->termios); - cflag = tty->termios->c_cflag; - - cflag &= ~CBAUD; - switch (baud) { case 19200: - cflag |= B19200; dtr = TRUE; rts = FALSE; break; case 115200: - cflag |= B115200; dtr = rts = TRUE; break; case 9600: default: - cflag |= B9600; dtr = FALSE; rts = TRUE; break; } - /* Change speed of serial driver */ - tty->termios->c_cflag = cflag; - tty->driver.set_termios(tty, &old_termios); - irtty_set_dtr_rts(tty, dtr, rts); + /* Change speed of dongle */ + irda_device_set_dtr_rts(idev, dtr, rts); } static void esi_reset( struct irda_device *idev, int unused) @@ -148,14 +127,17 @@ static void esi_reset( struct irda_device *idev, int unused) * Init QoS capabilities for the dongle * */ -static void esi_qos_init( struct irda_device *idev, struct qos_info *qos) +static void esi_qos_init(struct irda_device *idev, struct qos_info *qos) { qos->baud_rate.bits &= IR_9600|IR_19200|IR_115200; qos->min_turn_time.bits &= 0x01; /* Needs at least 10 ms */ } #ifdef MODULE - + +MODULE_AUTHOR("Dag Brattli "); +MODULE_DESCRIPTION("Extended Systems JetEye PC dongle driver"); + /* * Function init_module (void) * diff --git a/drivers/net/irda/girbil.c b/drivers/net/irda/girbil.c index 128b32a23e22..3b06f3838ad7 100644 --- a/drivers/net/irda/girbil.c +++ b/drivers/net/irda/girbil.c @@ -1,12 +1,12 @@ /********************************************************************* * * Filename: girbil.c - * Version: 1.0 + * Version: 1.1 * Description: Implementation for the Greenwich GIrBIL dongle * Status: Experimental. * Author: Dag Brattli * Created at: Sat Feb 6 21:02:33 1999 - * Modified at: Sat Apr 10 19:53:12 1999 + * Modified at: Mon May 10 16:01:33 1999 * Modified by: Dag Brattli * * Copyright (c) 1999 Dag Brattli, All Rights Reserved. @@ -80,19 +80,19 @@ static struct dongle dongle = { girbil_init_qos, }; -__initfunc(void girbil_init(void)) +__initfunc(int girbil_init(void)) { - irtty_register_dongle(&dongle); + return irda_device_register_dongle(&dongle); } void girbil_cleanup(void) { - irtty_unregister_dongle(&dongle); + irda_device_unregister_dongle(&dongle); } static void girbil_open(struct irda_device *idev, int type) { - strcat( idev->description, " <-> girbil"); + strcat(idev->description, " <-> girbil"); idev->io.dongle_id = type; idev->flags |= IFF_DONGLE; @@ -100,8 +100,11 @@ static void girbil_open(struct irda_device *idev, int type) MOD_INC_USE_COUNT; } -static void girbil_close(struct irda_device *dev) +static void girbil_close(struct irda_device *idev) { + /* Power off dongle */ + irda_device_set_dtr_rts(idev, FALSE, FALSE); + MOD_DEC_USE_COUNT; } @@ -114,71 +117,42 @@ static void girbil_close(struct irda_device *dev) */ 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); + irda_device_set_dtr_rts(idev, FALSE, TRUE); /* Write control bytes */ - if (tty->driver.write) - tty->driver.write(self->tty, 0, control, 2); + irda_device_raw_write(idev, 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); + irda_device_set_dtr_rts(idev, TRUE, TRUE); } /* @@ -193,44 +167,32 @@ static void girbil_change_speed(struct irda_device *idev, int speed) */ void girbil_reset(struct irda_device *idev, int unused) { - struct irtty_cb *self; - struct tty_struct *tty; __u8 control = GIRBIL_TXEN | GIRBIL_RXEN; 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); + irda_device_set_dtr_rts(idev, 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); + irda_device_set_dtr_rts(idev, FALSE, TRUE); current->state = TASK_INTERRUPTIBLE; schedule_timeout(2); /* Write control byte */ - if (tty->driver.write) - tty->driver.write(self->tty, 0, &control, 1); + irda_device_raw_write(idev, &control, 1); current->state = TASK_INTERRUPTIBLE; schedule_timeout(2); /* Go back to normal mode */ - irtty_set_dtr_rts(tty, TRUE, TRUE); + irda_device_set_dtr_rts(idev, TRUE, TRUE); } /* @@ -258,8 +220,7 @@ MODULE_DESCRIPTION("Greenwich GIrBIL dongle driver"); */ int init_module(void) { - girbil_init(); - return(0); + return girbil_init(); } /* diff --git a/drivers/net/irda/irport.c b/drivers/net/irda/irport.c index 5ea6dba738a0..7c8864f5d79e 100644 --- a/drivers/net/irda/irport.c +++ b/drivers/net/irda/irport.c @@ -64,58 +64,168 @@ #define IO_EXTENT 8 -/* static unsigned int io[] = { 0x3e8, ~0, ~0, ~0 }; */ -/* static unsigned int irq[] = { 11, 0, 0, 0 }; */ +/* + * Currently you'll need to set these values using insmod like this: + * insmod irport io=0x3e8 irq=11 + */ +static unsigned int io[] = { ~0, ~0, ~0, ~0 }; +static unsigned int irq[] = { 0, 0, 0, 0 }; + +static unsigned int qos_mtt_bits = 0x03; + +static struct irda_device *dev_self[] = { NULL, NULL, NULL, NULL}; +static char *driver_name = "irport"; + +static int irport_open(int i, unsigned int iobase, unsigned int irq); +static int irport_close(struct irda_device *idev); static void irport_write_wakeup(struct irda_device *idev); static int irport_write(int iobase, int fifo_size, __u8 *buf, int len); static void irport_receive(struct irda_device *idev); +static int irport_net_init(struct device *dev); +static int irport_net_open(struct device *dev); +static int irport_net_close(struct device *dev); +static void irport_wait_until_sent(struct irda_device *idev); +static int irport_is_receiving(struct irda_device *idev); +static void irport_set_dtr_rts(struct irda_device *idev, int dtr, int rts); +static int irport_raw_write(struct irda_device *idev, __u8 *buf, int len); + __initfunc(int irport_init(void)) { -/* int i; */ - -/* for ( i=0; (io[i] < 2000) && (i < 4); i++) { */ -/* int ioaddr = io[i]; */ -/* if (check_region(ioaddr, IO_EXTENT)) */ -/* continue; */ -/* if (irport_open( i, io[i], io2[i], irq[i], dma[i]) == 0) */ -/* return 0; */ -/* } */ -/* return -ENODEV; */ - return 0; + int i; + + for (i=0; (io[i] < 2000) && (i < 4); i++) { + int ioaddr = io[i]; + if (check_region(ioaddr, IO_EXTENT)) + continue; + if (irport_open(i, io[i], irq[i]) == 0) + return 0; + } + /* + * Maybe something failed, but we can still be usable for FIR drivers + */ + return 0; } /* - * Function pc87108_cleanup () + * Function irport_cleanup () * - * Close all configured chips + * Close all configured ports * */ #ifdef MODULE static void irport_cleanup(void) { -/* int i; */ + int i; DEBUG( 4, __FUNCTION__ "()\n"); - /* for ( i=0; i < 4; i++) { */ -/* if ( dev_self[i]) */ -/* irport_close( &(dev_self[i]->idev)); */ -/* } */ + for (i=0; i < 4; i++) { + if (dev_self[i]) + irport_close(dev_self[i]); + } } #endif /* MODULE */ -/* - * Function irport_open (void) - * - * Start IO port - * - */ -int irport_open(int iobase) +static int irport_open(int i, unsigned int iobase, unsigned int irq) { - DEBUG(4, __FUNCTION__ "(), iobase=%#x\n", iobase); + struct irda_device *idev; + int ret; + + DEBUG( 0, __FUNCTION__ "()\n"); + +/* if (irport_probe(iobase, irq) == -1) */ +/* return -1; */ + + /* + * Allocate new instance of the driver + */ + idev = kmalloc(sizeof(struct irda_device), GFP_KERNEL); + if (idev == NULL) { + printk( KERN_ERR "IrDA: Can't allocate memory for " + "IrDA control block!\n"); + return -ENOMEM; + } + memset(idev, 0, sizeof(struct irda_device)); + + /* Need to store self somewhere */ + dev_self[i] = idev; + + /* Initialize IO */ + idev->io.iobase2 = iobase; + idev->io.irq2 = irq; + idev->io.io_ext = IO_EXTENT; + idev->io.fifo_size = 16; + + /* Lock the port that we need */ + ret = check_region(idev->io.iobase2, idev->io.io_ext); + if (ret < 0) { + DEBUG( 0, __FUNCTION__ "(), can't get iobase of 0x%03x\n", + idev->io.iobase2); + /* w83977af_cleanup( self->idev); */ + return -ENODEV; + } + request_region(idev->io.iobase2, idev->io.io_ext, idev->name); + + /* Initialize QoS for this device */ + irda_init_max_qos_capabilies(&idev->qos); + + idev->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600| + IR_115200; + + idev->qos.min_turn_time.bits = qos_mtt_bits; + irda_qos_bits_to_value(&idev->qos); + + idev->flags = IFF_SIR|IFF_PIO; + + /* Specify which buffer allocation policy we need */ + idev->rx_buff.flags = GFP_KERNEL; + idev->tx_buff.flags = GFP_KERNEL; + + idev->rx_buff.truesize = 4000; + idev->tx_buff.truesize = 4000; + + /* Initialize callbacks */ + idev->change_speed = irport_change_speed; + idev->wait_until_sent = irport_wait_until_sent; + idev->is_receiving = irport_is_receiving; + idev->set_dtr_rts = irport_set_dtr_rts; + idev->raw_write = irport_raw_write; + + /* Override the network functions we need to use */ + idev->netdev.init = irport_net_init; + idev->netdev.hard_start_xmit = irport_hard_xmit; + idev->netdev.open = irport_net_open; + idev->netdev.stop = irport_net_close; + + /* Open the IrDA device */ + irda_device_open(idev, driver_name, NULL); + + return 0; +} + +static int irport_close(struct irda_device *idev) +{ + DEBUG(0, __FUNCTION__ "()\n"); + + ASSERT(idev != NULL, return -1;); + ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;); + + /* Release the PORT that this driver is using */ + DEBUG(0 , __FUNCTION__ "(), Releasing Region %03x\n", + idev->io.iobase2); + release_region(idev->io.iobase2, idev->io.io_ext); + + irda_device_close(idev); + + kfree(idev); + + return 0; +} +void irport_start(int iobase) +{ /* Initialize UART */ outb(UART_LCR_WLEN8, iobase+UART_LCR); /* Reset DLAB */ outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), iobase+UART_MCR); @@ -123,24 +233,29 @@ int irport_open(int iobase) /* Turn on interrups */ outb((UART_IER_RLSI | UART_IER_RDI), iobase+UART_IER); - return 0; +} + +void irport_stop(int iobase) +{ + /* Reset UART */ + outb(0, iobase+UART_MCR); + + /* Turn off interrupts */ + outb(0, iobase+UART_IER); } /* - * Function irport_cleanup () + * Function irport_probe (void) * - * Stop IO port + * Start IO port * */ -void irport_close(int iobase) +int irport_probe(int iobase) { - DEBUG(4, __FUNCTION__ "()\n"); + DEBUG(4, __FUNCTION__ "(), iobase=%#x\n", iobase); - /* Reset UART */ - outb(0, iobase+UART_MCR); - /* Turn off interrupts */ - outb(0, iobase+UART_IER); + return 0; } /* @@ -149,14 +264,23 @@ void irport_close(int iobase) * Set speed of port to specified baudrate * */ -void irport_change_speed( int iobase, int speed) +void irport_change_speed(struct irda_device *idev, int speed) { + int iobase; int fcr; /* FIFO control reg */ int lcr; /* Line control reg */ int divisor; DEBUG( 0, __FUNCTION__ "(), Setting speed to: %d\n", speed); + ASSERT(idev != NULL, return;); + ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); + + iobase = idev->io.iobase2; + + /* Update accounting for new speed */ + idev->io.baudrate = speed; + /* Turn off interrupts */ outb(0, iobase+UART_IER); @@ -373,8 +497,145 @@ void irport_interrupt(int irq, void *dev_id, struct pt_regs *regs) idev->netdev.interrupt = 0; } +static int irport_net_init(struct device *dev) +{ + /* Set up to be a normal IrDA network device driver */ + irda_device_setup(dev); + + /* Insert overrides below this line! */ + + return 0; +} + +/* + * Function irport_net_open (dev) + * + * + * + */ +static int irport_net_open(struct device *dev) +{ + struct irda_device *idev; + int iobase; + + ASSERT(dev != NULL, return -1;); + idev = (struct irda_device *) dev->priv; + + iobase = idev->io.iobase2; + + if (request_irq(idev->io.irq2, irport_interrupt, 0, idev->name, + (void *) idev)) { + return -EAGAIN; + } + + /* Ready to play! */ + dev->tbusy = 0; + dev->interrupt = 0; + dev->start = 1; + + MOD_INC_USE_COUNT; + + irport_start(iobase); + + return 0; +} + +/* + * Function irport_net_close (idev) + * + * + * + */ +static int irport_net_close(struct device *dev) +{ + struct irda_device *idev; + int iobase; + + ASSERT(dev != NULL, return -1;); + idev = (struct irda_device *) dev->priv; + + DEBUG(4, __FUNCTION__ "()\n"); + + iobase = idev->io.iobase2; + + irport_stop(iobase); + + /* Stop device */ + dev->tbusy = 1; + dev->start = 0; + + free_irq(idev->io.irq2, idev); + + MOD_DEC_USE_COUNT; + + return 0; +} + +static void irport_wait_until_sent(struct irda_device *idev) +{ + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(60*HZ/1000); +} + +static int irport_is_receiving(struct irda_device *idev) +{ + return (idev->rx_buff.state != OUTSIDE_FRAME); +} + +/* + * Function irtty_set_dtr_rts (tty, dtr, rts) + * + * This function can be used by dongles etc. to set or reset the status + * of the dtr and rts lines + */ +static void irport_set_dtr_rts(struct irda_device *idev, int dtr, int rts) +{ + int iobase; + + ASSERT(idev != NULL, return;); + ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); + + iobase = idev->io.iobase2; + + if (dtr) + dtr = UART_MCR_DTR; + if (rts) + rts = UART_MCR_RTS; + + outb(dtr|rts|UART_MCR_OUT2, iobase+UART_MCR); +} + +static int irport_raw_write(struct irda_device *idev, __u8 *buf, int len) +{ + int iobase; + int actual = 0; + + ASSERT(idev != NULL, return -1;); + ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;); + + iobase = idev->io.iobase2; + + /* Tx FIFO should be empty! */ + if (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) { + DEBUG( 0, __FUNCTION__ "(), failed, fifo not empty!\n"); + return -1; + } + + /* Fill FIFO with current frame */ + while (actual < len) { + /* Transmit next byte */ + outb(buf[actual], iobase+UART_TX); + actual++; + } + + return actual; +} + #ifdef MODULE +MODULE_PARM(io, "1-4i"); +MODULE_PARM(irq, "1-4i"); + /* * Function cleanup_module (void) * @@ -393,11 +654,7 @@ void cleanup_module(void) */ int init_module(void) { - if (irport_init() < 0) { - cleanup_module(); - return 1; - } - return(0); + return irport_init(); } #endif /* MODULE */ diff --git a/drivers/net/irda/irtty.c b/drivers/net/irda/irtty.c index cc7ab91a4c49..ad8d2dc0ef10 100644 --- a/drivers/net/irda/irtty.c +++ b/drivers/net/irda/irtty.c @@ -6,12 +6,12 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Tue Dec 9 21:18:38 1997 - * Modified at: Thu Apr 22 09:20:24 1999 + * Modified at: Mon May 10 15:45:50 1999 * Modified by: Dag Brattli * Sources: slip.c by Laurence Culhane, * Fred N. van Kempen, * - * Copyright (c) 1998 Dag Brattli, All Rights Reserved. + * Copyright (c) 1998-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 @@ -38,19 +38,21 @@ #include #include #include -#include static hashbin_t *irtty = NULL; -static hashbin_t *dongles = NULL; static struct tty_ldisc irda_ldisc; -static int irtty_hard_xmit(struct sk_buff *skb, struct device *dev); +static int qos_mtt_bits = 0x03; /* 5 ms or more */ + +static int irtty_hard_xmit(struct sk_buff *skb, struct device *dev); static void irtty_wait_until_sent(struct irda_device *driver); -static int irtty_is_receiving(struct irda_device *idev); -static int irtty_net_init(struct device *dev); -static int irtty_net_open(struct device *dev); -static int irtty_net_close(struct device *dev); +static int irtty_is_receiving(struct irda_device *idev); +static void irtty_set_dtr_rts(struct irda_device *idev, int dtr, int rts); +static int irtty_raw_write(struct irda_device *idev, __u8 *buf, int len); +static int irtty_net_init(struct device *dev); +static int irtty_net_open(struct device *dev); +static int irtty_net_close(struct device *dev); static int irtty_open(struct tty_struct *tty); static void irtty_close(struct tty_struct *tty); @@ -73,13 +75,6 @@ __initfunc(int irtty_init(void)) return -ENOMEM; } - dongles = hashbin_new(HB_LOCAL); - if (dongles == NULL) { - printk(KERN_WARNING - "IrDA: Can't allocate dongles hashbin!\n"); - return -ENOMEM; - } - /* Fill in our line protocol discipline, and register it */ memset(&irda_ldisc, 0, sizeof( irda_ldisc)); @@ -132,7 +127,6 @@ static void irtty_cleanup(void) * function to hashbin_destroy(). */ hashbin_delete(irtty, NULL); - hashbin_delete(dongles, NULL); } #endif /* MODULE */ @@ -201,7 +195,7 @@ static int irtty_open(struct tty_struct *tty) /* The only value we must override it the baudrate */ self->idev.qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600| IR_115200; - self->idev.qos.min_turn_time.bits = 0x0f; + self->idev.qos.min_turn_time.bits = qos_mtt_bits; self->idev.flags = IFF_SIR | IFF_PIO; irda_qos_bits_to_value(&self->idev.qos); @@ -216,7 +210,8 @@ static int irtty_open(struct tty_struct *tty) /* Initialize callbacks */ self->idev.change_speed = irtty_change_speed; self->idev.is_receiving = irtty_is_receiving; - /* self->idev.is_tbusy = irtty_is_tbusy; */ + self->idev.set_dtr_rts = irtty_set_dtr_rts; + self->idev.raw_write = irtty_raw_write; self->idev.wait_until_sent = irtty_wait_until_sent; /* Override the network functions we need to use */ @@ -248,10 +243,6 @@ static void irtty_close(struct tty_struct *tty) ASSERT(self != NULL, return;); ASSERT(self->magic == IRTTY_MAGIC, return;); - /* We are not using any dongle anymore! */ - if (self->dongle_q) - self->dongle_q->dongle->close(&self->idev); - /* Remove driver */ irda_device_close(&self->idev); @@ -358,68 +349,6 @@ static void irtty_change_speed(struct irda_device *idev, int baud) self->tty->driver.set_termios(self->tty, &old_termios); } -/* - * Function irtty_init_dongle (self, type) - * - * Initialize attached dongle. Warning, must be called with a process - * context! - */ -static void irtty_init_dongle(struct irtty_cb *self, int type) -{ - struct dongle_q *node; - - ASSERT(self != NULL, return;); - ASSERT(self->magic == IRTTY_MAGIC, return;); - -#ifdef CONFIG_KMOD - /* Try to load the module needed */ - switch( type) { - case ESI_DONGLE: - MESSAGE("IrDA: Trying to initialize ESI dongle!\n"); - request_module("esi"); - break; - case TEKRAM_DONGLE: - MESSAGE("IrDA: Trying to initialize Tekram dongle!\n"); - request_module("tekram"); - break; - case ACTISYS_DONGLE: /* FALLTHROUGH */ - case ACTISYS_PLUS_DONGLE: - MESSAGE("IrDA: Trying to initialize ACTiSYS dongle!\n"); - request_module("actisys"); - break; - case GIRBIL_DONGLE: - MESSAGE("IrDA: Trying to initialize GIrBIL dongle!\n"); - request_module("girbil"); - break; - default: - ERROR("Unknown dongle type!\n"); - return; - } -#endif /* CONFIG_KMOD */ - - node = hashbin_find(dongles, type, NULL); - if ( !node) { - ERROR("Unable to find requested dongle\n"); - return; - } - self->dongle_q = node; - - /* Use this change speed function instead of the default */ - self->idev.change_speed = node->dongle->change_speed; - - /* - * Now initialize the dongle! - */ - node->dongle->open(&self->idev, type); - node->dongle->qos_init(&self->idev, &self->idev.qos); - - /* Reset dongle */ - node->dongle->reset(&self->idev, 0); - - /* Set to default baudrate */ - node->dongle->change_speed(&self->idev, 9600); -} - /* * Function irtty_ioctl (tty, file, cmd, arg) * @@ -452,7 +381,7 @@ static int irtty_ioctl(struct tty_struct *tty, void *file, int cmd, void *arg) break; case IRTTY_IOCTDONGLE: /* Initialize dongle */ - irtty_init_dongle(self, (int) arg); + irda_device_init_dongle(&self->idev, (int) arg); break; default: return -ENOIOCTLCMD; @@ -645,54 +574,23 @@ static void irtty_wait_until_sent(struct irda_device *idev) tty_wait_until_sent(self->tty, 0); } -int irtty_register_dongle(struct dongle *dongle) -{ - struct dongle_q *new; - - /* Check if this compressor has been registred before */ - if ( hashbin_find ( dongles, dongle->type, NULL)) { - DEBUG( 0, __FUNCTION__ "(), Dongle already registered\n"); - return 0; - } - - /* Make new IrDA dongle */ - new = (struct dongle_q *) kmalloc(sizeof(struct dongle_q), GFP_KERNEL); - if (new == NULL) - return -1; - - memset(new, 0, sizeof( struct dongle_q)); - new->dongle = dongle; - - /* Insert IrDA dongle into hashbin */ - hashbin_insert(dongles, (QUEUE *) new, dongle->type, NULL); - - return 0; -} - -void irtty_unregister_dongle(struct dongle *dongle) -{ - struct dongle_q *node; - - node = hashbin_remove(dongles, dongle->type, NULL); - if (!node) { - ERROR(__FUNCTION__ "(), dongle not found!\n"); - return; - } - kfree(node); -} - - /* * Function irtty_set_dtr_rts (tty, dtr, rts) * * This function can be used by dongles etc. to set or reset the status * of the dtr and rts lines */ -void irtty_set_dtr_rts(struct tty_struct *tty, int dtr, int rts) +static void irtty_set_dtr_rts(struct irda_device *idev, int dtr, int rts) { + struct tty_struct *tty; + struct irtty_cb *self; mm_segment_t fs; int arg = 0; + self = (struct irtty_cb *) idev->priv; + + tty = self->tty; + #ifdef TIOCM_OUT2 /* Not defined for ARM */ arg = TIOCM_OUT2; #endif @@ -718,6 +616,25 @@ void irtty_set_dtr_rts(struct tty_struct *tty, int dtr, int rts) set_fs(fs); } +static int irtty_raw_write(struct irda_device *idev, __u8 *buf, int len) +{ + struct irtty_cb *self; + int actual = 0; + + 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;); + + if (self->tty->driver.write) + actual = self->tty->driver.write(self->tty, 0, buf, len); + + return actual; +} + static int irtty_net_init(struct device *dev) { /* Set up to be a normal IrDA network device driver */ @@ -760,6 +677,8 @@ static int irtty_net_close(struct device *dev) MODULE_AUTHOR("Dag Brattli "); MODULE_DESCRIPTION("IrDA TTY device driver"); +MODULE_PARM(qos_mtt_bits, "i"); + /* * Function init_module (void) * diff --git a/drivers/net/irda/litelink.c b/drivers/net/irda/litelink.c new file mode 100644 index 000000000000..e27bab10c3f7 --- /dev/null +++ b/drivers/net/irda/litelink.c @@ -0,0 +1,209 @@ +/********************************************************************* + * + * Filename: litelink.c + * Version: 1.0 + * Description: Driver for the Parallax LiteLink dongle + * Status: Stable + * Author: Dag Brattli + * Created at: Fri May 7 12:50:33 1999 + * Modified at: Mon May 10 15:12:18 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ********************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +static void litelink_reset(struct irda_device *dev, int unused); +static void litelink_open(struct irda_device *idev, int type); +static void litelink_close(struct irda_device *dev); +static void litelink_change_speed( struct irda_device *dev, int baudrate); +static void litelink_reset(struct irda_device *dev, int unused); +static void litelink_init_qos(struct irda_device *idev, struct qos_info *qos); + +/* These are the baudrates supported */ +static int baud_rates[] = { 115200, 57600, 38400, 19200, 9600 }; + +static struct dongle dongle = { + LITELINK_DONGLE, + litelink_open, + litelink_close, + litelink_reset, + litelink_change_speed, + litelink_init_qos, +}; + +__initfunc(int litelink_init(void)) +{ + return irda_device_register_dongle(&dongle); +} + +void litelink_cleanup(void) +{ + irda_device_unregister_dongle(&dongle); +} + +static void litelink_open(struct irda_device *idev, int type) +{ + strcat(idev->description, " <-> litelink"); + + idev->io.dongle_id = type; + idev->flags |= IFF_DONGLE; + + MOD_INC_USE_COUNT; +} + +static void litelink_close(struct irda_device *idev) +{ + /* Power off dongle */ + irda_device_set_dtr_rts(idev, FALSE, FALSE); + + MOD_DEC_USE_COUNT; +} + +/* + * Function litelink_change_speed (tty, baud) + * + * Change speed of the Litelink dongle. To cycle through the available + * baud rates, pulse RTS low for a few ms. + */ +static void litelink_change_speed(struct irda_device *idev, int baudrate) +{ + int i; + + ASSERT(idev != NULL, return;); + ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); + + /* Clear RTS to reset dongle */ + irda_device_set_dtr_rts(idev, TRUE, FALSE); + + /* Sleep a minimum of 15 us */ + udelay(15); + + /* Go back to normal mode */ + irda_device_set_dtr_rts(idev, TRUE, TRUE); + + /* Sleep a minimum of 15 us */ + udelay(15); + + /* Cycle through avaiable baudrates until we reach the correct one */ + for (i=0; i<5 && baud_rates[i] != baudrate; i++) { + + /* Set DTR, clear RTS */ + irda_device_set_dtr_rts(idev, FALSE, TRUE); + + /* Sleep a minimum of 15 us */ + udelay(15); + + /* Set DTR, Set RTS */ + irda_device_set_dtr_rts(idev, TRUE, TRUE); + + /* Sleep a minimum of 15 us */ + udelay(15); + } +} + +/* + * Function litelink_reset (dev) + * + * Reset the Litelink type dongle. Warning, this function must only be + * called with a process context! + * + */ +static void litelink_reset(struct irda_device *idev, int unused) +{ + struct irtty_cb *self; + struct tty_struct *tty; + + ASSERT(idev != NULL, return;); + ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); + + /* Power on dongle */ + irda_device_set_dtr_rts(idev, TRUE, TRUE); + + /* Sleep a minimum of 15 us */ + udelay(15); + + /* Clear RTS to reset dongle */ + irda_device_set_dtr_rts(idev, TRUE, FALSE); + + /* Sleep a minimum of 15 us */ + udelay(15); + + /* Go back to normal mode */ + irda_device_set_dtr_rts(idev, TRUE, TRUE); + + /* Sleep a minimum of 15 us */ + udelay(15); + + /* This dongles speed defaults to 115200 bps */ + idev->qos.baud_rate.value = 115200; +} + +/* + * Function litelink_init_qos (qos) + * + * Initialize QoS capabilities + * + */ +static void litelink_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 &= 0x40; /* Needs 0.01 ms */ +} + +#ifdef MODULE + +MODULE_AUTHOR("Dag Brattli "); +MODULE_DESCRIPTION("Parallax Litelink dongle driver"); + +/* + * Function init_module (void) + * + * Initialize Litelink module + * + */ +int init_module(void) +{ + return litelink_init(); +} + +/* + * Function cleanup_module (void) + * + * Cleanup Litelink module + * + */ +void cleanup_module(void) +{ + litelink_cleanup(); +} + +#endif diff --git a/drivers/net/irda/pc87108.c b/drivers/net/irda/pc87108.c index 878b2e33a846..340f836e7b9c 100644 --- a/drivers/net/irda/pc87108.c +++ b/drivers/net/irda/pc87108.c @@ -6,10 +6,10 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sat Nov 7 21:43:15 1998 - * Modified at: Tue Apr 20 11:11:39 1999 + * Modified at: Sun May 9 12:57:46 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli + * Copyright (c) 1998-1999 Dag Brattli * Copyright (c) 1998 Lichen Wang, * Copyright (c) 1998 Actisys Corp., www.actisys.com * All Rights Reserved @@ -67,6 +67,7 @@ #define BROKEN_DONGLE_ID static char *driver_name = "pc87108"; +static int qos_mtt_bits = 0x07; /* 1 ms or more */ #define CHIP_IO_EXTENT 8 @@ -219,7 +220,7 @@ static int pc87108_open( int i, unsigned int iobase, unsigned int board_addr, idev->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600| IR_115200|IR_576000|IR_1152000|(IR_4000000 << 8); - idev->qos.min_turn_time.bits = 0x07; + idev->qos.min_turn_time.bits = qos_mtt_bits; irda_qos_bits_to_value( &idev->qos); idev->flags = IFF_FIR|IFF_MIR|IFF_SIR|IFF_DMA|IFF_PIO|IFF_DONGLE; @@ -259,8 +260,9 @@ static int pc87108_open( int i, unsigned int iobase, unsigned int board_addr, * Close driver instance * */ -static int pc87108_close( struct irda_device *idev) +static int pc87108_close(struct irda_device *idev) { + struct pc87108 *self; int iobase; DEBUG( 4, __FUNCTION__ "()\n"); @@ -269,13 +271,16 @@ static int pc87108_close( struct irda_device *idev) ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return -1;); iobase = idev->io.iobase; + self = (struct pc87108 *) idev->priv; /* Release the PORT that this driver is using */ DEBUG( 4, __FUNCTION__ "(), Releasing Region %03x\n", idev->io.iobase); - release_region( idev->io.iobase, idev->io.io_ext); + release_region(idev->io.iobase, idev->io.io_ext); + + irda_device_close(idev); - irda_device_close( idev); + kfree(self); return 0; } @@ -805,7 +810,6 @@ static void pc87108_dma_write( struct irda_device *idev, int iobase) setup_dma(idev->io.dma, idev->tx_buff.data, idev->tx_buff.len, DMA_MODE_WRITE); - /* idev->media_busy = TRUE; */ idev->io.direction = IO_XMIT; /* Choose transmit DMA channel */ @@ -973,7 +977,7 @@ static int pc87108_dma_receive(struct irda_device *idev) * * */ -static int pc87108_dma_receive_complete( struct irda_device *idev, int iobase) +static int pc87108_dma_receive_complete(struct irda_device *idev, int iobase) { struct sk_buff *skb; struct pc87108 *self; @@ -988,8 +992,6 @@ static int pc87108_dma_receive_complete( struct irda_device *idev, int iobase) /* Save current bank */ bank = inb( iobase+BSR); - iobase = idev->io.iobase; - /* Read status FIFO */ switch_bank(iobase, BANK5); while (( status = inb( iobase+FRM_ST)) & FRM_ST_VLD) { @@ -1003,18 +1005,18 @@ static int pc87108_dma_receive_complete( struct irda_device *idev, int iobase) } /* Try to process all entries in status FIFO */ - switch_bank( iobase, BANK0); - while ( st_fifo->len) { + switch_bank(iobase, BANK0); + while (st_fifo->len) { /* Get first entry */ - status = st_fifo->entries[ st_fifo->head].status; - len = st_fifo->entries[ st_fifo->head].len; + status = st_fifo->entries[st_fifo->head].status; + len = st_fifo->entries[st_fifo->head].len; st_fifo->head++; st_fifo->len--; /* Check for errors */ - if ( status & FRM_ST_ERR_MSK) { - if ( status & FRM_ST_LOST_FR) { + if (status & FRM_ST_ERR_MSK) { + if (status & FRM_ST_LOST_FR) { /* Add number of lost frames to stats */ idev->stats.rx_errors += len; } else { @@ -1188,8 +1190,8 @@ static __u8 pc87108_fir_interrupt( struct irda_device *idev, int iobase, bank = inb( iobase+BSR); /* Status event, or end of frame detected in FIFO */ - if ( eir & (EIR_SFIF_EV|EIR_LS_EV)) { - if ( pc87108_dma_receive_complete( idev, iobase)) { + if (eir & (EIR_SFIF_EV|EIR_LS_EV)) { + if (pc87108_dma_receive_complete( idev, iobase)) { /* Wait for next status FIFO interrupt */ new_ier |= IER_SFIF_IE; @@ -1460,6 +1462,11 @@ static int pc87108_net_close(struct device *dev) #ifdef MODULE +MODULE_AUTHOR("Dag Brattli "); +MODULE_DESCRIPTION("NSC PC87108 IrDA Device Driver"); + +MODULE_PARM(qos_mtt_bits, "i"); + /* * Function init_module (void) * diff --git a/drivers/net/irda/tekram.c b/drivers/net/irda/tekram.c index de1a553a4aaf..e99cb0d44501 100644 --- a/drivers/net/irda/tekram.c +++ b/drivers/net/irda/tekram.c @@ -1,15 +1,15 @@ /********************************************************************* * * Filename: tekram.c - * Version: 1.0 + * Version: 1.1 * 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: Tue Apr 13 16:33:54 1999 + * Modified at: Mon May 10 16:10:17 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli, All Rights Reserved. + * Copyright (c) 1998-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 @@ -62,15 +62,15 @@ static struct dongle dongle = { __initfunc(int tekram_init(void)) { - return irtty_register_dongle(&dongle); + return irda_device_register_dongle(&dongle); } void tekram_cleanup(void) { - irtty_unregister_dongle( &dongle); + irda_device_unregister_dongle(&dongle); } -static void tekram_open( struct irda_device *idev, int type) +static void tekram_open(struct irda_device *idev, int type) { strcat(idev->description, " <-> tekram"); @@ -80,8 +80,11 @@ static void tekram_open( struct irda_device *idev, int type) MOD_INC_USE_COUNT; } -static void tekram_close( struct irda_device *dev) -{ +static void tekram_close(struct irda_device *idev) +{ + /* Power off dongle */ + irda_device_set_dtr_rts(idev, FALSE, FALSE); + MOD_DEC_USE_COUNT; } @@ -101,79 +104,49 @@ static void tekram_close( struct irda_device *dev) * 6. wait at least 50 us, new setting (baud rate, etc) takes effect here * after */ -static void tekram_change_speed( struct irda_device *dev, int baud) +static void tekram_change_speed(struct irda_device *idev, int baud) { - struct irtty_cb *self; - struct tty_struct *tty; - struct termios old_termios; - int cflag; __u8 byte; DEBUG(4, __FUNCTION__ "()\n"); - ASSERT(dev != NULL, return;); - ASSERT(dev->magic == IRDA_DEVICE_MAGIC, return;); - - self = (struct irtty_cb *) dev->priv; - - ASSERT(self != NULL, return;); - ASSERT(self->magic == IRTTY_MAGIC, return;); - - if (!self->tty) - return; - - tty = self->tty; + ASSERT(idev != NULL, return;); + ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); - old_termios = *(tty->termios); - cflag = tty->termios->c_cflag; - - cflag &= ~CBAUD; - switch (baud) { default: - /* FALLTHROUGH */ case 9600: - cflag |= B9600; byte = TEKRAM_PW|TEKRAM_9600; break; case 19200: - cflag |= B19200; byte = TEKRAM_PW|TEKRAM_19200; break; case 34800: - cflag |= B38400; byte = TEKRAM_PW|TEKRAM_38400; break; case 57600: - cflag |= B57600; byte = TEKRAM_PW|TEKRAM_57600; break; case 115200: - cflag |= B115200; byte = TEKRAM_PW|TEKRAM_115200; break; } /* Set DTR, Clear RTS */ - irtty_set_dtr_rts(tty, TRUE, FALSE); + irda_device_set_dtr_rts(idev, TRUE, FALSE); /* Wait at least 7us */ udelay(7); /* Write control byte */ - if (tty->driver.write) - tty->driver.write(self->tty, 0, &byte, 1); + irda_device_raw_write(idev, &byte, 1); /* Wait at least 100 ms */ current->state = TASK_INTERRUPTIBLE; schedule_timeout(MSECS_TO_JIFFIES(100)); /* Set DTR, Set RTS */ - 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); + irda_device_set_dtr_rts(idev, TRUE, TRUE); } /* @@ -189,41 +162,27 @@ static void tekram_change_speed( struct irda_device *dev, int baud) * 3. clear DTR to SPACE state, wait at least 50 us for further * operation */ -void tekram_reset(struct irda_device *dev, int unused) +void tekram_reset(struct irda_device *idev, int unused) { - struct irtty_cb *self; - struct tty_struct *tty; - - DEBUG(4, __FUNCTION__ "()\n"); - - ASSERT(dev != NULL, return;); - ASSERT(dev->magic == IRDA_DEVICE_MAGIC, return;); - - self = (struct irtty_cb *) dev->priv; + ASSERT(idev != NULL, return;); + ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); - ASSERT(self != NULL, return;); - ASSERT(self->magic == IRTTY_MAGIC, return;); - - tty = self->tty; - if (!tty) - return; - /* Power off dongle */ - irtty_set_dtr_rts(tty, FALSE, FALSE); + irda_device_set_dtr_rts(idev, FALSE, FALSE); /* Sleep 50 ms */ current->state = TASK_INTERRUPTIBLE; schedule_timeout(MSECS_TO_JIFFIES(50)); /* Clear DTR, Set RTS */ - irtty_set_dtr_rts(tty, FALSE, TRUE); + irda_device_set_dtr_rts(idev, FALSE, TRUE); /* Should sleep 1 ms, but 10-20 should not do any harm */ current->state = TASK_INTERRUPTIBLE; schedule_timeout(MSECS_TO_JIFFIES(20)); /* Set DTR, Set RTS */ - irtty_set_dtr_rts(tty, TRUE, TRUE); + irda_device_set_dtr_rts(idev, TRUE, TRUE); udelay(50); diff --git a/drivers/net/irda/toshoboe.c b/drivers/net/irda/toshoboe.c new file mode 100644 index 000000000000..c7ef984ea034 --- /dev/null +++ b/drivers/net/irda/toshoboe.c @@ -0,0 +1,901 @@ +/********************************************************************* + * + * Filename: toshoboe.c + * Version: 0.1 + * Description: Driver for the Toshiba OBOE (or type-O or 700 or 701) + * FIR Chipset. + * Status: Experimental. + * Author: James McKenzie + * Created at: Sat May 8 12:35:27 1999 + * + * Copyright (c) 1999 James McKenzie, 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 James McKenzie nor Cambridge University admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + * Applicable Models : Libretto 100CT. and many more + * Toshiba refers to this chip as the type-O IR port. + * + ********************************************************************/ + +/* This driver is experimental, I have only three ir devices */ +/* an olivetti notebook which doesn't have FIR, a toshiba libretto, and */ +/* an hp printer, this works fine at 4MBPS with my HP printer */ + +static char *rcsid = "$Id: toshoboe.c,v 1.5 1999/05/12 12:24:39 root Exp root $"; + +/* + * $Log: toshoboe.c,v $ + * Revision 1.5 1999/05/12 12:24:39 root + * *** empty log message *** + * + * Revision 1.4 1999/05/12 11:55:08 root + * *** empty log message *** + * + * Revision 1.3 1999/05/09 01:33:12 root + * *** empty log message *** + * + * Revision 1.2 1999/05/09 01:30:38 root + * *** empty log message *** + * + * Revision 1.1 1999/05/09 01:25:04 root + * Initial revision + * + */ + +/* Define this to have only one frame in the XMIT or RECV queue */ +/* Toshiba's drivers do this, but it disables back to back tansfers */ +/* I think that the chip may have some problems certainly, I have */ +/* seen it jump over tasks in the taskfile->xmit with this turned on */ +#define ONETASK + +/* To adjust the number of tasks in use edit toshoboe.h */ + +/* Define this to enable FIR and MIR support */ +#define ENABLE_FAST + +/* Number of ports this driver can support, you also need to edit dev_self below */ +#define NSELFS 4 + +/* Size of IO window */ +#define CHIP_IO_EXTENT 0x1f + +/* Transmit and receive buffer sizes, adjust at your peril */ +#define RX_BUF_SZ 4196 +#define TX_BUF_SZ 4196 + +/* No user servicable parts below here */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include + +static char *driver_name = "toshoboe"; + +static struct toshoboe_cb *dev_self[NSELFS + 1] = +{NULL, NULL, NULL, NULL, NULL}; + +/* Shutdown the chip and point the taskfile reg somewhere else */ +static void +toshoboe_stopchip (struct toshoboe_cb *self) +{ + DEBUG (4, __FUNCTION__ "()\n"); + + outb_p (0x0e, OBOE_REG_11); + + outb_p (0x00, OBOE_RST); + outb_p (0x3f, OBOE_TFP2); /*Write the taskfile address */ + outb_p (0xff, OBOE_TFP1); + outb_p (0xff, OBOE_TFP0); + outb_p (0x0f, OBOE_REG_1B); + outb_p (0xff, OBOE_REG_1A); + outb_p (0x00, OBOE_ISR); /*FIXME: should i do this to disbale ints */ + outb_p (0x80, OBOE_RST); + outb_p (0xe, OBOE_LOCK); +} + +/*Set the baud rate */ +static void +toshoboe_setbaud (struct toshoboe_cb *self, int baud) +{ + DEBUG (4, __FUNCTION__ "()\n"); + + printk (KERN_WARNING "ToshOboe: seting baud to %d\n", baud); + + cli (); + switch (baud) + { + case 2400: + outb_p (OBOE_PMDL_SIR, OBOE_PMDL); + outb_p (OBOE_SMDL_SIR, OBOE_SMDL); + outb_p (0xbf, OBOE_UDIV); + break; + case 4800: + outb_p (OBOE_PMDL_SIR, OBOE_PMDL); + outb_p (OBOE_SMDL_SIR, OBOE_SMDL); + outb_p (0x5f, OBOE_UDIV); + break; + case 9600: + outb_p (OBOE_PMDL_SIR, OBOE_PMDL); + outb_p (OBOE_SMDL_SIR, OBOE_SMDL); + outb_p (0x2f, OBOE_UDIV); + break; + case 19200: + outb_p (OBOE_PMDL_SIR, OBOE_PMDL); + outb_p (OBOE_SMDL_SIR, OBOE_SMDL); + outb_p (0x17, OBOE_UDIV); + break; + case 38400: + outb_p (OBOE_PMDL_SIR, OBOE_PMDL); + outb_p (OBOE_SMDL_SIR, OBOE_SMDL); + outb_p (0xb, OBOE_UDIV); + break; + case 57600: + outb_p (OBOE_PMDL_SIR, OBOE_PMDL); + outb_p (OBOE_SMDL_SIR, OBOE_SMDL); + outb_p (0x7, OBOE_UDIV); + break; + case 115200: + outb_p (OBOE_PMDL_SIR, OBOE_PMDL); + outb_p (OBOE_SMDL_SIR, OBOE_SMDL); + outb_p (0x3, OBOE_UDIV); + break; + case 1152000: + outb_p (OBOE_PMDL_MIR, OBOE_PMDL); + outb_p (OBOE_SMDL_MIR, OBOE_SMDL); + outb_p (0x1, OBOE_UDIV); + break; + case 4000000: + outb_p (OBOE_PMDL_FIR, OBOE_PMDL); + outb_p (OBOE_SMDL_FIR, OBOE_SMDL); + outb_p (0x0, OBOE_UDIV); + break; + } + + sti (); + + outb_p (0x00, OBOE_RST); + outb_p (0x80, OBOE_RST); + outb_p (0x01, OBOE_REG_9); + +} + +/* Wake the chip up and get it looking at the taskfile */ +static void +toshoboe_startchip (struct toshoboe_cb *self) +{ + __u32 physaddr; + + DEBUG (4, __FUNCTION__ "()\n"); + + + outb_p (0, OBOE_LOCK); + outb_p (0, OBOE_RST); + outb_p (OBOE_NTR_VAL, OBOE_NTR); + outb_p (0xf0, OBOE_REG_D); + outb_p (0xff, OBOE_ISR); + outb_p (0x0f, OBOE_REG_1A); + outb_p (0xff, OBOE_REG_1B); + + + physaddr = virt_to_bus (self->taskfile); + + outb_p ((physaddr >> 0x0a) & 0xff, OBOE_TFP0); + outb_p ((physaddr >> 0x12) & 0xff, OBOE_TFP1); + outb_p ((physaddr >> 0x1a) & 0x3f, OBOE_TFP2); + + outb_p (0x0e, OBOE_REG_11); + outb_p (0x80, OBOE_RST); + + toshoboe_setbaud (self, 9600); + +} + +/*Let the chip look at memory */ +static void +toshoboe_enablebm (struct toshoboe_cb *self) +{ + DEBUG (4, __FUNCTION__ "()\n"); + pci_set_master (self->pdev); +} + +/*Don't let the chip look at memory */ +static void +toshoboe_disablebm (struct toshoboe_cb *self) +{ + __u8 command; + DEBUG (4, __FUNCTION__ "()\n"); + + pci_read_config_byte (self->pdev, PCI_COMMAND, &command); + command &= ~PCI_COMMAND_MASTER; + pci_write_config_byte (self->pdev, PCI_COMMAND, command); + +} + +/*setup the taskfile */ +static void +toshoboe_initbuffs (struct toshoboe_cb *self) +{ + int i; + + DEBUG (4, __FUNCTION__ "()\n"); + + cli (); + + for (i = 0; i < TX_SLOTS; ++i) + { + self->taskfile->xmit[i].len = 0; + self->taskfile->xmit[i].control = 0x00; + self->taskfile->xmit[i].buffer = virt_to_bus (self->xmit_bufs[i]); + } + + for (i = 0; i < RX_SLOTS; ++i) + { + self->taskfile->recv[i].len = 0; + self->taskfile->recv[i].control = 0x83; + self->taskfile->recv[i].buffer = virt_to_bus (self->recv_bufs[i]); + } + + sti (); +} + + +/*Transmit something */ +static int +toshoboe_hard_xmit (struct sk_buff *skb, struct device *dev) +{ + struct irda_device *idev; + struct toshoboe_cb *self; + int mtt, len; + + idev = (struct irda_device *) dev->priv; + ASSERT (idev != NULL, return 0;); + ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return 0;); + + self = idev->priv; + ASSERT (self != NULL, return 0;); + + +#ifdef ONETASK + if (self->txpending) + return -EBUSY; + + self->txs = inb_p (OBOE_XMTT) - OBOE_XMTT_OFFSET; + + self->txs &= 0x3f; + +#endif + + if (self->taskfile->xmit[self->txs].control) + return -EBUSY; + + + if (inb_p (OBOE_RST) & OBOE_RST_WRAP) + { + len = async_wrap_skb (skb, self->xmit_bufs[self->txs], TX_BUF_SZ); + } + else + { + len = skb->len; + memcpy (self->xmit_bufs[self->txs], skb->data, len); + } + self->taskfile->xmit[self->txs].len = len & 0x0fff; + + + + outb_p (0, OBOE_RST); + outb_p (0x1e, OBOE_REG_11); + + self->taskfile->xmit[self->txs].control = 0x84; + + mtt = irda_get_mtt (skb); + if (mtt) + udelay (mtt); + + self->txpending++; + + /*FIXME: ask about tbusy,media_busy stuff, for the moment */ + /*tbusy means can't queue any more */ +#ifndef ONETASK + if (self->txpending == TX_SLOTS) + { +#else + { +#endif + if (irda_lock ((void *) &dev->tbusy) == FALSE) + return -EBUSY; + } + + outb_p (0x80, OBOE_RST); + outb_p (1, OBOE_REG_9); + + self->txs++; + self->txs %= TX_SLOTS; + + dev_kfree_skb (skb); + + return 0; +} + +/*interrupt handler */ +static void +toshoboe_interrupt (int irq, void *dev_id, struct pt_regs *regs) +{ + struct irda_device *idev = (struct irda_device *) dev_id; + struct toshoboe_cb *self; + __u8 irqstat; + struct sk_buff *skb; + + if (idev == NULL) + { + printk (KERN_WARNING "%s: irq %d for unknown device.\n", + driver_name, irq); + return; + } + + self = idev->priv; + + if (!self) + return; + + DEBUG (4, __FUNCTION__ "()\n"); + + irqstat = inb_p (OBOE_ISR); + +/* woz it us */ + if (!(irqstat & 0xf8)) + return; + + outb_p (irqstat, OBOE_ISR); /*Acknologede it */ + + +/* Txdone */ + if (irqstat & OBOE_ISR_TXDONE) + { + self->txpending--; + + idev->stats.tx_packets++; + + idev->media_busy = FALSE; + idev->netdev.tbusy = 0; + + mark_bh (NET_BH); + } + + if (irqstat & OBOE_ISR_RXDONE) + { + +#ifdef ONETASK + self->rxs = inb_p (OBOE_RCVT); + self->rxs += (RX_SLOTS - 1); + self->rxs %= RX_SLOTS; +#else + while (self->taskfile->recv[self->rxs].control == 0) +#endif + { + int len = self->taskfile->recv[self->rxs].len; + + if (len>2) len-=2; + + skb = dev_alloc_skb (len + 1); + if (skb) + { + skb_reserve (skb, 1); + + skb_put (skb, len); + memcpy (skb->data, self->recv_bufs[self->rxs], len); + + idev->stats.rx_packets++; + skb->dev = &idev->netdev; + skb->mac.raw = skb->data; + skb->protocol = htons (ETH_P_IRDA); + } + else + { + printk (KERN_INFO __FUNCTION__ + "(), memory squeeze, dropping frame.\n"); + } + + + + self->taskfile->recv[self->rxs].control = 0x83; + self->taskfile->recv[self->rxs].len = 0x0; + + self->rxs++; + self->rxs %= RX_SLOTS; + + if (skb) + netif_rx (skb); + + } + + } + + if (irqstat & OBOE_ISR_20) + { + printk (KERN_WARNING "Oboe_irq: 20\n"); + } + if (irqstat & OBOE_ISR_10) + { + printk (KERN_WARNING "Oboe_irq: 10\n"); + } + if (irqstat & 0x8) + { + /*FIXME: I think this is a TX or RX error of some sort */ + + idev->stats.tx_errors++; + idev->stats.rx_errors++; + + } + + +} + + + +/* Change the baud rate */ +static void +toshoboe_change_speed (struct irda_device *idev, int speed) +{ + struct toshoboe_cb *self; + DEBUG (4, __FUNCTION__ "()\n"); + + ASSERT (idev != NULL, return;); + ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return;); + + self = idev->priv; + ASSERT (self != NULL, return;); + + idev->io.baudrate = speed; + + toshoboe_setbaud (self, speed); + +} + + +/* Check all xmit_tasks finished */ +static void +toshoboe_wait_until_sent (struct irda_device *idev) +{ + struct toshoboe_cb *self; + int i; + + DEBUG (4, __FUNCTION__ "()\n"); + + ASSERT (idev != NULL, return;); + ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return;); + + self = idev->priv; + ASSERT (self != NULL, return;); + + for (i = 0; i < TX_SLOTS; ++i) + { + while (self->taskfile->xmit[i].control) + { + current->state = TASK_INTERRUPTIBLE; + schedule_timeout (6); + } + } + +} + +static int +toshoboe_is_receiving (struct irda_device *idev) +{ + DEBUG (4, __FUNCTION__ "()\n"); + +/*FIXME Can't tell! */ + return (FALSE); +} + + +static int +toshoboe_net_init (struct device *dev) +{ + DEBUG (4, __FUNCTION__ "()\n"); + + /* Setup to be a normal IrDA network device driver */ + irda_device_setup (dev); + + /* Insert overrides below this line! */ + return 0; +} + + + + +static int +toshoboe_net_open (struct device *dev) +{ + struct irda_device *idev; + struct toshoboe_cb *self; + + DEBUG (4, __FUNCTION__ "()\n"); + + ASSERT (dev != NULL, return -1;); + idev = (struct irda_device *) dev->priv; + + ASSERT (idev != NULL, return 0;); + ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return 0;); + + self = idev->priv; + ASSERT (self != NULL, return 0;); + + if (request_irq (idev->io.irq, toshoboe_interrupt, + SA_SHIRQ | SA_INTERRUPT, idev->name, (void *) idev)) + { + + return -EAGAIN; + } + + toshoboe_initbuffs (self); + toshoboe_enablebm (self); + toshoboe_startchip (self); + + + cli (); + + /*FIXME: need to test this carefully to check which one */ + /*of the two possible startup logics the chip uses */ + /*although it won't make any difference if no-one xmits durining init */ + /*and none what soever if using ONETASK */ + + self->rxs = inb_p (OBOE_RCVT); + self->txs = inb_p (OBOE_XMTT) - OBOE_XMTT_OFFSET; + +#ifdef 0 + self->rxs = 0; + self->txs = 0; +#endif +#ifdef 0 + self->rxs = RX_SLOTS - 1; + self->txs = 0; +#endif + + + self->txpending = 0; + + sti (); + + + dev->tbusy = 0; + dev->interrupt = 0; + dev->start = 1; + + MOD_INC_USE_COUNT; + + return 0; + +} + +static int +toshoboe_net_close (struct device *dev) +{ + struct irda_device *idev; + struct toshoboe_cb *self; + + DEBUG (4, __FUNCTION__ "()\n"); + + ASSERT (dev != NULL, return -1;); + idev = (struct irda_device *) dev->priv; + + ASSERT (idev != NULL, return 0;); + ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return 0;); + + dev->tbusy = 1; + dev->start = 0; + + + self = idev->priv; + + ASSERT (self != NULL, return 0;); + + free_irq (idev->io.irq, (void *) idev); + + toshoboe_stopchip (self); + toshoboe_disablebm (self); + + MOD_DEC_USE_COUNT; + + return 0; + +} + + + +#ifdef MODULE + +static int +toshoboe_close (struct irda_device *idev) +{ + struct toshoboe_cb *self; + int i; + + DEBUG (4, __FUNCTION__ "()\n"); + + ASSERT (idev != NULL, return -1;); + ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return -1;); + + self = idev->priv; + + ASSERT (self != NULL, return -1;); + + toshoboe_stopchip (self); + + release_region (idev->io.iobase, idev->io.io_ext); + + + for (i = 0; i < TX_SLOTS; ++i) + { + kfree (self->xmit_bufs[i]); + self->xmit_bufs[i] = NULL; + } + + for (i = 0; i < RX_SLOTS; ++i) + { + kfree (self->recv_bufs[i]); + self->recv_bufs[i] = NULL; + } + + + kfree (self->taskfilebuf); + self->taskfilebuf = NULL; + self->taskfile = NULL; + + + irda_device_close (idev); + + return (0); + +} + +#endif + + + +static int +toshoboe_open (struct pci_dev *pci_dev) +{ + struct toshoboe_cb *self; + struct irda_device *idev; + int i = 0; + int ok=0; + + + DEBUG (4, __FUNCTION__ "()\n"); + + while (dev_self[i]) + i++; + + if (i == NSELFS) + { + printk (KERN_ERR "Oboe: No more instances available"); + return -ENOMEM; + } + + self = kmalloc (sizeof (struct toshoboe_cb), GFP_KERNEL); + + if (self == NULL) + { + printk (KERN_ERR "IrDA: Can't allocate memory for " + "IrDA control block!\n"); + return -ENOMEM; + } + + memset (self, 0, sizeof (struct toshoboe_cb)); + + + dev_self[i] = self; + + self->pdev = pci_dev; + self->base = pci_dev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK; + + idev = &self->idev; + + /*Setup idev */ + + idev->io.iobase = self->base; + idev->io.irq = pci_dev->irq; + idev->io.io_ext = CHIP_IO_EXTENT; + + /* Lock the port that we need */ + i = check_region (idev->io.iobase, idev->io.io_ext); + if (i < 0) + { + DEBUG (0, __FUNCTION__ "(), can't get iobase of 0x%03x\n", + idev->io.iobase); + + dev_self[i] = NULL; + kfree (self); + + return -ENODEV; + } + + request_region (idev->io.iobase, idev->io.io_ext, driver_name); + + irda_init_max_qos_capabilies (&idev->qos); + + idev->qos.baud_rate.bits = IR_2400 | /*IR_4800 | */ IR_9600 | IR_19200 | + IR_115200; +#ifdef ENABLE_FAST + idev->qos.baud_rate.bits|= IR_576000 | IR_1152000 | (IR_4000000 << 8); +#endif + + idev->qos.min_turn_time.bits = 0xff; /*FIXME: what does this do? */ + + irda_qos_bits_to_value (&idev->qos); + + idev->flags = IFF_SIR | IFF_DMA | IFF_PIO; + +#ifdef ENABLE_FAST + idev->flags |= IFF_FIR; +#endif + + /* These aren't much use as we need to have a whole panoply of + * buffers running */ + + idev->rx_buff.flags = 0; + idev->tx_buff.flags = 0; + idev->rx_buff.truesize = 0; + idev->rx_buff.truesize = 0; + + idev->change_speed = toshoboe_change_speed; + idev->wait_until_sent = toshoboe_wait_until_sent; + idev->is_receiving = toshoboe_is_receiving; + + idev->netdev.init = toshoboe_net_init; + idev->netdev.hard_start_xmit = toshoboe_hard_xmit; + idev->netdev.open = toshoboe_net_open; + idev->netdev.stop = toshoboe_net_close; + + + /* Now setup the endless buffers we need */ + + self->txs = 0; + self->rxs = 0; + + self->taskfilebuf = kmalloc (OBOE_TASK_BUF_LEN, GFP_KERNEL | GFP_DMA); + if (!self->taskfilebuf) { + printk(KERN_ERR "toshoboe: kmalloc for DMA failed()\n"); + kfree(self); + return -ENOMEM; + } + + + memset (self->taskfilebuf, 0, OBOE_TASK_BUF_LEN); + + /*We need to align the taskfile on a taskfile size boundary */ + { + __u32 addr; + + addr = (__u32) self->taskfilebuf; + addr &= ~(sizeof (struct OboeTaskFile) - 1); + addr += sizeof (struct OboeTaskFile); + + self->taskfile = (struct OboeTaskFile *) addr; + } + + for (i = 0; i < TX_SLOTS; ++i) + { + self->xmit_bufs[i] = kmalloc (TX_BUF_SZ, GFP_KERNEL | GFP_DMA); + if (self->xmit_bufs[i]) ok++; + } + + for (i = 0; i < RX_SLOTS; ++i) + { + self->recv_bufs[i] = kmalloc (TX_BUF_SZ, GFP_KERNEL | GFP_DMA); + if (self->recv_bufs[i]) ok++; + } + + if (ok!=RX_SLOTS+TX_SLOTS) { + printk(KERN_ERR "toshoboe: kmalloc for buffers failed()\n"); + + + for (i = 0; i < TX_SLOTS; ++i) if (self->xmit_bufs[i]) kfree(self->xmit_bufs[i]); + for (i = 0; i < RX_SLOTS; ++i) if (self->recv_bufs[i]) kfree(self->recv_bufs[i]); + + kfree(self); + return -ENOMEM; + + } + + + irda_device_open (idev, driver_name, self); + + printk (KERN_WARNING "ToshOboe: Using "); +#ifdef ONETASK + printk ("single"); +#else + printk ("multiple"); +#endif + printk (" tasks, version %s\n", rcsid); + + return (0); +} + +__initfunc (int toshoboe_init (void)) +{ + struct pci_dev *pci_dev = NULL; + int found = 0; + + do + { + pci_dev = pci_find_device (PCI_VENDOR_ID_TOSHIBA, + PCI_DEVICE_ID_FIR701, pci_dev); + if (pci_dev) + { + printk (KERN_WARNING "ToshOboe: Found 701 chip at 0x%0lx irq %d\n", + pci_dev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK, + pci_dev->irq); + + if (!toshoboe_open (pci_dev)) + found++; + } + + } + while (pci_dev); + + if (found) + return 0; + + return -ENODEV; +} + +#ifdef MODULE + +static void +toshoboe_cleanup (void) +{ + int i; + + DEBUG (4, __FUNCTION__ "()\n"); + + for (i = 0; i < 4; i++) + { + if (dev_self[i]) + toshoboe_close (&(dev_self[i]->idev)); + } +} + + + +int +init_module (void) +{ + return toshoboe_init (); +} + + +void +cleanup_module (void) +{ + toshoboe_cleanup (); +} + + +#endif diff --git a/drivers/net/irda/uircc.c b/drivers/net/irda/uircc.c index 60c8e024a0d1..f3454c531d94 100644 --- a/drivers/net/irda/uircc.c +++ b/drivers/net/irda/uircc.c @@ -7,10 +7,10 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sat Dec 26 10:59:03 1998 - * Modified at: Tue Apr 20 11:15:52 1999 + * Modified at: Mon May 10 22:11:09 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli, All Rights Reserved. + * Copyright (c) 1998-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 @@ -216,7 +216,7 @@ static int uircc_open(int i, unsigned int iobase, unsigned int iobase2, idev->netdev.open = uircc_net_open; idev->netdev.stop = uircc_net_close; - irport_open(iobase2); + irport_start(iobase2); /* Open the IrDA device */ irda_device_open(idev, driver_name, self); @@ -233,6 +233,7 @@ static int uircc_open(int i, unsigned int iobase, unsigned int iobase2, #ifdef MODULE static int uircc_close(struct irda_device *idev) { + struct uircc_cb *self; int iobase; int status; @@ -242,6 +243,7 @@ static int uircc_close(struct irda_device *idev) ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;); iobase = idev->io.iobase; + self = (struct uircc_cb *) idev->priv; /* Some magic to disable FIR and enable SIR */ uircc_toshiba_cmd(&status, 0xffff, 0x001b, 0x0000); @@ -249,7 +251,7 @@ static int uircc_close(struct irda_device *idev) /* Disable modem */ outb(0x00, iobase+UIRCC_CR10); - irport_close(idev->io.iobase2); + irport_stop(idev->io.iobase2); /* Release the PORT that this driver is using */ DEBUG(4, __FUNCTION__ "(), Releasing Region %03x\n", idev->io.iobase); @@ -262,6 +264,8 @@ static int uircc_close(struct irda_device *idev) } irda_device_close(idev); + kfree(self); + return 0; } #endif /* MODULE */ @@ -346,8 +350,8 @@ static void uircc_change_speed(struct irda_device *idev, int speed) case 37600: case 57600: case 115200: - irport_open(idev->io.iobase2); - irport_change_speed( idev->io.iobase2, speed); + irport_start(idev->io.iobase2); + irport_change_speed(idev, speed); /* Some magic to disable FIR and enable SIR */ uircc_toshiba_cmd(&status, 0xffff, 0x001b, 0x0000); @@ -363,7 +367,7 @@ static void uircc_change_speed(struct irda_device *idev, int speed) DEBUG(0, __FUNCTION__ "(), handling baud of 1152000\n"); break; case 4000000: - irport_close(idev->io.iobase2); + irport_stop(idev->io.iobase2); /* Some magic to disable SIR and enable FIR */ uircc_toshiba_cmd(&status, 0xffff, 0x001b, 0x0001); diff --git a/drivers/net/irda/w83977af_ir.c b/drivers/net/irda/w83977af_ir.c index 9234c4a82022..f773172153e2 100644 --- a/drivers/net/irda/w83977af_ir.c +++ b/drivers/net/irda/w83977af_ir.c @@ -1,16 +1,16 @@ /********************************************************************* * * Filename: w83977af_ir.c - * Version: 0.8 - * Description: FIR/MIR driver for the Winbond W83977AF Super I/O chip + * Version: 1.0 + * Description: FIR driver for the Winbond W83977AF Super I/O chip * Status: Experimental. * Author: Paul VanderSpek * Created at: Wed Nov 4 11:46:16 1998 - * Modified at: Tue Apr 20 11:15:00 1999 + * Modified at: Thu May 13 08:03:27 1999 * Modified by: Dag Brattli * + * Copyright (c) 1998-1999 Dag Brattli * Copyright (c) 1998 Corel Computer Corp. - * Copyright (c) 1998 Dag Brattli * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -40,7 +40,7 @@ ********************************************************************/ #include - + #include #include #include @@ -61,44 +61,45 @@ #include #include -#define NETWINDER +#define CONFIG_NETWINDER /* Adjust to NetWinder differences */ +#undef CONFIG_NETWINDER_TX_DMA_PROBLEMS /* Not needed */ +#define CONFIG_NETWINDER_RX_DMA_PROBLEMS /* Must have this one! */ +#undef CONFIG_USE_INTERNAL_TIMER /* Just cannot make that timer work */ +#define CONFIG_USE_W977_PNP /* Currently needed */ +#define PIO_MAX_SPEED 115200 static char *driver_name = "w83977af_ir"; +static int qos_mtt_bits = 0x07; /* 1 ms or more */ #define CHIP_IO_EXTENT 8 static unsigned int io[] = { 0x180, ~0, ~0, ~0 }; static unsigned int irq[] = { 6, 0, 0, 0 }; -static unsigned int dma[] = { 0, 0, 0, 0 }; - -static struct irda_device *dev_self[] = { NULL, NULL, NULL, NULL}; +static unsigned int dma[] = +{ 1, 0, 0, 0 }; -/* For storing entries in the status FIFO */ -struct st_fifo_entry { - int status; - int len; -}; +static struct w83977af_ir *dev_self[] = { NULL, NULL, NULL, NULL}; static struct st_fifo_entry prev; /* Some prototypes */ -static int w83977af_open( int i, unsigned int iobase, unsigned int irq, - unsigned int dma); -static int w83977af_close( struct irda_device *idev); -static int w83977af_probe( int iobase, int irq, int dma); +static int w83977af_open(int i, unsigned int iobase, unsigned int irq, + unsigned int dma); +static int w83977af_close(struct irda_device *idev); +static int w83977af_probe(int iobase, int irq, int dma); static int w83977af_dma_receive(struct irda_device *idev); static int w83977af_dma_receive_complete(struct irda_device *idev); -static int w83977af_hard_xmit( struct sk_buff *skb, struct device *dev); -static int w83977af_pio_write( int iobase, __u8 *buf, int len, int fifo_size); -static void w83977af_dma_write( struct irda_device *idev, int iobase); -static void w83977af_change_speed( struct irda_device *idev, int baud); +static int w83977af_hard_xmit(struct sk_buff *skb, struct device *dev); +static int w83977af_pio_write(int iobase, __u8 *buf, int len, int fifo_size); +static void w83977af_dma_write(struct irda_device *idev, int iobase); +static void w83977af_change_speed(struct irda_device *idev, int baud); static void w83977af_interrupt(int irq, void *dev_id, struct pt_regs *regs); -static void w83977af_wait_until_sent( struct irda_device *idev); -static int w83977af_is_receiving( struct irda_device *idev); +static void w83977af_wait_until_sent(struct irda_device *idev); +static int w83977af_is_receiving(struct irda_device *idev); -static int w83977af_net_init( struct device *dev); -static int w83977af_net_open( struct device *dev); -static int w83977af_net_close( struct device *dev); +static int w83977af_net_init(struct device *dev); +static int w83977af_net_open(struct device *dev); +static int w83977af_net_close(struct device *dev); /* * Function w83977af_init () @@ -108,13 +109,13 @@ static int w83977af_net_close( struct device *dev); */ __initfunc(int w83977af_init(void)) { - int i; + int i; - DEBUG( 0, __FUNCTION__ "()\n"); + DEBUG(0, __FUNCTION__ "()\n"); prev.status = 0; - for ( i=0; (io[i] < 2000) && (i < 4); i++) { + for (i=0; (io[i] < 2000) && (i < 4); i++) { int ioaddr = io[i]; if (check_region(ioaddr, CHIP_IO_EXTENT) < 0) continue; @@ -135,11 +136,11 @@ void w83977af_cleanup(void) { int i; - DEBUG( 4, __FUNCTION__ "()\n"); + DEBUG(4, __FUNCTION__ "()\n"); - for ( i=0; i < 4; i++) { - if ( dev_self[i]) - w83977af_close( dev_self[i]); + for (i=0; i < 4; i++) { + if (dev_self[i]) + w83977af_close(&(dev_self[i]->idev)); } } #endif /* MODULE */ @@ -154,26 +155,29 @@ int w83977af_open( int i, unsigned int iobase, unsigned int irq, unsigned int dma) { struct irda_device *idev; + struct w83977af_ir *self; int ret; DEBUG( 0, __FUNCTION__ "()\n"); - if ( w83977af_probe( iobase, irq, dma) == -1) + if (w83977af_probe(iobase, irq, dma) == -1) return -1; /* * Allocate new instance of the driver */ - idev = kmalloc( sizeof(struct irda_device), GFP_KERNEL); - if ( idev == NULL) { + self = kmalloc(sizeof(struct w83977af_ir), GFP_KERNEL); + if (self == NULL) { printk( KERN_ERR "IrDA: Can't allocate memory for " "IrDA control block!\n"); return -ENOMEM; } - memset( idev, 0, sizeof(struct irda_device)); + memset(self, 0, sizeof(struct w83977af_ir)); /* Need to store self somewhere */ - dev_self[i] = idev; + dev_self[i] = self; + + idev = &self->idev; /* Initialize IO */ idev->io.iobase = iobase; @@ -183,17 +187,17 @@ int w83977af_open( int i, unsigned int iobase, unsigned int irq, idev->io.fifo_size = 32; /* Lock the port that we need */ - ret = check_region( idev->io.iobase, idev->io.io_ext); - if ( ret < 0) { + ret = check_region(idev->io.iobase, idev->io.io_ext); + if (ret < 0) { DEBUG( 0, __FUNCTION__ "(), can't get iobase of 0x%03x\n", idev->io.iobase); /* w83977af_cleanup( self->idev); */ return -ENODEV; } - request_region( idev->io.iobase, idev->io.io_ext, idev->name); + request_region(idev->io.iobase, idev->io.io_ext, idev->name); /* Initialize QoS for this device */ - irda_init_max_qos_capabilies( &idev->qos); + irda_init_max_qos_capabilies(&idev->qos); /* The only value we must override it the baudrate */ @@ -202,8 +206,8 @@ int w83977af_open( int i, unsigned int iobase, unsigned int irq, IR_115200|IR_576000|IR_1152000|(IR_4000000 << 8); /* 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->qos.min_turn_time.bits = qos_mtt_bits; + irda_qos_bits_to_value(&idev->qos); idev->flags = IFF_FIR|IFF_MIR|IFF_SIR|IFF_DMA|IFF_PIO; @@ -221,13 +225,13 @@ int w83977af_open( int i, unsigned int iobase, unsigned int irq, idev->is_receiving = w83977af_is_receiving; /* Override the network functions we need to use */ - idev->netdev.init = w83977af_net_init; + idev->netdev.init = w83977af_net_init; idev->netdev.hard_start_xmit = w83977af_hard_xmit; - idev->netdev.open = w83977af_net_open; - idev->netdev.stop = w83977af_net_close; + idev->netdev.open = w83977af_net_open; + idev->netdev.stop = w83977af_net_close; /* Open the IrDA device */ - irda_device_open( idev, driver_name, NULL); + irda_device_open(idev, driver_name, self); return 0; } @@ -240,15 +244,18 @@ int w83977af_open( int i, unsigned int iobase, unsigned int irq, */ static int w83977af_close( struct irda_device *idev) { + struct w83977af_ir *self; int iobase; - DEBUG( 0, __FUNCTION__ "()\n"); + DEBUG(0, __FUNCTION__ "()\n"); - ASSERT( idev != NULL, return -1;); - ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return -1;); + ASSERT(idev != NULL, return -1;); + ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;); iobase = idev->io.iobase; + self = (struct w83977af_ir *) idev->priv; +#ifdef CONFIG_USE_W977_PNP /* enter PnP configuration mode */ w977_efm_enter(); @@ -258,13 +265,15 @@ static int w83977af_close( struct irda_device *idev) w977_write_reg(0x30, 0x00); w977_efm_exit(); - +#endif /* CONFIG_USE_W977_PNP */ /* Release the PORT that this driver is using */ DEBUG(0 , __FUNCTION__ "(), Releasing Region %03x\n", idev->io.iobase); - release_region( idev->io.iobase, idev->io.io_ext); + release_region(idev->io.iobase, idev->io.io_ext); + + irda_device_close(idev); - irda_device_close( idev); + kfree(self); return 0; } @@ -280,7 +289,7 @@ int w83977af_probe( int iobase, int irq, int dma) int version; DEBUG( 0, __FUNCTION__ "()\n"); - +#ifdef CONFIG_USE_W977_PNP /* Enter PnP configuration mode */ w977_efm_enter(); @@ -289,14 +298,14 @@ int w83977af_probe( int iobase, int irq, int dma) /* Configure PnP port, IRQ, and DMA channel */ w977_write_reg(0x60, (iobase >> 8) & 0xff); w977_write_reg(0x61, (iobase) & 0xff); - /* w977_write_reg(0x70, 0x06); */ + w977_write_reg(0x70, irq); -#ifdef NETWINDER - w977_write_reg(0x74, dma+1); /* Netwinder uses one higher than Linux */ +#ifdef CONFIG_NETWINDER + w977_write_reg(0x74, dma+1); /* Netwinder uses 1 higher than Linux */ #else w977_write_reg(0x74, dma); #endif - w977_write_reg(0x75, dma); /* Disable Tx DMA */ + w977_write_reg(0x75, 0x04); /* Disable Tx DMA */ /* Set append hardware CRC, enable IR bank selection */ w977_write_reg(0xf0, APEDCRC|ENBNKSEL); @@ -305,26 +314,26 @@ int w83977af_probe( int iobase, int irq, int dma) w977_write_reg(0x30, 0x01); w977_efm_exit(); - +#endif /* Disable Advanced mode */ - switch_bank( iobase, SET2); + switch_bank(iobase, SET2); outb(iobase+2, 0x00); /* Turn on UART (global) interrupts */ - switch_bank( iobase, SET0); - outb( HCR_EN_IRQ, iobase+HCR); + switch_bank(iobase, SET0); + outb(HCR_EN_IRQ, iobase+HCR); /* Switch to advanced mode */ - switch_bank( iobase, SET2); - outb( inb( iobase+ADCR1) | ADCR1_ADV_SL, iobase+ADCR1); + switch_bank(iobase, SET2); + outb(inb(iobase+ADCR1) | ADCR1_ADV_SL, iobase+ADCR1); /* Set default IR-mode */ - switch_bank( iobase, SET0); - outb( HCR_SIR, iobase+HCR); + switch_bank(iobase, SET0); + outb(HCR_SIR, iobase+HCR); /* Read the Advanced IR ID */ switch_bank(iobase, SET3); - version = inb( iobase+AUID); + version = inb(iobase+AUID); /* Should be 0x1? */ if (0x10 != (version & 0xf0)) { @@ -333,18 +342,17 @@ int w83977af_probe( int iobase, int irq, int dma) } /* Set FIFO size to 32 */ - switch_bank( iobase, SET2); - outb( ADCR2_RXFS32|ADCR2_TXFS32, iobase+ADCR2); + switch_bank(iobase, SET2); + outb(ADCR2_RXFS32|ADCR2_TXFS32, iobase+ADCR2); /* Set FIFO threshold to TX17, RX16 */ switch_bank(iobase, SET0); outb(UFR_RXTL|UFR_TXTL|UFR_TXF_RST|UFR_RXF_RST|UFR_EN_FIFO,iobase+UFR); -/* outb( 0xa7, iobase+UFR); */ /* Receiver frame length */ - switch_bank( iobase, SET4); - outb( 2048 & 0xff, iobase+6); - outb(( 2048 >> 8) & 0x1f, iobase+7); + switch_bank(iobase, SET4); + outb(2048 & 0xff, iobase+6); + outb((2048 >> 8) & 0x1f, iobase+7); /* * Init HP HSDL-1100 transceiver. @@ -358,8 +366,8 @@ int w83977af_probe( int iobase, int irq, int dma) * FIRRX pin 39 connected to receiver (IRSL0) * CIRRX pin 40 connected to pin 37 */ - switch_bank( iobase, SET7); - outb( 0x40, iobase+7); + switch_bank(iobase, SET7); + outb(0x40, iobase+7); DEBUG(0, "W83977AF (IR) driver loaded. Version: 0x%02x\n", version); @@ -372,16 +380,14 @@ int w83977af_probe( int iobase, int irq, int dma) * Change the speed of the device * */ -void w83977af_change_speed( struct irda_device *idev, int speed) +void w83977af_change_speed(struct irda_device *idev, int speed) { int ir_mode = HCR_SIR; int iobase; __u8 set; - DEBUG( 0, __FUNCTION__ "()\n"); - - ASSERT( idev != NULL, return;); - ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;); + ASSERT(idev != NULL, return;); + ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); iobase = idev->io.iobase; @@ -389,22 +395,22 @@ void w83977af_change_speed( struct irda_device *idev, int speed) idev->io.baudrate = speed; /* Save current bank */ - set = inb( iobase+SSR); + set = inb(iobase+SSR); /* Disable interrupts */ - switch_bank( iobase, SET0); - outb( 0, iobase+ICR); + switch_bank(iobase, SET0); + outb(0, iobase+ICR); /* Select Set 2 */ - switch_bank( iobase, SET2); - - outb( 0x00, iobase+ABHL); - switch ( speed) { - case 9600: outb( 0x0c, iobase+ABLL); break; - case 19200: outb( 0x06, iobase+ABLL); break; - case 37600: outb( 0x03, iobase+ABLL); break; - case 57600: outb( 0x02, iobase+ABLL); break; - case 115200: outb( 0x01, iobase+ABLL); break; + switch_bank(iobase, SET2); + outb(0x00, iobase+ABHL); + + switch (speed) { + case 9600: outb(0x0c, iobase+ABLL); break; + case 19200: outb(0x06, iobase+ABLL); break; + case 37600: outb(0x03, iobase+ABLL); break; + case 57600: outb(0x02, iobase+ABLL); break; + case 115200: outb(0x01, iobase+ABLL); break; case 576000: ir_mode = HCR_MIR_576; DEBUG(0, __FUNCTION__ "(), handling baud of 576000\n"); @@ -419,34 +425,37 @@ void w83977af_change_speed( struct irda_device *idev, int speed) break; default: ir_mode = HCR_FIR; - DEBUG( 0, __FUNCTION__ "(), unknown baud rate of %d\n", speed); + DEBUG(0, __FUNCTION__ "(), unknown baud rate of %d\n", speed); break; } /* Set speed mode */ switch_bank(iobase, SET0); - outb( ir_mode, iobase+HCR); + outb(ir_mode, iobase+HCR); /* set FIFO size to 32 */ - switch_bank( iobase, SET2); - outb( ADCR2_RXFS32|ADCR2_TXFS32, iobase+ADCR2); + switch_bank(iobase, SET2); + outb(ADCR2_RXFS32|ADCR2_TXFS32, iobase+ADCR2); /* set FIFO threshold to TX17, RX16 */ switch_bank(iobase, SET0); - outb(UFR_RXTL|UFR_TXTL|UFR_TXF_RST|UFR_RXF_RST|UFR_EN_FIFO, iobase+UFR); - + + outb(0x00, iobase+UFR); /* Reset */ + outb(UFR_EN_FIFO, iobase+UFR); /* First we must enable FIFO */ + outb(0xa7, iobase+UFR); + idev->netdev.tbusy = 0; /* Enable some interrupts so we can receive frames */ switch_bank(iobase, SET0); - if ( speed > 115200) { - outb( ICR_EFSFI, iobase+ICR); - w83977af_dma_receive( idev); + if (speed > PIO_MAX_SPEED) { + outb(ICR_EFSFI, iobase+ICR); + w83977af_dma_receive(idev); } else - outb( ICR_ERBRI, iobase+ICR); + outb(ICR_ERBRI, iobase+ICR); /* Restore SSR */ - outb( set, iobase+SSR); + outb(set, iobase+SSR); } /* @@ -455,7 +464,7 @@ void w83977af_change_speed( struct irda_device *idev, int speed) * Sets up a DMA transfer to send the current frame. * */ -int w83977af_hard_xmit( struct sk_buff *skb, struct device *dev) +int w83977af_hard_xmit(struct sk_buff *skb, struct device *dev) { struct irda_device *idev; int iobase; @@ -474,20 +483,21 @@ int w83977af_hard_xmit( struct sk_buff *skb, struct device *dev) /* Lock transmit buffer */ if (irda_lock((void *) &dev->tbusy) == FALSE) return -EBUSY; - + /* Save current set */ set = inb(iobase+SSR); /* Decide if we should use PIO or DMA transfer */ - if (idev->io.baudrate > 115200) { + if (idev->io.baudrate > PIO_MAX_SPEED) { + idev->tx_buff.data = idev->tx_buff.head; memcpy(idev->tx_buff.data, skb->data, skb->len); idev->tx_buff.len = skb->len; - idev->tx_buff.data = idev->tx_buff.head; mtt = irda_get_mtt(skb); +#ifdef CONFIG_USE_INTERNAL_TIMER if (mtt > 50) { /* Adjust for timer resolution */ - mtt = mtt / 1000 + 1; + mtt /= 1000+1; /* Setup timer */ switch_bank(iobase, SET4); @@ -502,6 +512,8 @@ int w83977af_hard_xmit( struct sk_buff *skb, struct device *dev) switch_bank(iobase, SET0); outb(ICR_ETMRI, iobase+ICR); } else { +#endif + DEBUG(4,__FUNCTION__ "(%ld), mtt=%d\n", jiffies, mtt); if (mtt) udelay(mtt); @@ -509,7 +521,9 @@ int w83977af_hard_xmit( struct sk_buff *skb, struct device *dev) switch_bank(iobase, SET0); outb(ICR_EDMAI, iobase+ICR); w83977af_dma_write(idev, iobase); +#ifdef CONFIG_USE_INTERNAL_TIMER } +#endif } else { idev->tx_buff.data = idev->tx_buff.head; idev->tx_buff.len = async_wrap_skb(skb, idev->tx_buff.data, @@ -527,41 +541,57 @@ int w83977af_hard_xmit( struct sk_buff *skb, struct device *dev) return 0; } - /* * Function w83977af_dma_write (idev, iobase) * - * + * Send frame using DMA * */ -static void w83977af_dma_write( struct irda_device *idev, int iobase) +static void w83977af_dma_write(struct irda_device *idev, int iobase) { __u8 set; - - DEBUG( 4, __FUNCTION__ "()\n"); +#ifdef CONFIG_NETWINDER_TX_DMA_PROBLEMS + unsigned long flags; + __u8 hcr; +#endif + DEBUG(4, __FUNCTION__ "(), len=%d\n", idev->tx_buff.len); /* Save current set */ - set = inb( iobase+SSR); + set = inb(iobase+SSR); /* Disable DMA */ switch_bank(iobase, SET0); - outb( inb( iobase+HCR) & ~HCR_EN_DMA, iobase+HCR); - - setup_dma(idev->io.dma, idev->tx_buff.data, idev->tx_buff.len, - DMA_MODE_WRITE); - - /* idev->media_busy = TRUE; */ - idev->io.direction = IO_XMIT; - + outb(inb(iobase+HCR) & ~HCR_EN_DMA, iobase+HCR); + /* Choose transmit DMA channel */ switch_bank(iobase, SET2); - outb(inb(iobase+ADCR1) | ADCR1_D_CHSW|ADCR1_DMA_F|ADCR1_ADV_SL, - iobase+ADCR1); + outb(ADCR1_D_CHSW|/*ADCR1_DMA_F|*/ADCR1_ADV_SL, iobase+ADCR1); +#ifdef CONFIG_NETWINDER_TX_DMA_PROBLEMS + save_flags(flags); + cli(); + + disable_dma(idev->io.dma); + clear_dma_ff(idev->io.dma); + set_dma_mode(idev->io.dma, DMA_MODE_READ); + set_dma_addr(idev->io.dma, virt_to_bus(idev->tx_buff.data)); + set_dma_count(idev->io.dma, idev->tx_buff.len); +#else + setup_dma(idev->io.dma, idev->tx_buff.data, idev->tx_buff.len, + DMA_MODE_WRITE); +#endif + idev->io.direction = IO_XMIT; /* Enable DMA */ switch_bank(iobase, SET0); - outb(inb(iobase+HCR) | HCR_EN_DMA, iobase+HCR); - +#ifdef CONFIG_NETWINDER_TX_DMA_PROBLEMS + hcr = inb(iobase+HCR); + outb(hcr | HCR_EN_DMA, iobase+HCR); + enable_dma(idev->io.dma); + restore_flags(flags); +#else + outb(inb(iobase+HCR) | HCR_EN_DMA | HCR_TX_WT, iobase+HCR); +#endif + /* Restore set register */ outb(set, iobase+SSR); } @@ -577,17 +607,17 @@ static int w83977af_pio_write(int iobase, __u8 *buf, int len, int fifo_size) int actual = 0; __u8 set; - DEBUG( 4, __FUNCTION__ "()\n"); + DEBUG(4, __FUNCTION__ "()\n"); /* Save current bank */ - set = inb( iobase+SSR); + set = inb(iobase+SSR); - switch_bank( iobase, SET0); + switch_bank(iobase, SET0); if (!(inb_p(iobase+USR) & USR_TSRE)) { - DEBUG( 4, __FUNCTION__ "(), warning, FIFO not empty yet!\n"); + DEBUG(4, __FUNCTION__ "(), warning, FIFO not empty yet!\n"); fifo_size -= 17; - DEBUG( 4, __FUNCTION__ "%d bytes left in tx fifo\n", fifo_size); + DEBUG(4, __FUNCTION__ "%d bytes left in tx fifo\n", fifo_size); } /* Fill FIFO with current frame */ @@ -597,7 +627,7 @@ static int w83977af_pio_write(int iobase, __u8 *buf, int len, int fifo_size) } DEBUG(4, __FUNCTION__ "(), fifo_size %d ; %d sent of %d\n", - fifo_size, actual, len); + fifo_size, actual, len); /* Restore bank */ outb(set, iobase+SSR); @@ -617,7 +647,7 @@ void w83977af_dma_xmit_complete(struct irda_device *idev) int iobase; __u8 set; - DEBUG(4, __FUNCTION__ "()\n"); + DEBUG(4, __FUNCTION__ "(%ld)\n", jiffies); ASSERT(idev != NULL, return;); ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); @@ -663,9 +693,10 @@ void w83977af_dma_xmit_complete(struct irda_device *idev) */ int w83977af_dma_receive(struct irda_device *idev) { + struct w83977af_ir *self; int iobase; __u8 set; -#ifdef NETWINDER +#ifdef CONFIG_NETWINDER_RX_DMA_PROBLEMS unsigned long flags; __u8 hcr; #endif @@ -673,62 +704,60 @@ int w83977af_dma_receive(struct irda_device *idev) ASSERT(idev != NULL, return -1;); ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;); - DEBUG(0, __FUNCTION__ "\n"); + DEBUG(4, __FUNCTION__ "\n"); + self = idev->priv; iobase= idev->io.iobase; /* Save current set */ - set = inb( iobase+SSR); + set = inb(iobase+SSR); /* Disable DMA */ - switch_bank( iobase, SET0); - outb( inb( iobase+HCR) & ~HCR_EN_DMA, iobase+HCR); + switch_bank(iobase, SET0); + outb(inb(iobase+HCR) & ~HCR_EN_DMA, iobase+HCR); -#ifdef NETWINDER + /* Choose DMA Rx, DMA Fairness, and Advanced mode */ + switch_bank(iobase, SET2); + outb((inb(iobase+ADCR1) & ~ADCR1_D_CHSW)/*|ADCR1_DMA_F*/|ADCR1_ADV_SL, + iobase+ADCR1); + + idev->io.direction = IO_RECV; + idev->rx_buff.data = idev->rx_buff.head; + +#ifdef CONFIG_NETWINDER_RX_DMA_PROBLEMS save_flags(flags); cli(); - disable_dma( idev->io.dma); - clear_dma_ff( idev->io.dma); - set_dma_mode( idev->io.dma, DMA_MODE_READ); - set_dma_addr( idev->io.dma, virt_to_bus(idev->rx_buff.data)); - set_dma_count( idev->io.dma, idev->rx_buff.truesize); + disable_dma(idev->io.dma); + clear_dma_ff(idev->io.dma); + set_dma_mode(idev->io.dma, DMA_MODE_READ); + set_dma_addr(idev->io.dma, virt_to_bus(idev->rx_buff.data)); + set_dma_count(idev->io.dma, idev->rx_buff.truesize); #else - setup_dma(idev->io.dma, idev->rx_buff.data, - idev->rx_buff.truesize, DMA_MODE_READ); + setup_dma(idev->io.dma, idev->rx_buff.data, idev->rx_buff.truesize, + DMA_MODE_READ); #endif - /* driver->media_busy = FALSE; */ - idev->io.direction = IO_RECV; - idev->rx_buff.data = idev->rx_buff.head; - /* * Reset Rx FIFO. This will also flush the ST_FIFO, it's very * important that we don't reset the Tx FIFO since it might not * be finished transmitting yet */ - outb( UFR_RXTL|UFR_TXTL|UFR_RXF_RST|UFR_EN_FIFO, iobase+UFR); - prev.status = 0; - - /* Choose DMA Rx, DMA Fairness, and Advanced mode */ - switch_bank(iobase, SET2); - outb(( inb( iobase+ADCR1) & ~ADCR1_D_CHSW)|ADCR1_DMA_F|ADCR1_ADV_SL, - iobase+ADCR1); + switch_bank(iobase, SET0); + outb(UFR_RXTL|UFR_TXTL|UFR_RXF_RST|UFR_EN_FIFO, iobase+UFR); + self->st_fifo.len = self->st_fifo.tail = self->st_fifo.head = 0; /* Enable DMA */ switch_bank(iobase, SET0); -#ifdef NETWINDER - hcr = inb( iobase+HCR); - enable_dma( idev->io.dma); - outb( hcr | HCR_EN_DMA, iobase+HCR); +#ifdef CONFIG_NETWINDER_RX_DMA_PROBLEMS + hcr = inb(iobase+HCR); + outb(hcr | HCR_EN_DMA, iobase+HCR); + enable_dma(idev->io.dma); restore_flags(flags); #else - outb( inb( iobase+HCR) | HCR_EN_DMA, iobase+HCR); + outb(inb(iobase+HCR) | HCR_EN_DMA, iobase+HCR); #endif - /* Restore set */ - outb( set, iobase+SSR); - - DEBUG( 4, __FUNCTION__ "(), done!\n"); + outb(set, iobase+SSR); return 0; } @@ -742,12 +771,17 @@ int w83977af_dma_receive(struct irda_device *idev) int w83977af_dma_receive_complete(struct irda_device *idev) { struct sk_buff *skb; + struct w83977af_ir *self; + struct st_fifo *st_fifo; int len; int iobase; __u8 set; __u8 status; - DEBUG(0, __FUNCTION__ "\n"); + DEBUG(4, __FUNCTION__ "\n"); + + self = idev->priv; + st_fifo = &self->st_fifo; iobase = idev->io.iobase; @@ -756,22 +790,28 @@ int w83977af_dma_receive_complete(struct irda_device *idev) iobase = idev->io.iobase; + /* Read status FIFO */ switch_bank(iobase, SET5); - if (prev.status & FS_FO_FSFDR) { - status = prev.status; - len = prev.len; + while ((status = inb(iobase+FS_FO)) & FS_FO_FSFDR) { + st_fifo->entries[st_fifo->tail].status = status; - prev.status = 0; - } else { - status = inb(iobase+FS_FO); - len = inb(iobase+RFLFL); - len |= inb(iobase+RFLFH) << 8; + st_fifo->entries[st_fifo->tail].len = inb(iobase+RFLFL); + st_fifo->entries[st_fifo->tail].len |= inb(iobase+RFLFH) << 8; + + st_fifo->tail++; + st_fifo->len++; } + + while (st_fifo->len) { + /* Get first entry */ + status = st_fifo->entries[st_fifo->head].status; + len = st_fifo->entries[st_fifo->head].len; + st_fifo->head++; + st_fifo->len--; - while (status & FS_FO_FSFDR) { /* Check for errors */ if (status & FS_FO_ERR_MSK) { - if ( status & FS_FO_LST_FR) { + if (status & FS_FO_LST_FR) { /* Add number of lost frames to stats */ idev->stats.rx_errors += len; } else { @@ -800,14 +840,20 @@ int w83977af_dma_receive_complete(struct irda_device *idev) /* Check if we have transfered all data to memory */ switch_bank(iobase, SET0); if (inb(iobase+USR) & USR_RDR) { +#ifdef CONFIG_USE_INTERNAL_TIMER /* Put this entry back in fifo */ - prev.status = status; - prev.len = len; - + st_fifo->head--; + st_fifo->len++; + st_fifo->entries[st_fifo->head].status = status; + st_fifo->entries[st_fifo->head].len = len; + /* Restore set register */ - outb( set, iobase+SSR); + outb(set, iobase+SSR); return FALSE; /* I'll be back! */ +#else + udelay(80); /* Should be enough!? */ +#endif } skb = dev_alloc_skb(len+1); @@ -824,28 +870,23 @@ int w83977af_dma_receive_complete(struct irda_device *idev) skb_reserve(skb, 1); /* Copy frame without CRC */ - if ( idev->io.baudrate < 4000000) { - skb_put( skb, len-2); - memcpy( skb->data, idev->rx_buff.data, len-2); + if (idev->io.baudrate < 4000000) { + skb_put(skb, len-2); + memcpy(skb->data, idev->rx_buff.data, len-2); } else { - skb_put( skb, len-4); - memcpy( skb->data, idev->rx_buff.data, len-4); + skb_put(skb, len-4); + memcpy(skb->data, idev->rx_buff.data, len-4); } /* Move to next frame */ idev->rx_buff.data += len; + idev->stats.rx_packets++; skb->dev = &idev->netdev; skb->mac.raw = skb->data; skb->protocol = htons(ETH_P_IRDA); - netif_rx( skb); - idev->stats.rx_packets++; + netif_rx(skb); } - /* Read next entry in ST_FIFO */ - switch_bank(iobase, SET5); - status = inb( iobase+FS_FO); - len = inb( iobase+RFLFL); - len |= inb( iobase+RFLFH) << 8; } /* Restore set register */ outb(set, iobase+SSR); @@ -875,7 +916,6 @@ static void w83977af_pio_receive(struct irda_device *idev) do { byte = inb(iobase+RBR); async_unwrap_char(idev, byte); - } while (inb(iobase+USR) & USR_RDR); /* Data available */ } @@ -889,9 +929,12 @@ static __u8 w83977af_sir_interrupt(struct irda_device *idev, int isr) { int actual; __u8 new_icr = 0; + __u8 set; + int iobase; DEBUG(4, __FUNCTION__ "(), isr=%#x\n", isr); + iobase = idev->io.iobase; /* Transmit FIFO low on data */ if (isr & ISR_TXTH_I) { /* Write data left in transmit buffer */ @@ -899,16 +942,21 @@ static __u8 w83977af_sir_interrupt(struct irda_device *idev, int isr) idev->tx_buff.data, idev->tx_buff.len, idev->io.fifo_size); + idev->tx_buff.data += actual; idev->tx_buff.len -= actual; idev->io.direction = IO_XMIT; /* Check if finished */ - if (idev->tx_buff.len > 0) + if (idev->tx_buff.len > 0) { new_icr |= ICR_ETXTHI; - else { - DEBUG( 4, __FUNCTION__ "(), finished with frame!\n"); + } else { + set = inb(iobase+SSR); + switch_bank(iobase, SET0); + outb(AUDR_SFEND, iobase+AUDR); + outb(set, iobase+SSR); + idev->netdev.tbusy = 0; /* Unlock */ idev->stats.tx_packets++; @@ -917,7 +965,6 @@ static __u8 w83977af_sir_interrupt(struct irda_device *idev, int isr) new_icr |= ICR_ETBREI; } - } /* Check if transmission has completed */ if (isr & ISR_TXEMP_I) { @@ -943,22 +990,20 @@ static __u8 w83977af_sir_interrupt(struct irda_device *idev, int isr) * Handle MIR/FIR interrupt * */ -static __u8 w83977af_fir_interrupt( struct irda_device *idev, int isr) +static __u8 w83977af_fir_interrupt(struct irda_device *idev, int isr) { __u8 new_icr = 0; __u8 set; int iobase; - DEBUG( 4, __FUNCTION__ "(), isr=%#x\n", isr); - iobase = idev->io.iobase; - set = inb(iobase+SSR); /* End of frame detected in FIFO */ if (isr & (ISR_FEND_I|ISR_FSF_I)) { if (w83977af_dma_receive_complete(idev)) { + /* Wait for next status FIFO interrupt */ new_icr |= ICR_EFSFI; } else { /* DMA not finished yet */ @@ -982,7 +1027,7 @@ static __u8 w83977af_fir_interrupt( struct irda_device *idev, int isr) /* Clear timer event */ /* switch_bank(iobase, SET0); */ -/* outb( ASCR_CTE, iobase+ASCR); */ +/* outb(ASCR_CTE, iobase+ASCR); */ /* Check if this is a TX timer interrupt */ if (idev->io.direction == IO_XMIT) { @@ -998,15 +1043,18 @@ static __u8 w83977af_fir_interrupt( struct irda_device *idev, int isr) } /* Finished with DMA */ if (isr & ISR_DMA_I) { - w83977af_dma_xmit_complete( idev); - + w83977af_dma_xmit_complete(idev); + /* Check if there are more frames to be transmitted */ - if (irda_device_txqueue_empty( idev)) { + /* if (irda_device_txqueue_empty(idev)) { */ - /* Prepare for receive */ - w83977af_dma_receive(idev); - new_icr = ICR_EFSFI; - } + /* Prepare for receive + * + * ** Netwinder Tx DMA likes that we do this anyway ** + */ + w83977af_dma_receive(idev); + new_icr = ICR_EFSFI; + /* } */ } /* Restore set */ @@ -1030,7 +1078,7 @@ static void w83977af_interrupt(int irq, void *dev_id, struct pt_regs *regs) if (idev == NULL) { printk(KERN_WARNING "%s: irq %d for unknown device.\n", - driver_name, irq); + driver_name, irq); return; } @@ -1049,7 +1097,7 @@ static void w83977af_interrupt(int irq, void *dev_id, struct pt_regs *regs) if (isr) { /* Dispatch interrupt handler for the current speed */ - if ( idev->io.baudrate > 115200) + if (idev->io.baudrate > PIO_MAX_SPEED ) icr = w83977af_fir_interrupt(idev, isr); else icr = w83977af_sir_interrupt(idev, isr); @@ -1070,7 +1118,7 @@ static void w83977af_interrupt(int irq, void *dev_id, struct pt_regs *regs) static void w83977af_wait_until_sent(struct irda_device *idev) { current->state = TASK_INTERRUPTIBLE; - schedule_timeout(6); + schedule_timeout(60*HZ/1000); } /* @@ -1085,16 +1133,16 @@ static int w83977af_is_receiving(struct irda_device *idev) int iobase; __u8 set; - ASSERT( idev != NULL, return FALSE;); - ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return FALSE;); + ASSERT(idev != NULL, return FALSE;); + ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return FALSE;); - if ( idev->io.baudrate > 115200) { + if (idev->io.baudrate > 115200) { iobase = idev->io.iobase; /* Check if rx FIFO is not empty */ set = inb(iobase+SSR); - switch_bank( iobase, SET2); - if (( inb( iobase+RXFDTH) & 0x3f) != 0) { + switch_bank(iobase, SET2); + if ((inb(iobase+RXFDTH) & 0x3f) != 0) { /* We are receiving something */ status = TRUE; } @@ -1111,12 +1159,12 @@ static int w83977af_is_receiving(struct irda_device *idev) * * */ -static int w83977af_net_init( struct device *dev) +static int w83977af_net_init(struct device *dev) { DEBUG(0, __FUNCTION__ "()\n"); /* Set up to be a normal IrDA network device driver */ - irda_device_setup( dev); + irda_device_setup(dev); /* Insert overrides below this line! */ @@ -1130,7 +1178,7 @@ static int w83977af_net_init( struct device *dev) * Start the device * */ -static int w83977af_net_open( struct device *dev) +static int w83977af_net_open(struct device *dev) { struct irda_device *idev; int iobase; @@ -1147,7 +1195,7 @@ static int w83977af_net_open( struct device *dev) iobase = idev->io.iobase; if (request_irq(idev->io.irq, w83977af_interrupt, 0, idev->name, - (void *) idev)) { + (void *) idev)) { return -EAGAIN; } /* @@ -1170,13 +1218,13 @@ static int w83977af_net_open( struct device *dev) /* Enable some interrupts so we can receive frames again */ switch_bank(iobase, SET0); if (idev->io.baudrate > 115200) { - outb( ICR_EFSFI, iobase+ICR); - w83977af_dma_receive( idev); + outb(ICR_EFSFI, iobase+ICR); + w83977af_dma_receive(idev); } else - outb( ICR_ERBRI, iobase+ICR); + outb(ICR_ERBRI, iobase+ICR); /* Restore bank register */ - outb( set, iobase+SSR); + outb(set, iobase+SSR); MOD_INC_USE_COUNT; @@ -1195,34 +1243,34 @@ static int w83977af_net_close(struct device *dev) int iobase; __u8 set; - DEBUG( 0, __FUNCTION__ "()\n"); + DEBUG(0, __FUNCTION__ "()\n"); /* Stop device */ dev->tbusy = 1; dev->start = 0; - ASSERT( dev != NULL, return -1;); + ASSERT(dev != NULL, return -1;); idev = (struct irda_device *) dev->priv; - ASSERT( idev != NULL, return 0;); - ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return 0;); + ASSERT(idev != NULL, return 0;); + ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return 0;); iobase = idev->io.iobase; - disable_dma( idev->io.dma); + disable_dma(idev->io.dma); /* Save current set */ - set = inb( iobase+SSR); + set = inb(iobase+SSR); /* Disable interrupts */ - switch_bank( iobase, SET0); - outb( 0, iobase+ICR); + switch_bank(iobase, SET0); + outb(0, iobase+ICR); - free_irq( idev->io.irq, idev); - free_dma( idev->io.dma); + free_irq(idev->io.irq, idev); + free_dma(idev->io.dma); /* Restore bank register */ - outb( set, iobase+SSR); + outb(set, iobase+SSR); MOD_DEC_USE_COUNT; @@ -1231,6 +1279,11 @@ static int w83977af_net_close(struct device *dev) #ifdef MODULE +MODULE_AUTHOR("Dag Brattli "); +MODULE_DESCRIPTION("Winbond W83977AF IrDA Device Driver"); + +MODULE_PARM(qos_mtt_bits, "i"); + /* * Function init_module (void) * diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c index 580fb2dcad9b..f618fd5fb08b 100644 --- a/drivers/net/sunhme.c +++ b/drivers/net/sunhme.c @@ -1834,7 +1834,7 @@ static inline void sun4c_happy_meal_tx(struct happy_meal *hp) #define RXD(x) #endif -/* Originally I use to handle the allocation failure by just giving back just +/* Originally I used to handle the allocation failure by just giving back just * that one ring buffer to the happy meal. Problem is that usually when that * condition is triggered, the happy meal expects you to do something reasonable * with all of the packets it has DMA'd in. So now I just drop the entire diff --git a/drivers/video/cgsixfb.c b/drivers/video/cgsixfb.c index a62fd12adc1d..e1a692e164e2 100644 --- a/drivers/video/cgsixfb.c +++ b/drivers/video/cgsixfb.c @@ -1,4 +1,4 @@ -/* $Id: cgsixfb.c,v 1.16 1999/03/09 14:01:49 davem Exp $ +/* $Id: cgsixfb.c,v 1.16.2.1 1999/05/25 00:59:35 davem Exp $ * cgsixfb.c: CGsix (GX,GXplus) frame buffer driver * * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz) @@ -588,7 +588,7 @@ static void cg6_margins (struct fb_info_sbusfb *fb, struct display *p, int x_mar p->screen_base += (y_margin - fb->y_margin) * p->line_length + (x_margin - fb->x_margin); } -static char idstring[60] __initdata = { 0 }; +static char idstring[70] __initdata = { 0 }; __initfunc(char *cgsixfb_init(struct fb_info_sbusfb *fb)) { @@ -599,6 +599,7 @@ __initfunc(char *cgsixfb_init(struct fb_info_sbusfb *fb)) unsigned long phys = fb->sbdp->reg_addrs[0].phys_addr; u32 conf; char *p; + char *cardtype; struct bt_regs *bt; strcpy(fb->info.modename, "CGsix"); @@ -656,15 +657,29 @@ __initfunc(char *cgsixfb_init(struct fb_info_sbusfb *fb)) case CG6_FHC_CPU_68020: p = "68020"; break; default: p = "i386"; break; } + + if (((conf >> CG6_FHC_REV_SHIFT) & CG6_FHC_REV_MASK) >= 11) { + if (fix->smem_len <= 0x100000) { + cardtype = "TurboGX"; + } else { + cardtype = "TurboGX+"; + } + } else { + if (fix->smem_len <= 0x100000) { + cardtype = "GX"; + } else { + cardtype = "GX+"; + } + } sprintf(idstring, #ifdef __sparc_v9__ - "cgsix at %016lx TEC Rev %x CPU %s Rev %x", phys, + "cgsix at %016lx TEC Rev %x CPU %s Rev %x [%s]", phys, #else - "cgsix at %x.%08lx TEC Rev %x CPU %s Rev %x", fb->iospace, phys, + "cgsix at %x.%08lx TEC Rev %x CPU %s Rev %x [%s]", fb->iospace, phys, #endif (fb->s.cg6.thc->thc_misc >> CG6_THC_MISC_REV_SHIFT) & CG6_THC_MISC_REV_MASK, - p, conf >> CG6_FHC_REV_SHIFT & CG6_FHC_REV_MASK); + p, conf >> CG6_FHC_REV_SHIFT & CG6_FHC_REV_MASK, cardtype); cg6_reset(fb); diff --git a/fs/ext2/file.c b/fs/ext2/file.c index 2e4d2812cf04..4e75eede0e70 100644 --- a/fs/ext2/file.c +++ b/fs/ext2/file.c @@ -162,7 +162,7 @@ static ssize_t ext2_file_write (struct file * filp, const char * buf, struct buffer_head * bh, *bufferlist[NBUF]; struct super_block * sb; int err; - int i,buffercount,write_error; + int i,buffercount,write_error, new_buffer; /* POSIX: mtime/ctime may not change for 0 count */ if (!count) @@ -247,30 +247,59 @@ static ssize_t ext2_file_write (struct file * filp, const char * buf, } if (c > count) c = count; - if (c != sb->s_blocksize && !buffer_uptodate(bh)) { - ll_rw_block (READ, 1, &bh); - wait_on_buffer (bh); - if (!buffer_uptodate(bh)) { - brelse (bh); + + /* Tricky: what happens if we are writing the complete + * contents of a block which is not currently + * initialised? We have to obey the same + * synchronisation rules as the IO code, to prevent some + * other process from stomping on the buffer contents by + * refreshing them from disk while we are setting up the + * buffer. The copy_from_user() can page fault, after + * all. We also have to throw away partially successful + * copy_from_users to such buffers, since we can't trust + * the rest of the buffer_head in that case. --sct */ + + new_buffer = (!buffer_uptodate(bh) && !buffer_locked(bh) && + c == sb->s_blocksize); + + if (new_buffer) { + set_bit(BH_Lock, &bh->b_state); + c -= copy_from_user (bh->b_data + offset, buf, c); + if (c != sb->s_blocksize) { + c = 0; + unlock_buffer(bh); + brelse(bh); if (!written) - written = -EIO; + written = -EFAULT; break; } + mark_buffer_uptodate(bh, 1); + unlock_buffer(bh); + } else { + if (!buffer_uptodate(bh)) { + ll_rw_block (READ, 1, &bh); + wait_on_buffer (bh); + if (!buffer_uptodate(bh)) { + brelse (bh); + if (!written) + written = -EIO; + break; + } + } + c -= copy_from_user (bh->b_data + offset, buf, c); } - c -= copy_from_user (bh->b_data + offset, buf, c); if (!c) { brelse(bh); if (!written) written = -EFAULT; break; } + mark_buffer_dirty(bh, 0); update_vm_cache(inode, pos, bh->b_data + offset, c); pos += c; written += c; buf += c; count -= c; - mark_buffer_uptodate(bh, 1); - mark_buffer_dirty(bh, 0); if (filp->f_flags & O_SYNC) bufferlist[buffercount++] = bh; diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c index f93de5ffbacf..cfdf49f6e2f5 100644 --- a/fs/smbfs/inode.c +++ b/fs/smbfs/inode.c @@ -601,8 +601,6 @@ init_module(void) smb_current_vmalloced = 0; #endif - read_semaphore = MUTEX; - return init_smb_fs(); } diff --git a/include/net/irda/crc.h b/include/net/irda/crc.h index d4ee011e4ef5..61a5a648864d 100644 --- a/include/net/irda/crc.h +++ b/include/net/irda/crc.h @@ -6,25 +6,28 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Mon Aug 4 20:40:53 1997 - * Modified at: Tue Dec 15 22:18:53 1998 + * Modified at: Sun May 2 20:25:23 1999 * Modified by: Dag Brattli * ********************************************************************/ -#ifndef IR_CRC_H -#define IR_CRC_H +#ifndef IRDA_CRC_H +#define IRDA_CRC_H #include #define INIT_FCS 0xffff /* Initial FCS value */ #define GOOD_FCS 0xf0b8 /* Good final FCS value */ +extern __u16 const irda_crc16_table[]; + /* Recompute the FCS with one more character appended. */ -#define IR_FCS(fcs, c) (((fcs) >> 8) ^ irda_crc16_table[((fcs) ^ (c)) & 0xff]) +static inline __u16 irda_fcs(__u16 fcs, __u8 c) +{ + return (((fcs) >> 8) ^ irda_crc16_table[((fcs) ^ (c)) & 0xff]); +} /* Recompute the FCS with len bytes appended. */ unsigned short crc_calc( __u16 fcs, __u8 const *buf, size_t len); -extern __u16 const irda_crc16_table[]; - #endif diff --git a/include/net/irda/dongle.h b/include/net/irda/dongle.h index d8983c009d2c..64496d67191e 100644 --- a/include/net/irda/dongle.h +++ b/include/net/irda/dongle.h @@ -6,10 +6,10 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Wed Oct 21 22:47:12 1998 - * Modified at: Sat Feb 6 07:37:49 1999 + * Modified at: Mon May 10 14:51:06 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli, All Rights Reserved. + * Copyright (c) 1998-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 @@ -26,7 +26,6 @@ #define DONGLE_H #include -#include /* These are the currently known dongles */ typedef enum { @@ -35,8 +34,11 @@ typedef enum { ACTISYS_DONGLE, ACTISYS_PLUS_DONGLE, GIRBIL_DONGLE, + LITELINK_DONGLE, } DONGLE_T; +struct irda_device; + struct dongle { DONGLE_T type; void (*open)(struct irda_device *, int type); diff --git a/include/net/irda/ircomm_common.h b/include/net/irda/ircomm_common.h index cd1c41f86818..2319017ccefc 100644 --- a/include/net/irda/ircomm_common.h +++ b/include/net/irda/ircomm_common.h @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Takahide Higuchi * - * Copyright (c) 1998, Takahide Higuchi, , + * Copyright (c) 1998-1999, Takahide Higuchi, , * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -78,7 +78,7 @@ typedef enum { #define IRCOMM_MAGIC 0x434f4d4d #define COMM_INIT_CTRL_PARAM 3 /* length of initial control parameters */ #define COMM_HEADER 1 /* length of clen field */ -#define COMM_HEADER_SIZE (LAP_HEADER+LMP_HEADER+TTP_HEADER+COMM_HEADER) +#define COMM_HEADER_SIZE (TTP_MAX_HEADER+COMM_HEADER) #define COMM_DEFAULT_DATA_SIZE 64 #define IRCOMM_MAX_CONNECTION 1 /* Don't change for now */ @@ -167,7 +167,7 @@ typedef enum { #define LSR_BI 0x01 /* Break interrupt indicator */ -struct ircomm_cb{ +struct ircomm_cb { int magic; int state; /* Current state of IrCOMM layer: * DISCOVERY,COMM_IDLE, COMM_WAITR, @@ -178,7 +178,8 @@ struct ircomm_cb{ int ttp_stop; int max_txbuff_size; - __u32 maxsdusize; + __u32 max_sdu_size; + __u8 max_header_size; __u32 daddr; /* Device address of the peer device */ __u32 saddr; @@ -211,8 +212,6 @@ struct ircomm_cb{ int pending_control_tuples; int ignored_control_tuples; - - __u8 pi ; /* instruction of control channel*/ __u8 port_type; @@ -253,8 +252,6 @@ struct ircomm_cb{ int port_name_critical; }; - - void ircomm_connect_request(struct ircomm_cb *self, __u8 servicetype); void ircomm_connect_response(struct ircomm_cb *self, struct sk_buff *userdata, __u32 maxsdusize); diff --git a/include/net/irda/irda.h b/include/net/irda/irda.h index 35c15fadc272..61f9352b2d2d 100644 --- a/include/net/irda/irda.h +++ b/include/net/irda/irda.h @@ -6,10 +6,10 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Tue Dec 9 21:13:12 1997 - * Modified at: Wed Apr 21 17:49:00 1999 + * Modified at: Mon May 10 09:51:13 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli, All Rights Reserved. + * Copyright (c) 1998-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 @@ -109,6 +109,8 @@ struct irda_sock { __u32 max_sdu_size_rx; __u32 max_sdu_size_tx; + __u32 max_data_size; + __u8 max_header_size; struct qos_info qos_tx; __u16 mask; /* Hint bits mask */ @@ -225,10 +227,10 @@ struct notify_t { int (*udata_indication)(void *priv, void *sap, struct sk_buff *skb); void (*connect_confirm)(void *instance, void *sap, struct qos_info *qos, __u32 max_sdu_size, - struct sk_buff *skb); + __u8 max_header_size, struct sk_buff *skb); void (*connect_indication)(void *instance, void *sap, struct qos_info *qos, __u32 max_sdu_size, - struct sk_buff *skb); + __u8 max_header_size, struct sk_buff *skb); void (*disconnect_indication)(void *instance, void *sap, LM_REASON reason, struct sk_buff *); void (*flow_indication)(void *instance, void *sap, LOCAL_FLOW flow); diff --git a/include/net/irda/irda_device.h b/include/net/irda/irda_device.h index a3dcf2d6e78f..21b12e4ff4e7 100644 --- a/include/net/irda/irda_device.h +++ b/include/net/irda/irda_device.h @@ -4,24 +4,29 @@ * Version: * Description: * Status: Experimental. - * Author: Haris Zukanovic + * Author: Dag Brattli * Created at: Tue Apr 14 12:41:42 1998 - * Modified at: Tue Apr 20 11:06:28 1999 + * Modified at: Mon May 10 15:46:02 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Haris Zukanovic, - * Copyright (c) 1998 Dag Brattli, + * Copyright (c) 1999 Dag Brattli, All Rights Reserved. * Copyright (c) 1998 Thomas Davis, , - * All Rights Reserved. - * + * Copyright (c) 1998 Haris Zukanovic, + * * 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 Haris Zukanovic nor University of Tromsø admit liability nor - * provide warranty for any of this software. This material is - * provided "AS-IS" and at no charge. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA * ********************************************************************/ @@ -35,6 +40,7 @@ #include #include +#include #include #include @@ -52,6 +58,11 @@ #define IO_XMIT 0x01 #define IO_RECV 0x02 +struct dongle_q { + QUEUE q; + struct dongle *dongle; +}; + /* Chip specific info */ struct chipio_t { int iobase, iobase2; /* IO base */ @@ -111,6 +122,8 @@ struct irda_device { struct iobuff_t tx_buff; struct iobuff_t rx_buff; + struct dongle *dongle; /* Dongle driver */ + /* spinlock_t lock; */ /* For serializing operations */ /* Media busy stuff */ @@ -120,7 +133,8 @@ struct irda_device { /* Callbacks for driver specific implementation */ void (*change_speed)(struct irda_device *driver, int baud); int (*is_receiving)(struct irda_device *); /* receiving? */ - /* int (*is_tbusy)(struct irda_device *); */ /* transmitting? */ + void (*set_dtr_rts)(struct irda_device *idev, int dtr, int rts); + int (*raw_write)(struct irda_device *idev, __u8 *buf, int len); void (*wait_until_sent)(struct irda_device *); void (*set_caddr)(struct irda_device *); /* Set connection addr */ }; @@ -142,6 +156,9 @@ inline void irda_device_change_speed(struct irda_device *, int); inline struct qos_info *irda_device_get_qos(struct irda_device *self); int irda_device_txqueue_empty(struct irda_device *self); +void irda_device_init_dongle(struct irda_device *self, int type); +void irda_device_unregister_dongle(struct dongle *dongle); +int irda_device_register_dongle(struct dongle *dongle); int irda_device_setup(struct device *dev); @@ -153,7 +170,7 @@ void setup_dma(int channel, char *buffer, int count, int mode); * Utility function for getting the minimum turnaround time out of * the skb, where it has been hidden in the cb field. */ -inline static __u16 irda_get_mtt(struct sk_buff *skb) +extern inline __u16 irda_get_mtt(struct sk_buff *skb) { __u16 mtt; @@ -167,6 +184,23 @@ inline static __u16 irda_get_mtt(struct sk_buff *skb) return mtt; } +extern inline void irda_device_set_dtr_rts(struct irda_device *self, int dtr, + int rts) +{ + if (self->set_dtr_rts) + self->set_dtr_rts(self, dtr, rts); +} + +extern inline int irda_device_raw_write(struct irda_device *self, __u8 *buf, + int len) +{ + int ret = -1; + + if (self->raw_write) + ret = self->raw_write(self, buf, len); + return ret; +} + #endif diff --git a/include/net/irda/iriap.h b/include/net/irda/iriap.h index 071ed8561b0c..355751afa057 100644 --- a/include/net/irda/iriap.h +++ b/include/net/irda/iriap.h @@ -6,10 +6,10 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Thu Aug 21 00:02:07 1997 - * Modified at: Wed Apr 21 16:37:21 1999 + * Modified at: Sun May 9 10:56:57 1999 * Modified by: Dag Brattli * - * Copyright (c) 1997 Dag Brattli , All Rights Reserved. + * Copyright (c) 1997, 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 @@ -81,6 +81,8 @@ struct iriap_cb { CONFIRM_CALLBACK confirm; void *priv; + __u8 max_header_size; + struct timer_list watchdog_timer; }; @@ -92,8 +94,6 @@ void iriap_getvaluebyclass_request( char *name, char *attr, void iriap_getvaluebyclass_confirm(struct iriap_cb *self, struct sk_buff *skb); void iriap_send_ack( struct iriap_cb *self); -void iriap_connect_confirm(void *instance, void *sap, struct qos_info *qos, - __u32 max_sdu_size, struct sk_buff *skb); void iriap_call_indication(struct iriap_cb *self, struct sk_buff *skb); void iriap_register_server(void); diff --git a/include/net/irda/irlan_common.h b/include/net/irda/irlan_common.h index 35d83096faf5..131e3f9235a0 100644 --- a/include/net/irda/irlan_common.h +++ b/include/net/irda/irlan_common.h @@ -6,10 +6,11 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sun Aug 31 20:14:37 1997 - * Modified at: Thu Apr 22 14:30:37 1999 + * Modified at: Sun May 9 11:45:33 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli , All Rights Reserved. + * Copyright (c) 1998-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 @@ -98,7 +99,7 @@ #define IRLAN_SHORT 1 #define IRLAN_ARRAY 2 -#define IRLAN_MAX_HEADER (TTP_HEADER+LMP_HEADER+LAP_HEADER) +#define IRLAN_MAX_HEADER (TTP_HEADER+LMP_HEADER+LAP_MAX_HEADER) /* * IrLAN client @@ -109,7 +110,10 @@ struct irlan_client_cb { int open_retries; struct tsap_cb *tsap_ctrl; + __u32 max_sdu_size; + __u8 max_header_size; + int access_type; /* Access type of provider */ __u8 reconnect_key[255]; __u8 key_len; @@ -130,6 +134,8 @@ struct irlan_provider_cb { int state; struct tsap_cb *tsap_ctrl; + __u32 max_sdu_size; + __u8 max_header_size; /* * Store some values here which are used by the provider to parse @@ -140,42 +146,45 @@ struct irlan_provider_cb { int filter_mode; int filter_operation; int filter_entry; - + int access_type; /* Access type */ __u16 send_arb_val; __u8 mac_address[6]; /* Generated MAC address for peer device */ }; /* - * IrLAN + * IrLAN control block */ struct irlan_cb { QUEUE queue; /* Must be first */ int magic; char ifname[9]; - struct device dev; /* Ethernet device structure*/ + struct device dev; /* Ethernet device structure*/ struct enet_statistics stats; - __u32 saddr; /* Source devcie address */ - __u32 daddr; /* Destination device address */ + __u32 saddr; /* Source devcie address */ + __u32 daddr; /* Destination device address */ int netdev_registered; int notify_irmanager; - int media; /* Media type */ - int access_type; /* Currently used access type */ - __u8 version[2]; /* IrLAN version */ + int media; /* Media type */ + __u8 version[2]; /* IrLAN version */ struct tsap_cb *tsap_data; - int use_udata; /* Use Unit Data transfers */ + int master; /* Master instance? */ + int use_udata; /* Use Unit Data transfers */ - __u8 stsap_sel_data; /* Source data TSAP selector */ - __u8 dtsap_sel_data; /* Destination data TSAP selector */ - __u8 dtsap_sel_ctrl; /* Destination ctrl 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 */ - struct irlan_client_cb client; /* Client specific fields */ + struct irlan_client_cb client; /* Client specific fields */ struct irlan_provider_cb provider; /* Provider specific fields */ + + __u32 max_sdu_size; + __u8 max_header_size; struct timer_list watchdog_timer; }; diff --git a/include/net/irda/irlan_provider.h b/include/net/irda/irlan_provider.h index aafbf9141245..ca51d5b7c999 100644 --- a/include/net/irda/irlan_provider.h +++ b/include/net/irda/irlan_provider.h @@ -6,10 +6,10 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sun Aug 31 20:14:37 1997 - * Modified at: Thu Apr 22 14:29:16 1999 + * Modified at: Sun May 9 12:26:11 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli , All Rights Reserved. + * Copyright (c) 1998-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 @@ -36,13 +36,7 @@ void irlan_provider_ctrl_disconnect_indication(void *instance, void *sap, LM_REASON reason, struct sk_buff *skb); -void irlan_provider_ctrl_data_indication(void *instance, void *sap, - struct sk_buff *skb); -void irlan_provider_connect_indication(void *instance, void *sap, - struct qos_info *qos, - __u32 max_sdu_size, - struct sk_buff *skb); void irlan_provider_connect_response(struct irlan_cb *, struct tsap_cb *); int irlan_parse_open_data_cmd(struct irlan_cb *self, struct sk_buff *skb); diff --git a/include/net/irda/irlap.h b/include/net/irda/irlap.h index f3b26110f646..c5767397ea8c 100644 --- a/include/net/irda/irlap.h +++ b/include/net/irda/irlap.h @@ -6,10 +6,10 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Mon Aug 4 20:40:53 1997 - * Modified at: Fri Apr 23 09:51:15 1999 + * Modified at: Sun May 9 11:38:18 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli , All Rights Reserved. + * Copyright (c) 1998-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 @@ -42,11 +42,11 @@ #define LAP_COMP_HEADER 1 /* IrLAP Compression Header */ #ifdef CONFIG_IRDA_COMPRESSION -# define LAP_HEADER (LAP_ADDR_HEADER + LAP_CTRL_HEADER + LAP_COMP_HEADER) +# define LAP_MAX_HEADER (LAP_ADDR_HEADER + LAP_CTRL_HEADER + LAP_COMP_HEADER) # define IRDA_COMPRESSED 1 # define IRDA_NORMAL 0 #else -#define LAP_HEADER (LAP_ADDR_HEADER + LAP_CTRL_HEADER) +#define LAP_MAX_HEADER (LAP_ADDR_HEADER + LAP_CTRL_HEADER) #endif #define BROADCAST 0xffffffff /* Broadcast device address */ @@ -138,7 +138,7 @@ struct irlap_cb { __u8 vs; /* Next frame to be sent */ __u8 vr; /* Next frame to be received */ - int tmp; +/* int tmp; */ __u8 va; /* Last frame acked */ int window; /* Nr of I-frames allowed to send */ int window_size; /* Current negotiated window size */ @@ -155,8 +155,7 @@ struct irlap_cb { __u8 s; /* Current slot */ int frame_sent; /* Have we sent reply? */ - int discovery_count; - hashbin_t *discovery_log; + hashbin_t *discovery_log; discovery_t *discovery_cmd; struct qos_info qos_tx; /* QoS requested by peer */ @@ -227,4 +226,9 @@ void irlap_init_qos_capabilities(struct irlap_cb *, struct qos_info *); void irlap_apply_default_connection_parameters(struct irlap_cb *self); void irlap_apply_connection_parameters(struct irlap_cb *, struct qos_info *); +extern inline __u8 irlap_get_header_size(struct irlap_cb *self) +{ + return 2; +} + #endif diff --git a/include/net/irda/irlmp.h b/include/net/irda/irlmp.h index 31785883a584..e879c6b9413c 100644 --- a/include/net/irda/irlmp.h +++ b/include/net/irda/irlmp.h @@ -6,10 +6,10 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sun Aug 17 20:54:32 1997 - * Modified at: Fri Apr 23 09:15:07 1999 + * Modified at: Sun May 9 11:01:34 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli , All Rights Reserved. + * Copyright (c) 1998-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 @@ -52,7 +52,7 @@ #define LMP_HEADER 2 /* Dest LSAP + Source LSAP */ #define LMP_CONTROL_HEADER 4 -#define LMP_MAX_HEADER (LAP_HEADER+LMP_HEADER) +#define LMP_MAX_HEADER (LMP_CONTROL_HEADER+LAP_MAX_HEADER) #define LM_MAX_CONNECTIONS 10 diff --git a/include/net/irda/irlpt_common.h b/include/net/irda/irlpt_common.h index 83a9c307cc8f..688466b5f2cf 100644 --- a/include/net/irda/irlpt_common.h +++ b/include/net/irda/irlpt_common.h @@ -158,7 +158,8 @@ struct irlpt_cb { struct miscdevice ir_dev; /* used to register the misc device. */ int count; /* open count */ - int irlap_data_size; /* max frame size we can send */ + int max_data_size; /* max frame size we can send */ + int max_header_size; /* how much header space is needed */ int pkt_count; /* how many packets are queued up */ struct wait_queue *read_wait; /* wait queues */ diff --git a/include/net/irda/irport.h b/include/net/irda/irport.h index c4a036a4d91f..81981273b970 100644 --- a/include/net/irda/irport.h +++ b/include/net/irda/irport.h @@ -6,10 +6,10 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sun Aug 3 13:49:59 1997 - * Modified at: Thu Jan 7 14:17:31 1999 + * Modified at: Mon May 10 22:12:56 1999 * Modified by: Dag Brattli * - * Copyright (c) 1997, 1998 Dag Brattli + * Copyright (c) 1997, 1998-1999 Dag Brattli * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -49,13 +49,13 @@ #define FRAME_MAX_SIZE 2048 -void irport_close( int iobase); -int irport_open( int iobase); -int irport_detect(struct irda_device *idev); +void irport_start(int iobase); +void irport_stop(int iobase); +int irport_probe(int iobase); -void irport_change_speed( int iobase, int speed); +void irport_change_speed(struct irda_device *idev, int speed); void irport_interrupt(int irq, void *dev_id, struct pt_regs *regs); -int irport_hard_xmit( struct sk_buff *skb, struct device *dev); +int irport_hard_xmit(struct sk_buff *skb, struct device *dev); #endif diff --git a/include/net/irda/irttp.h b/include/net/irda/irttp.h index aec1d57dc157..3e6511ceae5b 100644 --- a/include/net/irda/irttp.h +++ b/include/net/irda/irttp.h @@ -6,10 +6,10 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sun Aug 31 20:14:31 1997 - * Modified at: Sat Apr 10 10:19:56 1999 + * Modified at: Mon May 10 19:14:51 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli , All Rights Reserved. + * Copyright (c) 1998-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 @@ -36,7 +36,8 @@ #define TTP_MAX_CONNECTIONS LM_MAX_CONNECTIONS #define TTP_HEADER 1 -#define TTP_HEADER_WITH_SAR 6 +#define TTP_MAX_HEADER (TTP_HEADER + LMP_MAX_HEADER) +#define TTP_SAR_HEADER 5 #define TTP_PARAMETERS 0x80 #define TTP_MORE 0x80 @@ -61,8 +62,6 @@ struct tsap_cb { 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 */ - __u8 stsap_sel; /* Source TSAP */ __u8 dtsap_sel; /* Destination TSAP */ @@ -88,6 +87,9 @@ struct tsap_cb { struct irda_statistics stats; struct timer_list todo_timer; + __u32 max_seg_size; /* Max data that fit into an IrLAP frame */ + __u8 max_header_size; + int rx_sdu_busy; /* RxSdu.busy */ __u32 rx_sdu_size; /* Current size of a partially received frame */ __u32 rx_max_sdu_size; /* Max receive user data size */ @@ -120,8 +122,6 @@ int irttp_connect_request(struct tsap_cb *self, __u8 dtsap_sel, __u32 saddr, __u32 daddr, struct qos_info *qos, __u32 max_sdu_size, struct sk_buff *userdata); -void irttp_connect_confirm(void *instance, void *sap, struct qos_info *qos, - __u32 max_sdu_size, struct sk_buff *skb); void irttp_connect_response(struct tsap_cb *self, __u32 max_sdu_size, struct sk_buff *userdata); struct tsap_cb *irttp_dup(struct tsap_cb *self, void *instance); diff --git a/include/net/irda/irtty.h b/include/net/irda/irtty.h index 920909600e54..38b5c4d81cd7 100644 --- a/include/net/irda/irtty.h +++ b/include/net/irda/irtty.h @@ -6,10 +6,10 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Tue Dec 9 21:13:12 1997 - * Modified at: Sun Feb 7 01:57:33 1999 + * Modified at: Mon May 10 13:22:23 1999 * Modified by: Dag Brattli * - * Copyright (c) 1997 Dag Brattli, All Rights Reserved. + * Copyright (c) 1997, 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 @@ -33,8 +33,6 @@ #include #include -#include - #define IRTTY_IOC_MAGIC 'e' #define IRTTY_IOCTDONGLE _IO(IRTTY_IOC_MAGIC, 1) #define IRTTY_IOC_MAXNR 1 @@ -43,28 +41,21 @@ #define N_IRDA 11 /* This one should go in */ #endif -struct dongle_q { - QUEUE q; - - struct dongle *dongle; -}; - struct irtty_cb { QUEUE q; /* Must be first */ -/* char name[16]; */ - int magic; struct tty_struct *tty; /* Ptr to TTY structure */ struct irda_device idev; - - struct dongle_q *dongle_q; /* Has this tty got a dongle attached? */ }; -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); +int irtty_register_dongle(struct dongle *dongle); +void irtty_unregister_dongle(struct dongle *dongle); #endif + + + + + diff --git a/include/net/irda/toshoboe.h b/include/net/irda/toshoboe.h new file mode 100644 index 000000000000..b2f5b953ba87 --- /dev/null +++ b/include/net/irda/toshoboe.h @@ -0,0 +1,165 @@ +/********************************************************************* + * + * Filename: toshoboe.h + * Version: 0.1 + * Description: Driver for the Toshiba OBOE (or type-O) + * FIR Chipset. + * Status: Experimental. + * Author: James McKenzie + * Created at: Sat May 8 12:35:27 1999 + * + * Copyright (c) 1999 James McKenzie, 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 James McKenzie nor Cambridge University admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + * Applicable Models : Libretto 100CT. and many more + * + ********************************************************************/ + +/* + * $Log: toshoboe.h,v $ + * Revision 1.2 1999/05/09 01:43:08 root + * *** empty log message *** + * + * Revision 1.1 1999/05/09 01:25:58 root + * Initial revision + * + */ + +#ifndef TOSHOBOE_H +#define TOSHOBOE_H + +/* Registers */ +/*Receive and transmit task registers (read only) */ +#define OBOE_RCVT (0x00+(self->base)) +#define OBOE_XMTT (0x01+(self->base)) +#define OBOE_XMTT_OFFSET 0x40 + +/*Page pointers to the TaskFile structure */ +#define OBOE_TFP2 (0x02+(self->base)) +#define OBOE_TFP0 (0x04+(self->base)) +#define OBOE_TFP1 (0x05+(self->base)) + +/*Dunno */ +#define OBOE_REG_3 (0x03+(self->base)) + +/*Number of tasks to use in Xmit and Recv queues */ +#define OBOE_NTR (0x07+(self->base)) +#define OBOE_NTR_XMIT4 0x00 +#define OBOE_NTR_XMIT8 0x10 +#define OBOE_NTR_XMIT16 0x30 +#define OBOE_NTR_XMIT32 0x70 +#define OBOE_NTR_XMIT64 0xf0 +#define OBOE_NTR_RECV4 0x00 +#define OBOE_NTR_RECV8 0x01 +#define OBOE_NTR_RECV6 0x03 +#define OBOE_NTR_RECV32 0x07 +#define OBOE_NTR_RECV64 0x0f + +/* Dunno */ +#define OBOE_REG_9 (0x09+(self->base)) + +/* Interrupt Status Register */ +#define OBOE_ISR (0x0c+(self->base)) +#define OBOE_ISR_TXDONE 0x80 +#define OBOE_ISR_RXDONE 0x40 +#define OBOE_ISR_20 0x20 +#define OBOE_ISR_10 0x10 +#define OBOE_ISR_8 0x08 /*This is collision or parity or something */ +#define OBOE_ISR_4 0x08 +#define OBOE_ISR_2 0x08 +#define OBOE_ISR_1 0x08 + +/*Dunno */ +#define OBOE_REG_D (0x0d+(self->base)) + +/*Register Lock Register */ +#define OBOE_LOCK ((self->base)+0x0e) + + + +/*Speed control registers */ +#define OBOE_PMDL (0x10+(self->base)) +#define OBOE_PMDL_SIR 0x18 +#define OBOE_PMDL_MIR 0xa0 +#define OBOE_PMDL_FIR 0x40 + +#define OBOE_SMDL (0x18+(self->base)) +#define OBOE_SMDL_SIR 0x20 +#define OBOE_SMDL_MIR 0x01 +#define OBOE_SMDL_FIR 0x0f + +#define OBOE_UDIV (0x19+(self->base)) + +/*Dunno */ +#define OBOE_REG_11 (0x11+(self->base)) + +/*Chip Reset Register */ +#define OBOE_RST (0x15+(self->base)) +#define OBOE_RST_WRAP 0x8 + +/*Dunno */ +#define OBOE_REG_1A (0x1a+(self->base)) +#define OBOE_REG_1B (0x1b+(self->base)) + +/* The PCI ID of the OBOE chip */ +#ifndef PCI_DEVICE_ID_FIR701 +#define PCI_DEVICE_ID_FIR701 0x0701 +#endif + +typedef unsigned int dword; +typedef unsigned short int word; +typedef unsigned char byte; +typedef dword Paddr; + +struct OboeTask + { + __u16 len; + __u8 unused; + __u8 control; + __u32 buffer; + }; + +#define OBOE_NTASKS 64 + +struct OboeTaskFile + { + struct OboeTask recv[OBOE_NTASKS]; + struct OboeTask xmit[OBOE_NTASKS]; + }; + +#define OBOE_TASK_BUF_LEN (sizeof(struct OboeTaskFile) << 1) + +/*These set the number of slots in use */ +#define TX_SLOTS 4 +#define RX_SLOTS 4 + +/* You need also to change this, toshiba uses 4,8 and 4,4 */ +/* It makes no difference if you are only going to use ONETASK mode */ +/* remember each buffer use XX_BUF_SZ more _PHYSICAL_ memory */ +#define OBOE_NTR_VAL (OBOE_NTR_XMIT4 | OBOE_NTR_RECV4) + +struct toshoboe_cb + { + struct irda_device idev; /*IRDA device */ + struct pci_dev *pdev; /*PCI device */ + int base; /*IO base */ + int txpending; /*how many tx's are pending */ + int txs, rxs; /*Which slots are we at */ + void *taskfilebuf; /*The unaligned taskfile buffer */ + struct OboeTaskFile *taskfile; /*The taskfile */ + void *xmit_bufs[TX_SLOTS]; /*The buffers */ + void *recv_bufs[RX_SLOTS]; + }; + + +#endif + + diff --git a/include/net/irda/w83977af_ir.h b/include/net/irda/w83977af_ir.h index 3e3200b2de3f..d86456ada552 100644 --- a/include/net/irda/w83977af_ir.h +++ b/include/net/irda/w83977af_ir.h @@ -6,10 +6,10 @@ * Status: Experimental. * Author: Paul VanderSpek * Created at: Thu Nov 19 13:55:34 1998 - * Modified at: Thu Dec 10 14:06:18 1998 + * Modified at: Mon May 3 12:07:25 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli, All Rights Reserved. + * Copyright (c) 1998-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 @@ -150,6 +150,29 @@ #define IRM_CR_IRX_MSL 0x40 #define IRM_CR_AF_MNT 0x80 /* Automatic format */ +/* For storing entries in the status FIFO */ +struct st_fifo_entry { + int status; + int len; +}; + +struct st_fifo { + struct st_fifo_entry entries[10]; + int head; + int tail; + int len; +}; + +/* Private data for each instance */ +struct w83977af_ir { + struct st_fifo st_fifo; + + int tx_buff_offsets[10]; /* Offsets between frames in tx_buff */ + int tx_len; /* Number of frames in tx_buff */ + + struct irda_device idev; +}; + static inline void switch_bank( int iobase, int set) { outb( set, iobase+SSR); diff --git a/include/net/irda/wrapper.h b/include/net/irda/wrapper.h index ca21ebec5123..fa7ceb25c221 100644 --- a/include/net/irda/wrapper.h +++ b/include/net/irda/wrapper.h @@ -1,15 +1,16 @@ /********************************************************************* * * Filename: wrapper.h - * Version: 1.0 - * Description: IrDA Wrapper layer + * Version: 1.2 + * Description: IrDA SIR async wrapper layer * Status: Experimental. * Author: Dag Brattli * Created at: Mon Aug 4 20:40:53 1997 - * Modified at: Fri Jan 29 10:15:46 1999 + * Modified at: Mon May 3 09:02:36 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli , All Rights Reserved. + * Copyright (c) 1998-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 @@ -38,17 +39,18 @@ #define STA BOF /* Start flag */ #define STO EOF /* End flag */ -#define IR_TRANS 0x20 /* Asynchronous transparency modifier */ +#define IRDA_TRANS 0x20 /* Asynchronous transparency modifier */ +/* States for receving a frame in async mode */ enum { - OUTSIDE_FRAME = 1, + OUTSIDE_FRAME, BEGIN_FRAME, LINK_ESCAPE, INSIDE_FRAME }; /* Proto definitions */ -int async_wrap_skb( struct sk_buff *skb, __u8 *tx_buff, int buffsize); -void async_unwrap_char( struct irda_device *, __u8 byte); +int async_wrap_skb(struct sk_buff *skb, __u8 *tx_buff, int buffsize); +inline void async_unwrap_char(struct irda_device *idev, __u8 byte); #endif diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c index fae22cbe7deb..39f4b9e7b4fd 100644 --- a/net/ipv4/ip_options.c +++ b/net/ipv4/ip_options.c @@ -452,7 +452,6 @@ eol: error: if (skb) { icmp_send(skb, ICMP_PARAMETERPROB, 0, htonl((pp_ptr-iph)<<24)); - kfree_skb(skb); } return -EINVAL; } diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 3760be8eb996..f50a9cbf17f8 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $Id: icmp.c,v 1.21 1999/03/21 05:22:51 davem Exp $ + * $Id: icmp.c,v 1.21.2.1 1999/05/19 22:07:36 davem Exp $ * * Based on net/ipv4/icmp.c * @@ -315,6 +315,7 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, fl.nl_u.ip6_u.daddr = &hdr->saddr; fl.nl_u.ip6_u.saddr = saddr; fl.oif = iif; + fl.fl6_flowlabel = 0; fl.uli_u.icmpt.type = type; fl.uli_u.icmpt.code = code; @@ -388,6 +389,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb) fl.nl_u.ip6_u.daddr = &hdr->saddr; fl.nl_u.ip6_u.saddr = saddr; fl.oif = skb->dev->ifindex; + fl.fl6_flowlabel = 0; fl.uli_u.icmpt.type = ICMPV6_ECHO_REPLY; fl.uli_u.icmpt.code = 0; diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c index 6dd118024871..385805ff219b 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 Apr 22 12:08:04 1999 + * Modified at: Tue May 11 12:42:26 1999 * Modified by: Dag Brattli * Sources: af_netroom.c, af_ax25.c, af_rose.c, af_x25.c etc. * @@ -30,6 +30,7 @@ #include #include #include +#include #include @@ -46,11 +47,12 @@ extern void irda_cleanup(void); extern int irlap_driver_rcv(struct sk_buff *, struct device *, struct packet_type *); -static struct proto_ops irda_proto_ops; +static struct proto_ops irda_stream_ops; +static struct proto_ops irda_dgram_ops; static hashbin_t *cachelog = NULL; static struct wait_queue *discovery_wait; /* Wait for discovery */ -#define IRDA_MAX_HEADER (TTP_HEADER+LMP_HEADER+LAP_HEADER) +#define IRDA_MAX_HEADER (TTP_MAX_HEADER) /* * Function irda_data_indication (instance, sap, skb) @@ -121,7 +123,8 @@ static void irda_disconnect_indication(void *instance, void *sap, */ static void irda_connect_confirm(void *instance, void *sap, struct qos_info *qos, - __u32 max_sdu_size, struct sk_buff *skb) + __u32 max_sdu_size, __u8 max_header_size, + struct sk_buff *skb) { struct irda_sock *self; struct sock *sk; @@ -130,13 +133,28 @@ static void irda_connect_confirm(void *instance, void *sap, self = (struct irda_sock *) instance; + /* How much header space do we need to reserve */ + self->max_header_size = max_header_size; + + /* IrTTP max SDU size in transmit direction */ self->max_sdu_size_tx = max_sdu_size; + + /* Find out what the largest chunk of data that we can transmit is */ + if (max_sdu_size == SAR_DISABLE) + self->max_data_size = qos->data_size.value - max_header_size; + else + self->max_data_size = max_sdu_size; + + DEBUG(0, __FUNCTION__ "(), max_data_size=%d\n", self->max_data_size); + memcpy(&self->qos_tx, qos, sizeof(struct qos_info)); sk = self->sk; if (sk == NULL) return; + skb_queue_tail(&sk->receive_queue, skb); + /* We are now connected! */ sk->state = TCP_ESTABLISHED; sk->state_change(sk); @@ -150,7 +168,7 @@ static void irda_connect_confirm(void *instance, void *sap, */ static void irda_connect_indication(void *instance, void *sap, struct qos_info *qos, __u32 max_sdu_size, - struct sk_buff *skb) + __u8 max_header_size, struct sk_buff *skb) { struct irda_sock *self; struct sock *sk; @@ -158,8 +176,21 @@ static void irda_connect_indication(void *instance, void *sap, DEBUG(1, __FUNCTION__ "()\n"); self = (struct irda_sock *) instance; - - self->max_sdu_size_tx = max_sdu_size; + + /* How much header space do we need to reserve */ + self->max_header_size = max_header_size; + + /* IrTTP max SDU size in transmit direction */ + self->max_sdu_size_tx = max_sdu_size; + + /* Find out what the largest chunk of data that we can transmit is */ + if (max_sdu_size == SAR_DISABLE) + self->max_data_size = qos->data_size.value - max_header_size; + else + self->max_data_size = max_sdu_size; + + DEBUG(0, __FUNCTION__ "(), max_data_size=%d\n", self->max_data_size); + memcpy(&self->qos_tx, qos, sizeof(struct qos_info)); sk = self->sk; @@ -187,12 +218,12 @@ void irda_connect_response(struct irda_sock *self) skb = dev_alloc_skb(64); if (skb == NULL) { - DEBUG( 0, __FUNCTION__ "() Could not allocate sk_buff!\n"); + DEBUG(0, __FUNCTION__ "() Unable to allocate sk_buff!\n"); return; } /* Reserve space for MUX_CONTROL and LAP header */ - skb_reserve(skb, TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER); + skb_reserve(skb, IRDA_MAX_HEADER); irttp_connect_response(self->tsap, self->max_sdu_size_rx, skb); } @@ -514,10 +545,13 @@ static int irda_accept(struct socket *sock, struct socket *newsock, int flags) new->stsap_sel = new->tsap->stsap_sel; new->dtsap_sel = new->tsap->dtsap_sel; new->saddr = irttp_get_saddr(new->tsap); - new->saddr = irttp_get_saddr(new->tsap); + new->daddr = irttp_get_daddr(new->tsap); new->max_sdu_size_tx = self->max_sdu_size_tx; new->max_sdu_size_rx = self->max_sdu_size_rx; + new->max_data_size = self->max_data_size; + new->max_header_size = self->max_header_size; + memcpy(&new->qos_tx, &self->qos_tx, sizeof(struct qos_info)); /* Clean up the original one to keep it in listen state */ @@ -669,7 +703,7 @@ static int irda_create(struct socket *sock, int protocol) sock_init_data(sock, sk); - sock->ops = &irda_proto_ops; + sock->ops = &irda_stream_ops; sk->protocol = protocol; /* Register as a client with IrLMP */ @@ -786,12 +820,20 @@ static int irda_sendmsg(struct socket *sock, struct msghdr *msg, int len, return -ENOTCONN; } - skb = sock_alloc_send_skb(sk, len + IRDA_MAX_HEADER, 0, + /* Check that we don't send out to big frames */ + if (len > self->max_data_size) { + DEBUG(0, __FUNCTION__ "(), Warning to much data! " + "Chopping frame from %d to %d bytes!\n", len, + self->max_data_size); + len = self->max_data_size; + } + + skb = sock_alloc_send_skb(sk, len + self->max_header_size, 0, msg->msg_flags & MSG_DONTWAIT, &err); if (!skb) return -ENOBUFS; - skb_reserve(skb, IRDA_MAX_HEADER); + skb_reserve(skb, self->max_header_size); DEBUG(4, __FUNCTION__ "(), appending user data\n"); asmptr = skb->h.raw = skb_put(skb, len); @@ -815,8 +857,8 @@ static int irda_sendmsg(struct socket *sock, struct msghdr *msg, int len, * Try to receive message and copy it to user * */ -static int irda_recvmsg(struct socket *sock, struct msghdr *msg, int size, - int flags, struct scm_cookie *scm) +static int irda_recvmsg_dgram(struct socket *sock, struct msghdr *msg, + int size, int flags, struct scm_cookie *scm) { struct irda_sock *self; struct sock *sk = sock->sk; @@ -861,6 +903,161 @@ static int irda_recvmsg(struct socket *sock, struct msghdr *msg, int size, return copied; } +/* + * Function irda_data_wait (sk) + * + * Sleep until data has arrive. But check for races.. + * + */ +static void irda_data_wait(struct sock *sk) +{ + if (!skb_peek(&sk->receive_queue)) { + sk->socket->flags |= SO_WAITDATA; + interruptible_sleep_on(sk->sleep); + sk->socket->flags &= ~SO_WAITDATA; + } +} + +/* + * Function irda_recvmsg_stream (sock, msg, size, flags, scm) + * + * + * + */ +static int irda_recvmsg_stream(struct socket *sock, struct msghdr *msg, + int size, int flags, struct scm_cookie *scm) +{ + struct irda_sock *self; + struct sock *sk = sock->sk; + int noblock = flags & MSG_DONTWAIT; + int copied = 0; + int target = 1; + + DEBUG(3, __FUNCTION__ "()\n"); + + self = sk->protinfo.irda; + ASSERT(self != NULL, return -1;); + + if (sock->flags & SO_ACCEPTCON) + return(-EINVAL); + + if (flags & MSG_OOB) + return -EOPNOTSUPP; + + if (flags & MSG_WAITALL) + target = size; + + + msg->msg_namelen = 0; + + /* Lock the socket to prevent queue disordering + * while sleeps in memcpy_tomsg + */ +/* down(&self->readsem); */ + + do { + int chunk; + struct sk_buff *skb; + + skb=skb_dequeue(&sk->receive_queue); + if (skb==NULL) { + if (copied >= target) + break; + + /* + * POSIX 1003.1g mandates this order. + */ + + if (sk->err) { + /* up(&self->readsem); */ + return sock_error(sk); + } + + if (sk->shutdown & RCV_SHUTDOWN) + break; + + /* up(&self->readsem); */ + + if (noblock) + return -EAGAIN; + irda_data_wait(sk); + if (signal_pending(current)) + return -ERESTARTSYS; + /* down(&self->readsem); */ + continue; + } + + /* Never glue messages from different writers */ +/* if (check_creds && */ +/* memcmp(UNIXCREDS(skb), &scm->creds, sizeof(scm->creds)) != 0) */ +/* { */ +/* skb_queue_head(&sk->receive_queue, skb); */ +/* break; */ +/* } */ + + chunk = min(skb->len, size); + if (memcpy_toiovec(msg->msg_iov, skb->data, chunk)) { + skb_queue_head(&sk->receive_queue, skb); + if (copied == 0) + copied = -EFAULT; + break; + } + copied += chunk; + size -= chunk; + + /* Copy credentials */ +/* scm->creds = *UNIXCREDS(skb); */ +/* check_creds = 1; */ + + /* Mark read part of skb as used */ + if (!(flags & MSG_PEEK)) { + skb_pull(skb, chunk); + +/* if (UNIXCB(skb).fp) */ +/* unix_detach_fds(scm, skb); */ + + /* put the skb back if we didn't use it up.. */ + if (skb->len) { + DEBUG(1, __FUNCTION__ "(), back on q!\n"); + skb_queue_head(&sk->receive_queue, skb); + break; + } + + kfree_skb(skb); + +/* if (scm->fp) */ +/* break; */ + } else { + DEBUG(0, __FUNCTION__ "() questionable!?\n"); + /* It is questionable, see note in unix_dgram_recvmsg. */ +/* if (UNIXCB(skb).fp) */ +/* scm->fp = scm_fp_dup(UNIXCB(skb).fp); */ + + /* put message back and return */ + skb_queue_head(&sk->receive_queue, skb); + break; + } + } while (size); + + /* + * Check if we have previously stopped IrTTP and we know + * have more free space in our rx_queue. If so tell IrTTP + * to start delivering frames again before our rx_queue gets + * empty + */ + if (self->rx_flow == FLOW_STOP) { + if ((atomic_read(&sk->rmem_alloc) << 2) <= sk->rcvbuf) { + DEBUG(2, __FUNCTION__ "(), Starting IrTTP\n"); + self->rx_flow = FLOW_START; + irttp_flow_request(self->tsap, FLOW_START); + } + } + + /* up(&self->readsem); */ + + return copied; +} + /* * Function irda_shutdown (sk, how) * @@ -875,19 +1072,45 @@ static int irda_shutdown( struct socket *sk, int how) return -EOPNOTSUPP; } - /* * Function irda_poll (file, sock, wait) * * * */ -unsigned int irda_poll(struct file *file, struct socket *sock, - struct poll_table_struct *wait) +static unsigned int irda_poll(struct file * file, struct socket *sock, + poll_table *wait) { - DEBUG(0, __FUNCTION__ "()\n"); + struct sock *sk = sock->sk; + unsigned int mask; - return 0; + DEBUG(1, __FUNCTION__ "()\n"); + + poll_wait(file, sk->sleep, wait); + mask = 0; + + /* exceptional events? */ + if (sk->err) + mask |= POLLERR; + if (sk->shutdown & RCV_SHUTDOWN) + mask |= POLLHUP; + + /* readable? */ + if (!skb_queue_empty(&sk->receive_queue)) + mask |= POLLIN | POLLRDNORM; + + /* Connection-based need to check for termination and startup */ + if (sk->type == SOCK_STREAM && sk->state==TCP_CLOSE) + mask |= POLLHUP; + + /* + * we set writable also when the other side has shut down the + * connection. This prevents stuck sockets. + */ + if (sk->sndbuf - (int)atomic_read(&sk->wmem_alloc) >= MIN_WRITE_SPACE) + mask |= POLLOUT | POLLWRNORM | POLLWRBAND; + + return mask; } /* @@ -947,6 +1170,7 @@ static int irda_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) return -EINVAL; default: + DEBUG(0, __FUNCTION__ "(), doing device ioctl!\n"); return dev_ioctl(cmd, (void *) arg); } @@ -1082,13 +1306,7 @@ static int irda_getsockopt(struct socket *sock, int level, int optname, return -EFAULT; break; case IRTTP_MAX_SDU_SIZE: - if (self->max_sdu_size_tx != SAR_DISABLE) - val = self->max_sdu_size_tx; - else - /* SAR is disabled, so use the IrLAP data size - * instead */ - val = self->qos_tx.data_size.value - IRDA_MAX_HEADER; - + val = self->max_data_size; DEBUG(0, __FUNCTION__ "(), getting max_sdu_size = %d\n", val); len = sizeof(int); if (put_user(len, optlen)) @@ -1110,7 +1328,7 @@ static struct net_proto_family irda_family_ops = irda_create }; -static struct proto_ops irda_proto_ops = { +static struct proto_ops irda_stream_ops = { PF_IRDA, sock_no_dup, @@ -1128,7 +1346,28 @@ static struct proto_ops irda_proto_ops = { irda_getsockopt, sock_no_fcntl, irda_sendmsg, - irda_recvmsg + irda_recvmsg_stream +}; + +static struct proto_ops irda_dgram_ops = { + PF_IRDA, + + sock_no_dup, + irda_release, + irda_bind, + irda_connect, + sock_no_socketpair, + irda_accept, + irda_getname, + datagram_poll, + irda_ioctl, + irda_listen, + irda_shutdown, + irda_setsockopt, + irda_getsockopt, + sock_no_fcntl, + irda_sendmsg, + irda_recvmsg_dgram }; /* @@ -1215,7 +1454,7 @@ 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); sock_unregister(PF_IRDA); irda_cleanup(); diff --git a/net/irda/crc.c b/net/irda/crc.c index 9a6f3021fa05..b3019d5c2095 100644 --- a/net/irda/crc.c +++ b/net/irda/crc.c @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Mon Aug 4 20:40:53 1997 - * Modified at: Sat Dec 12 09:56:35 1998 + * Modified at: Sun May 2 20:28:08 1999 * Modified by: Dag Brattli * Sources: ppp.c by Michael Callahan * Al Longyear @@ -59,7 +59,7 @@ __u16 const irda_crc16_table[256] = unsigned short crc_calc( __u16 fcs, __u8 const *buf, size_t len) { - while ( len--) - fcs = IR_FCS(fcs, *buf++); - return fcs; + while (len--) + fcs = irda_fcs(fcs, *buf++); + return fcs; } diff --git a/net/irda/discovery.c b/net/irda/discovery.c index 22def3a1e89c..41fc4d20a5e8 100644 --- a/net/irda/discovery.c +++ b/net/irda/discovery.c @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Tue Apr 6 15:33:50 1999 - * Modified at: Sun Apr 11 00:41:58 1999 + * Modified at: Sun May 9 22:40:43 1999 * Modified by: Dag Brattli * * Copyright (c) 1999 Dag Brattli, All Rights Reserved. @@ -39,28 +39,51 @@ /* * Function irlmp_add_discovery (cachelog, discovery) * - * - * + * Add a new discovery to the cachelog, and remove any old discoveries + * from the same device */ -void irlmp_add_discovery(hashbin_t *cachelog, discovery_t *discovery) +void irlmp_add_discovery(hashbin_t *cachelog, discovery_t *new) { - discovery_t *old; + discovery_t *discovery, *node; + unsigned long flags; - DEBUG(4, __FUNCTION__ "()\n"); + spin_lock_irqsave(&irlmp->lock, flags); + + /* + * Remove all discoveries of devices that has previously been + * discovered on the same link with the same name (info), or the + * same daddr. We do this since some devices (mostly PDAs) change + * their device address between every discovery. + */ + discovery = (discovery_t *) hashbin_get_first(cachelog); + while (discovery != NULL ) { + node = discovery; + + /* Be sure to stay one item ahead */ + discovery = (discovery_t *) hashbin_get_next(cachelog); + + if ((node->daddr == new->daddr) || + (strcmp(node->info, new->info) == 0)) + { + /* This discovery is a previous discovery + * from the same device, so just remove it + */ + hashbin_remove(cachelog, node->daddr, NULL); + kfree(node); + } + } - /* Check if we have discovered this device before */ - old = hashbin_remove(cachelog, discovery->daddr, NULL); - if (old) - kfree(old); /* Insert the new and updated version */ - hashbin_insert(cachelog, (QUEUE *) discovery, discovery->daddr, NULL); + hashbin_insert(cachelog, (QUEUE *) new, new->daddr, NULL); + + spin_unlock_irqrestore(&irlmp->lock, flags); } /* * Function irlmp_add_discovery_log (cachelog, log) * - * + * Merge a disovery log into the cachlog. * */ void irlmp_add_discovery_log(hashbin_t *cachelog, hashbin_t *log) diff --git a/net/irda/ircomm/ircomm_common.c b/net/irda/ircomm/ircomm_common.c index bc8758e1eff5..97fc3cf279d2 100644 --- a/net/irda/ircomm/ircomm_common.c +++ b/net/irda/ircomm/ircomm_common.c @@ -8,7 +8,7 @@ * Author: Takahide Higuchi * Source: irlpt_event.c * - * Copyright (c) 1998, Takahide Higuchi, , + * Copyright (c) 1998-1999, Takahide Higuchi, , * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -44,18 +44,17 @@ static char *revision_date = "Sun Apr 18 00:40:19 1999"; -static void ircomm_state_idle( struct ircomm_cb *self, IRCOMM_EVENT event, - struct sk_buff *skb ); - -static void ircomm_state_discoverywait( struct ircomm_cb *self, IRCOMM_EVENT event, +static void ircomm_state_idle(struct ircomm_cb *self, IRCOMM_EVENT event, + struct sk_buff *skb ); +static void ircomm_state_discoverywait(struct ircomm_cb *self, + IRCOMM_EVENT event, + struct sk_buff *skb ); +static void ircomm_state_queryparamwait(struct ircomm_cb *self, + IRCOMM_EVENT event, struct sk_buff *skb ); - -static void ircomm_state_queryparamwait( struct ircomm_cb *self, IRCOMM_EVENT event, - struct sk_buff *skb ); - -static void ircomm_state_querylsapwait( struct ircomm_cb *self, IRCOMM_EVENT event, - struct sk_buff *skb ); - +static void ircomm_state_querylsapwait(struct ircomm_cb *self, + IRCOMM_EVENT event, + struct sk_buff *skb ); static void ircomm_state_waiti( struct ircomm_cb *self, IRCOMM_EVENT event, struct sk_buff *skb ); static void ircomm_state_waitr( struct ircomm_cb *self, IRCOMM_EVENT event, @@ -207,7 +206,7 @@ __initfunc(int ircomm_init(void)) ircomm[i]->ack_char = 0x06; ircomm[i]->max_txbuff_size = COMM_DEFAULT_DATA_SIZE; /* 64 */ - ircomm[i]->maxsdusize = SAR_DISABLE; + ircomm[i]->max_sdu_size = SAR_DISABLE; ircomm[i]->ctrl_skb = dev_alloc_skb(COMM_DEFAULT_DATA_SIZE); if (ircomm[i]->ctrl_skb == NULL){ DEBUG(0,"ircomm:init_module:alloc_skb failed!\n"); @@ -226,7 +225,6 @@ __initfunc(int ircomm_init(void)) create_proc_entry("ircomm", 0, proc_irda)->get_info = ircomm_proc_read; #endif /* CONFIG_PROC_FS */ - discovering_instance = NULL; return 0; } @@ -275,51 +273,53 @@ void ircomm_cleanup(void) static int ircomm_accept_data_indication(void *instance, void *sap, struct sk_buff *skb) { - - struct ircomm_cb *self = (struct ircomm_cb *)instance; + struct ircomm_cb *self = (struct ircomm_cb *) instance; - ASSERT( self != NULL, return -1;); - ASSERT( self->magic == IRCOMM_MAGIC, return -1;); - ASSERT( skb != NULL, return -1;); + ASSERT(self != NULL, return -1;); + ASSERT(self->magic == IRCOMM_MAGIC, return -1;); + ASSERT(skb != NULL, return -1;); DEBUG(4,__FUNCTION__"():\n"); - ircomm_do_event( self, TTP_DATA_INDICATION, skb); + ircomm_do_event(self, TTP_DATA_INDICATION, skb); self->rx_packets++; return 0; } static void ircomm_accept_connect_confirm(void *instance, void *sap, - struct qos_info *qos, - __u32 maxsdusize, struct sk_buff *skb) + struct qos_info *qos, + __u32 max_sdu_size, + __u8 max_header_size, + struct sk_buff *skb) { + struct ircomm_cb *self = (struct ircomm_cb *) instance; - struct ircomm_cb *self = (struct ircomm_cb *)instance; - - ASSERT( self != NULL, return;); - ASSERT( self->magic == IRCOMM_MAGIC, return;); - ASSERT( skb != NULL, return;); - ASSERT( qos != NULL, return;); + ASSERT(self != NULL, return;); + ASSERT(self->magic == IRCOMM_MAGIC, return;); + ASSERT(skb != NULL, return;); + ASSERT(qos != NULL, return;); DEBUG(0,__FUNCTION__"(): got connected!\n"); - if(maxsdusize == SAR_DISABLE) - self->max_txbuff_size = qos->data_size.value; + if (max_sdu_size == SAR_DISABLE) + self->max_txbuff_size = qos->data_size.value - max_header_size; else { - ASSERT(maxsdusize >= COMM_DEFAULT_DATA_SIZE, return;); - self->max_txbuff_size = maxsdusize; /* use fragmentation */ + ASSERT(max_sdu_size >= COMM_DEFAULT_DATA_SIZE, return;); + self->max_txbuff_size = max_sdu_size; /* use fragmentation */ } self->qos = qos; - self->null_modem_mode = 0; /* disable null modem emulation */ + self->max_header_size = max_header_size; + self->null_modem_mode = 0; /* disable null modem emulation */ - ircomm_do_event( self, TTP_CONNECT_CONFIRM, skb); + ircomm_do_event(self, TTP_CONNECT_CONFIRM, skb); } static void ircomm_accept_connect_indication(void *instance, void *sap, - struct qos_info *qos, - __u32 maxsdusize, - struct sk_buff *skb ) + struct qos_info *qos, + __u32 max_sdu_size, + __u8 max_header_size, + struct sk_buff *skb) { struct ircomm_cb *self = (struct ircomm_cb *)instance; @@ -330,12 +330,14 @@ static void ircomm_accept_connect_indication(void *instance, void *sap, DEBUG(0,__FUNCTION__"()\n"); - if(maxsdusize == SAR_DISABLE) - self->max_txbuff_size = qos->data_size.value; + if (max_sdu_size == SAR_DISABLE) + self->max_txbuff_size = qos->data_size.value - max_header_size; else - self->max_txbuff_size = maxsdusize; + self->max_txbuff_size = max_sdu_size; self->qos = qos; + self->max_header_size = max_header_size; + ircomm_do_event( self, TTP_CONNECT_INDICATION, skb); /* stop connecting */ @@ -556,7 +558,7 @@ static void issue_connect_request(struct ircomm_cb *self, irttp_connect_request(self->tsap, self->dlsap, self->saddr, self->daddr, - NULL, self->maxsdusize, userdata); + NULL, self->max_sdu_size, userdata); break; default: @@ -588,9 +590,9 @@ static void connect_indication(struct ircomm_cb *self, struct qos_info *qos, /* if( !ircomm_parse_controlchannel( self, data)) */ /* self->servicetype = DEFAULT; TODOD:fix this! TH */ - if(self->notify.connect_indication) + if (self->notify.connect_indication) self->notify.connect_indication(self->notify.instance, self, - qos, 0, skb); + qos, 0, 0, skb); } #if 0 @@ -602,28 +604,26 @@ static void connect_indication_three_wire_raw(void) #endif -static void connect_confirmation(struct ircomm_cb *self, struct sk_buff *skb) +static void connect_confirm(struct ircomm_cb *self, struct sk_buff *skb) { DEBUG(4 ,__FUNCTION__"()\n"); /* give a connect_confirm to the client */ if( self->notify.connect_confirm ) self->notify.connect_confirm(self->notify.instance, - self, NULL, SAR_DISABLE, skb); + self, NULL, SAR_DISABLE, 0, skb); } static void issue_connect_response(struct ircomm_cb *self, struct sk_buff *skb) { - DEBUG(0,__FUNCTION__"()\n"); if( self->servicetype == THREE_WIRE_RAW){ DEBUG(0,__FUNCTION__"():THREE_WIRE_RAW is not implemented yet\n"); /* irlmp_connect_rsp(); */ - } else { - irttp_connect_response(self->tsap, self->maxsdusize, skb); - } + } else + irttp_connect_response(self->tsap, self->max_sdu_size, skb); } static void issue_disconnect_request(struct ircomm_cb *self, @@ -642,30 +642,29 @@ static void issue_data_request(struct ircomm_cb *self, { int err; - if(self->servicetype == THREE_WIRE_RAW){ + if (self->servicetype == THREE_WIRE_RAW){ /* irlmp_data_request(self->lmhandle,userdata); */ DEBUG(0,__FUNCTION__"():not implemented!"); return; } DEBUG(4,__FUNCTION__"():sending frame\n"); - err = irttp_data_request(self->tsap , userdata ); - if(err){ + err = irttp_data_request(self->tsap, userdata); + if (err){ printk(KERN_ERR __FUNCTION__":ttp_data_request failed\n"); - if(userdata) + if (userdata) dev_kfree_skb( userdata); } self->tx_packets++; } static void issue_control_request(struct ircomm_cb *self, - struct sk_buff *userdata ) + struct sk_buff *userdata) { int err; DEBUG(4,__FUNCTION__"()\n"); - if(self->servicetype == THREE_WIRE_RAW) - { + if (self->servicetype == THREE_WIRE_RAW) { DEBUG(0,__FUNCTION__"():THREE_WIRE_RAW is not implemented\n"); } @@ -676,7 +675,7 @@ static void issue_control_request(struct ircomm_cb *self, { printk( __FUNCTION__"():ttp_data_request failed\n"); if(userdata) - dev_kfree_skb( userdata); + dev_kfree_skb(userdata); } else self->tx_controls++; @@ -701,7 +700,7 @@ static void process_data(struct ircomm_cb *self, struct sk_buff *skb ) /* ircomm_parse_control(self, skb, CONTROL_CHANNEL); */ - if(self->notify.data_indication && skb->len) + if (self->notify.data_indication && skb->len) self->notify.data_indication(self->notify.instance, self, skb); } @@ -728,7 +727,7 @@ static void ircomm_do_event( struct ircomm_cb *self, IRCOMM_EVENT event, DEBUG( 4, __FUNCTION__": STATE = %s, EVENT = %s\n", ircommstate[self->state], ircommevent[event]); - (*state[ self->state ]) ( self, event, skb); + (*state[self->state])(self, event, skb); } static void ircomm_next_state( struct ircomm_cb *self, IRCOMM_STATE state) @@ -747,7 +746,7 @@ static void ircomm_next_state( struct ircomm_cb *self, IRCOMM_STATE state) static void ircomm_state_idle( struct ircomm_cb *self, IRCOMM_EVENT event, struct sk_buff *skb ) { - switch(event){ + switch (event){ case IRCOMM_CONNECT_REQUEST: /* ircomm_next_state(self, COMM_WAITI); */ @@ -779,7 +778,8 @@ static void ircomm_state_idle( struct ircomm_cb *self, IRCOMM_EVENT event, /* * ircomm_state_discoverywait */ -static void ircomm_state_discoverywait(struct ircomm_cb *self, IRCOMM_EVENT event, +static void ircomm_state_discoverywait(struct ircomm_cb *self, + IRCOMM_EVENT event, struct sk_buff *skb ) { switch(event){ @@ -817,11 +817,11 @@ static void ircomm_state_discoverywait(struct ircomm_cb *self, IRCOMM_EVENT even * ircomm_state_queryparamwait */ -static void ircomm_state_queryparamwait(struct ircomm_cb *self, IRCOMM_EVENT event, - struct sk_buff *skb ) +static void ircomm_state_queryparamwait(struct ircomm_cb *self, + IRCOMM_EVENT event, + struct sk_buff *skb) { - switch(event){ - + switch (event) { case TTP_CONNECT_INDICATION: ircomm_next_state(self, COMM_WAITR); @@ -855,10 +855,11 @@ static void ircomm_state_queryparamwait(struct ircomm_cb *self, IRCOMM_EVENT eve * ircomm_state_querylsapwait */ -static void ircomm_state_querylsapwait(struct ircomm_cb *self, IRCOMM_EVENT event, +static void ircomm_state_querylsapwait(struct ircomm_cb *self, + IRCOMM_EVENT event, struct sk_buff *skb ) { - switch(event){ + switch (event) { case TTP_CONNECT_INDICATION: @@ -898,10 +899,10 @@ static void ircomm_state_querylsapwait(struct ircomm_cb *self, IRCOMM_EVENT even static void ircomm_state_waiti(struct ircomm_cb *self, IRCOMM_EVENT event, struct sk_buff *skb ) { - switch(event){ + switch (event) { case TTP_CONNECT_CONFIRM: ircomm_next_state(self, COMM_CONN); - connect_confirmation( self, skb ); + connect_confirm(self, skb ); break; case TTP_DISCONNECT_INDICATION: ircomm_next_state(self, COMM_IDLE); @@ -921,21 +922,18 @@ 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){ + switch (event) { case IRCOMM_CONNECT_RESPONSE: /* issue_connect_response */ - if(self->servicetype==THREE_WIRE_RAW){ + if (self->servicetype==THREE_WIRE_RAW) { DEBUG(0,__FUNCTION__"():3WIRE_RAW is not implemented\n"); /* irlmp_connect_response(Vpeersap, * ACCEPT,null); @@ -987,7 +985,7 @@ 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 ) { - switch(event){ + switch (event) { case TTP_DATA_INDICATION: process_data(self, skb); break; @@ -1033,8 +1031,6 @@ static void ircomm_state_conn(struct ircomm_cb *self, IRCOMM_EVENT event, } } - - /* * ---------------------------------------------------------------------- * IrCOMM service interfaces and supporting functions @@ -1042,12 +1038,12 @@ static void ircomm_state_conn(struct ircomm_cb *self, IRCOMM_EVENT event, * ---------------------------------------------------------------------- */ -/* - * start_discovering() +/* + * Function start_discovering (self) + * + * Start discovering and enter DISCOVERY_WAIT state * - * start discovering and enter DISCOVERY_WAIT state */ - static void start_discovering(struct ircomm_cb *self) { __u16 hints; @@ -1092,19 +1088,26 @@ static void start_discovering(struct ircomm_cb *self) /* * queryias_done(self) * - * called when discovery process got wrong results, completed, or terminated. + * */ +/* + * Function queryias_done (self) + * + * Called when discovery process got wrong results, completed, or + * terminated. + * + */ static void queryias_done(struct ircomm_cb *self) { DEBUG(0, __FUNCTION__"():\n"); - if(self->queryias_lock){ + if (self->queryias_lock){ self->queryias_lock = 0; discovering_instance = NULL; MOD_DEC_USE_COUNT; irlmp_unregister_client(self->ckey); } - if(ircomm_cs != 1) + if (ircomm_cs != 1) irlmp_unregister_service(self->skey); return; } @@ -1120,7 +1123,6 @@ static void query_parameters(struct ircomm_cb *self) ircomm_getvalue_confirm, self ); } - static void query_lsapsel(struct ircomm_cb * self) { DEBUG(0, __FUNCTION__"():querying IAS: Lsapsel...\n"); @@ -1135,13 +1137,13 @@ static void query_lsapsel(struct ircomm_cb * self) } } -/* - * ircomm_connect_request() - * Impl. of this function is differ from one of the reference. - * This functin does discovery as well as sending connect request +/* + * Function ircomm_connect_request (self, servicetype) + * + * Impl. of this function is differ from one of the reference. This + * function does discovery as well as sending connect request + * */ - - void ircomm_connect_request(struct ircomm_cb *self, __u8 servicetype) { /* @@ -1158,12 +1160,12 @@ void ircomm_connect_request(struct ircomm_cb *self, __u8 servicetype) self->servicetype= servicetype; /* ircomm_control_request(self, SERVICETYPE); */ /*servictype*/ - self->maxsdusize = SAR_DISABLE; - ircomm_do_event( self, IRCOMM_CONNECT_REQUEST, NULL); + self->max_sdu_size = SAR_DISABLE; + ircomm_do_event(self, IRCOMM_CONNECT_REQUEST, NULL); } void ircomm_connect_response(struct ircomm_cb *self, struct sk_buff *userdata, - __u32 maxsdusize) + __u32 max_sdu_size) { ASSERT( self != NULL, return;); @@ -1177,10 +1179,11 @@ void ircomm_connect_response(struct ircomm_cb *self, struct sk_buff *userdata, * and send it with connect_response */ - if(!userdata){ + if (!userdata){ /* FIXME: check for errors and initialize? DB */ userdata = dev_alloc_skb(COMM_DEFAULT_DATA_SIZE); - ASSERT(userdata != NULL, return;); + if (userdata == NULL) + return; skb_reserve(userdata,COMM_HEADER_SIZE); } @@ -1188,9 +1191,10 @@ void ircomm_connect_response(struct ircomm_cb *self, struct sk_buff *userdata, /* enable null-modem emulation (i.e. server mode )*/ self->null_modem_mode = 1; - self->maxsdusize = maxsdusize; - if(maxsdusize != SAR_DISABLE) - self->max_txbuff_size = maxsdusize; + self->max_sdu_size = max_sdu_size; + if (max_sdu_size != SAR_DISABLE) + self->max_txbuff_size = max_sdu_size; + ircomm_do_event(self, IRCOMM_CONNECT_RESPONSE, userdata); } @@ -1341,14 +1345,13 @@ static void append_tuple(struct ircomm_cb *self, __u8 instruction, __u8 pl , self->control_ch_pending = 1; } - - /* - * ircomm_control_request(); - * this function is exported as a request to send some control-channel tuples - * to peer device + * Function ircomm_control_request (self, instruction) + * + * This function is exported as a request to send some control-channel + * tuples * to peer device + * */ - void ircomm_control_request(struct ircomm_cb *self, __u8 instruction) { diff --git a/net/irda/ircomm/irvtd_driver.c b/net/irda/ircomm/irvtd_driver.c index 2df2fdd6015d..356913ff4cf8 100644 --- a/net/irda/ircomm/irvtd_driver.c +++ b/net/irda/ircomm/irvtd_driver.c @@ -8,7 +8,7 @@ * Source: serial.c by Linus Torvalds * isdn_tty.c by Fritz Elfert * - * Copyright (c) 1998, Takahide Higuchi, , + * Copyright (c) 1998-1999, Takahide Higuchi, , * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -341,15 +341,15 @@ static void irvtd_send_data_request(struct irvtd_cb *driver) *********************************************************************** */ - /* * Function irvtd_connect_confirm (instance, sap, qos, max_sdu_size, skb) * - * ircomm_connect_request which we have send have succeed! + * ircomm_connect_request which we have send, has succeeded! * */ void irvtd_connect_confirm(void *instance, void *sap, struct qos_info *qos, - __u32 max_sdu_size, struct sk_buff *skb) + __u32 max_sdu_size, __u8 max_header_size, + struct sk_buff *skb) { struct irvtd_cb *driver = (struct irvtd_cb *)instance; ASSERT(driver != NULL, return;); @@ -364,7 +364,7 @@ void irvtd_connect_confirm(void *instance, void *sap, struct qos_info *qos, /* * sending initial control parameters here */ - if(driver->comm->servicetype == THREE_WIRE_RAW) + if (driver->comm->servicetype == THREE_WIRE_RAW) return; /* do nothing */ driver->comm->dte |= (MCR_DTR | MCR_RTS | DELTA_DTR | DELTA_RTS); @@ -376,7 +376,7 @@ void irvtd_connect_confirm(void *instance, void *sap, struct qos_info *qos, ircomm_control_request(driver->comm, XON_XOFF_CHAR); /* ircomm_control_request(driver->comm, ENQ_ACK_CHAR); */ - switch(driver->comm->servicetype){ + switch (driver->comm->servicetype) { case CENTRONICS: break; @@ -397,17 +397,18 @@ void irvtd_connect_confirm(void *instance, void *sap, struct qos_info *qos, * */ void irvtd_connect_indication(void *instance, void *sap, struct qos_info *qos, - __u32 max_sdu_size, struct sk_buff *skb) + __u32 max_sdu_size, __u8 max_header_size, + struct sk_buff *skb) { - struct irvtd_cb *driver = (struct irvtd_cb *)instance; struct ircomm_cb *comm = (struct ircomm_cb *)sap; + ASSERT(driver != NULL, return;); ASSERT(driver->magic == IRVTD_MAGIC, return;); ASSERT(comm != NULL, return;); ASSERT(comm->magic == IRCOMM_MAGIC, return;); - DEBUG(4,"irvtd_connect_indication:sending connect_response...\n"); + DEBUG(4, __FUNCTION__ "():sending connect_response...\n"); ircomm_connect_response(comm, NULL, SAR_DISABLE ); @@ -416,7 +417,7 @@ void irvtd_connect_indication(void *instance, void *sap, struct qos_info *qos, /* * send initial control parameters */ - if(driver->comm->servicetype == THREE_WIRE_RAW) + if (driver->comm->servicetype == THREE_WIRE_RAW) return; /* do nothing */ driver->comm->dte |= (MCR_DTR | MCR_RTS | DELTA_DTR | DELTA_RTS); @@ -426,6 +427,7 @@ void irvtd_connect_indication(void *instance, void *sap, struct qos_info *qos, ircomm_control_request(driver->comm, DTELINE_STATE); break; default: + DEBUG(0, __FUNCTION__ "(), not implemented!\n"); } @@ -576,6 +578,7 @@ void irvtd_control_indication(void *instance, void *sap, IRCOMM_CMD cmd) case DATA_RATE: case XON_XOFF_CHAR: case DTELINE_STATE: + case ENQ_ACK_CHAR: /* got this from win95 */ /* (maybe) nothing to do */ break; default: @@ -778,7 +781,7 @@ static int irvtd_startup(struct irvtd_cb *driver) skb_queue_head_init(&driver->rxbuff); driver->txbuff = dev_alloc_skb(COMM_DEFAULT_DATA_SIZE); if (!driver->txbuff){ - DEBUG(0,__FUNCTION__"():alloc_skb failed!\n"); + DEBUG(0,__FUNCTION__"(), alloc_skb failed!\n"); return -ENOMEM; } skb_reserve(driver->txbuff, COMM_HEADER_SIZE); @@ -793,9 +796,8 @@ static int irvtd_startup(struct irvtd_cb *driver) irvtd_notify.instance = driver; driver->comm = ircomm_open_instance(irvtd_notify); - if(!driver->comm){ + if (!driver->comm) return -ENODEV; - } /* diff --git a/net/irda/irda_device.c b/net/irda/irda_device.c index cf9e6ea3441d..d6452769fa7b 100644 --- a/net/irda/irda_device.c +++ b/net/irda/irda_device.c @@ -6,10 +6,10 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Wed Sep 2 20:22:08 1998 - * Modified at: Wed Apr 21 09:48:19 1999 + * Modified at: Mon May 10 23:02:47 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli, All Rights Reserved. + * Copyright (c) 1998-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 @@ -31,6 +31,8 @@ #include #include #include +#include +#include #include #include @@ -53,7 +55,8 @@ extern int tekram_init(void); extern int actisys_init(void); extern int girbil_init(void); -hashbin_t *irda_device = NULL; +static hashbin_t *irda_device = NULL; +static hashbin_t *dongles = NULL; /* Netdevice functions */ static int irda_device_net_rebuild_header(struct sk_buff *skb); @@ -61,9 +64,9 @@ 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_set_config( struct device *dev, struct ifmap *map); -static int irda_device_net_change_mtu( struct device *dev, int new_mtu); - +static int irda_device_net_set_config(struct device *dev, struct ifmap *map); +static int irda_device_net_change_mtu(struct device *dev, int new_mtu); +static int irda_device_net_ioctl(struct device *dev, struct ifreq *rq,int cmd); #ifdef CONFIG_PROC_FS int irda_device_proc_read( char *buf, char **start, off_t offset, int len, int unused); @@ -74,8 +77,15 @@ __initfunc(int irda_device_init( void)) { /* Allocate master array */ irda_device = hashbin_new( HB_LOCAL); - if ( irda_device == NULL) { - printk( KERN_WARNING "IrDA: Can't allocate irda_device hashbin!\n"); + if (irda_device == NULL) { + WARNING("IrDA: Can't allocate irda_device hashbin!\n"); + return -ENOMEM; + } + + dongles = hashbin_new(HB_LOCAL); + if (dongles == NULL) { + printk(KERN_WARNING + "IrDA: Can't allocate dongles hashbin!\n"); return -ENOMEM; } @@ -113,6 +123,7 @@ void irda_device_cleanup(void) ASSERT(irda_device != NULL, return;); + hashbin_delete(dongles, NULL); hashbin_delete(irda_device, (FREE_FUNC) irda_device_close); } @@ -238,7 +249,7 @@ void __irda_device_close(struct irda_device *self) /* * Function irda_device_close (self) * - * + * Close the device * */ void irda_device_close(struct irda_device *self) @@ -248,6 +259,10 @@ void irda_device_close(struct irda_device *self) ASSERT(self != NULL, return;); ASSERT(self->magic == IRDA_DEVICE_MAGIC, return;); + /* We are not using any dongle anymore! */ + if (self->dongle) + self->dongle->close(self); + /* Stop and remove instance of IrLAP */ if (self->irlap) irlap_close(self->irlap); @@ -298,15 +313,19 @@ static void __irda_device_change_speed(struct irda_device *self, int speed) */ if (self->wait_until_sent) { self->wait_until_sent(self); + + if (self->dongle) + self->dongle->change_speed(self, speed); + if (self->change_speed) { self->change_speed(self, speed); - + /* Update the QoS value only */ self->qos.baud_rate.value = speed; } } else { - printk(KERN_WARNING "wait_until_sent() " - "has not implemented by the IrDA device driver!\n"); + WARNING("IrDA: wait_until_sent() " + "has not implemented by the IrDA device driver!\n"); } } @@ -386,6 +405,7 @@ int irda_device_setup(struct device *dev) 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->do_ioctl = irda_device_net_ioctl; dev->hard_header_len = 0; dev->addr_len = 0; @@ -444,6 +464,125 @@ static int irda_device_net_change_mtu( struct device *dev, int new_mtu) return 0; } +static int irda_device_net_ioctl(struct device *dev, /* ioctl device */ + struct ifreq *rq, /* Data passed */ + int cmd) /* Ioctl number */ +{ + unsigned long flags; + int ret = 0; +#ifdef WIRELESS_EXT + struct iwreq *wrq = (struct iwreq *) rq; +#endif + struct irda_device *self; + + DEBUG(4, __FUNCTION__ "()\n"); + + ASSERT(dev != NULL, return -1;); + + self = (struct irda_device *) dev->priv; + + ASSERT(self != NULL, return -1;); + ASSERT(self->magic == IRDA_DEVICE_MAGIC, return -1;); + + DEBUG(0, "%s: ->irda_device_net_ioctl(cmd=0x%X)\n", dev->name, cmd); + + /* Disable interrupts & save flags */ + save_flags(flags); + cli(); + + /* Look what is the request */ + switch (cmd) { +#ifdef WIRELESS_EXT + case SIOCGIWNAME: + /* Get name */ + strcpy(wrq->u.name, self->name); + break; + case SIOCSIWNWID: + /* Set domain */ + if (wrq->u.nwid.on) { + + } break; + case SIOCGIWNWID: + /* Read domain*/ +/* wrq->u.nwid.nwid = domain; */ +/* wrq->u.nwid.on = 1; */ + break; + case SIOCGIWENCODE: + /* Get scramble key */ + /* wrq->u.encoding.code = scramble_key; */ +/* wrq->u.encoding.method = 1; */ + break; + case SIOCSIWENCODE: + /* Set scramble key */ + /* scramble_key = wrq->u.encoding.code; */ + break; + case SIOCGIWRANGE: + /* Basic checking... */ + if(wrq->u.data.pointer != (caddr_t) 0) { + struct iw_range range; + + /* Verify the user buffer */ + ret = verify_area(VERIFY_WRITE, wrq->u.data.pointer, + sizeof(struct iw_range)); + if(ret) + break; + + /* Set the length (useless : its constant...) */ + wrq->u.data.length = sizeof(struct iw_range); + + /* Set information in the range struct */ + range.throughput = 1.6 * 1024 * 1024; /* don't argue on this ! */ + range.min_nwid = 0x0000; + range.max_nwid = 0x01FF; + + range.num_channels = range.num_frequency = 0; + + range.sensitivity = 0x3F; + range.max_qual.qual = 255; + range.max_qual.level = 255; + range.max_qual.noise = 0; + + /* Copy structure to the user buffer */ + copy_to_user(wrq->u.data.pointer, &range, + sizeof(struct iw_range)); + } + break; + case SIOCGIWPRIV: + /* Basic checking... */ +#if 0 + if (wrq->u.data.pointer != (caddr_t) 0) { + struct iw_priv_args priv[] = + { /* cmd, set_args, get_args, name */ + { SIOCGIPSNAP, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 0, + sizeof(struct site_survey), + "getsitesurvey" }, + }; + + /* Verify the user buffer */ + ret = verify_area(VERIFY_WRITE, wrq->u.data.pointer, + sizeof(priv)); + if (ret) + break; + + /* Set the number of ioctl available */ + wrq->u.data.length = 1; + + /* Copy structure to the user buffer */ + copy_to_user(wrq->u.data.pointer, (u_char *) priv, + sizeof(priv)); + } +#endif + break; +#endif + default: + ret = -EOPNOTSUPP; + } + + restore_flags(flags); + + return ret; +} + /* * Function irda_device_transmit_finished (void) * @@ -451,7 +590,7 @@ static int irda_device_net_change_mtu( struct device *dev, int new_mtu) * device. Maybe we should use: q->q.qlen == 0. * */ -int irda_device_txqueue_empty( struct irda_device *self) +int irda_device_txqueue_empty(struct irda_device *self) { ASSERT(self != NULL, return -1;); ASSERT(self->magic == IRDA_DEVICE_MAGIC, return -1;); @@ -462,6 +601,117 @@ int irda_device_txqueue_empty( struct irda_device *self) return TRUE; } +/* + * Function irda_device_init_dongle (self, type) + * + * Initialize attached dongle. Warning, must be called with a process + * context! + */ +void irda_device_init_dongle(struct irda_device *self, int type) +{ + struct dongle_q *node; + + ASSERT(self != NULL, return;); + ASSERT(self->magic == IRDA_DEVICE_MAGIC, return;); + +#ifdef CONFIG_KMOD + /* Try to load the module needed */ + switch (type) { + case ESI_DONGLE: + MESSAGE("IrDA: Initializing ESI dongle!\n"); + request_module("esi"); + break; + case TEKRAM_DONGLE: + MESSAGE("IrDA: Initializing Tekram dongle!\n"); + request_module("tekram"); + break; + case ACTISYS_DONGLE: /* FALLTHROUGH */ + case ACTISYS_PLUS_DONGLE: + MESSAGE("IrDA: Initializing ACTiSYS dongle!\n"); + request_module("actisys"); + break; + case GIRBIL_DONGLE: + MESSAGE("IrDA: Initializing GIrBIL dongle!\n"); + request_module("girbil"); + break; + case LITELINK_DONGLE: + MESSAGE("IrDA: Initializing Litelink dongle!\n"); + request_module("litelink"); + break; + default: + ERROR("Unknown dongle type!\n"); + return; + } +#endif /* CONFIG_KMOD */ + + node = hashbin_find(dongles, type, NULL); + if (!node) { + ERROR("IrDA: Unable to find requested dongle\n"); + return; + } + + /* Set the dongle to be used by this driver */ + self->dongle = node->dongle; + + /* Now initialize the dongle! */ + node->dongle->open(self, type); + node->dongle->qos_init(self, &self->qos); + + /* Reset dongle */ + node->dongle->reset(self, 0); + + /* Set to default baudrate */ + irda_device_change_speed(self, 9600); +} + +/* + * Function irda_device_register_dongle (dongle) + * + * + * + */ +int irda_device_register_dongle(struct dongle *dongle) +{ + struct dongle_q *new; + + /* Check if this dongle has been registred before */ + if (hashbin_find(dongles, dongle->type, NULL)) { + MESSAGE(__FUNCTION__ "(), Dongle already registered\n"); + return 0; + } + + /* Make new IrDA dongle */ + new = (struct dongle_q *) kmalloc(sizeof(struct dongle_q), GFP_KERNEL); + if (new == NULL) + return -1; + + memset(new, 0, sizeof( struct dongle_q)); + new->dongle = dongle; + + /* Insert IrDA dongle into hashbin */ + hashbin_insert(dongles, (QUEUE *) new, dongle->type, NULL); + + return 0; +} + +/* + * Function irda_device_unregister_dongle (dongle) + * + * + * + */ +void irda_device_unregister_dongle(struct dongle *dongle) +{ + struct dongle_q *node; + + node = hashbin_remove(dongles, dongle->type, NULL); + if (!node) { + ERROR(__FUNCTION__ "(), dongle not found!\n"); + return; + } + kfree(node); +} + /* * Function setup_dma (idev, buffer, count, mode) * @@ -536,7 +786,7 @@ int irda_device_proc_read(char *buf, char **start, off_t offset, int len, self = (struct irda_device *) hashbin_get_first(irda_device); while ( self != NULL) { - len += sprintf(buf+len, "%s,", self->name); + len += sprintf(buf+len, "\n%s,", self->name); len += sprintf(buf+len, "\tbinding: %s\n", self->description); diff --git a/net/irda/iriap.c b/net/irda/iriap.c index b87ccbd02814..f3b752eb05fd 100644 --- a/net/irda/iriap.c +++ b/net/irda/iriap.c @@ -6,10 +6,10 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Thu Aug 21 00:02:07 1997 - * Modified at: Fri Apr 23 09:57:12 1999 + * Modified at: Sun May 9 15:59:05 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli , + * Copyright (c) 1998-1999 Dag Brattli , * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -62,12 +62,17 @@ static __u32 service_handle; 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_close(struct iriap_cb *self); static void iriap_disconnect_indication(void *instance, void *sap, LM_REASON reason, struct sk_buff *skb); static void iriap_connect_indication(void *instance, void *sap, struct qos_info *qos, __u32 max_sdu_size, + __u8 max_header_size, struct sk_buff *skb); +static void iriap_connect_confirm(void *instance, void *sap, + struct qos_info *qos, + __u32 max_sdu_size, __u8 max_header_size, + struct sk_buff *skb); static int iriap_data_indication(void *instance, void *sap, struct sk_buff *skb); @@ -181,7 +186,7 @@ struct iriap_cb *iriap_open( __u8 slsap_sel, int mode) 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); @@ -206,7 +211,7 @@ static void __iriap_close( struct iriap_cb *self) ASSERT( self != NULL, return;); ASSERT( self->magic == IAS_MAGIC, return;); - del_timer( &self->watchdog_timer); + del_timer(&self->watchdog_timer); self->magic = 0; @@ -260,7 +265,7 @@ static void iriap_disconnect_indication( void *instance, void *sap, 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"); @@ -284,9 +289,8 @@ static void iriap_disconnect_indication( void *instance, void *sap, NULL); } - if ( userdata) { + if (userdata) dev_kfree_skb( userdata); - } } /* @@ -295,28 +299,28 @@ static void iriap_disconnect_indication( void *instance, void *sap, * * */ -void iriap_disconnect_request( struct iriap_cb *self) +void iriap_disconnect_request(struct iriap_cb *self) { struct sk_buff *skb; - DEBUG( 4, __FUNCTION__ "()\n"); + DEBUG(4, __FUNCTION__ "()\n"); - ASSERT( self != NULL, return;); - ASSERT( self->magic == IAS_MAGIC, return;); + ASSERT(self != NULL, return;); + ASSERT(self->magic == IAS_MAGIC, return;); - skb = dev_alloc_skb( 64); + skb = dev_alloc_skb(64); if (skb == NULL) { - DEBUG( 0, __FUNCTION__ - "(), 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; } /* - * Reserve space for MUX and LAP header + * Reserve space for MUX control and LAP header */ - skb_reserve( skb, LMP_CONTROL_HEADER+LAP_HEADER); + skb_reserve(skb, LMP_MAX_HEADER); - irlmp_disconnect_request( self->lsap, skb); + irlmp_disconnect_request(self->lsap, skb); } void iriap_getinfobasedetails_request(void) @@ -381,7 +385,7 @@ void iriap_getvaluebyclass_request(char *name, char *attr, /* Give ourselves 10 secs to finish this operation */ iriap_start_watchdog_timer(self, 10*HZ); - skb = dev_alloc_skb( 64); + skb = dev_alloc_skb(64); if (!skb) return; @@ -389,7 +393,7 @@ void iriap_getvaluebyclass_request(char *name, char *attr, attr_len = strlen(attr); /* Reserve space for MUX and LAP header */ - skb_reserve(skb, LMP_CONTROL_HEADER+LAP_HEADER); + skb_reserve(skb, self->max_header_size); skb_put(skb, 3+name_len+attr_len); frame = skb->data; @@ -535,13 +539,13 @@ void iriap_getvaluebyclass_response(struct iriap_cb *self, __u16 obj_id, * 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(value->len + LMP_HEADER + LAP_HEADER + 9); + skb = dev_alloc_skb(value->len + self->max_header_size + 9); if (!skb) return; /* Reserve space for MUX and LAP header */ - skb_reserve( skb, LMP_HEADER+LAP_HEADER); - skb_put( skb, 6); + skb_reserve(skb, self->max_header_size); + skb_put(skb, 6); fp = skb->data; @@ -666,7 +670,7 @@ void iriap_getvaluebyclass_indication(struct iriap_cb *self, /* * Function iriap_send_ack (void) * - * + * Currently not used * */ void iriap_send_ack( struct iriap_cb *self) @@ -679,13 +683,13 @@ void iriap_send_ack( struct iriap_cb *self) ASSERT( self != NULL, return;); ASSERT( self->magic == IAS_MAGIC, return;); - skb = dev_alloc_skb( 64); + skb = dev_alloc_skb(64); if (!skb) return; /* Reserve space for MUX and LAP header */ - skb_reserve( skb, 4); - skb_put( skb, 3); + skb_reserve(skb, self->max_header_size); + skb_put(skb, 1); frame = skb->data; /* Build frame */ @@ -698,8 +702,10 @@ void iriap_send_ack( struct iriap_cb *self) * LSAP connection confirmed! * */ -void iriap_connect_confirm(void *instance, void *sap, struct qos_info *qos, - __u32 max_sdu_size, struct sk_buff *userdata) +static void iriap_connect_confirm(void *instance, void *sap, + struct qos_info *qos, + __u32 max_sdu_size, __u8 header_size, + struct sk_buff *userdata) { struct iriap_cb *self; @@ -711,7 +717,7 @@ void iriap_connect_confirm(void *instance, void *sap, struct qos_info *qos, DEBUG(4, __FUNCTION__ "()\n"); - /* del_timer( &self->watchdog_timer); */ + del_timer(&self->watchdog_timer); iriap_do_client_event(self, IAP_LM_CONNECT_CONFIRM, userdata); } @@ -724,19 +730,17 @@ void iriap_connect_confirm(void *instance, void *sap, struct qos_info *qos, */ static void iriap_connect_indication(void *instance, void *sap, struct qos_info *qos, __u32 max_sdu_size, + __u8 header_size, struct sk_buff *userdata) { struct iriap_cb *self; - DEBUG( 4, __FUNCTION__ "()\n"); - - self = ( struct iriap_cb *) instance; + self = (struct iriap_cb *) instance; - ASSERT( self != NULL, return;); - ASSERT( self->magic == IAS_MAGIC, return;); - ASSERT( self->mode == IAS_SERVER, return;); + ASSERT(self != NULL, return;); + ASSERT(self->magic == IAS_MAGIC, return;); - iriap_do_server_event( self, IAP_LM_CONNECT_INDICATION, userdata); + iriap_do_server_event(self, IAP_LM_CONNECT_INDICATION, userdata); } /* @@ -856,7 +860,7 @@ void iriap_call_indication( struct iriap_cb *self, struct sk_buff *skb) } opcode &= 0x7f; /* Mask away LST bit */ - switch( opcode) { + switch (opcode) { case GET_INFO_BASE: DEBUG( 0, "IrLMP GetInfoBaseDetails not implemented!\n"); break; diff --git a/net/irda/iriap_event.c b/net/irda/iriap_event.c index ccba78ecefc2..18a70fec3e6a 100644 --- a/net/irda/iriap_event.c +++ b/net/irda/iriap_event.c @@ -6,10 +6,10 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Thu Aug 21 00:02:07 1997 - * Modified at: Tue Jan 26 12:29:36 1999 + * Modified at: Sun May 9 11:01:47 1999 * Modified by: Dag Brattli * - * Copyright (c) 1997 Dag Brattli , All Rights Reserved. + * Copyright (c) 1997, 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 @@ -387,9 +387,9 @@ static void state_r_disconnect( struct iriap_cb *self, IRIAP_EVENT event, } /* Reserve space for MUX_CONTROL and LAP header */ - skb_reserve( tx_skb, LMP_CONTROL_HEADER+LAP_HEADER); + skb_reserve(tx_skb, LMP_MAX_HEADER); - irlmp_connect_response( self->lsap, tx_skb); + irlmp_connect_response(self->lsap, tx_skb); /*LM_Idle_request(idle); */ iriap_next_server_state( self, R_CALL); diff --git a/net/irda/irlan/irlan_client.c b/net/irda/irlan/irlan_client.c index f2f8271cf5a0..66b94eec8092 100644 --- a/net/irda/irlan/irlan_client.c +++ b/net/irda/irlan/irlan_client.c @@ -6,13 +6,14 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sun Aug 31 20:14:37 1997 - * Modified at: Thu Apr 22 23:03:55 1999 + * Modified at: Tue May 11 00:22:39 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. + * Copyright (c) 1998-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 @@ -61,6 +62,7 @@ static int irlan_client_ctrl_data_indication(void *instance, void *sap, static void irlan_client_ctrl_connect_confirm(void *instance, void *sap, struct qos_info *qos, __u32 max_sdu_size, + __u8 max_header_size, struct sk_buff *); static void irlan_check_response_param(struct irlan_cb *self, char *param, char *value, int val_len); @@ -79,7 +81,7 @@ static void irlan_client_kick_timer_expired(unsigned long data) * 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) && + if ((self->provider.access_type == ACCESS_PEER) && (self->client.state == IRLAN_IDLE) && (self->provider.state != IRLAN_IDLE)) { irlan_client_wakeup(self, self->saddr, self->daddr); @@ -105,23 +107,29 @@ void irlan_client_wakeup(struct irlan_cb *self, __u32 saddr, __u32 daddr) { struct irmanager_event mgr_event; - DEBUG(0, __FUNCTION__ "()\n"); + DEBUG(1, __FUNCTION__ "()\n"); ASSERT(self != NULL, return;); ASSERT(self->magic == IRLAN_MAGIC, return;); - /* Check if we are already awake */ - if (self->client.state != IRLAN_IDLE) + /* + * Check if we are already awake, or if we are a provider in direct + * mode (in that case we must leave the client idle + */ + if ((self->client.state != IRLAN_IDLE) || + (self->provider.access_type == ACCESS_DIRECT)) return; /* saddr may have changed! */ self->saddr = saddr; - /* Check if network device is up */ + /* Before we try to connect, we check if network device is up. If it + * is up, that means that the "user" really wants to connect. If not + * we notify the user about the possibility of an IrLAN connection + */ 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); @@ -161,7 +169,7 @@ void irlan_client_discovery_indication(discovery_t *discovery) struct irlan_cb *self, *entry; __u32 saddr, daddr; - DEBUG(0, __FUNCTION__"()\n"); + DEBUG(1, __FUNCTION__"()\n"); ASSERT(irlan != NULL, return;); ASSERT(discovery != NULL, return;); @@ -176,7 +184,8 @@ void irlan_client_discovery_indication(discovery_t *discovery) if (self) { ASSERT(self->magic == IRLAN_MAGIC, return;); - DEBUG(2, __FUNCTION__ "(), Found instance!\n"); + DEBUG(1, __FUNCTION__ "(), Found instance (%08x)!\n", + daddr); irlan_client_wakeup(self, saddr, daddr); @@ -184,30 +193,13 @@ void irlan_client_discovery_indication(discovery_t *discovery) } /* - * We have no instance for daddr, so try and find an unused one + * We have no instance for daddr, so start a new one */ - self = hashbin_find(irlan, DEV_ADDR_ANY, NULL); - if (self) { - DEBUG(0, __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(1, __FUNCTION__ "(), starting new instance!\n"); + self = irlan_open(saddr, daddr, TRUE); - DEBUG(0, __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); - - /* Restart watchdog timer */ - irlan_start_watchdog_timer(self, IRLAN_TIMEOUT); - } + /* Restart watchdog timer */ + irlan_start_watchdog_timer(self, IRLAN_TIMEOUT); } /* @@ -302,6 +294,7 @@ void irlan_client_open_ctrl_tsap(struct irlan_cb *self) static void irlan_client_ctrl_connect_confirm(void *instance, void *sap, struct qos_info *qos, __u32 max_sdu_size, + __u8 max_header_size, struct sk_buff *skb) { struct irlan_cb *self; @@ -313,6 +306,9 @@ static void irlan_client_ctrl_connect_confirm(void *instance, void *sap, ASSERT(self != NULL, return;); ASSERT(self->magic == IRLAN_MAGIC, return;); + self->client.max_sdu_size = max_sdu_size; + self->client.max_header_size = max_header_size; + /* TODO: we could set the MTU depending on the max_sdu_size */ irlan_do_client_event(self, IRLAN_CONNECT_COMPLETE, NULL); @@ -339,7 +335,7 @@ void irlan_client_reconnect_data_channel(struct irlan_cb *self) return; /* Reserve space for TTP, LMP, and LAP header */ - skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER); + skb_reserve(skb, self->max_header_size); skb_put(skb, 2); frame = skb->data; @@ -410,11 +406,11 @@ void irlan_client_parse_response(struct irlan_cb *self, struct sk_buff *skb) /* For all parameters */ for (i=0; iaccess_type = ACCESS_DIRECT; + self->client.access_type = ACCESS_DIRECT; else if (strcmp(value, "PEER") == 0) - self->access_type = ACCESS_PEER; + self->client.access_type = ACCESS_PEER; else if (strcmp(value, "HOSTED") == 0) - self->access_type = ACCESS_HOSTED; + self->client.access_type = ACCESS_HOSTED; else { DEBUG(2, __FUNCTION__ "(), unknown access type!\n"); } diff --git a/net/irda/irlan/irlan_client_event.c b/net/irda/irlan/irlan_client_event.c index 1544c093e14d..682cda8540e9 100644 --- a/net/irda/irlan/irlan_client_event.c +++ b/net/irda/irlan/irlan_client_event.c @@ -6,10 +6,10 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sun Aug 31 20:14:37 1997 - * Modified at: Thu Apr 22 12:23:22 1999 + * Modified at: Thu May 6 13:42:38 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli , + * Copyright (c) 1998-1999 Dag Brattli , * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -97,7 +97,7 @@ static int irlan_client_state_idle(struct irlan_cb *self, IRLAN_EVENT event, ASSERT(self != NULL, return -1;); ASSERT(self->magic == IRLAN_MAGIC, return -1;); - switch(event) { + switch (event) { case IRLAN_DISCOVERY_INDICATION: /* Get some values from peer IAS */ iriap_getvaluebyclass_request( @@ -152,7 +152,7 @@ static int irlan_client_state_query(struct irlan_cb *self, IRLAN_EVENT event, irlan_next_client_state(self, IRLAN_IDLE); /* Give the client a kick! */ - if ((self->access_type == ACCESS_PEER) && + if ((self->provider.access_type == ACCESS_PEER) && (self->provider.state != IRLAN_IDLE)) irlan_client_wakeup(self, self->saddr, self->daddr); break; @@ -222,7 +222,7 @@ static int irlan_client_state_info(struct irlan_cb *self, IRLAN_EVENT event, ASSERT(self != NULL, return -1;); - switch(event) { + switch (event) { case IRLAN_DATA_INDICATION: ASSERT(skb != NULL, return -1;); @@ -314,7 +314,7 @@ static int irlan_client_state_open(struct irlan_cb *self, IRLAN_EVENT event, ASSERT(self->dtsap_sel_data != 0, return -1;); /* Check which access type we are dealing with */ - switch(self->access_type) { + switch (self->client.access_type) { case ACCESS_PEER: if (self->provider.state == IRLAN_OPEN) { diff --git a/net/irda/irlan/irlan_common.c b/net/irda/irlan/irlan_common.c index 6a30574ca765..1284d561a7fa 100644 --- a/net/irda/irlan/irlan_common.c +++ b/net/irda/irlan/irlan_common.c @@ -6,10 +6,11 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sun Aug 31 20:14:37 1997 - * Modified at: Thu Apr 22 23:13:47 1999 + * Modified at: Sun May 9 11:48:49 1999 * Modified by: Dag Brattli * - * Copyright (c) 1997 Dag Brattli , All Rights Reserved. + * Copyright (c) 1997, 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 @@ -93,19 +94,25 @@ 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); +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); extern struct proc_dir_entry *proc_irda; -#endif +#endif /* CONFIG_PROC_FS */ +/* + * Function irlan_watchdog_timer_expired (data) + * + * + * + */ void irlan_watchdog_timer_expired(unsigned long data) { struct irmanager_event mgr_event; - struct irlan_cb *self, *entry; + struct irlan_cb *self; DEBUG(0, __FUNCTION__ "()\n"); @@ -116,6 +123,7 @@ void irlan_watchdog_timer_expired(unsigned long data) /* Check if device still configured */ if (self->dev.start) { + DEBUG(0, __FUNCTION__ "(), notifying irmanager to stop irlan!\n"); mgr_event.event = EVENT_IRLAN_STOP; sprintf(mgr_event.devname, "%s", self->ifname); irmanager_notify(&mgr_event); @@ -128,22 +136,13 @@ void irlan_watchdog_timer_expired(unsigned long data) */ self->notify_irmanager = FALSE; } else { - DEBUG(0, __FUNCTION__ "(), recycling instance!\n"); + DEBUG(0, __FUNCTION__ "(), closing instance!\n"); if (self->netdev_registered) { DEBUG(0, __FUNCTION__ "(), removing netdev!\n"); unregister_netdev(&self->dev); self->netdev_registered = FALSE; } - - /* Unbind from daddr */ - entry = hashbin_remove(irlan, self->daddr, NULL); - ASSERT(entry == self, return;); - - self->daddr = DEV_ADDR_ANY; - self->saddr = DEV_ADDR_ANY; - - DEBUG(2, __FUNCTION__ "(), daddr=%08x\n", self->daddr); - hashbin_insert(irlan, (QUEUE*) self, self->daddr, NULL); + irlan_close(self); } } @@ -195,12 +194,12 @@ __initfunc(int irlan_init(void)) /* Register with IrLMP as a service */ skey = irlmp_register_service(hints); - /* Start the first IrLAN instance */ + /* Start the master IrLAN instance */ new = irlan_open(DEV_ADDR_ANY, DEV_ADDR_ANY, FALSE); - irlan_open_data_tsap(new); - irlan_client_open_ctrl_tsap(new); + /* The master will only open its (listen) control TSAP */ irlan_provider_open_ctrl_tsap(new); + new->master = TRUE; /* Do some fast discovery! */ irlmp_discovery_request(DISCOVERY_DEFAULT_SLOTS); @@ -293,7 +292,7 @@ struct irlan_cb *irlan_open(__u32 saddr, __u32 daddr, int netdev) self->daddr = daddr; /* Provider access can only be PEER, DIRECT, or HOSTED */ - self->access_type = access; + self->provider.access_type = access; self->media = MEDIA_802_3; self->notify_irmanager = TRUE; @@ -359,8 +358,11 @@ void irlan_close(struct irlan_cb *self) /* Check if device is still configured */ if (self->dev.start) { - DEBUG(2, __FUNCTION__ + DEBUG(0, __FUNCTION__ "(), Device still configured, closing later!\n"); + + /* Give it a chance to reconnect */ + irlan_start_watchdog_timer(self, IRLAN_TIMEOUT); return; } DEBUG(2, __FUNCTION__ "(), daddr=%08x\n", self->daddr); @@ -371,8 +373,15 @@ void irlan_close(struct irlan_cb *self) __irlan_close(self); } +/* + * Function irlan_connect_indication (instance, sap, qos, max_sdu_size, skb) + * + * Here we receive the connect indication for the data channel + * + */ void irlan_connect_indication(void *instance, void *sap, struct qos_info *qos, - __u32 max_sdu_size, struct sk_buff *skb) + __u32 max_sdu_size, __u8 max_header_size, + struct sk_buff *skb) { struct irlan_cb *self; struct tsap_cb *tsap; @@ -386,13 +395,17 @@ void irlan_connect_indication(void *instance, void *sap, struct qos_info *qos, ASSERT(self->magic == IRLAN_MAGIC, return;); ASSERT(tsap == self->tsap_data,return;); - DEBUG(2, "IrLAN, We are now connected!\n"); + self->max_sdu_size = max_sdu_size; + self->max_header_size = max_header_size; + + DEBUG(0, "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) { + if (self->provider.access_type == ACCESS_PEER) { /* * Data channel is open, so we are now allowed to * configure the remote filter @@ -400,12 +413,13 @@ void irlan_connect_indication(void *instance, void *sap, struct qos_info *qos, irlan_get_unicast_addr(self); irlan_open_unicast_addr(self); } - /* Ready to transfer Ethernet frames */ + /* Ready to transfer Ethernet frames (at last) */ self->dev.tbusy = 0; } void irlan_connect_confirm(void *instance, void *sap, struct qos_info *qos, - __u32 max_sdu_size, struct sk_buff *skb) + __u32 max_sdu_size, __u8 max_header_size, + struct sk_buff *skb) { struct irlan_cb *self; @@ -416,6 +430,9 @@ void irlan_connect_confirm(void *instance, void *sap, struct qos_info *qos, ASSERT(self != NULL, return;); ASSERT(self->magic == IRLAN_MAGIC, return;); + self->max_sdu_size = max_sdu_size; + self->max_header_size = max_header_size; + /* TODO: we could set the MTU depending on the max_sdu_size */ DEBUG(2, "IrLAN, We are now connected!\n"); @@ -444,7 +461,7 @@ void irlan_disconnect_indication(void *instance, void *sap, LM_REASON reason, struct irlan_cb *self; struct tsap_cb *tsap; - DEBUG(2, __FUNCTION__ "(), reason=%d\n", reason); + DEBUG(0, __FUNCTION__ "(), reason=%d\n", reason); self = (struct irlan_cb *) instance; tsap = (struct tsap_cb *) sap; @@ -460,7 +477,7 @@ void irlan_disconnect_indication(void *instance, void *sap, LM_REASON reason, switch(reason) { case LM_USER_REQUEST: /* User request */ - //irlan_close(self); + irlan_close(self); break; case LM_LAP_DISCONNECT: /* Unexpected IrLAP disconnect */ irlan_start_watchdog_timer(self, IRLAN_TIMEOUT); @@ -490,7 +507,7 @@ void irlan_open_data_tsap(struct irlan_cb *self) struct notify_t notify; struct tsap_cb *tsap; - DEBUG(4, __FUNCTION__ "()\n"); + DEBUG(0, __FUNCTION__ "()\n"); ASSERT(self != NULL, return;); ASSERT(self->magic == IRLAN_MAGIC, return;); @@ -500,7 +517,7 @@ void irlan_open_data_tsap(struct irlan_cb *self) return; irda_notify_init(¬ify); - + notify.data_indication = irlan_eth_receive; notify.udata_indication = irlan_eth_receive; notify.connect_indication = irlan_connect_indication; @@ -620,7 +637,7 @@ void irlan_get_provider_info(struct irlan_cb *self) return; /* Reserve space for TTP, LMP, and LAP header */ - skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER); + skb_reserve(skb, self->client.max_header_size); skb_put(skb, 2); frame = skb->data; @@ -651,7 +668,7 @@ void irlan_open_data_channel(struct irlan_cb *self) if (!skb) return; - skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER); + skb_reserve(skb, self->client.max_header_size); skb_put(skb, 2); frame = skb->data; @@ -683,7 +700,7 @@ void irlan_close_data_channel(struct irlan_cb *self) if (!skb) return; - skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER); + skb_reserve(skb, self->client.max_header_size); skb_put(skb, 2); frame = skb->data; @@ -719,7 +736,7 @@ void irlan_open_unicast_addr(struct irlan_cb *self) return; /* Reserve space for TTP, LMP, and LAP header */ - skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER); + skb_reserve(skb, self->max_header_size); skb_put(skb, 2); frame = skb->data; @@ -757,7 +774,7 @@ void irlan_set_broadcast_filter(struct irlan_cb *self, int status) return; /* Reserve space for TTP, LMP, and LAP header */ - skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER); + skb_reserve(skb, self->client.max_header_size); skb_put(skb, 2); frame = skb->data; @@ -796,7 +813,7 @@ void irlan_set_multicast_filter(struct irlan_cb *self, int status) return; /* Reserve space for TTP, LMP, and LAP header */ - skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER); + skb_reserve(skb, self->client.max_header_size); skb_put(skb, 2); frame = skb->data; @@ -836,7 +853,7 @@ void irlan_get_unicast_addr(struct irlan_cb *self) return; /* Reserve space for TTP, LMP, and LAP header */ - skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER); + skb_reserve(skb, self->client.max_header_size); skb_put(skb, 2); frame = skb->data; @@ -871,7 +888,7 @@ void irlan_get_media_char(struct irlan_cb *self) return; /* Reserve space for TTP, LMP, and LAP header */ - skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER); + skb_reserve(skb, self->client.max_header_size); skb_put(skb, 2); frame = skb->data; @@ -1033,7 +1050,7 @@ int irlan_extract_param(__u8 *buf, char *name, char *value, __u16 *len) /* get parameter name */ memcpy(name, buf+n, name_len); - name[ name_len] = '\0'; + name[name_len] = '\0'; n+=name_len; /* @@ -1051,7 +1068,7 @@ int irlan_extract_param(__u8 *buf, char *name, char *value, __u16 *len) /* get parameter value */ memcpy(value, buf+n, val_len); - value[ val_len] = '\0'; + value[val_len] = '\0'; n+=val_len; DEBUG(4, "Parameter: %s ", name); @@ -1085,31 +1102,35 @@ static int irlan_proc_read(char *buf, char **start, off_t offset, int len, while (self != NULL) { ASSERT(self->magic == IRLAN_MAGIC, return len;); - 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"); + /* Don't display the master server */ + if (self->master == 0) { + 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->client.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); } diff --git a/net/irda/irlan/irlan_eth.c b/net/irda/irlan/irlan_eth.c index c1965a11714f..26b16a196dcd 100644 --- a/net/irda/irlan/irlan_eth.c +++ b/net/irda/irlan/irlan_eth.c @@ -6,13 +6,13 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Thu Oct 15 08:37:58 1998 - * Modified at: Thu Apr 22 14:26:39 1999 + * Modified at: Mon May 10 20:23:49 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. + * Copyright (c) 1998-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 @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -67,19 +68,19 @@ int irlan_eth_init(struct device *dev) dev->tx_queue_len = TTP_MAX_QUEUE; -#if 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 + if (self->provider.access_type == ACCESS_DIRECT) { + /* + * Since we are emulating an IrLAN sever we will have to + * give ourself an ethernet address! + */ + dev->dev_addr[0] = 0x40; + dev->dev_addr[1] = 0x00; + dev->dev_addr[2] = 0x00; + dev->dev_addr[3] = 0x00; + get_random_bytes(dev->dev_addr+4, 1); + get_random_bytes(dev->dev_addr+5, 1); + } + /* * Network device has now been registered, so tell irmanager about * it, so it can be configured with network parameters @@ -180,8 +181,6 @@ int irlan_eth_xmit(struct sk_buff *skb, struct device *dev) { struct irlan_cb *self; - DEBUG(4, __FUNCTION__ "()\n"); - self = (struct irlan_cb *) dev->priv; ASSERT(self != NULL, return 0;); @@ -202,19 +201,19 @@ int irlan_eth_xmit(struct sk_buff *skb, struct device *dev) dev->trans_start = jiffies; } - 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 all IrDA-headers? */ + if ((skb_headroom(skb) < self->max_header_size) || (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;); + skb_realloc_headroom(skb, self->max_header_size); - /* Free original skb, and use the new one */ + /* We have to free the original skb anyway */ dev_kfree_skb(skb); + + /* Did the realloc succeed? */ + if (new_skb == NULL) + return 0; + + /* Use the new skb instead */ skb = new_skb; } @@ -222,31 +221,26 @@ int irlan_eth_xmit(struct sk_buff *skb, struct device *dev) self->stats.tx_packets++; self->stats.tx_bytes += skb->len; - /* - * Now queue the packet in the transport layer - * FIXME: clean up the code below! DB - */ - if (self->use_udata) { + /* Now queue the packet in the transport layer */ + 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) { - /* - * IrTTPs tx queue is full, so we just have to drop the - * frame! You might think that we should just return -1 - * and don't deallocate the frame, but that is dangerous - * since it's possible that we have replaced the original - * skb with a new one with larger headroom, and that would - * really confuse do_dev_queue_xmit() in dev.c! I have - * tried :-) DB - */ - dev_kfree_skb(skb); - ++self->stats.tx_dropped; + else { + if (irttp_data_request(self->tsap_data, skb) < 0) { + /* + * IrTTPs tx queue is full, so we just have to + * drop the frame! You might think that we should + * just return -1 and don't deallocate the frame, + * but that is dangerous since it's possible that + * we have replaced the original skb with a new + * one with larger headroom, and that would really + * confuse do_dev_queue_xmit() in dev.c! I have + * tried :-) DB + */ + dev_kfree_skb(skb); + ++self->stats.tx_dropped; - return 0; + return 0; + } } dev->tbusy = 0; /* Finished! */ @@ -314,26 +308,16 @@ void irlan_eth_flow_indication(void *instance, void *sap, LOCAL_FLOW flow) switch (flow) { case FLOW_STOP: - DEBUG(4, "IrLAN, stopping Ethernet layer\n"); - dev->tbusy = 1; break; case FLOW_START: - /* - * Tell upper layers that its time to transmit frames again - */ - DEBUG(4, "IrLAN, starting Ethernet layer\n"); - + default: + /* Tell upper layers that its time to transmit frames again */ dev->tbusy = 0; - /* - * Ready to receive more frames, so schedule the network - * layer - */ + /* Schedule network layer */ mark_bh(NET_BH); break; - default: - DEBUG(0, __FUNCTION__ "(), Unknown flow command!\n"); } } @@ -373,7 +357,7 @@ void irlan_etc_send_gratuitous_arp(struct device *dev) in_dev = dev->ip_ptr; arp_send(ARPOP_REQUEST, ETH_P_ARP, in_dev->ifa_list->ifa_address, - &dev, + dev, in_dev->ifa_list->ifa_address, NULL, dev->dev_addr, NULL); } diff --git a/net/irda/irlan/irlan_event.c b/net/irda/irlan/irlan_event.c index d54e7cc122c0..93d7c4efe10d 100644 --- a/net/irda/irlan/irlan_event.c +++ b/net/irda/irlan/irlan_event.c @@ -6,10 +6,10 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Tue Oct 20 09:10:16 1998 - * Modified at: Wed Feb 3 21:42:27 1999 + * Modified at: Sun May 9 21:17:44 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli, All Rights Reserved. + * Copyright (c) 1998-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 @@ -38,22 +38,22 @@ char *irlan_state[] = { "IRLAN_SYNC", }; -void irlan_next_client_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;); + ASSERT(self != NULL, return;); + ASSERT(self->magic == IRLAN_MAGIC, return;); self->client.state = state; } -void irlan_next_provider_state( struct irlan_cb *self, IRLAN_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;); + 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 index c4c1079dde7b..4f199e4ee74f 100644 --- a/net/irda/irlan/irlan_filter.c +++ b/net/irda/irlan/irlan_filter.c @@ -6,10 +6,10 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Fri Jan 29 11:16:38 1999 - * Modified at: Thu Feb 25 15:10:54 1999 + * Modified at: Sat May 8 15:25:23 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli, All Rights Reserved. + * Copyright (c) 1998-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 @@ -41,29 +41,29 @@ void handle_filter_request(struct irlan_cb *self, struct sk_buff *skb) (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) { + if (self->provider.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; + get_random_bytes(self->provider.mac_address+4, 1); + get_random_bytes(self->provider.mac_address+5, 1); } 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); + irlan_insert_array_param(skb, "FILTER_ENTRY", + self->provider.mac_address, 6); return; } @@ -138,8 +138,7 @@ void handle_filter_request(struct irlan_cb *self, struct sk_buff *skb) * Check parameters in request from peer device * */ -void irlan_check_command_param(struct irlan_cb *self, char *param, - char *value) +void irlan_check_command_param(struct irlan_cb *self, char *param, char *value) { __u8 *bytes; @@ -210,6 +209,12 @@ void irlan_check_command_param(struct irlan_cb *self, char *param, } } +/* + * Function irlan_print_filter (filter_type, buf) + * + * Print status of filter. Used by /proc file system + * + */ int irlan_print_filter(int filter_type, char *buf) { int len = 0; diff --git a/net/irda/irlan/irlan_provider.c b/net/irda/irlan/irlan_provider.c index 8e2c3c25ab89..947141872494 100644 --- a/net/irda/irlan/irlan_provider.c +++ b/net/irda/irlan/irlan_provider.c @@ -6,13 +6,14 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sun Aug 31 20:14:37 1997 - * Modified at: Thu Apr 22 14:28:52 1999 + * Modified at: Sun May 9 12:22:56 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. + * Copyright (c) 1998-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 @@ -31,6 +32,7 @@ #include #include #include +#include #include #include @@ -50,14 +52,20 @@ #include #include +static void irlan_provider_connect_indication(void *instance, void *sap, + struct qos_info *qos, + __u32 max_sdu_size, + __u8 max_header_size, + struct sk_buff *skb); + /* * Function irlan_provider_control_data_indication (handle, skb) * * This function gets the data that is received on the control channel * */ -int irlan_provider_data_indication(void *instance, void *sap, - struct sk_buff *skb) +static int irlan_provider_data_indication(void *instance, void *sap, + struct sk_buff *skb) { struct irlan_cb *self; __u8 code; @@ -111,14 +119,17 @@ int irlan_provider_data_indication(void *instance, void *sap, * Got connection from peer IrLAN layer * */ -void irlan_provider_connect_indication(void *instance, void *sap, - struct qos_info *qos, - __u32 max_sdu_size, struct sk_buff *skb) +static void irlan_provider_connect_indication(void *instance, void *sap, + struct qos_info *qos, + __u32 max_sdu_size, + __u8 max_header_size, + struct sk_buff *skb) { - struct irlan_cb *self, *entry, *new; + struct irlan_cb *self, *new; struct tsap_cb *tsap; + __u32 saddr, daddr; - DEBUG(2, __FUNCTION__ "()\n"); + DEBUG(0, __FUNCTION__ "()\n"); self = (struct irlan_cb *) instance; tsap = (struct tsap_cb *) sap; @@ -126,34 +137,69 @@ void irlan_provider_connect_indication(void *instance, void *sap, ASSERT(self != NULL, return;); ASSERT(self->magic == IRLAN_MAGIC, return;); + self->provider.max_sdu_size = max_sdu_size; + self->provider.max_header_size = max_header_size; + ASSERT(tsap == self->provider.tsap_ctrl,return;); ASSERT(self->provider.state == IRLAN_IDLE, return;); - /* Check if this provider is currently 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); + daddr = irttp_get_daddr(tsap); + saddr = irttp_get_saddr(tsap); + + /* Check if we already dealing with this client or peer */ + new = (struct irlan_cb *) hashbin_find(irlan, daddr, NULL); + if (new) { + ASSERT(new->magic == IRLAN_MAGIC, return;); + DEBUG(0, __FUNCTION__ "(), found instance!\n"); + + /* Update saddr, since client may have moved to a new link */ + new->saddr = saddr; + DEBUG(2, __FUNCTION__ "(), saddr=%08x\n", new->saddr); + + /* Make sure that any old provider control TSAP is removed */ + if ((new != self) && new->provider.tsap_ctrl) { + irttp_disconnect_request(new->provider.tsap_ctrl, + NULL, P_NORMAL); + irttp_close_tsap(new->provider.tsap_ctrl); + new->provider.tsap_ctrl = 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! + /* This must be the master instance, so start a new instance */ + DEBUG(0, __FUNCTION__ "(), starting new provider!\n"); + + new = irlan_open(saddr, daddr, TRUE); + } + + /* + * Check if the connection came in on the master server, or the + * slave server. If it came on the slave, then everything is + * really, OK (reconnect), if not we need to dup the connection and + * hand it over to the slave. + */ + if (new != self) { + + /* Now attach up the new "socket" */ + new->provider.tsap_ctrl = irttp_dup(self->provider.tsap_ctrl, + new); + if (!new->provider.tsap_ctrl) { + DEBUG(0, __FUNCTION__ "(), dup failed!\n"); + return; + } + + /* new->stsap_sel = new->tsap->stsap_sel; */ + new->dtsap_sel_ctrl = new->provider.tsap_ctrl->dtsap_sel; + + /* Clean up the original one to keep it in listen state */ + self->provider.tsap_ctrl->dtsap_sel = LSAP_ANY; + self->provider.tsap_ctrl->lsap->dlsap_sel = LSAP_ANY; + self->provider.tsap_ctrl->lsap->lsap_state = LSAP_DISCONNECTED; + + /* + * Use the new instance from here instead of the master + * struct! */ - ASSERT(self->daddr == irttp_get_daddr(tsap), return;); + self = new; } - - /* 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); @@ -165,9 +211,10 @@ void irlan_provider_connect_indication(void *instance, void *sap, * 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)) + if ((self->provider.access_type == ACCESS_PEER) && + (self->client.state == IRLAN_IDLE)) { irlan_client_wakeup(self, self->saddr, self->daddr); + } } /* @@ -225,6 +272,9 @@ int irlan_parse_open_data_cmd(struct irlan_cb *self, struct sk_buff *skb) ret = irlan_provider_parse_command(self, CMD_OPEN_DATA_CHANNEL, skb); + /* Open data channel */ + irlan_open_data_tsap(self); + return ret; } @@ -314,7 +364,7 @@ void irlan_provider_send_reply(struct irlan_cb *self, int command, return; /* Reserve space for TTP, LMP, and LAP header */ - skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER); + skb_reserve(skb, self->provider.max_header_size); skb_put(skb, 2); switch (command) { @@ -334,6 +384,7 @@ void irlan_provider_send_reply(struct irlan_cb *self, int command, } 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 */ @@ -341,7 +392,7 @@ void irlan_provider_send_reply(struct irlan_cb *self, int command, irlan_insert_string_param(skb, "FILTER_TYPE", "BROADCAST"); irlan_insert_string_param(skb, "FILTER_TYPE", "MULTICAST"); - switch(self->access_type) { + switch (self->provider.access_type) { case ACCESS_DIRECT: irlan_insert_string_param(skb, "ACCESS_TYPE", "DIRECT"); break; diff --git a/net/irda/irlan/irlan_provider_event.c b/net/irda/irlan/irlan_provider_event.c index 6bdf503f1075..29e660fa72dc 100644 --- a/net/irda/irlan/irlan_provider_event.c +++ b/net/irda/irlan/irlan_provider_event.c @@ -6,10 +6,10 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sun Aug 31 20:14:37 1997 - * Modified at: Thu Apr 22 10:46:28 1999 + * Modified at: Fri May 7 10:53:58 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli , All Rights Reserved. + * Copyright (c) 1998-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 @@ -108,7 +108,7 @@ static int irlan_provider_state_info(struct irlan_cb *self, IRLAN_EVENT event, switch(event) { case IRLAN_GET_INFO_CMD: /* Be sure to use 802.3 in case of peer mode */ - if (self->access_type == ACCESS_PEER) { + if (self->provider.access_type == ACCESS_PEER) { self->media = MEDIA_802_3; /* Check if client has started yet */ @@ -129,7 +129,7 @@ static int irlan_provider_state_info(struct irlan_cb *self, IRLAN_EVENT event, break; case IRLAN_OPEN_DATA_CMD: ret = irlan_parse_open_data_cmd(self, skb); - if (self->access_type == ACCESS_PEER) { + if (self->provider.access_type == ACCESS_PEER) { /* FIXME: make use of random functions! */ self->provider.send_arb_val = (jiffies & 0xffff); } @@ -205,8 +205,6 @@ static int irlan_provider_state_open(struct irlan_cb *self, IRLAN_EVENT event, 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;); @@ -220,10 +218,6 @@ static int irlan_provider_state_data(struct irlan_cb *self, IRLAN_EVENT event, 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: diff --git a/net/irda/irlap_comp.c b/net/irda/irlap_comp.c index 9959b64bc14e..57a6b420bebc 100644 --- a/net/irda/irlap_comp.c +++ b/net/irda/irlap_comp.c @@ -6,11 +6,11 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Fri Oct 9 09:18:07 1998 - * Modified at: Mon Feb 8 01:23:52 1999 + * Modified at: Sun May 9 11:37:06 1999 * Modified by: Dag Brattli * Sources: ppp.c, isdn_ppp.c * - * Copyright (c) 1998 Dag Brattli, All Rights Reserved. + * Copyright (c) 1998-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 @@ -255,11 +255,11 @@ struct sk_buff *irlap_compress_frame( struct irlap_cb *self, } /* FIXME: Find out what is the max overhead (not 10) */ - new_skb = dev_alloc_skb( skb->len+LAP_HEADER+10); + new_skb = dev_alloc_skb( skb->len+LAP_MAX_HEADER+10); if(!new_skb) return skb; - skb_reserve( new_skb, LAP_HEADER); + skb_reserve( new_skb, LAP_MAX_HEADER); skb_put( new_skb, skb->len+10); count = (self->compressor.cp->compress)( self->compressor.state, diff --git a/net/irda/irlap_event.c b/net/irda/irlap_event.c index a2fbadf65045..936401339cfd 100644 --- a/net/irda/irlap_event.c +++ b/net/irda/irlap_event.c @@ -6,10 +6,10 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sat Aug 16 00:59:29 1997 - * Modified at: Fri Apr 23 11:55:12 1999 + * Modified at: Sun May 9 22:44:32 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli , + * Copyright (c) 1998-1999 Dag Brattli , * Thomas Davis * All Rights Reserved. * @@ -274,22 +274,22 @@ void irlap_do_event( struct irlap_cb *self, IRLAP_EVENT event, * Switches state and provides debug information * */ -void irlap_next_state( struct irlap_cb *self, IRLAP_STATE state) +void irlap_next_state(struct irlap_cb *self, IRLAP_STATE state) { - if ( !self || self->magic != LAP_MAGIC) + if (!self || self->magic != LAP_MAGIC) return; - DEBUG( 4, "next LAP state = %s\n", irlap_state[ state]); + DEBUG(4, "next LAP state = %s\n", irlap_state[ state]); self->state = state; /* * If we are swithing away from a XMIT state then we are allowed to * transmit a maximum number of bytes again when we enter the XMIT - * state again. Since its possible to "switch" from XMIT to XMIT and + * state again. Since its possible to "switch" from XMIT to XMIT, * we cannot do this when swithing into the XMIT state :-) */ - if (( state != LAP_XMIT_P) && ( state != LAP_XMIT_S)) + if ((state != LAP_XMIT_P) && (state != LAP_XMIT_S)) self->bytes_left = self->window_bytes; } @@ -310,7 +310,7 @@ static int irlap_state_ndm( struct irlap_cb *self, IRLAP_EVENT event, ASSERT( self != NULL, return -1;); ASSERT( self->magic == LAP_MAGIC, return -1;); - switch( event) { + switch(event) { case CONNECT_REQUEST: ASSERT( self->irdev != NULL, return -1;); @@ -393,7 +393,6 @@ static int irlap_state_ndm( struct irlap_cb *self, IRLAP_EVENT event, irlap_start_query_timer( self, QUERY_TIMEOUT); irlap_next_state( self, LAP_REPLY); } - dev_kfree_skb(skb); break; @@ -530,7 +529,7 @@ static int irlap_state_reply(struct irlap_cb *self, IRLAP_EVENT event, irlap_send_discovery_xid_frame(self, info->S, self->slot, FALSE, discovery_rsp); - + self->frame_sent = TRUE; irlap_next_state(self, LAP_REPLY); } @@ -568,27 +567,28 @@ static int irlap_state_conn(struct irlap_cb *self, IRLAP_EVENT event, switch (event) { case CONNECT_RESPONSE: - skb_pull( skb, 11); + /* skb_pull(skb, 11); */ + skb_pull(skb, sizeof(struct snrm_frame)); - ASSERT( self->irdev != NULL, return -1;); - irda_qos_negotiate( &self->qos_rx, &self->qos_tx, skb); + ASSERT(self->irdev != NULL, return -1;); + irda_qos_negotiate(&self->qos_rx, &self->qos_tx, skb); irlap_initiate_connection_state( self); /* * We are allowed to send two frames! */ - irlap_send_ua_response_frame( self, &self->qos_rx); - irlap_send_ua_response_frame( self, &self->qos_rx); + irlap_send_ua_response_frame(self, &self->qos_rx); + irlap_send_ua_response_frame(self, &self->qos_rx); - irlap_apply_connection_parameters( self, &self->qos_tx); + irlap_apply_connection_parameters(self, &self->qos_tx); /* * The WD-timer could be set to the duration of the P-timer - * for this case, but it is recommomended to use twice the + * for this case, but it is recommended to use twice the * value (note 3 IrLAP p. 60). */ - irlap_start_wd_timer( self, self->wd_timeout); + irlap_start_wd_timer(self, self->wd_timeout); irlap_next_state( self, LAP_NRM_S); break; @@ -669,28 +669,30 @@ static int irlap_state_setup( struct irlap_cb *self, IRLAP_EVENT event, * The device with the largest device address wins the battle * (both have sent a SNRM command!) */ - if ( info->daddr > self->saddr) { - del_timer( &self->final_timer); - irlap_initiate_connection_state( self); + if (info->daddr > self->saddr) { + del_timer(&self->final_timer); + irlap_initiate_connection_state(self); - ASSERT( self->irdev != NULL, return -1;); - irda_qos_negotiate( &self->qos_rx, &self->qos_tx, skb); + ASSERT(self->irdev != NULL, return -1;); + /* skb_pull(skb, 11); */ + skb_pull(skb, sizeof(struct snrm_frame)); + irda_qos_negotiate(&self->qos_rx, &self->qos_tx, skb); irlap_send_ua_response_frame(self, &self->qos_rx); - irlap_apply_connection_parameters( self, &self->qos_tx); - irlap_connect_confirm( self, skb); + irlap_apply_connection_parameters(self, &self->qos_tx); + irlap_connect_confirm(self, skb); /* * The WD-timer could be set to the duration of the - * P-timer for this case, but it is recommomended + * P-timer for this case, but it is recommended * to use twice the value (note 3 IrLAP p. 60). */ - irlap_start_wd_timer( self, self->wd_timeout); + irlap_start_wd_timer(self, self->wd_timeout); - irlap_next_state( self, LAP_NRM_S); + irlap_next_state(self, LAP_NRM_S); } else { /* We just ignore the other device! */ - irlap_next_state( self, LAP_SETUP); + irlap_next_state(self, LAP_SETUP); } break; case RECV_UA_RSP: @@ -702,9 +704,10 @@ static int irlap_state_setup( struct irlap_cb *self, IRLAP_EVENT event, /* Negotiate connection parameters */ ASSERT( skb->len > 10, return -1;); - skb_pull( skb, 10); + /* skb_pull(skb, 10); */ + skb_pull(skb, sizeof(struct ua_frame)); - ASSERT( self->irdev != NULL, return -1;); + ASSERT(self->irdev != NULL, return -1;); irda_qos_negotiate( &self->qos_rx, &self->qos_tx, skb); irlap_apply_connection_parameters( self, &self->qos_tx); @@ -1570,7 +1573,7 @@ static int irlap_state_nrm_s( struct irlap_cb *self, IRLAP_EVENT event, /* * poll bit cleared? */ - if ( !info->pf) { + if (!info->pf) { self->vr = (self->vr + 1) % 8; /* Update Nr received */ @@ -1600,27 +1603,32 @@ static int irlap_state_nrm_s( struct irlap_cb *self, IRLAP_EVENT event, * also before changing to XMIT_S * state. (note 1, IrLAP p. 82) */ - irlap_wait_min_turn_around( self, &self->qos_tx); - /* - * Any pending data requests? + irlap_wait_min_turn_around(self, &self->qos_tx); + + /* + * Give higher layers a chance to + * immediately reply with some data before + * we decide if we should send a RR frame + * or not */ - if (( skb_queue_len( &self->tx_list) > 0) && - ( self->window > 0)) + irlap_data_indication(self, skb); + + /* Any pending data requests? */ + if ((skb_queue_len(&self->tx_list) > 0) && + (self->window > 0)) { self->ack_required = TRUE; - del_timer( &self->wd_timer); + del_timer(&self->wd_timer); - irlap_next_state( self, LAP_XMIT_S); + irlap_next_state(self, LAP_XMIT_S); } else { - irlap_send_rr_frame( self, RSP_FRAME); - irlap_start_wd_timer( self, self->wd_timeout); + irlap_send_rr_frame(self, RSP_FRAME); + irlap_start_wd_timer(self, self->wd_timeout); /* Keep the state */ - irlap_next_state( self, LAP_NRM_S); + irlap_next_state(self, LAP_NRM_S); } - irlap_data_indication( self, skb); - break; } } diff --git a/net/irda/irlap_frame.c b/net/irda/irlap_frame.c index cda78e7f1d53..8ffd26a6e051 100644 --- a/net/irda/irlap_frame.c +++ b/net/irda/irlap_frame.c @@ -6,10 +6,10 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Tue Aug 19 10:27:26 1997 - * Modified at: Fri Apr 23 09:30:42 1999 + * Modified at: Sun May 9 22:55:11 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli , All Rights Resrved. + * Copyright (c) 1998-1999 Dag Brattli , All Rights Resrved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -1056,8 +1056,8 @@ static inline void irlap_recv_i_frame(struct irlap_cb *self, * Receive and parse an Unnumbered Information (UI) frame * */ -static void irlap_recv_ui_frame( struct irlap_cb *self, struct sk_buff *skb, - struct irlap_info *info) +static void irlap_recv_ui_frame(struct irlap_cb *self, struct sk_buff *skb, + struct irlap_info *info) { __u8 *frame; @@ -1254,7 +1254,7 @@ int irlap_driver_rcv(struct sk_buff *skb, struct device *dev, * Received S(upervisory) frame, check which frame type it is * only the first nibble is of interest */ - switch(control & 0x0f) { + switch (control & 0x0f) { case RR: irlap_recv_rr_frame( self, skb, &info, command); self->stats.rx_packets++; @@ -1279,7 +1279,7 @@ int irlap_driver_rcv(struct sk_buff *skb, struct device *dev, /* * This must be a C(ontrol) frame */ - switch(control) { + switch (control) { case XID_RSP: irlap_recv_discovery_xid_rsp(self, skb, &info); break; diff --git a/net/irda/irlmp.c b/net/irda/irlmp.c index d76661b6cf1e..f4d4608cb9dc 100644 --- a/net/irda/irlmp.c +++ b/net/irda/irlmp.c @@ -6,10 +6,10 @@ * Status: Stable. * Author: Dag Brattli * Created at: Sun Aug 17 20:54:32 1997 - * Modified at: Fri Apr 23 09:13:24 1999 + * Modified at: Sun May 9 22:45:06 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli , + * Copyright (c) 1998-1999 Dag Brattli , * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -197,7 +197,7 @@ struct lsap_cb *irlmp_open_lsap(__u8 slsap_sel, struct notify_t *notify) } /* - * Function irlmp_close_lsap (self) + * Function __irlmp_close_lsap (self) * * Remove an instance of LSAP */ @@ -369,11 +369,11 @@ int irlmp_connect_request(struct lsap_cb *self, __u8 dlsap_sel, if (!skb) return -ENOMEM; - skb_reserve(skb, LMP_CONTROL_HEADER+LAP_HEADER); + skb_reserve(skb, LMP_MAX_HEADER); } else skb = userdata; - /* Make room for MUX control header ( 3 bytes) */ + /* Make room for MUX control header (3 bytes) */ ASSERT(skb_headroom(skb) >= LMP_CONTROL_HEADER, return -1;); skb_push(skb, LMP_CONTROL_HEADER); @@ -443,25 +443,36 @@ int irlmp_connect_request(struct lsap_cb *self, __u8 dlsap_sel, void irlmp_connect_indication(struct lsap_cb *self, struct sk_buff *skb) { int max_seg_size; - - DEBUG(3, __FUNCTION__ "()\n"); + int lap_header_size; + int max_header_size; ASSERT(self != NULL, return;); ASSERT(self->magic == LMP_LSAP_MAGIC, return;); ASSERT(skb != NULL, return;); ASSERT(self->lap != NULL, return;); + DEBUG(0, __FUNCTION__ "(), slsap_sel=%02x, dlsap_sel=%02x\n", + self->slsap_sel, self->dlsap_sel); + self->qos = *self->lap->qos; - max_seg_size = self->lap->qos->data_size.value; - DEBUG(4, __FUNCTION__ "(), max_seg_size=%d\n", max_seg_size); + lap_header_size = irlap_get_header_size(self->lap->irlap); + + max_seg_size = self->lap->qos->data_size.value-LMP_HEADER- + lap_header_size; + DEBUG(2, __FUNCTION__ "(), max_seg_size=%d\n", max_seg_size); + max_header_size = LMP_HEADER + lap_header_size; + + DEBUG(2, __FUNCTION__ "(), max_header_size=%d\n", max_header_size); + /* Hide LMP_CONTROL_HEADER header from layer above */ 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->qos, max_seg_size, + max_header_size, skb); } /* @@ -470,24 +481,22 @@ void irlmp_connect_indication(struct lsap_cb *self, struct sk_buff *skb) * Service user is accepting connection * */ -void irlmp_connect_response( struct lsap_cb *self, struct sk_buff *userdata) +void irlmp_connect_response(struct lsap_cb *self, struct sk_buff *userdata) { - DEBUG(3, __FUNCTION__ "()\n"); - - ASSERT( self != NULL, return;); - ASSERT( self->magic == LMP_LSAP_MAGIC, return;); - ASSERT( userdata != NULL, return;); + ASSERT(self != NULL, return;); + ASSERT(self->magic == LMP_LSAP_MAGIC, return;); + ASSERT(userdata != NULL, return;); self->connected = TRUE; - DEBUG( 4, "irlmp_connect_response: slsap_sel=%02x, dlsap_sel=%02x\n", - self->slsap_sel, self->dlsap_sel); + DEBUG(2, __FUNCTION__ "(), slsap_sel=%02x, dlsap_sel=%02x\n", + self->slsap_sel, self->dlsap_sel); /* Make room for MUX control header ( 3 bytes) */ - ASSERT( skb_headroom( userdata) >= LMP_CONTROL_HEADER, return;); - skb_push( userdata, LMP_CONTROL_HEADER); + ASSERT(skb_headroom(userdata) >= LMP_CONTROL_HEADER, return;); + skb_push(userdata, LMP_CONTROL_HEADER); - irlmp_do_lsap_event( self, LM_CONNECT_RESPONSE, userdata); + irlmp_do_lsap_event(self, LM_CONNECT_RESPONSE, userdata); } /* @@ -498,25 +507,35 @@ void irlmp_connect_response( struct lsap_cb *self, struct sk_buff *userdata) void irlmp_connect_confirm(struct lsap_cb *self, struct sk_buff *skb) { int max_seg_size; + int max_header_size; + int lap_header_size; DEBUG(3, __FUNCTION__ "()\n"); - ASSERT( skb != NULL, return;); - ASSERT( self != NULL, return;); - ASSERT( self->magic == LMP_LSAP_MAGIC, return;); + ASSERT(skb != NULL, return;); + ASSERT(self != NULL, return;); + ASSERT(self->magic == LMP_LSAP_MAGIC, return;); - ASSERT( self->lap != NULL, return;); + ASSERT(self->lap != NULL, return;); self->qos = *self->lap->qos; - max_seg_size = self->qos.data_size.value; - DEBUG( 4, __FUNCTION__ "(), max_seg_size=%d\n", max_seg_size); + lap_header_size = irlap_get_header_size(self->lap->irlap); + + max_seg_size = self->lap->qos->data_size.value-LMP_HEADER- + lap_header_size; + DEBUG(2, __FUNCTION__ "(), max_seg_size=%d\n", max_seg_size); + max_header_size = LMP_HEADER + lap_header_size; + + DEBUG(2, __FUNCTION__ "(), max_header_size=%d\n", max_header_size); + /* Hide LMP_CONTROL_HEADER header from layer above */ - skb_pull( skb, LMP_CONTROL_HEADER); + skb_pull(skb, LMP_CONTROL_HEADER); - if ( self->notify.connect_confirm) { - self->notify.connect_confirm( self->notify.instance, self, - &self->qos, max_seg_size, skb); + if (self->notify.connect_confirm) { + self->notify.connect_confirm(self->notify.instance, self, + &self->qos, max_seg_size, + max_header_size, skb); } } @@ -620,8 +639,8 @@ void irlmp_disconnect_request(struct lsap_cb *self, struct sk_buff *userdata) * * LSAP is being closed! */ -void irlmp_disconnect_indication( struct lsap_cb *self, LM_REASON reason, - struct sk_buff *userdata) +void irlmp_disconnect_indication(struct lsap_cb *self, LM_REASON reason, + struct sk_buff *userdata) { struct lsap_cb *lsap; @@ -637,6 +656,10 @@ void irlmp_disconnect_indication( struct lsap_cb *self, LM_REASON reason, self->connected = FALSE; self->dlsap_sel = LSAP_ANY; +#ifdef CONFIG_IRDA_CACHE_LAST_LSAP + irlmp->cache.valid = FALSE; +#endif + /* * Remove association between this LSAP and the link it used */ @@ -975,7 +998,7 @@ void irlmp_status_request(void) DEBUG( 1, "irlmp_status_request(), Not implemented\n"); } -void irlmp_status_indication( LINK_STATUS link, LOCK_STATUS lock) +void irlmp_status_indication(LINK_STATUS link, LOCK_STATUS lock) { DEBUG( 4, "irlmp_status_indication(), Not implemented\n"); } @@ -1418,14 +1441,14 @@ __u32 irlmp_get_daddr(struct lsap_cb *self) * Give some info to the /proc file system * */ -int irlmp_proc_read( char *buf, char **start, off_t offset, int len, - int unused) +int irlmp_proc_read(char *buf, char **start, off_t offset, int len, + int unused) { struct lsap_cb *self; struct lap_cb *lap; unsigned long flags; - ASSERT( irlmp != NULL, return 0;); + ASSERT(irlmp != NULL, return 0;); save_flags( flags); cli(); @@ -1449,35 +1472,34 @@ int irlmp_proc_read( char *buf, char **start, off_t offset, int len, } len += sprintf( buf+len, "\nRegistred Link Layers:\n"); - lap = (struct lap_cb *) hashbin_get_first( irlmp->links); - while ( lap != NULL) { - ASSERT( lap->magic == LMP_LAP_MAGIC, return 0;); - len += sprintf( buf+len, "lap state: %s, ", - irlmp_state[ lap->lap_state]); + lap = (struct lap_cb *) hashbin_get_first(irlmp->links); + while (lap != NULL) { + len += sprintf(buf+len, "lap state: %s, ", + irlmp_state[lap->lap_state]); - len += sprintf( buf+len, "saddr: %#08x, daddr: %#08x, ", - lap->saddr, lap->daddr); - len += sprintf( buf+len, "\n"); + len += sprintf(buf+len, "saddr: %#08x, daddr: %#08x, ", + lap->saddr, lap->daddr); + len += sprintf(buf+len, "\n"); len += sprintf( buf+len, "\nConnected LSAPs:\n"); self = (struct lsap_cb *) hashbin_get_first( lap->lsaps); - while ( self != NULL) { - ASSERT( self->magic == LMP_LSAP_MAGIC, return 0;); - len += sprintf( buf+len, "lsap state: %s, ", - irlsap_state[ self->lsap_state]); - len += sprintf( buf+len, - "slsap_sel: %#02x, dlsap_sel: %#02x, ", - self->slsap_sel, self->dlsap_sel); - len += sprintf( buf+len, "(%s)", self->notify.name); - len += sprintf( buf+len, "\n"); + while (self != NULL) { + ASSERT(self->magic == LMP_LSAP_MAGIC, return 0;); + len += sprintf(buf+len, "lsap state: %s, ", + irlsap_state[ self->lsap_state]); + len += sprintf(buf+len, + "slsap_sel: %#02x, dlsap_sel: %#02x, ", + self->slsap_sel, self->dlsap_sel); + len += sprintf(buf+len, "(%s)", self->notify.name); + len += sprintf(buf+len, "\n"); - self = ( struct lsap_cb *) hashbin_get_next( + self = (struct lsap_cb *) hashbin_get_next( lap->lsaps); } + len += sprintf(buf+len, "\n"); - lap = ( struct lap_cb *) hashbin_get_next( - irlmp->links); + lap = (struct lap_cb *) hashbin_get_next(irlmp->links); } restore_flags( flags); diff --git a/net/irda/irlmp_frame.c b/net/irda/irlmp_frame.c index bf1bab31ecf7..ff396c4ff7bd 100644 --- a/net/irda/irlmp_frame.c +++ b/net/irda/irlmp_frame.c @@ -1,15 +1,15 @@ /********************************************************************* * * Filename: irlmp_frame.c - * Version: 0.8 + * Version: 0.9 * Description: IrLMP frame implementation * Status: Experimental. * Author: Dag Brattli * Created at: Tue Aug 19 02:09:59 1997 - * Modified at: Fri Apr 23 09:12:23 1999 + * Modified at: Sun May 9 21:00:05 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli + * Copyright (c) 1998-1999 Dag Brattli * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -59,16 +59,16 @@ inline void irlmp_send_data_pdu(struct lap_cb *self, __u8 dlsap, __u8 slsap, * * Send Link Control Frame to IrLAP */ -void irlmp_send_lcf_pdu( struct lap_cb *self, __u8 dlsap, __u8 slsap, - __u8 opcode, struct sk_buff *skb) +void irlmp_send_lcf_pdu(struct lap_cb *self, __u8 dlsap, __u8 slsap, + __u8 opcode, struct sk_buff *skb) { __u8 *frame; - DEBUG( 4, __FUNCTION__ "()\n"); + DEBUG(4, __FUNCTION__ "()\n"); - ASSERT( self != NULL, return;); - ASSERT( self->magic == LMP_LAP_MAGIC, return;); - ASSERT( skb != NULL, return;); + ASSERT(self != NULL, return;); + ASSERT(self->magic == LMP_LAP_MAGIC, return;); + ASSERT(skb != NULL, return;); frame = skb->data; @@ -82,8 +82,8 @@ void irlmp_send_lcf_pdu( struct lap_cb *self, __u8 dlsap, __u8 slsap, else frame[3] = 0x00; /* rsvd */ - ASSERT( self->irlap != NULL, return;); - irlap_data_request( self->irlap, skb, TRUE); + ASSERT(self->irlap != NULL, return;); + irlap_data_request(self->irlap, skb, TRUE); } /* @@ -112,7 +112,7 @@ void irlmp_link_data_indication(struct lap_cb *self, int reliable, */ slsap_sel = fp[0] & LSAP_MASK; dlsap_sel = fp[1]; - + /* * Check if this is an incoming connection, since we must deal with * it in a different way than other established connections. @@ -224,11 +224,11 @@ void irlmp_link_disconnect_indication(struct lap_cb *lap, * Incoming LAP connection! * */ -void irlmp_link_connect_indication( struct lap_cb *self, __u32 saddr, - __u32 daddr, struct qos_info *qos, - struct sk_buff *skb) +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"); + DEBUG(4, __FUNCTION__ "()\n"); /* Copy QoS settings for this session */ self->qos = qos; @@ -237,7 +237,7 @@ void irlmp_link_connect_indication( struct lap_cb *self, __u32 saddr, self->daddr = daddr; ASSERT(self->saddr == saddr, return;); - irlmp_do_lap_event( self, LM_LAP_CONNECT_INDICATION, skb); + irlmp_do_lap_event(self, LM_LAP_CONNECT_INDICATION, skb); } /* @@ -246,19 +246,19 @@ void irlmp_link_connect_indication( struct lap_cb *self, __u32 saddr, * LAP connection confirmed! * */ -void irlmp_link_connect_confirm( struct lap_cb *self, struct qos_info *qos, - struct sk_buff *userdata) +void irlmp_link_connect_confirm(struct lap_cb *self, struct qos_info *qos, + struct sk_buff *userdata) { - DEBUG( 4, "irlmp_link_connect_confirm()\n"); + DEBUG(4, __FUNCTION__ "()\n"); - ASSERT( self != NULL, return;); - ASSERT( self->magic == LMP_LAP_MAGIC, return;); - ASSERT( qos != NULL, return;); + ASSERT(self != NULL, return;); + ASSERT(self->magic == LMP_LAP_MAGIC, return;); + ASSERT(qos != NULL, return;); /* Copy QoS settings for this session */ self->qos = qos; - irlmp_do_lap_event( self, LM_LAP_CONNECT_CONFIRM, NULL); + irlmp_do_lap_event(self, LM_LAP_CONNECT_CONFIRM, NULL); } /* @@ -276,7 +276,9 @@ void irlmp_link_discovery_indication(struct lap_cb *self, irlmp_add_discovery(irlmp->cachelog, discovery); /* Just handle it the same way as a discovery confirm */ +#if 0 irlmp_do_lap_event(self, LM_LAP_DISCOVERY_CONFIRM, NULL); +#endif } /* @@ -365,7 +367,7 @@ static struct lsap_cb *irlmp_find_lsap(struct lap_cb *self, __u8 dlsap_sel, #endif return lsap; } - lsap = ( struct lsap_cb *) hashbin_get_next(queue); + lsap = (struct lsap_cb *) hashbin_get_next(queue); } /* Sorry not found! */ diff --git a/net/irda/irlpt/irlpt_cli.c b/net/irda/irlpt/irlpt_cli.c index a0fbe23d6789..9e02465ccae9 100644 --- a/net/irda/irlpt/irlpt_cli.c +++ b/net/irda/irlpt/irlpt_cli.c @@ -51,10 +51,11 @@ static void irlpt_client_discovery_indication(discovery_t *); static void irlpt_client_connect_confirm(void *instance, void *sap, struct qos_info *qos, __u32 max_seg_size, + __u8 max_header_size, struct sk_buff *skb); -static void irlpt_client_disconnect_indication( void *instance, void *sap, - LM_REASON reason, - struct sk_buff *userdata); +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 @@ -187,7 +188,7 @@ __initfunc(int irlpt_client_init(void)) #ifdef CONFIG_PROC_FS create_proc_entry("irlpt_client", 0, proc_irda)->get_info - = irlpt_client_proc_read; + = irlpt_client_proc_read; #endif /* CONFIG_PROC_FS */ DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n"); @@ -215,7 +216,6 @@ static void irlpt_client_cleanup(void) #ifdef CONFIG_PROC_FS remove_proc_entry("irlpt_client", proc_irda); #endif - DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n"); } #endif /* MODULE */ @@ -403,9 +403,8 @@ static void irlpt_client_disconnect_indication( void *instance, irlpt_client_do_event( self, LMP_DISCONNECT, NULL, NULL); - if (skb) { + if (skb) dev_kfree_skb( skb); - } DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n"); } @@ -417,7 +416,8 @@ static void irlpt_client_disconnect_indication( void *instance, */ static void irlpt_client_connect_confirm(void *instance, void *sap, struct qos_info *qos, - __u32 max_sdu_size, + __u32 max_seg_size, + __u8 max_header_size, struct sk_buff *skb) { struct irlpt_info info; @@ -443,14 +443,14 @@ static void irlpt_client_connect_confirm(void *instance, void *sap, } #endif - self->irlap_data_size = (qos->data_size.value - IRLPT_MAX_HEADER); + self->max_data_size = max_seg_size; + self->max_header_size = max_header_size; self->connected = TRUE; irlpt_client_do_event( self, LMP_CONNECT, NULL, NULL); - if (skb) { + if (skb) dev_kfree_skb( skb); - } DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n"); } @@ -603,7 +603,7 @@ static void irlpt_client_expired(unsigned long data) return; } - skb_reserve( skb, LMP_CONTROL_HEADER+LAP_HEADER); + skb_reserve(skb, LMP_MAX_HEADER); irlmp_disconnect_request(self->lsap, skb); DEBUG(irlpt_client_debug, __FUNCTION__ ": irlmp_close_slap(self->lsap)\n"); diff --git a/net/irda/irlpt/irlpt_cli_fsm.c b/net/irda/irlpt/irlpt_cli_fsm.c index 75598742aa88..83a2e69915d5 100644 --- a/net/irda/irlpt/irlpt_cli_fsm.c +++ b/net/irda/irlpt/irlpt_cli_fsm.c @@ -6,10 +6,10 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Tue Jan 12 11:06:00 1999 - * Modified at: Tue Jan 26 12:02:31 1999 + * Modified at: Sun May 9 13:36:13 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998, Thomas Davis, + * Copyright (c) 1998-1999, Thomas Davis, * Copyright (c) 1998, Dag Brattli, * All Rights Reserved. * @@ -43,10 +43,10 @@ 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_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, struct sk_buff *skb, diff --git a/net/irda/irlpt/irlpt_common.c b/net/irda/irlpt/irlpt_common.c index b4512736a6da..c6401416bb38 100644 --- a/net/irda/irlpt/irlpt_common.c +++ b/net/irda/irlpt/irlpt_common.c @@ -251,18 +251,18 @@ ssize_t irlpt_write(struct file *file, const char *buffer, } DEBUG( irlpt_common_debug, __FUNCTION__ - ": count = %d, irlap_data_size = %d, IRLPT_MAX_HEADER = %d\n", - count, self->irlap_data_size, IRLPT_MAX_HEADER); + ": count = %d, max_data_size = %d, IRLPT_MAX_HEADER = %d\n", + count, self->max_data_size, IRLPT_MAX_HEADER); - if (count > (self->irlap_data_size - IRLPT_MAX_HEADER)) { - count = (self->irlap_data_size - IRLPT_MAX_HEADER); + if (count > self->max_data_size) { + count = self->max_data_size; DEBUG(irlpt_common_debug, __FUNCTION__ ": setting count to %d\n", count); } DEBUG( irlpt_common_debug, __FUNCTION__ ": count = %d\n", count); - skb = dev_alloc_skb(count + IRLPT_MAX_HEADER); + skb = dev_alloc_skb(count + self->max_header_size); if ( skb == NULL) { printk( KERN_INFO __FUNCTION__ ": couldn't allocate skbuff!\n"); @@ -417,7 +417,7 @@ int irlpt_close(struct inode *inode, return 0; } - skb_reserve( skb, LMP_CONTROL_HEADER+LAP_HEADER); + skb_reserve( skb, LMP_MAX_HEADER); irlmp_disconnect_request(self->lsap, skb); DEBUG(irlpt_common_debug, __FUNCTION__ ": irlmp_close_slap(self->lsap)\n"); diff --git a/net/irda/irlpt/irlpt_srvr.c b/net/irda/irlpt/irlpt_srvr.c index a1362d0dc600..12e5867a5434 100644 --- a/net/irda/irlpt/irlpt_srvr.c +++ b/net/irda/irlpt/irlpt_srvr.c @@ -51,15 +51,21 @@ int irlpt_server_init(void); static void irlpt_server_disconnect_indication(void *instance, void *sap, LM_REASON reason, struct sk_buff *skb); + +#if 0 static void irlpt_server_connect_confirm(void *instance, void *sap, struct qos_info *qos, __u32 max_seg_size, + __u8 max_header_size, struct sk_buff *skb); static void irlpt_server_connect_indication(void *instance, void *sap, struct qos_info *qos, __u32 max_seg_size, + __u8 max_header_size, struct sk_buff *skb); +#endif + static int irlpt_server_data_indication(void *instance, void *sap, struct sk_buff *skb); static void register_irlpt_server(void); @@ -161,7 +167,6 @@ static int irlpt_server_proc_read(char *buf, char **start, off_t offset, } extern struct proc_dir_entry *proc_irda; - #endif /* CONFIG_PROC_FS */ /* @@ -171,9 +176,9 @@ extern struct proc_dir_entry *proc_irda; * */ -/*int irlpt_init( struct device *dev) {*/ __initfunc(int irlpt_server_init(void)) { + struct irmanager_event mgr_event; __u16 hints; DEBUG( irlpt_server_debug, "--> " __FUNCTION__ "\n"); @@ -212,6 +217,10 @@ __initfunc(int irlpt_server_init(void)) = irlpt_server_proc_read; #endif /* CONFIG_PROC_FS */ + mgr_event.event = EVENT_IRLPT_START; + sprintf(mgr_event.devname, "%s", irlpt_server->ifname); + irmanager_notify(&mgr_event); + DEBUG( irlpt_server_debug, __FUNCTION__ " -->\n"); return 0; @@ -225,6 +234,7 @@ __initfunc(int irlpt_server_init(void)) */ static void irlpt_server_cleanup(void) { + struct irmanager_event mgr_event; struct sk_buff *skb; DEBUG( irlpt_server_debug, "--> " __FUNCTION__ "\n"); @@ -245,6 +255,10 @@ static void irlpt_server_cleanup(void) remove_proc_entry("irlpt_server", proc_irda); #endif + mgr_event.event = EVENT_IRLPT_STOP; + sprintf( mgr_event.devname, "%s", irlpt_server->ifname); + irmanager_notify( &mgr_event); + DEBUG( irlpt_server_debug, __FUNCTION__ " -->\n"); } @@ -304,6 +318,7 @@ static void irlpt_server_connect_confirm(void *instance, void *sap, struct qos_info *qos, __u32 max_seg_size, + __u8 max_header_size, struct sk_buff *skb) { struct irlpt_cb *self; @@ -314,6 +329,9 @@ static void irlpt_server_connect_confirm(void *instance, ASSERT( self != NULL, return;); ASSERT( self->magic == IRLPT_MAGIC, return;); + self->max_data_size = max_seg_size; + self->max_header_size = max_header_size; + self->connected = TRUE; irlpt_server_do_event( self, LMP_CONNECT, NULL, NULL); @@ -329,6 +347,7 @@ static void irlpt_server_connect_indication(void *instance, void *sap, struct qos_info *qos, __u32 max_seg_size, + __u8 max_header_size, struct sk_buff *skb) { struct irlpt_cb *self; @@ -343,14 +362,16 @@ static void irlpt_server_connect_indication(void *instance, ASSERT( self != NULL, return;); ASSERT( self->magic == IRLPT_MAGIC, return;); + self->max_data_size = max_seg_size; + self->max_header_size = max_header_size; + self->connected = IRLPT_CONNECTED; self->eof = FALSE; irlpt_server_do_event( self, LMP_CONNECT, NULL, &info); - if (skb) { + if (skb) dev_kfree_skb( skb); - } DEBUG( irlpt_server_debug, __FUNCTION__ " -->\n"); } diff --git a/net/irda/irmod.c b/net/irda/irmod.c index 88d61c2cd62b..445a645a052b 100644 --- a/net/irda/irmod.c +++ b/net/irda/irmod.c @@ -6,10 +6,10 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Mon Dec 15 13:55:39 1997 - * Modified at: Mon Apr 12 11:31:01 1999 + * Modified at: Mon May 10 15:28:49 1999 * Modified by: Dag Brattli * - * Copyright (c) 1997 Dag Brattli, All Rights Reserved. + * Copyright (c) 1997, 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 @@ -110,6 +110,7 @@ EXPORT_SYMBOL(irttp_disconnect_request); EXPORT_SYMBOL(irttp_flow_request); EXPORT_SYMBOL(irttp_connect_request); EXPORT_SYMBOL(irttp_udata_request); +EXPORT_SYMBOL(irttp_dup); /* Main IrDA module */ #ifdef CONFIG_IRDA_DEBUG @@ -151,6 +152,7 @@ EXPORT_SYMBOL(irlmp_connect_response); EXPORT_SYMBOL(irlmp_disconnect_request); EXPORT_SYMBOL(irlmp_get_daddr); EXPORT_SYMBOL(irlmp_get_saddr); +EXPORT_SYMBOL(irlmp_dup); EXPORT_SYMBOL(lmp_reasons); /* Queue */ @@ -174,10 +176,15 @@ 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(irda_device_init_dongle); +EXPORT_SYMBOL(irda_device_register_dongle); +EXPORT_SYMBOL(irda_device_unregister_dongle); + EXPORT_SYMBOL(async_wrap_skb); EXPORT_SYMBOL(async_unwrap_char); EXPORT_SYMBOL(irda_start_timer); -EXPORT_SYMBOL(irda_get_mtt); +/* EXPORT_SYMBOL(irda_get_mtt); */ EXPORT_SYMBOL(setup_dma); #ifdef CONFIG_IRTTY @@ -505,19 +512,28 @@ void irda_mod_dec_use_count(void) #endif } -#ifdef MODULE -#ifdef CONFIG_PROC_FS +/* + * Function irda_proc_modcount (inode, fill) + * + * Use by the proc file system functions to prevent the irda module + * being removed while the use is standing in the net/irda directory + */ void irda_proc_modcount(struct inode *inode, int fill) { +#ifdef MODULE +#ifdef CONFIG_PROC_FS if (fill) MOD_INC_USE_COUNT; else MOD_DEC_USE_COUNT; -} #endif /* CONFIG_PROC_FS */ +#endif /* MODULE */ +} + +#ifdef MODULE MODULE_AUTHOR("Dag Brattli "); -MODULE_DESCRIPTION("The Linux IrDA protocol subsystem"); +MODULE_DESCRIPTION("The Linux IrDA Protocol Subsystem"); MODULE_PARM(irda_debug, "1l"); /* diff --git a/net/irda/irproc.c b/net/irda/irproc.c index f3b710b95324..a04951694167 100644 --- a/net/irda/irproc.c +++ b/net/irda/irproc.c @@ -6,10 +6,10 @@ * Status: Experimental. * Author: Thomas Davis, * Created at: Sat Feb 21 21:33:24 1998 - * Modified at: Tue Apr 6 19:07:06 1999 + * Modified at: Fri May 7 08:06:49 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998, Thomas Davis, , + * Copyright (c) 1998-1999, Thomas Davis, , * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -20,8 +20,6 @@ * I, Thomas Davis, provide no warranty for any of this software. * This material is provided "AS-IS" and at no charge. * - * Portions lifted from the linux/fs/procfs/ files. - * ********************************************************************/ #include @@ -44,28 +42,27 @@ extern int irias_proc_read(char *buf, char **start, off_t offset, int len, int unused); extern int discovery_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); -enum irda_directory_inos { - PROC_IRDA_LAP = 1, - PROC_IRDA_LMP, - PROC_IRDA_TTP, - PROC_IRDA_LPT, - PROC_IRDA_COMM, - PROC_IRDA_IRDA_DEVICE, - PROC_IRDA_IRIAS -}; +/* enum irda_directory_inos { */ +/* PROC_IRDA_LAP = 1, */ +/* PROC_IRDA_LMP, */ +/* PROC_IRDA_TTP, */ +/* PROC_IRDA_LPT, */ +/* PROC_IRDA_COMM, */ +/* PROC_IRDA_IRDA_DEVICE, */ +/* PROC_IRDA_IRIAS */ +/* }; */ struct irda_entry { char *name; - int (*fn)(char*,char**,off_t,int,int); + int (*fn)(char*, char**, off_t, int, int); }; struct proc_dir_entry *proc_irda; - + static struct irda_entry dir[] = { -#if 0 - {"lpt", irlpt_proc_read}, -#endif {"discovery", discovery_proc_read}, {"irda_device", irda_device_proc_read}, {"irttp", irttp_proc_read}, @@ -75,19 +72,22 @@ static struct irda_entry dir[] = { }; #define IRDA_ENTRIES_NUM (sizeof(dir)/sizeof(dir[0])) - + /* * Function irda_proc_register (void) * * Register irda entry in /proc file system * */ -void irda_proc_register(void) { +void irda_proc_register(void) +{ int i; + proc_irda = create_proc_entry("net/irda", S_IFDIR, NULL); #ifdef MODULE proc_irda->fill_inode = &irda_proc_modcount; #endif /* MODULE */ + for (i=0;iget_info=dir[i].fn; } @@ -98,9 +98,14 @@ void irda_proc_register(void) { * Unregister irda entry in /proc file system * */ -void irda_proc_unregister(void) { +void irda_proc_unregister(void) +{ int i; + for (i=0;i * Created at: Sun May 24 22:12:06 1998 - * Modified at: Fri Apr 23 09:46:38 1999 + * Modified at: Thu May 6 21:32:46 1999 * Modified by: Dag Brattli * - * Copyright (c) 1997 Dag Brattli, All Rights Reserved. + * Copyright (c) 1997, 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 diff --git a/net/irda/irttp.c b/net/irda/irttp.c index bf0624eee0f9..23b2a256e945 100644 --- a/net/irda/irttp.c +++ b/net/irda/irttp.c @@ -6,10 +6,10 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sun Aug 31 20:14:31 1997 - * Modified at: Sat Apr 10 10:32:21 1999 + * Modified at: Mon May 10 17:12:53 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli , + * Copyright (c) 1998-1999 Dag Brattli , * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -48,8 +48,10 @@ static void irttp_disconnect_indication(void *instance, void *sap, struct sk_buff *); static void irttp_connect_indication(void *instance, void *sap, struct qos_info *qos, __u32 max_sdu_size, - struct sk_buff *skb); - + __u8 header_size, struct sk_buff *skb); +static void irttp_connect_confirm(void *instance, void *sap, + struct qos_info *qos, __u32 max_sdu_size, + __u8 header_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); @@ -337,6 +339,7 @@ int irttp_data_request(struct tsap_cb *self, struct sk_buff *skb) /* Queue frame, or queue frame segments */ if ((self->tx_max_sdu_size == 0) || (skb->len < self->max_seg_size)) { /* Queue frame */ + ASSERT(skb_headroom(skb) >= TTP_HEADER, return -1;); frame = skb_push(skb, TTP_HEADER); frame[0] = 0x00; /* Clear more bit */ @@ -360,8 +363,8 @@ int irttp_data_request(struct tsap_cb *self, struct sk_buff *skb) self->tx_sdu_busy = TRUE; if (self->notify.flow_indication) { - self->notify.flow_indication( - self->notify.instance, self, FLOW_STOP); + self->notify.flow_indication(self->notify.instance, + self, FLOW_STOP); } } @@ -472,7 +475,7 @@ void irttp_give_credit(struct tsap_cb *self) return; /* Reserve space for LMP, and LAP header */ - skb_reserve(tx_skb, LMP_HEADER+LAP_HEADER); + skb_reserve(tx_skb, self->max_header_size); /* * Since we can transmit and receive frames concurrently, @@ -655,15 +658,14 @@ int irttp_connect_request(struct tsap_cb *self, __u8 dtsap_sel, return -ENOMEM; /* Reserve space for MUX_CONTROL and LAP header */ - skb_reserve(skb, (TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER)); + skb_reserve(skb, TTP_MAX_HEADER); } else { skb = userdata; /* * Check that the client has reserved enough space for * headers */ - ASSERT(skb_headroom(userdata) >= - (TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER), return -1;); + ASSERT(skb_headroom(userdata) >= TTP_MAX_HEADER, return -1;); } /* Initialize connection parameters */ @@ -691,12 +693,11 @@ int irttp_connect_request(struct tsap_cb *self, __u8 dtsap_sel, /* SAR enabled? */ if (max_sdu_size > 0) { - ASSERT(skb_headroom(skb) >= - (TTP_HEADER_WITH_SAR+LMP_CONTROL_HEADER+LAP_HEADER), - return -1;); + ASSERT(skb_headroom(skb) >= (TTP_MAX_HEADER + TTP_SAR_HEADER), + return -1;); /* Insert SAR parameters */ - frame = skb_push(skb, TTP_HEADER_WITH_SAR); + frame = skb_push(skb, TTP_HEADER+TTP_SAR_HEADER); frame[0] = TTP_PARAMETERS | n; frame[1] = 0x04; /* Length */ @@ -724,8 +725,10 @@ int irttp_connect_request(struct tsap_cb *self, __u8 dtsap_sel, * Sevice user confirms TSAP connection with peer. * */ -void irttp_connect_confirm(void *instance, void *sap, struct qos_info *qos, - __u32 max_seg_size, struct sk_buff *skb) +static void irttp_connect_confirm(void *instance, void *sap, + struct qos_info *qos, + __u32 max_seg_size, __u8 max_header_size, + struct sk_buff *skb) { struct tsap_cb *self; int parameters; @@ -741,7 +744,8 @@ void irttp_connect_confirm(void *instance, void *sap, struct qos_info *qos, ASSERT(self->magic == TTP_TSAP_MAGIC, return;); ASSERT(skb != NULL, return;); - self->max_seg_size = max_seg_size-LMP_HEADER-LAP_HEADER; + self->max_seg_size = max_seg_size; + self->max_header_size = max_header_size + TTP_HEADER; /* * Check if we have got some QoS parameters back! This should be the @@ -797,9 +801,9 @@ void irttp_connect_confirm(void *instance, void *sap, struct qos_info *qos, 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); + self->notify.connect_confirm(self->notify.instance, self, qos, + self->tx_max_sdu_size, + self->max_header_size, skb); } } @@ -809,8 +813,8 @@ 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, __u32 max_seg_size, +void irttp_connect_indication(void *instance, void *sap, struct qos_info *qos, + __u32 max_seg_size, __u8 max_header_size, struct sk_buff *skb) { struct tsap_cb *self; @@ -828,7 +832,9 @@ void irttp_connect_indication(void *instance, void *sap, lsap = (struct lsap_cb *) sap; - self->max_seg_size = max_seg_size-LMP_HEADER-LAP_HEADER; + self->max_seg_size = max_seg_size; + + self->max_header_size = max_header_size+TTP_HEADER; DEBUG(4, __FUNCTION__ "(), TSAP sel=%02x\n", self->stsap_sel); @@ -850,7 +856,7 @@ void irttp_connect_indication(void *instance, void *sap, switch (pl) { case 1: - self->tx_max_sdu_size = *(frame+4); + self->tx_max_sdu_size = frame[4]; break; case 2: self->tx_max_sdu_size = @@ -878,7 +884,7 @@ void irttp_connect_indication(void *instance, void *sap, if (self->notify.connect_indication) { self->notify.connect_indication(self->notify.instance, self, qos, self->rx_max_sdu_size, - skb); + self->max_header_size, skb); } } @@ -909,15 +915,14 @@ void irttp_connect_response(struct tsap_cb *self, __u32 max_sdu_size, return; /* Reserve space for MUX_CONTROL and LAP header */ - skb_reserve(skb, (TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER)); + skb_reserve(skb, TTP_MAX_HEADER); } else { skb = userdata; /* * Check that the client has reserved enough space for * headers */ - ASSERT(skb_headroom(skb) >= - (TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER), return;); + ASSERT(skb_headroom(skb) >= TTP_MAX_HEADER, return;); } self->avail_credit = 0; @@ -939,12 +944,11 @@ void irttp_connect_response(struct tsap_cb *self, __u32 max_sdu_size, /* SAR enabled? */ if (max_sdu_size > 0) { - ASSERT(skb_headroom(skb) >= - (TTP_HEADER_WITH_SAR+LMP_CONTROL_HEADER+LAP_HEADER), + ASSERT(skb_headroom(skb) >= (TTP_MAX_HEADER+TTP_SAR_HEADER), return;); /* Insert TTP header with SAR parameters */ - frame = skb_push(skb, TTP_HEADER_WITH_SAR); + frame = skb_push(skb, TTP_HEADER+TTP_SAR_HEADER); frame[0] = TTP_PARAMETERS | n; frame[1] = 0x04; /* Length */ @@ -1079,7 +1083,7 @@ void irttp_disconnect_request(struct tsap_cb *self, struct sk_buff *userdata, /* * Reserve space for MUX and LAP header */ - skb_reserve(skb, LMP_CONTROL_HEADER+LAP_HEADER); + skb_reserve(skb, TTP_MAX_HEADER); userdata = skb; } @@ -1357,13 +1361,11 @@ static void irttp_fragment_skb(struct tsap_cb *self, struct sk_buff *skb) } /* Make new segment */ - frag = dev_alloc_skb(self->max_seg_size+ - TTP_HEADER+LMP_HEADER+ - LAP_HEADER); + frag = dev_alloc_skb(self->max_seg_size+self->max_header_size); if (!frag) return; - skb_reserve(frag, LMP_HEADER+LAP_HEADER); + skb_reserve(frag, self->max_header_size); /* * Copy data from the original skb into this fragment. We diff --git a/net/irda/qos.c b/net/irda/qos.c index 7b226dfa6481..82f7fc28a70d 100644 --- a/net/irda/qos.c +++ b/net/irda/qos.c @@ -6,10 +6,11 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Tue Sep 9 00:00:26 1997 - * Modified at: Mon Apr 12 11:49:24 1999 + * Modified at: Mon May 3 21:15:08 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli , All Rights Reserved. + * Copyright (c) 1998-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 @@ -52,10 +53,10 @@ int compression[] = { CI_BZIP2, CI_DEFLATE, CI_DEFLATE_DRAFT }; * Compute the intersection of the old QoS capabilites with new ones * */ -void irda_qos_compute_intersection( struct qos_info *qos, struct qos_info *new) +void irda_qos_compute_intersection(struct qos_info *qos, struct qos_info *new) { - ASSERT( qos != NULL, return;); - ASSERT( new != NULL, return;); + ASSERT(qos != NULL, return;); + ASSERT(new != NULL, return;); /* Apply */ qos->baud_rate.bits &= new->baud_rate.bits; diff --git a/net/irda/wrapper.c b/net/irda/wrapper.c index c4822e2c6e86..b78368bc0e69 100644 --- a/net/irda/wrapper.c +++ b/net/irda/wrapper.c @@ -1,15 +1,15 @@ /********************************************************************* * * Filename: wrapper.c - * Version: 1.1 - * Description: SIR wrapper layer + * Version: 1.2 + * Description: IrDA SIR async wrapper layer * Status: Experimental. * Author: Dag Brattli * Created at: Mon Aug 4 20:40:53 1997 - * Modified at: Wed Apr 21 12:45:55 1999 + * Modified at: Sun May 2 21:58:00 1999 * Modified by: Dag Brattli * - * Copyright (c) 1998 Dag Brattli , + * Copyright (c) 1998-1999 Dag Brattli , * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -34,7 +34,20 @@ #include #include -inline static int stuff_byte(__u8 byte, __u8 *buf); +static inline int stuff_byte(__u8 byte, __u8 *buf); + +static void state_outside_frame(struct irda_device *idev, __u8 byte); +static void state_begin_frame(struct irda_device *idev, __u8 byte); +static void state_link_escape(struct irda_device *idev, __u8 byte); +static void state_inside_frame(struct irda_device *idev, __u8 byte); + +static void (*state[])(struct irda_device *idev, __u8 byte) = +{ + state_outside_frame, + state_begin_frame, + state_link_escape, + state_inside_frame, +}; /* * Function async_wrap (skb, *tx_buff) @@ -52,8 +65,6 @@ int async_wrap_skb(struct sk_buff *skb, __u8 *tx_buff, int buffsize) __u8 bytes[2]; } fcs; - ASSERT(skb != NULL, return 0;); - /* Initialize variables */ fcs.value = INIT_FCS; n = 0; @@ -74,13 +85,9 @@ int async_wrap_skb(struct sk_buff *skb, __u8 *tx_buff, int buffsize) } else xbofs = ((struct irlap_skb_cb *)(skb->cb))->xbofs; -#if 0 - for (i=0; idata[i], tx_buff+n); - fcs.value = IR_FCS(fcs.value, skb->data[i]); + fcs.value = irda_fcs(fcs.value, skb->data[i]); } /* Insert CRC in little endian format (LSB first) */ @@ -108,15 +115,6 @@ int async_wrap_skb(struct sk_buff *skb, __u8 *tx_buff, int buffsize) #endif tx_buff[n++] = EOF; -#if 0 - { - int i; - - for (i=0;istats.rx_bytes += skb->len; } -/* - * Function async_unwrap (skb) - * - * Parse and de-stuff frame received from the IR-port - * - */ -void async_unwrap_char(struct irda_device *idev, __u8 byte) -{ - /* State machine for receiving frames */ - switch (idev->rx_buff.state) { - case OUTSIDE_FRAME: - switch(byte) { - case BOF: - idev->rx_buff.state = BEGIN_FRAME; - idev->rx_buff.in_frame = TRUE; - 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: - /* Stuffed byte */ - idev->rx_buff.state = LINK_ESCAPE; - break; - case EOF: - /* Abort frame */ - idev->rx_buff.state = OUTSIDE_FRAME; - - idev->stats.rx_errors++; - idev->stats.rx_frame_errors++; - break; - default: - /* Got first byte of frame */ - idev->rx_buff.data = idev->rx_buff.head; - idev->rx_buff.len = 0; - - idev->rx_buff.data[idev->rx_buff.len++] = byte; - - idev->rx_buff.fcs = IR_FCS(INIT_FCS, byte); - idev->rx_buff.state = INSIDE_FRAME; - break; - } - break; - case LINK_ESCAPE: - switch (byte) { - case BOF: - /* New frame? */ - idev->rx_buff.state = BEGIN_FRAME; - irda_device_set_media_busy(idev, TRUE); - break; - case CE: - DEBUG(4, "WARNING: State not defined\n"); - break; - case EOF: - /* Abort frame */ - idev->rx_buff.state = OUTSIDE_FRAME; - break; - default: - /* - * Stuffed char, complement bit 5 of byte - * following CE, IrLAP p.114 - */ - byte ^= IR_TRANS; - 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.state = INSIDE_FRAME; - } else { - DEBUG(1, __FUNCTION__ - "(), Rx buffer overflow, aborting\n"); - idev->rx_buff.state = OUTSIDE_FRAME; - } - break; - } - break; - case INSIDE_FRAME: - switch (byte) { - case BOF: - /* New frame? */ - idev->rx_buff.state = BEGIN_FRAME; - irda_device_set_media_busy(idev, TRUE); - break; - case CE: - /* Stuffed char */ - idev->rx_buff.state = LINK_ESCAPE; - break; - case EOF: - /* End of frame */ - idev->rx_buff.state = OUTSIDE_FRAME; - idev->rx_buff.in_frame = FALSE; - - /* - * Test FCS and deliver frame if it's good - */ - if (idev->rx_buff.fcs == GOOD_FCS) { - async_bump(idev, idev->rx_buff.data, - idev->rx_buff.len); - } else { - /* Wrong CRC, discard frame! */ - irda_device_set_media_busy(idev, TRUE); - - idev->stats.rx_errors++; - idev->stats.rx_crc_errors++; - } - break; - default: - /* Next byte of frame */ - 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 { - DEBUG(1, __FUNCTION__ - "(), Rx buffer overflow, aborting\n"); - idev->rx_buff.state = OUTSIDE_FRAME; - } - break; - } - break; - } -} - /* * Function stuff_byte (byte, buf) * @@ -295,7 +159,7 @@ 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) +static inline int stuff_byte(__u8 byte, __u8 *buf) { switch (byte) { case BOF: /* FALLTHROUGH */ @@ -303,7 +167,7 @@ inline static int stuff_byte(__u8 byte, __u8 *buf) case CE: /* Insert transparently coded */ buf[0] = CE; /* Send link escape */ - buf[1] = byte^IR_TRANS; /* Complement bit 5 */ + buf[1] = byte^IRDA_TRANS; /* Complement bit 5 */ return 2; /* break; */ default: @@ -313,7 +177,159 @@ inline static int stuff_byte(__u8 byte, __u8 *buf) /* break; */ } } + +/* + * Function async_unwrap (skb) + * + * Parse and de-stuff frame received from the IrDA-port + * + */ +inline void async_unwrap_char(struct irda_device *idev, __u8 byte) +{ + (*state[idev->rx_buff.state]) (idev, byte); +} +/* + * Function state_outside_frame (idev, byte) + * + * + * + */ +static void state_outside_frame(struct irda_device *idev, __u8 byte) +{ + switch (byte) { + case BOF: + idev->rx_buff.state = BEGIN_FRAME; + idev->rx_buff.in_frame = TRUE; + break; + case XBOF: + /* idev->xbofs++; */ + break; + case EOF: + irda_device_set_media_busy( idev, TRUE); + break; + default: + break; + } +} +/* + * Function state_begin_frame (idev, byte) + * + * + * + */ +static void state_begin_frame(struct irda_device *idev, __u8 byte) +{ + switch (byte) { + case BOF: + /* Continue */ + break; + case CE: + /* Stuffed byte */ + idev->rx_buff.state = LINK_ESCAPE; + break; + case EOF: + /* Abort frame */ + idev->rx_buff.state = OUTSIDE_FRAME; + + idev->stats.rx_errors++; + idev->stats.rx_frame_errors++; + break; + default: + /* Got first byte of frame */ + idev->rx_buff.data = idev->rx_buff.head; + idev->rx_buff.len = 0; + + idev->rx_buff.data[idev->rx_buff.len++] = byte; + + idev->rx_buff.fcs = irda_fcs(INIT_FCS, byte); + idev->rx_buff.state = INSIDE_FRAME; + break; + } +} + +/* + * Function state_link_escape (idev, byte) + * + * + * + */ +static void state_link_escape(struct irda_device *idev, __u8 byte) +{ + switch (byte) { + case BOF: /* New frame? */ + idev->rx_buff.state = BEGIN_FRAME; + irda_device_set_media_busy(idev, TRUE); + break; + case CE: + DEBUG(4, "WARNING: State not defined\n"); + break; + case EOF: /* Abort frame */ + idev->rx_buff.state = OUTSIDE_FRAME; + break; + default: + /* + * Stuffed char, complement bit 5 of byte + * following CE, IrLAP p.114 + */ + byte ^= IRDA_TRANS; + if (idev->rx_buff.len < idev->rx_buff.truesize) { + idev->rx_buff.data[idev->rx_buff.len++] = byte; + idev->rx_buff.fcs = irda_fcs(idev->rx_buff.fcs, byte); + idev->rx_buff.state = INSIDE_FRAME; + } else { + DEBUG(1, __FUNCTION__ + "(), Rx buffer overflow, aborting\n"); + idev->rx_buff.state = OUTSIDE_FRAME; + } + break; + } +} + +/* + * Function state_inside_frame (idev, byte) + * + * + * + */ +static void state_inside_frame(struct irda_device *idev, __u8 byte) +{ + switch (byte) { + case BOF: /* New frame? */ + idev->rx_buff.state = BEGIN_FRAME; + irda_device_set_media_busy(idev, TRUE); + break; + case CE: /* Stuffed char */ + idev->rx_buff.state = LINK_ESCAPE; + break; + case EOF: /* End of frame */ + idev->rx_buff.state = OUTSIDE_FRAME; + idev->rx_buff.in_frame = FALSE; + + /* Test FCS and deliver frame if it's good */ + if (idev->rx_buff.fcs == GOOD_FCS) { + async_bump(idev, idev->rx_buff.data, + idev->rx_buff.len); + } else { + /* Wrong CRC, discard frame! */ + irda_device_set_media_busy(idev, TRUE); + + idev->stats.rx_errors++; + idev->stats.rx_crc_errors++; + } + break; + default: /* Must be the next byte of the frame */ + if (idev->rx_buff.len < idev->rx_buff.truesize) { + idev->rx_buff.data[idev->rx_buff.len++] = byte; + idev->rx_buff.fcs = irda_fcs(idev->rx_buff.fcs, byte); + } else { + DEBUG(1, __FUNCTION__ + "(), Rx buffer overflow, aborting\n"); + idev->rx_buff.state = OUTSIDE_FRAME; + } + break; + } +} -- 2.39.5