summaryrefslogtreecommitdiffstats
path: root/drivers/net/irda
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/irda')
-rw-r--r--drivers/net/irda/Config.in33
-rw-r--r--drivers/net/irda/Makefile80
-rw-r--r--drivers/net/irda/actisys.c150
-rw-r--r--drivers/net/irda/esi.c78
-rw-r--r--drivers/net/irda/girbil.c95
-rw-r--r--drivers/net/irda/irport.c557
-rw-r--r--drivers/net/irda/irtty.c167
-rw-r--r--drivers/net/irda/pc87108.c252
-rw-r--r--drivers/net/irda/tekram.c106
-rw-r--r--drivers/net/irda/uircc.c18
-rw-r--r--drivers/net/irda/w83977af_ir.c535
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)
*