diff options
Diffstat (limited to 'drivers/net/irda')
-rw-r--r-- | drivers/net/irda/Config.in | 33 | ||||
-rw-r--r-- | drivers/net/irda/Makefile | 80 | ||||
-rw-r--r-- | drivers/net/irda/actisys.c | 150 | ||||
-rw-r--r-- | drivers/net/irda/esi.c | 78 | ||||
-rw-r--r-- | drivers/net/irda/girbil.c | 95 | ||||
-rw-r--r-- | drivers/net/irda/irport.c | 557 | ||||
-rw-r--r-- | drivers/net/irda/irtty.c | 167 | ||||
-rw-r--r-- | drivers/net/irda/pc87108.c | 252 | ||||
-rw-r--r-- | drivers/net/irda/tekram.c | 106 | ||||
-rw-r--r-- | drivers/net/irda/uircc.c | 18 | ||||
-rw-r--r-- | drivers/net/irda/w83977af_ir.c | 535 |
11 files changed, 1169 insertions, 902 deletions
diff --git a/drivers/net/irda/Config.in b/drivers/net/irda/Config.in index 64f6c327e..df988de48 100644 --- a/drivers/net/irda/Config.in +++ b/drivers/net/irda/Config.in @@ -1,18 +1,25 @@ 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 +dep_tristate 'SMC IrCC' CONFIG_SMC_IRCC_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 6a7920a6e..b92dde935 100644 --- a/drivers/net/irda/Makefile +++ b/drivers/net/irda/Makefile @@ -20,6 +20,30 @@ 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_IRPORT_SIR),y) +L_OBJS += irport.o +else + ifeq ($(CONFIG_IRPORT_SIR),m) + M_OBJS += irport.o + 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 +68,38 @@ 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_TOSHIBA_FIR),y) +L_OBJS += toshoboe.o +else + ifeq ($(CONFIG_TOSHIBA_FIR),m) + M_OBJS += toshoboe.o + 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_SMC_IRCC_FIR),y) +L_OBJS += irport.o smc-ircc.o +else + ifeq ($(CONFIG_SMC_IRCC_FIR),m) + M_OBJS += irport.o smc-ircc.o + endif +endif + ifeq ($(CONFIG_ESI_DONGLE),y) L_OBJS += esi.o else @@ -76,6 +132,30 @@ else endif endif +ifeq ($(CONFIG_LITELINK_DONGLE),y) +L_OBJS += litelink.o +else + ifeq ($(CONFIG_LITELINK_DONGLE),m) + M_OBJS += litelink.o + endif +endif + +ifeq ($(CONFIG_LITELINK_DONGLE),y) +L_OBJS += litelink.o +else + ifeq ($(CONFIG_LITELINK_DONGLE),m) + M_OBJS += litelink.o + 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 46ce2badf..8e86770a1 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 <dagb@cs.uit.no> * Created at: Wed Oct 21 20:02:35 1998 - * Modified at: Mon Apr 12 11:56:35 1999 + * Modified at: Sun May 16 14:35:11 1999 * Modified by: Dag Brattli <dagb@cs.uit.no> * - * 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,22 +29,16 @@ #include <linux/sched.h> #include <linux/init.h> -#include <asm/ioctls.h> -#include <asm/segment.h> -#include <asm/uaccess.h> - #include <net/irda/irda.h> #include <net/irda/irmod.h> #include <net/irda/irda_device.h> -#include <net/irda/irtty.h> #include <net/irda/dongle.h> -static void 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); +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_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 +52,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 +92,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 +107,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;); + 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;); - current_baudrate = idev->qos.baud_rate.value; /* Find the correct baudrate index for the currently used baudrate */ @@ -117,69 +125,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 +164,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) { - 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 +188,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 +212,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 5395d2829..b1f47b775 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, <ratbert@radiks.net> * Created at: Sat Feb 21 18:54:38 1998 - * Modified at: Mon Apr 12 11:55:30 1999 + * Modified at: Sun May 16 14:35:21 1999 * Modified by: Dag Brattli <dagb@cs.uit.no> * Sources: esi.c * + * Copyright (c) 1998-1999, Dag Brattli, <dagb@cs.uit.no> * Copyright (c) 1998, Thomas Davis, <ratbert@radiks.net>, - * Copyright (c) 1998, Dag Brattli, <dagb@cs.uit.no> * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -31,21 +31,17 @@ #include <linux/sched.h> #include <linux/init.h> -#include <asm/ioctls.h> -#include <asm/segment.h> -#include <asm/uaccess.h> - #include <net/irda/irda.h> #include <net/irda/irmod.h> #include <net/irda/irda_device.h> #include <net/irda/irtty.h> #include <net/irda/dongle.h> -static void 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); +static void esi_qos_init(struct irda_device *idev, struct qos_info *qos); static struct dongle dongle = { ESI_DONGLE, @@ -58,17 +54,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 +72,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,57 +86,33 @@ 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;); + 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 (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) +static void esi_reset( struct irda_device *idev) { /* Empty */ } @@ -148,14 +123,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 <dagb@cs.uit.no>"); +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 128b32a23..938315bc5 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 <dagb@cs.uit.no> * Created at: Sat Feb 6 21:02:33 1999 - * Modified at: Sat Apr 10 19:53:12 1999 + * Modified at: Tue Jun 1 08:47:41 1999 * Modified by: Dag Brattli <dagb@cs.uit.no> * * Copyright (c) 1999 Dag Brattli, All Rights Reserved. @@ -28,17 +28,13 @@ #include <linux/sched.h> #include <linux/init.h> -#include <asm/ioctls.h> -#include <asm/segment.h> -#include <asm/uaccess.h> - #include <net/irda/irda.h> #include <net/irda/irmod.h> #include <net/irda/irda_device.h> #include <net/irda/irtty.h> #include <net/irda/dongle.h> -static void girbil_reset(struct irda_device *dev, int unused); +static void girbil_reset(struct irda_device *dev); static void girbil_open(struct irda_device *dev, int type); static void girbil_close(struct irda_device *dev); static void girbil_change_speed(struct irda_device *dev, int baud); @@ -80,19 +76,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 +96,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 +113,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); } /* @@ -191,46 +161,38 @@ static void girbil_change_speed(struct irda_device *idev, int speed) * 0. set RTS, and wait at least 5 ms * 1. clear RTS */ -void girbil_reset(struct irda_device *idev, int unused) +void girbil_reset(struct irda_device *idev) { - 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); + schedule_timeout(MSECS_TO_JIFFIES(20)); /* 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); + schedule_timeout(MSECS_TO_JIFFIES(20)); /* 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); + schedule_timeout(MSECS_TO_JIFFIES(20)); /* Go back to normal mode */ - irtty_set_dtr_rts(tty, TRUE, TRUE); + irda_device_set_dtr_rts(idev, TRUE, TRUE); + + /* Make sure the IrDA chip also goes to defalt speed */ + if (idev->change_speed) + idev->change_speed(idev, 9600); } /* @@ -242,7 +204,7 @@ void girbil_reset(struct irda_device *idev, int unused) static void girbil_init_qos(struct irda_device *idev, struct qos_info *qos) { qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200; - qos->min_turn_time.bits &= 0xfe; /* All except 0 ms */ + qos->min_turn_time.bits &= 0x03; } #ifdef MODULE @@ -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 5ea6dba73..5fb0cd4f2 100644 --- a/drivers/net/irda/irport.c +++ b/drivers/net/irda/irport.c @@ -1,43 +1,38 @@ /********************************************************************* - * + * * Filename: irport.c - * Version: 0.9 - * Description: Serial driver for IrDA. + * Version: 1.0 + * Description: Half duplex serial port SIR driver for IrDA. * Status: Experimental. * Author: Dag Brattli <dagb@cs.uit.no> * Created at: Sun Aug 3 13:49:59 1997 - * Modified at: Sat May 23 23:15:20 1998 + * Modified at: Tue Jun 1 10:02:42 1999 * Modified by: Dag Brattli <dagb@cs.uit.no> * Sources: serial.c by Linus Torvalds * - * Copyright (c) 1997,1998 Dag Brattli <dagb@cs.uit.no> - * All Rights Reserved. + * Copyright (c) 1997, 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 * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. - * - * Neither Dag Brattli nor University of Tromsų admit liability nor - * provide warranty for any of this software. This material is - * provided "AS-IS" and at no charge. - * - * NOTICE: + * + * 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 * * This driver is ment to be a small half duplex serial driver to be - * used for IR-chipsets that has a UART (16550) compatibility mode. If - * your chipset is is UART only, you should probably use IrTTY instead - * since the Linux serial driver is probably more robust and optimized. - * - * The functions in this file may be used by FIR drivers, but this - * driver knows nothing about FIR drivers so don't ever insert such - * code into this file. Instead you should code your FIR driver in a - * separate file, and then call the functions in this file if - * necessary. This is becase it is difficult to use the Linux serial - * driver with a FIR driver becase they must share interrupts etc. Most - * FIR chipsets can function in advanced SIR mode, and you should - * probably use that mode instead of the UART compatibility mode (and - * then just forget about this file) + * used for IR-chipsets that has a UART (16550) compatibility mode. + * Eventually it will replace irtty, because of irtty has some + * problems that is hard to get around when we don't have control + * over the serial driver. This driver may also be used by FIR + * drivers to handle SIR mode for them. * ********************************************************************/ @@ -48,14 +43,15 @@ #include <linux/ioport.h> #include <linux/malloc.h> #include <linux/string.h> -#include <asm/system.h> -#include <asm/bitops.h> -#include <asm/io.h> +#include <linux/skbuff.h> +#include <linux/serial_reg.h> #include <linux/errno.h> #include <linux/init.h> -#include <linux/skbuff.h> -#include <linux/serial_reg.h> +#include <asm/system.h> +#include <asm/bitops.h> +#include <asm/io.h> +#include <asm/spinlock.h> #include <net/irda/irda.h> #include <net/irda/irmod.h> @@ -64,105 +60,254 @@ #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 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; + + idev->netdev.base_addr = iobase; + idev->netdev.irq = irq; + + /* 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); + /* irport_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) +{ + ASSERT(idev != NULL, return -1;); + ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;); + + /* Release the IO-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(struct irda_device *idev, int iobase) +{ + unsigned long flags; + + spin_lock_irqsave(&idev->lock, flags); + + irport_stop(idev, 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); /* Turn on interrups */ - outb((UART_IER_RLSI | UART_IER_RDI), iobase+UART_IER); + outb(UART_IER_RLSI | UART_IER_RDI |UART_IER_THRI, iobase+UART_IER); - return 0; + spin_unlock_irqrestore(&idev->lock, flags); } -/* - * Function irport_cleanup () - * - * Stop IO port - * - */ -void irport_close(int iobase) +void irport_stop(struct irda_device *idev, int iobase) { - DEBUG(4, __FUNCTION__ "()\n"); + unsigned long flags; + + spin_lock_irqsave(&idev->lock, flags); /* Reset UART */ outb(0, iobase+UART_MCR); - + /* Turn off interrupts */ outb(0, iobase+UART_IER); + + spin_unlock_irqrestore(&idev->lock, flags); +} + +/* + * Function irport_probe (void) + * + * Start IO port + * + */ +int irport_probe(int iobase) +{ + DEBUG(4, __FUNCTION__ "(), iobase=%#x\n", iobase); + + return 0; } /* * Function irport_change_speed (idev, speed) * - * Set speed of port to specified baudrate + * Set speed of IrDA port to specified baudrate * */ -void irport_change_speed( int iobase, int speed) +void irport_change_speed(struct irda_device *idev, int speed) { + unsigned long flags; + int iobase; int fcr; /* FIFO control reg */ int lcr; /* Line control reg */ int divisor; - DEBUG( 0, __FUNCTION__ "(), Setting speed to: %d\n", speed); + 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; + + spin_lock_irqsave(&idev->lock, flags); /* Turn off interrupts */ outb(0, iobase+UART_IER); divisor = SPEED_MAX/speed; - fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_14; + fcr = UART_FCR_ENABLE_FIFO; + + /* + * Use trigger level 1 to avoid 3 ms. timeout delay at 9600 bps, and + * almost 1,7 ms at 19200 bps. At speeds above that we can just forget + * about this timeout since it will always be fast enough. + */ + if (idev->io.baudrate < 38400) + fcr |= UART_FCR_TRIGGER_1; + else + fcr |= UART_FCR_TRIGGER_14; /* IrDA ports use 8N1 */ lcr = UART_LCR_WLEN8; @@ -173,8 +318,10 @@ void irport_change_speed( int iobase, int speed) outb(lcr, iobase+UART_LCR); /* Set 8N1 */ outb(fcr, iobase+UART_FCR); /* Enable FIFO's */ - /* Turn on receive interrups */ - outb(UART_IER_RLSI|UART_IER_RDI, iobase+UART_IER); + /* Turn on interrups */ + outb(UART_IER_RLSI|UART_IER_RDI|UART_IER_THRI, iobase+UART_IER); + + spin_unlock_irqrestore(&self->lock, flags); } /* @@ -188,10 +335,13 @@ static void irport_write_wakeup(struct irda_device *idev) { int actual = 0; int iobase; + int fcr; ASSERT(idev != NULL, return;); ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); + DEBUG(4, __FUNCTION__ "()\n"); + /* Finished with frame? */ if (idev->tx_buff.len > 0) { /* Write data left in transmit buffer */ @@ -211,9 +361,18 @@ static void irport_write_wakeup(struct irda_device *idev) /* Schedule network layer, so we can get some more frames */ mark_bh(NET_BH); - outb(UART_FCR_ENABLE_FIFO | - UART_FCR_TRIGGER_14 | - UART_FCR_CLEAR_RCVR, iobase+UART_FCR); /* Enable FIFO's */ + fcr = UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR; + + if (idev->io.baudrate < 38400) + fcr |= UART_FCR_TRIGGER_1; + else + fcr |= UART_FCR_TRIGGER_14; + + /* + * Reset Rx FIFO to make sure that all reflected transmit data + * will be discarded + */ + outb(fcr, iobase+UART_FCR); /* Turn on receive interrupts */ outb(UART_IER_RLSI|UART_IER_RDI, iobase+UART_IER); @@ -223,7 +382,7 @@ static void irport_write_wakeup(struct irda_device *idev) /* * Function irport_write (driver) * - * + * Fill Tx FIFO with transmit data * */ static int irport_write(int iobase, int fifo_size, __u8 *buf, int len) @@ -232,21 +391,18 @@ static int irport_write(int iobase, int fifo_size, __u8 *buf, int len) /* Tx FIFO should be empty! */ if (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) { - DEBUG( 0, __FUNCTION__ "(), failed, fifo not empty!\n"); + DEBUG(0, __FUNCTION__ "(), failed, fifo not empty!\n"); return -1; } /* Fill FIFO with current frame */ - while (( fifo_size-- > 0) && (actual < len)) { + while ((fifo_size-- > 0) && (actual < len)) { /* Transmit next byte */ - outb( buf[actual], iobase+UART_TX); + outb(buf[actual], iobase+UART_TX); actual++; } - DEBUG(4, __FUNCTION__ "(), fifo_size %d ; %d sent of %d\n", - fifo_size, actual, len); - return actual; } @@ -260,11 +416,10 @@ static int irport_write(int iobase, int fifo_size, __u8 *buf, int len) int irport_hard_xmit(struct sk_buff *skb, struct device *dev) { struct irda_device *idev; + unsigned long flags; int actual = 0; int iobase; - DEBUG(5, __FUNCTION__ "(), dev=%p\n", dev); - ASSERT(dev != NULL, return 0;); idev = (struct irda_device *) dev->priv; @@ -275,8 +430,19 @@ int irport_hard_xmit(struct sk_buff *skb, struct device *dev) iobase = idev->io.iobase2; /* Lock transmit buffer */ - if (irda_lock((void *) &dev->tbusy) == FALSE) - return -EBUSY; + if (irda_lock((void *) &dev->tbusy) == FALSE) { + int tickssofar = jiffies - dev->trans_start; + if (tickssofar < 5) + return -EBUSY; + + WARNING("%s: transmit timed out\n", dev->name); + irport_start(idev, iobase); + irport_change_speed(idev, idev->io.baudrate); + + dev->trans_start = jiffies; + } + + spin_lock_irqsave(&idev->lock, flags); /* Init tx buffer */ idev->tx_buff.data = idev->tx_buff.head; @@ -291,6 +457,8 @@ int irport_hard_xmit(struct sk_buff *skb, struct device *dev) /* Turn on transmit finished interrupt. Will fire immediately! */ outb(UART_IER_THRI, iobase+UART_IER); + spin_unlock_irqrestore(&idev->lock, flags); + dev_kfree_skb(skb); return 0; @@ -307,10 +475,7 @@ static void irport_receive(struct irda_device *idev) int iobase; int boguscount = 0; - if (!idev) - return; - - DEBUG(4, __FUNCTION__ "()\n"); + ASSERT(idev != NULL, return;); iobase = idev->io.iobase2; @@ -342,27 +507,42 @@ void irport_interrupt(int irq, void *dev_id, struct pt_regs *regs) int boguscount = 0; if (!idev) { - printk(KERN_WARNING __FUNCTION__ - "() irq %d for unknown device.\n", irq); + WARNING(__FUNCTION__ "() irq %d for unknown device.\n", irq); return; } + spin_lock(&idev->lock); + idev->netdev.interrupt = 1; iobase = idev->io.iobase2; - iir = inb(iobase + UART_IIR) & UART_IIR_ID; + iir = inb(iobase+UART_IIR) & UART_IIR_ID; while (iir) { /* Clear interrupt */ lsr = inb(iobase+UART_LSR); - if ((iir & UART_IIR_THRI) && (lsr & UART_LSR_THRE)) { - /* Transmitter ready for data */ - irport_write_wakeup(idev); - } else if ((iir & UART_IIR_RDI) && (lsr & UART_LSR_DR)) { - /* Receive interrupt */ - irport_receive(idev); - } + DEBUG(4, __FUNCTION__ "(), iir=%02x, lsr=%02x, iobase=%#x\n", + iir, lsr, iobase); + + switch (iir) { + case UART_IIR_RLSI: + DEBUG(0, __FUNCTION__ "(), RLSI\n"); + break; + case UART_IIR_RDI: + if (lsr & UART_LSR_DR) + /* Receive interrupt */ + irport_receive(idev); + break; + case UART_IIR_THRI: + if (lsr & UART_LSR_THRE) + /* Transmitter ready for data */ + irport_write_wakeup(idev); + break; + default: + DEBUG(0, __FUNCTION__ "(), unhandled IIR=%#x\n", iir); + break; + } /* Make sure we don't stay here to long */ if (boguscount++ > 32) @@ -371,10 +551,175 @@ void irport_interrupt(int irq, void *dev_id, struct pt_regs *regs) iir = inb(iobase + UART_IIR) & UART_IIR_ID; } idev->netdev.interrupt = 0; + + spin_unlock(&idev->lock); +} + +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; + + irport_start(idev, iobase); + + MOD_INC_USE_COUNT; + + /* Ready to play! */ + dev->tbusy = 0; + dev->interrupt = 0; + dev->start = 1; + + /* Change speed to make sure dongles follow us again */ + if (idev->change_speed) + idev->change_speed(idev, 9600); + + 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; + + /* Stop device */ + dev->tbusy = 1; + dev->start = 0; + + irport_stop(idev, iobase); + + free_irq(idev->io.irq2, idev); + + MOD_DEC_USE_COUNT; + + return 0; +} + +/* + * Function irport_wait_until_sent (idev) + * + * Delay exectution until finished transmitting + * + */ +void irport_wait_until_sent(struct irda_device *idev) +{ + int iobase; + + iobase = idev->io.iobase2; + + /* Wait until Tx FIFO is empty */ + while (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) { + DEBUG(2, __FUNCTION__ "(), waiting!\n"); + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(MSECS_TO_JIFFIES(60)); + } +} + +/* + * Function irport_is_receiving (idev) + * + * Returns true is we are currently receiving data + * + */ +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"); + +MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>"); +MODULE_DESCRIPTION("Half duplex serial driver for IrDA SIR mode"); + /* * Function cleanup_module (void) * @@ -393,11 +738,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 cc7ab91a4..ad8d2dc0e 100644 --- a/drivers/net/irda/irtty.c +++ b/drivers/net/irda/irtty.c @@ -6,12 +6,12 @@ * Status: Experimental. * Author: Dag Brattli <dagb@cs.uit.no> * 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 <dagb@cs.uit.no> * Sources: slip.c by Laurence Culhane, <loz@holmes.demon.co.uk> * Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org> * - * 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 <net/irda/irlap.h> #include <net/irda/timer.h> #include <net/irda/irda_device.h> -#include <linux/kmod.h> 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); @@ -359,68 +350,6 @@ static void irtty_change_speed(struct irda_device *idev, int baud) } /* - * 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) * * The Swiss army knife of system calls :-) @@ -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 <dagb@cs.uit.no>"); MODULE_DESCRIPTION("IrDA TTY device driver"); +MODULE_PARM(qos_mtt_bits, "i"); + /* * Function init_module (void) * diff --git a/drivers/net/irda/pc87108.c b/drivers/net/irda/pc87108.c index 878b2e33a..9433ec6b5 100644 --- a/drivers/net/irda/pc87108.c +++ b/drivers/net/irda/pc87108.c @@ -6,10 +6,10 @@ * Status: Experimental. * Author: Dag Brattli <dagb@cs.uit.no> * Created at: Sat Nov 7 21:43:15 1998 - * Modified at: Tue Apr 20 11:11:39 1999 + * Modified at: Mon May 24 15:19:21 1999 * Modified by: Dag Brattli <dagb@cs.uit.no> * - * Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no> + * Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no> * Copyright (c) 1998 Lichen Wang, <lwang@actisys.com> * Copyright (c) 1998 Actisys Corp., www.actisys.com * All Rights Reserved @@ -67,11 +67,12 @@ #define BROKEN_DONGLE_ID static char *driver_name = "pc87108"; +static int qos_mtt_bits = 0x07; /* 1 ms or more */ #define CHIP_IO_EXTENT 8 static unsigned int io[] = { 0x2f8, ~0, ~0, ~0 }; -static unsigned int io2[] = { 0x150, 0, 0, 0}; +static unsigned int io2[] = { 0x150, 0, 0, 0 }; static unsigned int irq[] = { 3, 0, 0, 0 }; static unsigned int dma[] = { 0, 0, 0, 0 }; @@ -97,28 +98,28 @@ static char *dongle_types[] = { }; /* Some prototypes */ -static int pc87108_open( int i, unsigned int iobase, unsigned int board_addr, - unsigned int irq, unsigned int dma); +static int pc87108_open(int i, unsigned int iobase, unsigned int board_addr, + unsigned int irq, unsigned int dma); #ifdef MODULE -static int pc87108_close( struct irda_device *idev); +static int pc87108_close(struct irda_device *idev); #endif /* MODULE */ -static int pc87108_probe( int iobase, int board_addr, int irq, int dma); -static void pc87108_pio_receive( struct irda_device *idev); -static int pc87108_dma_receive( struct irda_device *idev); +static int pc87108_probe(int iobase, int board_addr, int irq, int dma); +static void pc87108_pio_receive(struct irda_device *idev); +static int pc87108_dma_receive(struct irda_device *idev); static int pc87108_dma_receive_complete(struct irda_device *idev, int iobase); -static int pc87108_hard_xmit( struct sk_buff *skb, struct device *dev); -static int pc87108_pio_write( int iobase, __u8 *buf, int len, int fifo_size); -static void pc87108_dma_write( struct irda_device *idev, int iobase); -static void pc87108_change_speed( struct irda_device *idev, int baud); +static int pc87108_hard_xmit(struct sk_buff *skb, struct device *dev); +static int pc87108_pio_write(int iobase, __u8 *buf, int len, int fifo_size); +static void pc87108_dma_write(struct irda_device *idev, int iobase); +static void pc87108_change_speed(struct irda_device *idev, int baud); static void pc87108_interrupt(int irq, void *dev_id, struct pt_regs *regs); -static void pc87108_wait_until_sent( struct irda_device *idev); -static int pc87108_is_receiving( struct irda_device *idev); -static int pc87108_read_dongle_id ( int iobase); -static void pc87108_init_dongle_interface ( int iobase, int dongle_id); +static void pc87108_wait_until_sent(struct irda_device *idev); +static int pc87108_is_receiving(struct irda_device *idev); +static int pc87108_read_dongle_id (int iobase); +static void pc87108_init_dongle_interface (int iobase, int dongle_id); -static int pc87108_net_init( struct device *dev); -static int pc87108_net_open( struct device *dev); -static int pc87108_net_close( struct device *dev); +static int pc87108_net_init(struct device *dev); +static int pc87108_net_open(struct device *dev); +static int pc87108_net_close(struct device *dev); /* * Function pc87108_init () @@ -130,11 +131,11 @@ __initfunc(int pc87108_init(void)) { int i; - 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; - if (pc87108_open( i, io[i], io2[i], irq[i], dma[i]) == 0) + if (pc87108_open(i, io[i], io2[i], irq[i], dma[i]) == 0) return 0; } return -ENODEV; @@ -166,29 +167,29 @@ static void pc87108_cleanup(void) * Open driver instance * */ -static int pc87108_open( int i, unsigned int iobase, unsigned int board_addr, - unsigned int irq, unsigned int dma) +static int pc87108_open(int i, unsigned int iobase, unsigned int board_addr, + unsigned int irq, unsigned int dma) { struct pc87108 *self; struct irda_device *idev; int ret; int dongle_id; - DEBUG( 0, __FUNCTION__ "()\n"); + DEBUG(0, __FUNCTION__ "()\n"); - if (( dongle_id = pc87108_probe( iobase, board_addr, irq, dma)) == -1) + if ((dongle_id = pc87108_probe(iobase, board_addr, irq, dma)) == -1) return -1; /* * Allocate new instance of the driver */ - self = kmalloc( sizeof(struct pc87108), GFP_KERNEL); - if ( self == NULL) { - printk( KERN_ERR "IrDA: Can't allocate memory for " - "IrDA control block!\n"); + self = kmalloc(sizeof(struct pc87108), 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 pc87108)); + memset(self, 0, sizeof(struct pc87108)); /* Need to store self somewhere */ dev_self[i] = self; @@ -203,24 +204,24 @@ static int pc87108_open( int i, unsigned int iobase, unsigned int board_addr, idev->io.fifo_size = 32; /* Lock the port that we need */ - 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); + 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); /* pc87108_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 */ 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; - 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|IFF_DONGLE; @@ -244,10 +245,10 @@ static int pc87108_open( int i, unsigned int iobase, unsigned int board_addr, idev->netdev.stop = pc87108_net_close; idev->io.dongle_id = dongle_id; - pc87108_init_dongle_interface( iobase, dongle_id); + pc87108_init_dongle_interface(iobase, dongle_id); /* Open the IrDA device */ - irda_device_open( idev, driver_name, self); + irda_device_open(idev, driver_name, self); return 0; } @@ -259,23 +260,26 @@ 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"); - 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 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); + DEBUG(4, __FUNCTION__ "(), Releasing Region %03x\n", idev->io.iobase); + release_region(idev->io.iobase, idev->io.io_ext); - irda_device_close( idev); + irda_device_close(idev); + + kfree(self); return 0; } @@ -287,22 +291,22 @@ static int pc87108_close( struct irda_device *idev) * Returns non-negative on success. * */ -static int pc87108_probe( int iobase, int board_addr, int irq, int dma) +static int pc87108_probe(int iobase, int board_addr, int irq, int dma) { int version; __u8 temp=0; int dongle_id; - DEBUG( 4, __FUNCTION__ "()\n"); + DEBUG(4, __FUNCTION__ "()\n"); /* Base Address and Interrupt Control Register BAIC */ outb(0, board_addr); - switch ( iobase) { - case 0x3E8: outb( 0x14, board_addr+1); break; - case 0x2E8: outb( 0x15, board_addr+1); break; - case 0x3F8: outb( 0x16, board_addr+1); break; - case 0x2F8: outb( 0x17, board_addr+1); break; - default: DEBUG(0, __FUNCTION__ "(), invalid base_address"); + switch (iobase) { + case 0x3E8: outb(0x14, board_addr+1); break; + case 0x2E8: outb(0x15, board_addr+1); break; + case 0x3F8: outb(0x16, board_addr+1); break; + case 0x2F8: outb(0x17, board_addr+1); break; + default: ERROR(__FUNCTION__ "(), invalid base_address"); } /* Control Signal Routing Register CSRT */ @@ -314,74 +318,73 @@ static int pc87108_probe( int iobase, int board_addr, int irq, int dma) case 9: temp = 0x05; break; case 11: temp = 0x06; break; case 15: temp = 0x07; break; - default: DEBUG( 0, __FUNCTION__ "(), invalid irq"); + default: ERROR(__FUNCTION__ "(), invalid irq"); } - outb( 1, board_addr); - + outb(1, board_addr); + switch (dma) { - case 0: outb( 0x08+temp, board_addr+1); break; - case 1: outb( 0x10+temp, board_addr+1); break; - case 3: outb( 0x18+temp, board_addr+1); break; + case 0: outb(0x08+temp, board_addr+1); break; + case 1: outb(0x10+temp, board_addr+1); break; + case 3: outb(0x18+temp, board_addr+1); break; default: DEBUG( 0, __FUNCTION__ "(), invalid dma"); } /* Mode Control Register MCTL */ - outb( 2, board_addr); - outb( 0x03, board_addr+1); + outb(2, board_addr); + outb(0x03, board_addr+1); /* read the Module ID */ - switch_bank( iobase, BANK3); - version = inb( iobase+MID); + switch_bank(iobase, BANK3); + version = inb(iobase+MID); /* should be 0x2? */ - if (0x20 != (version & 0xf0)) - { - DEBUG( 0, __FUNCTION__ "(), Wrong chip version"); + if (0x20 != (version & 0xf0)) { + ERROR(__FUNCTION__ "(), Wrong chip version %02x\n", version); return -1; } /* Switch to advanced mode */ switch_bank( iobase, BANK2); - outb( ECR1_EXT_SL, iobase+ECR1); - switch_bank( iobase, BANK0); + outb(ECR1_EXT_SL, iobase+ECR1); + switch_bank(iobase, BANK0); - dongle_id = pc87108_read_dongle_id( iobase); - DEBUG( 0, __FUNCTION__ "(), Found dongle: %s\n", - dongle_types[ dongle_id]); + dongle_id = pc87108_read_dongle_id(iobase); + DEBUG(0, __FUNCTION__ "(), Found dongle: %s\n", + dongle_types[ dongle_id]); /* Set FIFO threshold to TX17, RX16, reset and enable FIFO's */ - switch_bank( iobase, BANK0); - outb( FCR_RXTH|FCR_TXTH|FCR_TXSR|FCR_RXSR|FCR_FIFO_EN, iobase+FCR); + switch_bank(iobase, BANK0); + outb(FCR_RXTH|FCR_TXTH|FCR_TXSR|FCR_RXSR|FCR_FIFO_EN, iobase+FCR); /* Set FIFO size to 32 */ - switch_bank( iobase, BANK2); - outb( EXCR2_RFSIZ|EXCR2_TFSIZ, iobase+EXCR2); + switch_bank(iobase, BANK2); + outb(EXCR2_RFSIZ|EXCR2_TFSIZ, iobase+EXCR2); /* IRCR2: FEND_MD is set */ - switch_bank( iobase, BANK5); - outb( 0x2a, iobase+4); + switch_bank(iobase, BANK5); + outb(0x2a, iobase+4); /* Make sure that some defaults are OK */ - switch_bank( iobase, BANK6); - outb( 0x20, iobase+0); /* Set 32 bits FIR CRC */ - outb( 0x0a, iobase+1); /* Set MIR pulse width */ - outb( 0x0d, iobase+2); /* Set SIR pulse width */ - outb( 0x2a, iobase+4); /* Set beginning frag, and preamble length */ + switch_bank(iobase, BANK6); + outb(0x20, iobase+0); /* Set 32 bits FIR CRC */ + outb(0x0a, iobase+1); /* Set MIR pulse width */ + outb(0x0d, iobase+2); /* Set SIR pulse width */ + outb(0x2a, iobase+4); /* Set beginning frag, and preamble length */ /* Receiver frame length */ - switch_bank( iobase, BANK4); - outb( 2048 & 0xff, iobase+6); - outb(( 2048 >> 8) & 0x1f, iobase+7); + switch_bank(iobase, BANK4); + outb(2048 & 0xff, iobase+6); + outb((2048 >> 8) & 0x1f, iobase+7); /* Transmitter frame length */ - outb( 2048 & 0xff, iobase+4); - outb(( 2048 >> 8) & 0x1f, iobase+5); + outb(2048 & 0xff, iobase+4); + outb((2048 >> 8) & 0x1f, iobase+5); - DEBUG( 0, "PC87108 driver loaded. Version: 0x%02x\n", version); + DEBUG(0, "PC87108 driver loaded. Version: 0x%02x\n", version); /* Enable receive interrupts */ - switch_bank( iobase, BANK0); - outb( IER_RXHDL_IE, iobase+IER); + switch_bank(iobase, BANK0); + outb(IER_RXHDL_IE, iobase+IER); return dongle_id; } @@ -404,10 +407,10 @@ static int pc87108_read_dongle_id ( int iobase) bank = inb( iobase+BSR); /* Select Bank 7 */ - switch_bank( iobase, BANK7); + switch_bank(iobase, BANK7); /* IRCFG4: IRSL0_DS and IRSL21_DS are cleared */ - outb( 0x00, iobase+7); + outb(0x00, iobase+7); /* ID0, 1, and 2 are pulled up/down very slowly */ udelay(50); @@ -416,16 +419,16 @@ static int pc87108_read_dongle_id ( int iobase) dongle_id = inb( iobase+4) & 0x0f; #ifdef BROKEN_DONGLE_ID - if ( dongle_id == 0x0a) + if (dongle_id == 0x0a) dongle_id = 0x09; #endif - + /* Go back to bank 0 before returning */ - switch_bank( iobase, BANK0); + switch_bank(iobase, BANK0); - DEBUG( 0, __FUNCTION__ "(), Dongle = %#x\n", dongle_id); + DEBUG(0, __FUNCTION__ "(), Dongle = %#x\n", dongle_id); - outb( bank, iobase+BSR); + outb(bank, iobase+BSR); return dongle_id; } @@ -438,7 +441,7 @@ static int pc87108_read_dongle_id ( int iobase) * power-on/reset. It also needs to be used whenever you suspect that * the dongle is changed. */ -static void pc87108_init_dongle_interface ( int iobase, int dongle_id) +static void pc87108_init_dongle_interface (int iobase, int dongle_id) { int bank; @@ -805,7 +808,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 */ @@ -814,11 +816,11 @@ static void pc87108_dma_write( struct irda_device *idev, int iobase) iobase+ECR1); /* Enable DMA */ - switch_bank( iobase, BANK0); - outb( inb( iobase+MCR)|MCR_DMA_EN, iobase+MCR); + switch_bank(iobase, BANK0); + outb(inb(iobase+MCR)|MCR_DMA_EN, iobase+MCR); /* Restore bank register */ - outb( bsr, iobase+BSR); + outb(bsr, iobase+BSR); } /* @@ -828,7 +830,7 @@ static void pc87108_dma_write( struct irda_device *idev, int iobase) * got transfered * */ -static int pc87108_pio_write( int iobase, __u8 *buf, int len, int fifo_size) +static int pc87108_pio_write(int iobase, __u8 *buf, int len, int fifo_size) { int actual = 0; __u8 bank; @@ -847,16 +849,16 @@ static int pc87108_pio_write( int iobase, __u8 *buf, int len, int fifo_size) } /* Fill FIFO with current frame */ - while (( fifo_size-- > 0) && (actual < len)) { + while ((fifo_size-- > 0) && (actual < len)) { /* Transmit next byte */ - outb( buf[actual++], iobase+TXD); + outb(buf[actual++], iobase+TXD); } - DEBUG( 4, __FUNCTION__ "(), fifo_size %d ; %d sent of %d\n", - fifo_size, actual, len); + DEBUG(4, __FUNCTION__ "(), fifo_size %d ; %d sent of %d\n", + fifo_size, actual, len); /* Restore bank */ - outb( bank, iobase+BSR); + outb(bank, iobase+BSR); return actual; } @@ -973,7 +975,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 +990,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 +1003,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 +1188,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 +1460,14 @@ static int pc87108_net_close(struct device *dev) #ifdef MODULE +MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>"); +MODULE_DESCRIPTION("NSC PC87108 IrDA Device Driver"); + +MODULE_PARM(qos_mtt_bits, "i"); +MODULE_PARM(io, "1-4i"); +MODULE_PARM(io2, "1-4i"); +MODULE_PARM(irq, "1-4i"); + /* * Function init_module (void) * diff --git a/drivers/net/irda/tekram.c b/drivers/net/irda/tekram.c index de1a553a4..123e2bd28 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.2 * Description: Implementation of the Tekram IrMate IR-210B dongle * Status: Experimental. * Author: Dag Brattli <dagb@cs.uit.no> * Created at: Wed Oct 21 20:02:35 1998 - * Modified at: Tue Apr 13 16:33:54 1999 + * Modified at: Sun May 16 14:33:42 1999 * Modified by: Dag Brattli <dagb@cs.uit.no> * - * 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 @@ -28,16 +28,12 @@ #include <linux/sched.h> #include <linux/init.h> -#include <asm/ioctls.h> -#include <asm/segment.h> -#include <asm/uaccess.h> - #include <net/irda/irda.h> #include <net/irda/irda_device.h> #include <net/irda/irtty.h> #include <net/irda/dongle.h> -static void tekram_reset(struct irda_device *dev, int unused); +static void tekram_reset(struct irda_device *dev); static void tekram_open(struct irda_device *dev, int type); static void tekram_close(struct irda_device *dev); static void tekram_change_speed(struct irda_device *dev, int baud); @@ -49,7 +45,7 @@ static void tekram_init_qos(struct irda_device *idev, struct qos_info *qos); #define TEKRAM_19200 0x03 #define TEKRAM_9600 0x04 -#define TEKRAM_PW 0x10 /* Pulse select bit */ +#define TEKRAM_PW 0x10 /* Pulse select bit */ static struct dongle dongle = { TEKRAM_DONGLE, @@ -62,15 +58,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 +76,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 +100,52 @@ 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; - - old_termios = *(tty->termios); - cflag = tty->termios->c_cflag; - - cflag &= ~CBAUD; + ASSERT(idev != NULL, return;); + ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); 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; + case 38400: 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; } + /* Need to reset the dongle and go to 9600 bps before programming */ + tekram_reset(idev); + /* 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,45 +161,33 @@ 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) { - struct irtty_cb *self; - struct tty_struct *tty; - - DEBUG(4, __FUNCTION__ "()\n"); - - ASSERT(dev != NULL, return;); - ASSERT(dev->magic == IRDA_DEVICE_MAGIC, return;); + ASSERT(idev != NULL, return;); + ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;); - self = (struct irtty_cb *) dev->priv; - - 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); - - /* Finished! */ + + /* Make sure the IrDA chip also goes to defalt speed */ + if (idev->change_speed) + idev->change_speed(idev, 9600); } /* diff --git a/drivers/net/irda/uircc.c b/drivers/net/irda/uircc.c index 60c8e024a..d9e1e107f 100644 --- a/drivers/net/irda/uircc.c +++ b/drivers/net/irda/uircc.c @@ -7,10 +7,10 @@ * Status: Experimental. * Author: Dag Brattli <dagb@cs.uit.no> * Created at: Sat Dec 26 10:59:03 1998 - * Modified at: Tue Apr 20 11:15:52 1999 + * Modified at: Wed May 19 15:29:56 1999 * Modified by: Dag Brattli <dagb@cs.uit.no> * - * 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(idev, 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, 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, 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, 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 9234c4a82..029d6de51 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: Fri May 21 22:18:19 1999 * Modified by: Dag Brattli <dagb@cs.uit.no> * + * Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no> * Copyright (c) 1998 Corel Computer Corp. - * Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no> * * 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 <linux/module.h> - + #include <linux/kernel.h> #include <linux/types.h> #include <linux/skbuff.h> @@ -61,44 +61,43 @@ #include <net/irda/w83977af.h> #include <net/irda/w83977af_ir.h> -#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 st_fifo_entry prev; +static struct w83977af_ir *dev_self[] = { NULL, NULL, NULL, NULL}; /* 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 +107,11 @@ static int w83977af_net_close( struct device *dev); */ __initfunc(int w83977af_init(void)) { - int i; + int i; - DEBUG( 0, __FUNCTION__ "()\n"); - - prev.status = 0; + DEBUG(0, __FUNCTION__ "()\n"); - 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 +132,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 +151,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 +183,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 +202,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 +221,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 +240,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 +261,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 +285,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 +294,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 +310,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 +338,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 +362,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 +376,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 +391,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 +421,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 +460,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 +479,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 +508,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 +517,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 +537,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 +603,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 +623,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 +643,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 +689,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 +700,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); + + /* 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 NETWINDER +#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 +767,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 +786,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 +836,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 +866,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 +912,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 +925,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 +938,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 +961,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 +986,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 +1023,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 +1039,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 +1074,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 +1093,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 +1114,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 +1129,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 +1155,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 +1174,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 +1191,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 +1214,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 +1239,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 +1275,11 @@ static int w83977af_net_close(struct device *dev) #ifdef MODULE +MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>"); +MODULE_DESCRIPTION("Winbond W83977AF IrDA Device Driver"); + +MODULE_PARM(qos_mtt_bits, "i"); + /* * Function init_module (void) * |