Linux-2.6.12-rc2

Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.

Let it rip!
Esse commit está contido em:
Linus Torvalds
2005-04-16 15:20:36 -07:00
commit 1da177e4c3
17291 arquivos alterados com 6718755 adições e 0 exclusões

404
drivers/net/irda/Kconfig Arquivo normal
Ver arquivo

@@ -0,0 +1,404 @@
menu "Infrared-port device drivers"
depends on IRDA!=n
comment "SIR device drivers"
config IRTTY_SIR
tristate "IrTTY (uses Linux serial driver)"
depends on IRDA
help
Say Y here if you want to build support for the IrTTY line
discipline. To compile it as a module, choose M here: the module
will be called irtty-sir. IrTTY makes it possible to use Linux's
own serial driver for all IrDA ports that are 16550 compatible.
Most IrDA chips are 16550 compatible so you should probably say Y
to this option. Using IrTTY will however limit the speed of the
connection to 115200 bps (IrDA SIR mode).
If unsure, say Y.
comment "Dongle support"
config DONGLE
bool "Serial dongle support"
depends on IRTTY_SIR
help
Say Y here if you have an infrared device that connects to your
computer's serial port. These devices are called dongles. Then say Y
or M to the driver for your particular dongle below.
Note that the answer to this question won't directly affect the
kernel: saying N will just cause the configurator to skip all
the questions about serial dongles.
config ESI_DONGLE
tristate "ESI JetEye PC dongle"
depends on DONGLE && IRDA
help
Say Y here if you want to build support for the Extended Systems
JetEye PC dongle. To compile it as a module, choose M here. The ESI
dongle attaches to the normal 9-pin serial port connector, and can
currently only be used by IrTTY. To activate support for ESI
dongles you will have to start irattach like this:
"irattach -d esi".
config ACTISYS_DONGLE
tristate "ACTiSYS IR-220L and IR220L+ dongle"
depends on DONGLE && IRDA
help
Say Y here if you want to build support for the ACTiSYS IR-220L and
IR220L+ dongles. To compile it as a module, choose M here. The
ACTiSYS dongles attaches to the normal 9-pin serial port connector,
and can currently only be used by IrTTY. To activate support for
ACTiSYS dongles you will have to start irattach like this:
"irattach -d actisys" or "irattach -d actisys+".
config TEKRAM_DONGLE
tristate "Tekram IrMate 210B dongle"
depends on DONGLE && IRDA
help
Say Y here if you want to build support for the Tekram IrMate 210B
dongle. To compile it as a module, choose M here. The Tekram dongle
attaches to the normal 9-pin serial port connector, and can
currently only be used by IrTTY. To activate support for Tekram
dongles you will have to start irattach like this:
"irattach -d tekram".
config LITELINK_DONGLE
tristate "Parallax LiteLink dongle"
depends on DONGLE && IRDA
help
Say Y here if you want to build support for the Parallax Litelink
dongle. To compile it as a module, choose M here. The Parallax
dongle attaches to the normal 9-pin serial port connector, and can
currently only be used by IrTTY. To activate support for Parallax
dongles you will have to start irattach like this:
"irattach -d litelink".
config MA600_DONGLE
tristate "Mobile Action MA600 dongle"
depends on DONGLE && IRDA && EXPERIMENTAL
help
Say Y here if you want to build support for the Mobile Action MA600
dongle. To compile it as a module, choose M here. The MA600 dongle
attaches to the normal 9-pin serial port connector, and can
currently only be used by IrTTY. The driver should also support
the MA620 USB version of the dongle, if the integrated USB-to-RS232
converter is supported by usbserial. To activate support for
MA600 dongle you will have to start irattach like this:
"irattach -d ma600".
config GIRBIL_DONGLE
tristate "Greenwich GIrBIL dongle"
depends on DONGLE && IRDA && EXPERIMENTAL
help
Say Y here if you want to build support for the Greenwich GIrBIL
dongle. If you want to compile it as a module, choose M here.
The Greenwich dongle attaches to the normal 9-pin serial port
connector, and can currently only be used by IrTTY. To activate
support for Greenwich dongles you will have to start irattach
like this: "irattach -d girbil".
config MCP2120_DONGLE
tristate "Microchip MCP2120"
depends on DONGLE && IRDA && EXPERIMENTAL
help
Say Y here if you want to build support for the Microchip MCP2120
dongle. If you want to compile it as a module, choose M here.
The MCP2120 dongle attaches to the normal 9-pin serial port
connector, and can currently only be used by IrTTY. To activate
support for MCP2120 dongles you will have to start irattach
like this: "irattach -d mcp2120".
You must build this dongle yourself. For more information see:
<http://www.eyetap.org/~tangf/irda_sir_linux.html>
config OLD_BELKIN_DONGLE
tristate "Old Belkin dongle"
depends on DONGLE && IRDA && EXPERIMENTAL
help
Say Y here if you want to build support for the Adaptec Airport 1000
and 2000 dongles. If you want to compile it as a module, choose
M here. Some information is contained in the comments
at the top of <file:drivers/net/irda/old_belkin.c>.
config ACT200L_DONGLE
tristate "ACTiSYS IR-200L dongle"
depends on DONGLE && IRDA && EXPERIMENTAL
help
Say Y here if you want to build support for the ACTiSYS IR-200L
dongle. If you want to compile it as a module, choose M here.
The ACTiSYS IR-200L dongle attaches to the normal 9-pin serial
port connector, and can currently only be used by IrTTY.
To activate support for ACTiSYS IR-200L dongle you will have to
start irattach like this: "irattach -d act200l".
comment "Old SIR device drivers"
config IRPORT_SIR
tristate "IrPORT (IrDA serial driver)"
depends on IRDA && BROKEN_ON_SMP
---help---
Say Y here if you want to build support for the IrPORT IrDA device
driver. To compile it as a module, choose M here: the module will be
called irport. IrPORT can be used instead of IrTTY and sometimes
this can be better. One example is if your IrDA port does not
have echo-canceling, which will work OK with IrPORT since this
driver is working in half-duplex mode only. You don't need to use
irattach with IrPORT, but you just insert it the same way as FIR
drivers (insmod irport io=0x3e8 irq=11). Notice that IrPORT is a
SIR device driver which means that speed is limited to 115200 bps.
If unsure, say Y.
comment "Old Serial dongle support"
config DONGLE_OLD
bool "Old Serial dongle support"
depends on (IRTTY_OLD || IRPORT_SIR) && BROKEN_ON_SMP
help
Say Y here if you have an infrared device that connects to your
computer's serial port. These devices are called dongles. Then say Y
or M to the driver for your particular dongle below.
Note that the answer to this question won't directly affect the
kernel: saying N will just cause the configurator to skip all
the questions about serial dongles.
config ESI_DONGLE_OLD
tristate "ESI JetEye PC dongle"
depends on DONGLE_OLD && IRDA
help
Say Y here if you want to build support for the Extended Systems
JetEye PC dongle. To compile it as a module, choose M here. The ESI
dongle attaches to the normal 9-pin serial port connector, and can
currently only be used by IrTTY. To activate support for ESI
dongles you will have to start irattach like this:
"irattach -d esi".
config ACTISYS_DONGLE_OLD
tristate "ACTiSYS IR-220L and IR220L+ dongle"
depends on DONGLE_OLD && IRDA
help
Say Y here if you want to build support for the ACTiSYS IR-220L and
IR220L+ dongles. To compile it as a module, choose M here. The
ACTiSYS dongles attaches to the normal 9-pin serial port connector,
and can currently only be used by IrTTY. To activate support for
ACTiSYS dongles you will have to start irattach like this:
"irattach -d actisys" or "irattach -d actisys+".
config TEKRAM_DONGLE_OLD
tristate "Tekram IrMate 210B dongle"
depends on DONGLE_OLD && IRDA
help
Say Y here if you want to build support for the Tekram IrMate 210B
dongle. To compile it as a module, choose M here. The Tekram dongle
attaches to the normal 9-pin serial port connector, and can
currently only be used by IrTTY. To activate support for Tekram
dongles you will have to start irattach like this:
"irattach -d tekram".
config GIRBIL_DONGLE_OLD
tristate "Greenwich GIrBIL dongle"
depends on DONGLE_OLD && IRDA
help
Say Y here if you want to build support for the Greenwich GIrBIL
dongle. To compile it as a module, choose M here. The Greenwich
dongle attaches to the normal 9-pin serial port connector, and can
currently only be used by IrTTY. To activate support for Greenwich
dongles you will have to insert "irattach -d girbil" in the
/etc/irda/drivers script.
config LITELINK_DONGLE_OLD
tristate "Parallax LiteLink dongle"
depends on DONGLE_OLD && IRDA
help
Say Y here if you want to build support for the Parallax Litelink
dongle. To compile it as a module, choose M here. The Parallax
dongle attaches to the normal 9-pin serial port connector, and can
currently only be used by IrTTY. To activate support for Parallax
dongles you will have to start irattach like this:
"irattach -d litelink".
config MCP2120_DONGLE_OLD
tristate "Microchip MCP2120"
depends on DONGLE_OLD && IRDA
help
Say Y here if you want to build support for the Microchip MCP2120
dongle. To compile it as a module, choose M here. The MCP2120 dongle
attaches to the normal 9-pin serial port connector, and can
currently only be used by IrTTY. To activate support for MCP2120
dongles you will have to insert "irattach -d mcp2120" in the
/etc/irda/drivers script.
You must build this dongle yourself. For more information see:
<http://www.eyetap.org/~tangf/irda_sir_linux.html>
config OLD_BELKIN_DONGLE_OLD
tristate "Old Belkin dongle"
depends on DONGLE_OLD && IRDA
help
Say Y here if you want to build support for the Adaptec Airport 1000
and 2000 dongles. To compile it as a module, choose M here: the module
will be called old_belkin. Some information is contained in the
comments at the top of <file:drivers/net/irda/old_belkin.c>.
config ACT200L_DONGLE_OLD
tristate "ACTiSYS IR-200L dongle (EXPERIMENTAL)"
depends on DONGLE_OLD && EXPERIMENTAL && IRDA
help
Say Y here if you want to build support for the ACTiSYS IR-200L
dongle. To compile it as a module, choose M here. The ACTiSYS
IR-200L dongle attaches to the normal 9-pin serial port connector,
and can currently only be used by IrTTY. To activate support for
ACTiSYS IR-200L dongles you will have to start irattach like this:
"irattach -d act200l".
config MA600_DONGLE_OLD
tristate "Mobile Action MA600 dongle (EXPERIMENTAL)"
depends on DONGLE_OLD && EXPERIMENTAL && IRDA
---help---
Say Y here if you want to build support for the Mobile Action MA600
dongle. To compile it as a module, choose M here. The MA600 dongle
attaches to the normal 9-pin serial port connector, and can
currently only be tested on IrCOMM. To activate support for MA600
dongles you will have to insert "irattach -d ma600" in the
/etc/irda/drivers script. Note: irutils 0.9.15 requires no
modification. irutils 0.9.9 needs modification. For more
information, download the following tar gzip file.
There is a pre-compiled module on
<http://engsvr.ust.hk/~eetwl95/ma600.html>
config EP7211_IR
tristate "EP7211 I/R support"
depends on DONGLE_OLD && ARCH_EP7211 && IRDA
comment "FIR device drivers"
config USB_IRDA
tristate "IrDA USB dongles"
depends on IRDA && USB
---help---
Say Y here if you want to build support for the USB IrDA FIR Dongle
device driver. To compile it as a module, choose M here: the module
will be called irda-usb. IrDA-USB support the various IrDA USB
dongles available and most of their pecularities. Those dongles
plug in the USB port of your computer, are plug and play, and
support SIR and FIR (4Mbps) speeds. On the other hand, those
dongles tend to be less efficient than a FIR chipset.
Please note that the driver is still experimental. And of course,
you will need both USB and IrDA support in your kernel...
config SIGMATEL_FIR
tristate "SigmaTel STIr4200 bridge (EXPERIMENTAL)"
depends on IRDA && USB && EXPERIMENTAL
select CRC32
---help---
Say Y here if you want to build support for the SigmaTel STIr4200
USB IrDA FIR bridge device driver.
USB bridge based on the SigmaTel STIr4200 don't conform to the
IrDA-USB device class specification, and therefore need their
own specific driver. Those dongles support SIR and FIR (4Mbps)
speeds.
To compile it as a module, choose M here: the module will be called
stir4200.
config NSC_FIR
tristate "NSC PC87108/PC87338"
depends on IRDA && ISA
help
Say Y here if you want to build support for the NSC PC87108 and
PC87338 IrDA chipsets. This driver supports SIR,
MIR and FIR (4Mbps) speeds.
To compile it as a module, choose M here: the module will be called
nsc-ircc.
config WINBOND_FIR
tristate "Winbond W83977AF (IR)"
depends on IRDA && ISA
help
Say Y here if you want to build IrDA support for the Winbond
W83977AF super-io chipset. This driver should be used for the IrDA
chipset in the Corel NetWinder. The driver supports SIR, MIR and
FIR (4Mbps) speeds.
To compile it as a module, choose M here: the module will be called
w83977af_ir.
config TOSHIBA_FIR
tristate "Toshiba Type-O IR Port"
depends on IRDA && PCI && !64BIT
help
Say Y here if you want to build support for the Toshiba Type-O IR
and Donau oboe chipsets. These chipsets are used by the Toshiba
Libretto 100/110CT, Tecra 8100, Portege 7020 and many more laptops.
To compile it as a module, choose M here: the module will be called
donauboe.
config AU1000_FIR
tristate "Alchemy Au1000 SIR/FIR"
depends on MIPS_AU1000 && IRDA
config SMC_IRCC_FIR
tristate "SMSC IrCC (EXPERIMENTAL)"
depends on EXPERIMENTAL && IRDA && ISA
help
Say Y here if you want to build support for the SMC Infrared
Communications Controller. It is used in a wide variety of
laptops (Fujitsu, Sony, Compaq and some Toshiba).
To compile it as a module, choose M here: the module will be called
smsc-ircc2.o.
config ALI_FIR
tristate "ALi M5123 FIR (EXPERIMENTAL)"
depends on EXPERIMENTAL && IRDA && ISA
help
Say Y here if you want to build support for the ALi M5123 FIR
Controller. The ALi M5123 FIR Controller is embedded in ALi M1543C,
M1535, M1535D, M1535+, M1535D Sourth Bridge. This driver supports
SIR, MIR and FIR (4Mbps) speeds.
To compile it as a module, choose M here: the module will be called
ali-ircc.
config VLSI_FIR
tristate "VLSI 82C147 SIR/MIR/FIR (EXPERIMENTAL)"
depends on EXPERIMENTAL && IRDA && PCI
help
Say Y here if you want to build support for the VLSI 82C147
PCI-IrDA Controller. This controller is used by the HP OmniBook 800
and 5500 notebooks. The driver provides support for SIR, MIR and
FIR (4Mbps) speeds.
To compile it as a module, choose M here: the module will be called
vlsi_ir.
config SA1100_FIR
tristate "SA1100 Internal IR"
depends on ARCH_SA1100 && IRDA
config VIA_FIR
tristate "VIA VT8231/VT1211 SIR/MIR/FIR"
depends on IRDA && ISA && PCI
help
Say Y here if you want to build support for the VIA VT8231
and VIA VT1211 IrDA controllers, found on the motherboards using
those those VIA chipsets. To use this controller, you will need
to plug a specific 5 pins FIR IrDA dongle in the specific
motherboard connector. The driver provides support for SIR, MIR
and FIR (4Mbps) speeds.
You will need to specify the 'dongle_id' module parameter to
indicate the FIR dongle attached to the controller.
To compile it as a module, choose M here: the module will be called
via-ircc.
endmenu

47
drivers/net/irda/Makefile Arquivo normal
Ver arquivo

@@ -0,0 +1,47 @@
#
# Makefile for the Linux IrDA infrared port device drivers.
#
# 9 Aug 2000, Christoph Hellwig <hch@infradead.org>
# Rewritten to use lists instead of if-statements.
#
# Old SIR drivers
obj-$(CONFIG_IRPORT_SIR) += irport.o
# FIR drivers
obj-$(CONFIG_USB_IRDA) += irda-usb.o
obj-$(CONFIG_SIGMATEL_FIR) += stir4200.o
obj-$(CONFIG_NSC_FIR) += nsc-ircc.o
obj-$(CONFIG_WINBOND_FIR) += w83977af_ir.o
obj-$(CONFIG_SA1100_FIR) += sa1100_ir.o
obj-$(CONFIG_TOSHIBA_FIR) += donauboe.o
obj-$(CONFIG_SMC_IRCC_FIR) += smsc-ircc2.o
obj-$(CONFIG_ALI_FIR) += ali-ircc.o
obj-$(CONFIG_VLSI_FIR) += vlsi_ir.o
obj-$(CONFIG_VIA_FIR) += via-ircc.o
# Old dongle drivers for old SIR drivers
obj-$(CONFIG_ESI_DONGLE_OLD) += esi.o
obj-$(CONFIG_TEKRAM_DONGLE_OLD) += tekram.o
obj-$(CONFIG_ACTISYS_DONGLE_OLD) += actisys.o
obj-$(CONFIG_GIRBIL_DONGLE_OLD) += girbil.o
obj-$(CONFIG_LITELINK_DONGLE_OLD) += litelink.o
obj-$(CONFIG_OLD_BELKIN_DONGLE_OLD) += old_belkin.o
obj-$(CONFIG_MCP2120_DONGLE_OLD) += mcp2120.o
obj-$(CONFIG_ACT200L_DONGLE_OLD) += act200l.o
obj-$(CONFIG_MA600_DONGLE_OLD) += ma600.o
obj-$(CONFIG_EP7211_IR) += ep7211_ir.o
obj-$(CONFIG_AU1000_FIR) += au1k_ir.o
# New SIR drivers
obj-$(CONFIG_IRTTY_SIR) += irtty-sir.o sir-dev.o
# New dongles drivers for new SIR drivers
obj-$(CONFIG_ESI_DONGLE) += esi-sir.o
obj-$(CONFIG_TEKRAM_DONGLE) += tekram-sir.o
obj-$(CONFIG_ACTISYS_DONGLE) += actisys-sir.o
obj-$(CONFIG_LITELINK_DONGLE) += litelink-sir.o
obj-$(CONFIG_GIRBIL_DONGLE) += girbil-sir.o
obj-$(CONFIG_OLD_BELKIN_DONGLE) += old_belkin-sir.o
obj-$(CONFIG_MCP2120_DONGLE) += mcp2120-sir.o
obj-$(CONFIG_ACT200L_DONGLE) += act200l-sir.o
obj-$(CONFIG_MA600_DONGLE) += ma600-sir.o
# The SIR helper module
sir-dev-objs := sir_core.o sir_dev.o sir_dongle.o sir_kthread.o

257
drivers/net/irda/act200l-sir.c Arquivo normal
Ver arquivo

@@ -0,0 +1,257 @@
/*********************************************************************
*
* Filename: act200l.c
* Version: 0.8
* Description: Implementation for the ACTiSYS ACT-IR200L dongle
* Status: Experimental.
* Author: SHIMIZU Takuya <tshimizu@ga2.so-net.ne.jp>
* Created at: Fri Aug 3 17:35:42 2001
* Modified at: Fri Aug 17 10:22:40 2001
* Modified by: SHIMIZU Takuya <tshimizu@ga2.so-net.ne.jp>
*
* Copyright (c) 2001 SHIMIZU Takuya, 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.
*
********************************************************************/
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <net/irda/irda.h>
#include "sir-dev.h"
static int act200l_reset(struct sir_dev *dev);
static int act200l_open(struct sir_dev *dev);
static int act200l_close(struct sir_dev *dev);
static int act200l_change_speed(struct sir_dev *dev, unsigned speed);
/* Regsiter 0: Control register #1 */
#define ACT200L_REG0 0x00
#define ACT200L_TXEN 0x01 /* Enable transmitter */
#define ACT200L_RXEN 0x02 /* Enable receiver */
/* Register 1: Control register #2 */
#define ACT200L_REG1 0x10
#define ACT200L_LODB 0x01 /* Load new baud rate count value */
#define ACT200L_WIDE 0x04 /* Expand the maximum allowable pulse */
/* Register 4: Output Power register */
#define ACT200L_REG4 0x40
#define ACT200L_OP0 0x01 /* Enable LED1C output */
#define ACT200L_OP1 0x02 /* Enable LED2C output */
#define ACT200L_BLKR 0x04
/* Register 5: Receive Mode register */
#define ACT200L_REG5 0x50
#define ACT200L_RWIDL 0x01 /* fixed 1.6us pulse mode */
/* Register 6: Receive Sensitivity register #1 */
#define ACT200L_REG6 0x60
#define ACT200L_RS0 0x01 /* receive threshold bit 0 */
#define ACT200L_RS1 0x02 /* receive threshold bit 1 */
/* Register 7: Receive Sensitivity register #2 */
#define ACT200L_REG7 0x70
#define ACT200L_ENPOS 0x04 /* Ignore the falling edge */
/* Register 8,9: Baud Rate Dvider register #1,#2 */
#define ACT200L_REG8 0x80
#define ACT200L_REG9 0x90
#define ACT200L_2400 0x5f
#define ACT200L_9600 0x17
#define ACT200L_19200 0x0b
#define ACT200L_38400 0x05
#define ACT200L_57600 0x03
#define ACT200L_115200 0x01
/* Register 13: Control register #3 */
#define ACT200L_REG13 0xd0
#define ACT200L_SHDW 0x01 /* Enable access to shadow registers */
/* Register 15: Status register */
#define ACT200L_REG15 0xf0
/* Register 21: Control register #4 */
#define ACT200L_REG21 0x50
#define ACT200L_EXCK 0x02 /* Disable clock output driver */
#define ACT200L_OSCL 0x04 /* oscillator in low power, medium accuracy mode */
static struct dongle_driver act200l = {
.owner = THIS_MODULE,
.driver_name = "ACTiSYS ACT-IR200L",
.type = IRDA_ACT200L_DONGLE,
.open = act200l_open,
.close = act200l_close,
.reset = act200l_reset,
.set_speed = act200l_change_speed,
};
static int __init act200l_sir_init(void)
{
return irda_register_dongle(&act200l);
}
static void __exit act200l_sir_cleanup(void)
{
irda_unregister_dongle(&act200l);
}
static int act200l_open(struct sir_dev *dev)
{
struct qos_info *qos = &dev->qos;
IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
/* Power on the dongle */
sirdev_set_dtr_rts(dev, TRUE, TRUE);
/* Set the speeds we can accept */
qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
qos->min_turn_time.bits = 0x03;
irda_qos_bits_to_value(qos);
/* irda thread waits 50 msec for power settling */
return 0;
}
static int act200l_close(struct sir_dev *dev)
{
IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
/* Power off the dongle */
sirdev_set_dtr_rts(dev, FALSE, FALSE);
return 0;
}
/*
* Function act200l_change_speed (dev, speed)
*
* Set the speed for the ACTiSYS ACT-IR200L type dongle.
*
*/
static int act200l_change_speed(struct sir_dev *dev, unsigned speed)
{
u8 control[3];
int ret = 0;
IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
/* Clear DTR and set RTS to enter command mode */
sirdev_set_dtr_rts(dev, FALSE, TRUE);
switch (speed) {
default:
ret = -EINVAL;
/* fall through */
case 9600:
control[0] = ACT200L_REG8 | (ACT200L_9600 & 0x0f);
control[1] = ACT200L_REG9 | ((ACT200L_9600 >> 4) & 0x0f);
break;
case 19200:
control[0] = ACT200L_REG8 | (ACT200L_19200 & 0x0f);
control[1] = ACT200L_REG9 | ((ACT200L_19200 >> 4) & 0x0f);
break;
case 38400:
control[0] = ACT200L_REG8 | (ACT200L_38400 & 0x0f);
control[1] = ACT200L_REG9 | ((ACT200L_38400 >> 4) & 0x0f);
break;
case 57600:
control[0] = ACT200L_REG8 | (ACT200L_57600 & 0x0f);
control[1] = ACT200L_REG9 | ((ACT200L_57600 >> 4) & 0x0f);
break;
case 115200:
control[0] = ACT200L_REG8 | (ACT200L_115200 & 0x0f);
control[1] = ACT200L_REG9 | ((ACT200L_115200 >> 4) & 0x0f);
break;
}
control[2] = ACT200L_REG1 | ACT200L_LODB | ACT200L_WIDE;
/* Write control bytes */
sirdev_raw_write(dev, control, 3);
msleep(5);
/* Go back to normal mode */
sirdev_set_dtr_rts(dev, TRUE, TRUE);
dev->speed = speed;
return ret;
}
/*
* Function act200l_reset (driver)
*
* Reset the ACTiSYS ACT-IR200L type dongle.
*/
#define ACT200L_STATE_WAIT1_RESET (SIRDEV_STATE_DONGLE_RESET+1)
#define ACT200L_STATE_WAIT2_RESET (SIRDEV_STATE_DONGLE_RESET+2)
static int act200l_reset(struct sir_dev *dev)
{
unsigned state = dev->fsm.substate;
unsigned delay = 0;
u8 control[9] = {
ACT200L_REG15,
ACT200L_REG13 | ACT200L_SHDW,
ACT200L_REG21 | ACT200L_EXCK | ACT200L_OSCL,
ACT200L_REG13,
ACT200L_REG7 | ACT200L_ENPOS,
ACT200L_REG6 | ACT200L_RS0 | ACT200L_RS1,
ACT200L_REG5 | ACT200L_RWIDL,
ACT200L_REG4 | ACT200L_OP0 | ACT200L_OP1 | ACT200L_BLKR,
ACT200L_REG0 | ACT200L_TXEN | ACT200L_RXEN
};
int ret = 0;
IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
switch (state) {
case SIRDEV_STATE_DONGLE_RESET:
/* Reset the dongle : set RTS low for 25 ms */
sirdev_set_dtr_rts(dev, TRUE, FALSE);
state = ACT200L_STATE_WAIT1_RESET;
delay = 50;
break;
case ACT200L_STATE_WAIT1_RESET:
/* Clear DTR and set RTS to enter command mode */
sirdev_set_dtr_rts(dev, FALSE, TRUE);
udelay(25); /* better wait for some short while */
/* Write control bytes */
sirdev_raw_write(dev, control, sizeof(control));
state = ACT200L_STATE_WAIT2_RESET;
delay = 15;
break;
case ACT200L_STATE_WAIT2_RESET:
/* Go back to normal mode */
sirdev_set_dtr_rts(dev, TRUE, TRUE);
dev->speed = 9600;
break;
default:
IRDA_ERROR("%s(), unknown state %d\n", __FUNCTION__, state);
ret = -1;
break;
}
dev->fsm.substate = state;
return (delay > 0) ? delay : ret;
}
MODULE_AUTHOR("SHIMIZU Takuya <tshimizu@ga2.so-net.ne.jp>");
MODULE_DESCRIPTION("ACTiSYS ACT-IR200L dongle driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("irda-dongle-10"); /* IRDA_ACT200L_DONGLE */
module_init(act200l_sir_init);
module_exit(act200l_sir_cleanup);

297
drivers/net/irda/act200l.c Arquivo normal
Ver arquivo

@@ -0,0 +1,297 @@
/*********************************************************************
*
* Filename: act200l.c
* Version: 0.8
* Description: Implementation for the ACTiSYS ACT-IR200L dongle
* Status: Experimental.
* Author: SHIMIZU Takuya <tshimizu@ga2.so-net.ne.jp>
* Created at: Fri Aug 3 17:35:42 2001
* Modified at: Fri Aug 17 10:22:40 2001
* Modified by: SHIMIZU Takuya <tshimizu@ga2.so-net.ne.jp>
*
* Copyright (c) 2001 SHIMIZU Takuya, 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.
*
********************************************************************/
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/tty.h>
#include <linux/init.h>
#include <net/irda/irda.h>
#include <net/irda/irda_device.h>
static int act200l_reset(struct irda_task *task);
static void act200l_open(dongle_t *self, struct qos_info *qos);
static void act200l_close(dongle_t *self);
static int act200l_change_speed(struct irda_task *task);
/* Regsiter 0: Control register #1 */
#define ACT200L_REG0 0x00
#define ACT200L_TXEN 0x01 /* Enable transmitter */
#define ACT200L_RXEN 0x02 /* Enable receiver */
/* Register 1: Control register #2 */
#define ACT200L_REG1 0x10
#define ACT200L_LODB 0x01 /* Load new baud rate count value */
#define ACT200L_WIDE 0x04 /* Expand the maximum allowable pulse */
/* Register 4: Output Power register */
#define ACT200L_REG4 0x40
#define ACT200L_OP0 0x01 /* Enable LED1C output */
#define ACT200L_OP1 0x02 /* Enable LED2C output */
#define ACT200L_BLKR 0x04
/* Register 5: Receive Mode register */
#define ACT200L_REG5 0x50
#define ACT200L_RWIDL 0x01 /* fixed 1.6us pulse mode */
/* Register 6: Receive Sensitivity register #1 */
#define ACT200L_REG6 0x60
#define ACT200L_RS0 0x01 /* receive threshold bit 0 */
#define ACT200L_RS1 0x02 /* receive threshold bit 1 */
/* Register 7: Receive Sensitivity register #2 */
#define ACT200L_REG7 0x70
#define ACT200L_ENPOS 0x04 /* Ignore the falling edge */
/* Register 8,9: Baud Rate Dvider register #1,#2 */
#define ACT200L_REG8 0x80
#define ACT200L_REG9 0x90
#define ACT200L_2400 0x5f
#define ACT200L_9600 0x17
#define ACT200L_19200 0x0b
#define ACT200L_38400 0x05
#define ACT200L_57600 0x03
#define ACT200L_115200 0x01
/* Register 13: Control register #3 */
#define ACT200L_REG13 0xd0
#define ACT200L_SHDW 0x01 /* Enable access to shadow registers */
/* Register 15: Status register */
#define ACT200L_REG15 0xf0
/* Register 21: Control register #4 */
#define ACT200L_REG21 0x50
#define ACT200L_EXCK 0x02 /* Disable clock output driver */
#define ACT200L_OSCL 0x04 /* oscillator in low power, medium accuracy mode */
static struct dongle_reg dongle = {
.type = IRDA_ACT200L_DONGLE,
.open = act200l_open,
.close = act200l_close,
.reset = act200l_reset,
.change_speed = act200l_change_speed,
.owner = THIS_MODULE,
};
static int __init act200l_init(void)
{
return irda_device_register_dongle(&dongle);
}
static void __exit act200l_cleanup(void)
{
irda_device_unregister_dongle(&dongle);
}
static void act200l_open(dongle_t *self, struct qos_info *qos)
{
IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
/* Power on the dongle */
self->set_dtr_rts(self->dev, TRUE, TRUE);
/* Set the speeds we can accept */
qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
qos->min_turn_time.bits = 0x03;
}
static void act200l_close(dongle_t *self)
{
IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
/* Power off the dongle */
self->set_dtr_rts(self->dev, FALSE, FALSE);
}
/*
* Function act200l_change_speed (dev, speed)
*
* Set the speed for the ACTiSYS ACT-IR200L type dongle.
*
*/
static int act200l_change_speed(struct irda_task *task)
{
dongle_t *self = (dongle_t *) task->instance;
__u32 speed = (__u32) task->param;
__u8 control[3];
int ret = 0;
IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
self->speed_task = task;
switch (task->state) {
case IRDA_TASK_INIT:
if (irda_task_execute(self, act200l_reset, NULL, task,
(void *) speed))
{
/* Dongle need more time to reset */
irda_task_next_state(task, IRDA_TASK_CHILD_WAIT);
/* Give reset 1 sec to finish */
ret = msecs_to_jiffies(1000);
}
break;
case IRDA_TASK_CHILD_WAIT:
IRDA_WARNING("%s(), resetting dongle timed out!\n",
__FUNCTION__);
ret = -1;
break;
case IRDA_TASK_CHILD_DONE:
/* Clear DTR and set RTS to enter command mode */
self->set_dtr_rts(self->dev, FALSE, TRUE);
switch (speed) {
case 9600:
default:
control[0] = ACT200L_REG8 | (ACT200L_9600 & 0x0f);
control[1] = ACT200L_REG9 | ((ACT200L_9600 >> 4) & 0x0f);
break;
case 19200:
control[0] = ACT200L_REG8 | (ACT200L_19200 & 0x0f);
control[1] = ACT200L_REG9 | ((ACT200L_19200 >> 4) & 0x0f);
break;
case 38400:
control[0] = ACT200L_REG8 | (ACT200L_38400 & 0x0f);
control[1] = ACT200L_REG9 | ((ACT200L_38400 >> 4) & 0x0f);
break;
case 57600:
control[0] = ACT200L_REG8 | (ACT200L_57600 & 0x0f);
control[1] = ACT200L_REG9 | ((ACT200L_57600 >> 4) & 0x0f);
break;
case 115200:
control[0] = ACT200L_REG8 | (ACT200L_115200 & 0x0f);
control[1] = ACT200L_REG9 | ((ACT200L_115200 >> 4) & 0x0f);
break;
}
control[2] = ACT200L_REG1 | ACT200L_LODB | ACT200L_WIDE;
/* Write control bytes */
self->write(self->dev, control, 3);
irda_task_next_state(task, IRDA_TASK_WAIT);
ret = msecs_to_jiffies(5);
break;
case IRDA_TASK_WAIT:
/* Go back to normal mode */
self->set_dtr_rts(self->dev, TRUE, TRUE);
irda_task_next_state(task, IRDA_TASK_DONE);
self->speed_task = NULL;
break;
default:
IRDA_ERROR("%s(), unknown state %d\n",
__FUNCTION__, task->state);
irda_task_next_state(task, IRDA_TASK_DONE);
self->speed_task = NULL;
ret = -1;
break;
}
return ret;
}
/*
* Function act200l_reset (driver)
*
* Reset the ACTiSYS ACT-IR200L type dongle.
*/
static int act200l_reset(struct irda_task *task)
{
dongle_t *self = (dongle_t *) task->instance;
__u8 control[9] = {
ACT200L_REG15,
ACT200L_REG13 | ACT200L_SHDW,
ACT200L_REG21 | ACT200L_EXCK | ACT200L_OSCL,
ACT200L_REG13,
ACT200L_REG7 | ACT200L_ENPOS,
ACT200L_REG6 | ACT200L_RS0 | ACT200L_RS1,
ACT200L_REG5 | ACT200L_RWIDL,
ACT200L_REG4 | ACT200L_OP0 | ACT200L_OP1 | ACT200L_BLKR,
ACT200L_REG0 | ACT200L_TXEN | ACT200L_RXEN
};
int ret = 0;
IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
self->reset_task = task;
switch (task->state) {
case IRDA_TASK_INIT:
/* Power on the dongle */
self->set_dtr_rts(self->dev, TRUE, TRUE);
irda_task_next_state(task, IRDA_TASK_WAIT1);
ret = msecs_to_jiffies(50);
break;
case IRDA_TASK_WAIT1:
/* Reset the dongle : set RTS low for 25 ms */
self->set_dtr_rts(self->dev, TRUE, FALSE);
irda_task_next_state(task, IRDA_TASK_WAIT2);
ret = msecs_to_jiffies(50);
break;
case IRDA_TASK_WAIT2:
/* Clear DTR and set RTS to enter command mode */
self->set_dtr_rts(self->dev, FALSE, TRUE);
/* Write control bytes */
self->write(self->dev, control, 9);
irda_task_next_state(task, IRDA_TASK_WAIT3);
ret = msecs_to_jiffies(15);
break;
case IRDA_TASK_WAIT3:
/* Go back to normal mode */
self->set_dtr_rts(self->dev, TRUE, TRUE);
irda_task_next_state(task, IRDA_TASK_DONE);
self->reset_task = NULL;
break;
default:
IRDA_ERROR("%s(), unknown state %d\n",
__FUNCTION__, task->state);
irda_task_next_state(task, IRDA_TASK_DONE);
self->reset_task = NULL;
ret = -1;
break;
}
return ret;
}
MODULE_AUTHOR("SHIMIZU Takuya <tshimizu@ga2.so-net.ne.jp>");
MODULE_DESCRIPTION("ACTiSYS ACT-IR200L dongle driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("irda-dongle-10"); /* IRDA_ACT200L_DONGLE */
/*
* Function init_module (void)
*
* Initialize ACTiSYS ACT-IR200L module
*
*/
module_init(act200l_init);
/*
* Function cleanup_module (void)
*
* Cleanup ACTiSYS ACT-IR200L module
*
*/
module_exit(act200l_cleanup);

246
drivers/net/irda/actisys-sir.c Arquivo normal
Ver arquivo

@@ -0,0 +1,246 @@
/*********************************************************************
*
* Filename: actisys.c
* Version: 1.1
* Description: Implementation for the ACTiSYS IR-220L and IR-220L+
* dongles
* Status: Beta.
* Authors: Dag Brattli <dagb@cs.uit.no> (initially)
* Jean Tourrilhes <jt@hpl.hp.com> (new version)
* Martin Diehl <mad@mdiehl.de> (new version for sir_dev)
* Created at: Wed Oct 21 20:02:35 1998
* Modified at: Sun Oct 27 22:02:13 2002
* Modified by: Martin Diehl <mad@mdiehl.de>
*
* Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
* Copyright (c) 1999 Jean Tourrilhes
* Copyright (c) 2002 Martin Diehl
*
* 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<6D> admit liability nor
* provide warranty for any of this software. This material is
* provided "AS-IS" and at no charge.
*
********************************************************************/
/*
* Changelog
*
* 0.8 -> 0.9999 - Jean
* o New initialisation procedure : much safer and correct
* o New procedure the change speed : much faster and simpler
* o Other cleanups & comments
* Thanks to Lichen Wang @ Actisys for his excellent help...
*
* 1.0 -> 1.1 - Martin Diehl
* modified for new sir infrastructure
*/
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <net/irda/irda.h>
#include "sir-dev.h"
/*
* Define the timing of the pulses we send to the dongle (to reset it, and
* to toggle speeds). Basically, the limit here is the propagation speed of
* the signals through the serial port, the dongle being much faster. Any
* serial port support 115 kb/s, so we are sure that pulses 8.5 us wide can
* go through cleanly . If you are on the wild side, you can try to lower
* this value (Actisys recommended me 2 us, and 0 us work for me on a P233!)
*/
#define MIN_DELAY 10 /* 10 us to be on the conservative side */
static int actisys_open(struct sir_dev *);
static int actisys_close(struct sir_dev *);
static int actisys_change_speed(struct sir_dev *, unsigned);
static int actisys_reset(struct sir_dev *);
/* These are the baudrates supported, in the order available */
/* Note : the 220L doesn't support 38400, but we will fix that below */
static unsigned baud_rates[] = { 9600, 19200, 57600, 115200, 38400 };
#define MAX_SPEEDS (sizeof(baud_rates)/sizeof(baud_rates[0]))
static struct dongle_driver act220l = {
.owner = THIS_MODULE,
.driver_name = "Actisys ACT-220L",
.type = IRDA_ACTISYS_DONGLE,
.open = actisys_open,
.close = actisys_close,
.reset = actisys_reset,
.set_speed = actisys_change_speed,
};
static struct dongle_driver act220l_plus = {
.owner = THIS_MODULE,
.driver_name = "Actisys ACT-220L+",
.type = IRDA_ACTISYS_PLUS_DONGLE,
.open = actisys_open,
.close = actisys_close,
.reset = actisys_reset,
.set_speed = actisys_change_speed,
};
static int __init actisys_sir_init(void)
{
int ret;
/* First, register an Actisys 220L dongle */
ret = irda_register_dongle(&act220l);
if (ret < 0)
return ret;
/* Now, register an Actisys 220L+ dongle */
ret = irda_register_dongle(&act220l_plus);
if (ret < 0) {
irda_unregister_dongle(&act220l);
return ret;
}
return 0;
}
static void __exit actisys_sir_cleanup(void)
{
/* We have to remove both dongles */
irda_unregister_dongle(&act220l_plus);
irda_unregister_dongle(&act220l);
}
static int actisys_open(struct sir_dev *dev)
{
struct qos_info *qos = &dev->qos;
sirdev_set_dtr_rts(dev, TRUE, TRUE);
/* Set the speeds we can accept */
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 (dev->dongle_drv->type == IRDA_ACTISYS_DONGLE)
qos->baud_rate.bits &= ~IR_38400;
qos->min_turn_time.bits = 0x7f; /* Needs 0.01 ms */
irda_qos_bits_to_value(qos);
/* irda thread waits 50 msec for power settling */
return 0;
}
static int actisys_close(struct sir_dev *dev)
{
/* Power off the dongle */
sirdev_set_dtr_rts(dev, FALSE, FALSE);
return 0;
}
/*
* Function actisys_change_speed (task)
*
* Change speed of the ACTiSYS IR-220L and IR-220L+ type IrDA dongles.
* To cycle through the available baud rates, pulse RTS low for a few us.
*
* First, we reset the dongle to always start from a known state.
* Then, we cycle through the speeds by pulsing RTS low and then up.
* The dongle allow us to pulse quite fast, se we can set speed in one go,
* which is must faster ( < 100 us) and less complex than what is found
* in some other dongle drivers...
* Note that even if the new speed is the same as the current speed,
* we reassert the speed. This make sure that things are all right,
* and it's fast anyway...
* By the way, this function will work for both type of dongles,
* because the additional speed is at the end of the sequence...
*/
static int actisys_change_speed(struct sir_dev *dev, unsigned speed)
{
int ret = 0;
int i = 0;
IRDA_DEBUG(4, "%s(), speed=%d (was %d)\n", __FUNCTION__,
speed, dev->speed);
/* dongle was already resetted from irda_request state machine,
* we are in known state (dongle default)
*/
/*
* Now, we can set the speed requested. Send RTS pulses until we
* reach the target speed
*/
for (i = 0; i < MAX_SPEEDS; i++) {
if (speed == baud_rates[i]) {
dev->speed = speed;
break;
}
/* Set RTS low for 10 us */
sirdev_set_dtr_rts(dev, TRUE, FALSE);
udelay(MIN_DELAY);
/* Set RTS high for 10 us */
sirdev_set_dtr_rts(dev, TRUE, TRUE);
udelay(MIN_DELAY);
}
/* Check if life is sweet... */
if (i >= MAX_SPEEDS) {
actisys_reset(dev);
ret = -EINVAL; /* This should not happen */
}
/* Basta lavoro, on se casse d'ici... */
return ret;
}
/*
* Function actisys_reset (task)
*
* Reset the Actisys type dongle. Warning, this function must only be
* called with a process context!
*
* We need to do two things in this function :
* o first make sure that the dongle is in a state where it can operate
* o second put the dongle in a know state
*
* The dongle is powered of the RTS and DTR lines. In the dongle, there
* is a big capacitor to accommodate the current spikes. This capacitor
* takes a least 50 ms to be charged. In theory, the Bios set those lines
* up, so by the time we arrive here we should be set. It doesn't hurt
* to be on the conservative side, so we will wait...
* <Martin : move above comment to irda_config_fsm>
* Then, we set the speed to 9600 b/s to get in a known state (see in
* change_speed for details). It is needed because the IrDA stack
* has tried to set the speed immediately after our first return,
* so before we can be sure the dongle is up and running.
*/
static int actisys_reset(struct sir_dev *dev)
{
/* Reset the dongle : set DTR low for 10 us */
sirdev_set_dtr_rts(dev, FALSE, TRUE);
udelay(MIN_DELAY);
/* Go back to normal mode */
sirdev_set_dtr_rts(dev, TRUE, TRUE);
dev->speed = 9600; /* That's the default */
return 0;
}
MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no> - Jean Tourrilhes <jt@hpl.hp.com>");
MODULE_DESCRIPTION("ACTiSYS IR-220L and IR-220L+ dongle driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("irda-dongle-2"); /* IRDA_ACTISYS_DONGLE */
MODULE_ALIAS("irda-dongle-3"); /* IRDA_ACTISYS_PLUS_DONGLE */
module_init(actisys_sir_init);
module_exit(actisys_sir_cleanup);

288
drivers/net/irda/actisys.c Arquivo normal
Ver arquivo

@@ -0,0 +1,288 @@
/*********************************************************************
*
* Filename: actisys.c
* Version: 1.0
* Description: Implementation for the ACTiSYS IR-220L and IR-220L+
* dongles
* Status: Beta.
* Authors: Dag Brattli <dagb@cs.uit.no> (initially)
* Jean Tourrilhes <jt@hpl.hp.com> (new version)
* Created at: Wed Oct 21 20:02:35 1998
* Modified at: Fri Dec 17 09:10:43 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
* Copyright (c) 1999 Jean Tourrilhes
*
* 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<6D> admit liability nor
* provide warranty for any of this software. This material is
* provided "AS-IS" and at no charge.
*
********************************************************************/
/*
* Changelog
*
* 0.8 -> 0.9999 - Jean
* o New initialisation procedure : much safer and correct
* o New procedure the change speed : much faster and simpler
* o Other cleanups & comments
* Thanks to Lichen Wang @ Actisys for his excellent help...
*/
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/tty.h>
#include <linux/init.h>
#include <net/irda/irda.h>
#include <net/irda/irda_device.h>
/*
* Define the timing of the pulses we send to the dongle (to reset it, and
* to toggle speeds). Basically, the limit here is the propagation speed of
* the signals through the serial port, the dongle being much faster. Any
* serial port support 115 kb/s, so we are sure that pulses 8.5 us wide can
* go through cleanly . If you are on the wild side, you can try to lower
* this value (Actisys recommended me 2 us, and 0 us work for me on a P233!)
*/
#define MIN_DELAY 10 /* 10 us to be on the conservative side */
static int actisys_change_speed(struct irda_task *task);
static int actisys_reset(struct irda_task *task);
static void actisys_open(dongle_t *self, struct qos_info *qos);
static void actisys_close(dongle_t *self);
/* These are the baudrates supported, in the order available */
/* Note : the 220L doesn't support 38400, but we will fix that below */
static __u32 baud_rates[] = { 9600, 19200, 57600, 115200, 38400 };
#define MAX_SPEEDS 5
static struct dongle_reg dongle = {
.type = IRDA_ACTISYS_DONGLE,
.open = actisys_open,
.close = actisys_close,
.reset = actisys_reset,
.change_speed = actisys_change_speed,
.owner = THIS_MODULE,
};
static struct dongle_reg dongle_plus = {
.type = IRDA_ACTISYS_PLUS_DONGLE,
.open = actisys_open,
.close = actisys_close,
.reset = actisys_reset,
.change_speed = actisys_change_speed,
.owner = THIS_MODULE,
};
/*
* Function actisys_change_speed (task)
*
* There is two model of Actisys dongle we are dealing with,
* the 220L and 220L+. At this point, only irattach knows with
* kind the user has requested (it was an argument on irattach
* command line).
* So, we register a dongle of each sort and let irattach
* pick the right one...
*/
static int __init actisys_init(void)
{
int ret;
/* First, register an Actisys 220L dongle */
ret = irda_device_register_dongle(&dongle);
if (ret < 0)
return ret;
/* Now, register an Actisys 220L+ dongle */
ret = irda_device_register_dongle(&dongle_plus);
if (ret < 0) {
irda_device_unregister_dongle(&dongle);
return ret;
}
return 0;
}
static void __exit actisys_cleanup(void)
{
/* We have to remove both dongles */
irda_device_unregister_dongle(&dongle);
irda_device_unregister_dongle(&dongle_plus);
}
static void actisys_open(dongle_t *self, struct qos_info *qos)
{
/* Power on the dongle */
self->set_dtr_rts(self->dev, TRUE, TRUE);
/* Set the speeds we can accept */
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 (self->issue->type == IRDA_ACTISYS_DONGLE)
qos->baud_rate.bits &= ~IR_38400;
qos->min_turn_time.bits = 0x7f; /* Needs 0.01 ms */
}
static void actisys_close(dongle_t *self)
{
/* Power off the dongle */
self->set_dtr_rts(self->dev, FALSE, FALSE);
}
/*
* Function actisys_change_speed (task)
*
* Change speed of the ACTiSYS IR-220L and IR-220L+ type IrDA dongles.
* To cycle through the available baud rates, pulse RTS low for a few us.
*
* First, we reset the dongle to always start from a known state.
* Then, we cycle through the speeds by pulsing RTS low and then up.
* The dongle allow us to pulse quite fast, se we can set speed in one go,
* which is must faster ( < 100 us) and less complex than what is found
* in some other dongle drivers...
* Note that even if the new speed is the same as the current speed,
* we reassert the speed. This make sure that things are all right,
* and it's fast anyway...
* By the way, this function will work for both type of dongles,
* because the additional speed is at the end of the sequence...
*/
static int actisys_change_speed(struct irda_task *task)
{
dongle_t *self = (dongle_t *) task->instance;
__u32 speed = (__u32) task->param; /* Target speed */
int ret = 0;
int i = 0;
IRDA_DEBUG(4, "%s(), speed=%d (was %d)\n", __FUNCTION__, speed,
self->speed);
/* Go to a known state by reseting the dongle */
/* Reset the dongle : set DTR low for 10 us */
self->set_dtr_rts(self->dev, FALSE, TRUE);
udelay(MIN_DELAY);
/* Go back to normal mode (we are now at 9600 b/s) */
self->set_dtr_rts(self->dev, TRUE, TRUE);
/*
* Now, we can set the speed requested. Send RTS pulses until we
* reach the target speed
*/
for (i=0; i<MAX_SPEEDS; i++) {
if (speed == baud_rates[i]) {
self->speed = baud_rates[i];
break;
}
/* Make sure previous pulse is finished */
udelay(MIN_DELAY);
/* Set RTS low for 10 us */
self->set_dtr_rts(self->dev, TRUE, FALSE);
udelay(MIN_DELAY);
/* Set RTS high for 10 us */
self->set_dtr_rts(self->dev, TRUE, TRUE);
}
/* Check if life is sweet... */
if (i >= MAX_SPEEDS)
ret = -1; /* This should not happen */
/* Basta lavoro, on se casse d'ici... */
irda_task_next_state(task, IRDA_TASK_DONE);
return ret;
}
/*
* Function actisys_reset (task)
*
* Reset the Actisys type dongle. Warning, this function must only be
* called with a process context!
*
* We need to do two things in this function :
* o first make sure that the dongle is in a state where it can operate
* o second put the dongle in a know state
*
* The dongle is powered of the RTS and DTR lines. In the dongle, there
* is a big capacitor to accommodate the current spikes. This capacitor
* takes a least 50 ms to be charged. In theory, the Bios set those lines
* up, so by the time we arrive here we should be set. It doesn't hurt
* to be on the conservative side, so we will wait...
* Then, we set the speed to 9600 b/s to get in a known state (see in
* change_speed for details). It is needed because the IrDA stack
* has tried to set the speed immediately after our first return,
* so before we can be sure the dongle is up and running.
*/
static int actisys_reset(struct irda_task *task)
{
dongle_t *self = (dongle_t *) task->instance;
int ret = 0;
IRDA_ASSERT(task != NULL, return -1;);
self->reset_task = task;
switch (task->state) {
case IRDA_TASK_INIT:
/* Set both DTR & RTS to power up the dongle */
/* In theory redundant with power up in actisys_open() */
self->set_dtr_rts(self->dev, TRUE, TRUE);
/* Sleep 50 ms to make sure capacitor is charged */
ret = msecs_to_jiffies(50);
irda_task_next_state(task, IRDA_TASK_WAIT);
break;
case IRDA_TASK_WAIT:
/* Reset the dongle : set DTR low for 10 us */
self->set_dtr_rts(self->dev, FALSE, TRUE);
udelay(MIN_DELAY);
/* Go back to normal mode */
self->set_dtr_rts(self->dev, TRUE, TRUE);
irda_task_next_state(task, IRDA_TASK_DONE);
self->reset_task = NULL;
self->speed = 9600; /* That's the default */
break;
default:
IRDA_ERROR("%s(), unknown state %d\n",
__FUNCTION__, task->state);
irda_task_next_state(task, IRDA_TASK_DONE);
self->reset_task = NULL;
ret = -1;
break;
}
return ret;
}
MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no> - Jean Tourrilhes <jt@hpl.hp.com>");
MODULE_DESCRIPTION("ACTiSYS IR-220L and IR-220L+ dongle driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("irda-dongle-2"); /* IRDA_ACTISYS_DONGLE */
MODULE_ALIAS("irda-dongle-3"); /* IRDA_ACTISYS_PLUS_DONGLE */
/*
* Function init_module (void)
*
* Initialize Actisys module
*
*/
module_init(actisys_init);
/*
* Function cleanup_module (void)
*
* Cleanup Actisys module
*
*/
module_exit(actisys_cleanup);

2277
drivers/net/irda/ali-ircc.c Arquivo normal

Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff

231
drivers/net/irda/ali-ircc.h Arquivo normal
Ver arquivo

@@ -0,0 +1,231 @@
/*********************************************************************
*
* Filename: ali-ircc.h
* Version: 0.5
* Description: Driver for the ALI M1535D and M1543C FIR Controller
* Status: Experimental.
* Author: Benjamin Kong <benjamin_kong@ali.com.tw>
* Created at: 2000/10/16 03:46PM
* Modified at: 2001/1/3 02:56PM
* Modified by: Benjamin Kong <benjamin_kong@ali.com.tw>
*
* Copyright (c) 2000 Benjamin Kong <benjamin_kong@ali.com.tw>
* 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.
*
********************************************************************/
#ifndef ALI_IRCC_H
#define ALI_IRCC_H
#include <linux/time.h>
#include <linux/spinlock.h>
#include <linux/pm.h>
#include <linux/types.h>
#include <asm/io.h>
/* SIR Register */
/* Usr definition of linux/serial_reg.h */
/* FIR Register */
#define BANK0 0x20
#define BANK1 0x21
#define BANK2 0x22
#define BANK3 0x23
#define FIR_MCR 0x07 /* Master Control Register */
/* Bank 0 */
#define FIR_DR 0x00 /* Alias 0, FIR Data Register (R/W) */
#define FIR_IER 0x01 /* Alias 1, FIR Interrupt Enable Register (R/W) */
#define FIR_IIR 0x02 /* Alias 2, FIR Interrupt Identification Register (Read only) */
#define FIR_LCR_A 0x03 /* Alias 3, FIR Line Control Register A (R/W) */
#define FIR_LCR_B 0x04 /* Alias 4, FIR Line Control Register B (R/W) */
#define FIR_LSR 0x05 /* Alias 5, FIR Line Status Register (R/W) */
#define FIR_BSR 0x06 /* Alias 6, FIR Bus Status Register (Read only) */
/* Alias 1 */
#define IER_FIFO 0x10 /* FIR FIFO Interrupt Enable */
#define IER_TIMER 0x20 /* Timer Interrupt Enable */
#define IER_EOM 0x40 /* End of Message Interrupt Enable */
#define IER_ACT 0x80 /* Active Frame Interrupt Enable */
/* Alias 2 */
#define IIR_FIFO 0x10 /* FIR FIFO Interrupt */
#define IIR_TIMER 0x20 /* Timer Interrupt */
#define IIR_EOM 0x40 /* End of Message Interrupt */
#define IIR_ACT 0x80 /* Active Frame Interrupt */
/* Alias 3 */
#define LCR_A_FIFO_RESET 0x80 /* FIFO Reset */
/* Alias 4 */
#define LCR_B_BW 0x10 /* Brick Wall */
#define LCR_B_SIP 0x20 /* SIP Enable */
#define LCR_B_TX_MODE 0x40 /* Transmit Mode */
#define LCR_B_RX_MODE 0x80 /* Receive Mode */
/* Alias 5 */
#define LSR_FIR_LSA 0x00 /* FIR Line Status Address */
#define LSR_FRAME_ABORT 0x08 /* Frame Abort */
#define LSR_CRC_ERROR 0x10 /* CRC Error */
#define LSR_SIZE_ERROR 0x20 /* Size Error */
#define LSR_FRAME_ERROR 0x40 /* Frame Error */
#define LSR_FIFO_UR 0x80 /* FIFO Underrun */
#define LSR_FIFO_OR 0x80 /* FIFO Overrun */
/* Alias 6 */
#define BSR_FIFO_NOT_EMPTY 0x80 /* FIFO Not Empty */
/* Bank 1 */
#define FIR_CR 0x00 /* Alias 0, FIR Configuration Register (R/W) */
#define FIR_FIFO_TR 0x01 /* Alias 1, FIR FIFO Threshold Register (R/W) */
#define FIR_DMA_TR 0x02 /* Alias 2, FIR DMA Threshold Register (R/W) */
#define FIR_TIMER_IIR 0x03 /* Alias 3, FIR Timer interrupt interval register (W/O) */
#define FIR_FIFO_FR 0x03 /* Alias 3, FIR FIFO Flag register (R/O) */
#define FIR_FIFO_RAR 0x04 /* Alias 4, FIR FIFO Read Address register (R/O) */
#define FIR_FIFO_WAR 0x05 /* Alias 5, FIR FIFO Write Address register (R/O) */
#define FIR_TR 0x06 /* Alias 6, Test REgister (W/O) */
/* Alias 0 */
#define CR_DMA_EN 0x01 /* DMA Enable */
#define CR_DMA_BURST 0x02 /* DMA Burst Mode */
#define CR_TIMER_EN 0x08 /* Timer Enable */
/* Alias 3 */
#define TIMER_IIR_500 0x00 /* 500 us */
#define TIMER_IIR_1ms 0x01 /* 1 ms */
#define TIMER_IIR_2ms 0x02 /* 2 ms */
#define TIMER_IIR_4ms 0x03 /* 4 ms */
/* Bank 2 */
#define FIR_IRDA_CR 0x00 /* Alias 0, IrDA Control Register (R/W) */
#define FIR_BOF_CR 0x01 /* Alias 1, BOF Count Register (R/W) */
#define FIR_BW_CR 0x02 /* Alias 2, Brick Wall Count Register (R/W) */
#define FIR_TX_DSR_HI 0x03 /* Alias 3, TX Data Size Register (high) (R/W) */
#define FIR_TX_DSR_LO 0x04 /* Alias 4, TX Data Size Register (low) (R/W) */
#define FIR_RX_DSR_HI 0x05 /* Alias 5, RX Data Size Register (high) (R/W) */
#define FIR_RX_DSR_LO 0x06 /* Alias 6, RX Data Size Register (low) (R/W) */
/* Alias 0 */
#define IRDA_CR_HDLC1152 0x80 /* 1.152Mbps HDLC Select */
#define IRDA_CR_CRC 0X40 /* CRC Select. */
#define IRDA_CR_HDLC 0x20 /* HDLC select. */
#define IRDA_CR_HP_MODE 0x10 /* HP mode (read only) */
#define IRDA_CR_SD_ST 0x08 /* SD/MODE State. */
#define IRDA_CR_FIR_SIN 0x04 /* FIR SIN Select. */
#define IRDA_CR_ITTX_0 0x02 /* SOUT State. IRTX force to 0 */
#define IRDA_CR_ITTX_1 0x03 /* SOUT State. IRTX force to 1 */
/* Bank 3 */
#define FIR_ID_VR 0x00 /* Alias 0, FIR ID Version Register (R/O) */
#define FIR_MODULE_CR 0x01 /* Alias 1, FIR Module Control Register (R/W) */
#define FIR_IO_BASE_HI 0x02 /* Alias 2, FIR Higher I/O Base Address Register (R/O) */
#define FIR_IO_BASE_LO 0x03 /* Alias 3, FIR Lower I/O Base Address Register (R/O) */
#define FIR_IRQ_CR 0x04 /* Alias 4, FIR IRQ Channel Register (R/O) */
#define FIR_DMA_CR 0x05 /* Alias 5, FIR DMA Channel Register (R/O) */
struct ali_chip {
char *name;
int cfg[2];
unsigned char entr1;
unsigned char entr2;
unsigned char cid_index;
unsigned char cid_value;
int (*probe)(struct ali_chip *chip, chipio_t *info);
int (*init)(struct ali_chip *chip, chipio_t *info);
};
typedef struct ali_chip ali_chip_t;
/* DMA modes needed */
#define DMA_TX_MODE 0x08 /* Mem to I/O, ++, demand. */
#define DMA_RX_MODE 0x04 /* I/O to mem, ++, demand. */
#define MAX_TX_WINDOW 7
#define MAX_RX_WINDOW 7
#define TX_FIFO_Threshold 8
#define RX_FIFO_Threshold 1
#define TX_DMA_Threshold 1
#define RX_DMA_Threshold 1
/* For storing entries in the status FIFO */
struct st_fifo_entry {
int status;
int len;
};
struct st_fifo {
struct st_fifo_entry entries[MAX_RX_WINDOW];
int pending_bytes;
int head;
int tail;
int len;
};
struct frame_cb {
void *start; /* Start of frame in DMA mem */
int len; /* Lenght of frame in DMA mem */
};
struct tx_fifo {
struct frame_cb queue[MAX_TX_WINDOW]; /* Info about frames in queue */
int ptr; /* Currently being sent */
int len; /* Lenght of queue */
int free; /* Next free slot */
void *tail; /* Next free start in DMA mem */
};
/* Private data for each instance */
struct ali_ircc_cb {
struct st_fifo st_fifo; /* Info about received frames */
struct tx_fifo tx_fifo; /* Info about frames to be transmitted */
struct net_device *netdev; /* Yes! we are some kind of netdevice */
struct net_device_stats stats;
struct irlap_cb *irlap; /* The link layer we are binded to */
struct qos_info qos; /* QoS capabilities for this device */
chipio_t io; /* IrDA controller information */
iobuff_t tx_buff; /* Transmit buffer */
iobuff_t rx_buff; /* Receive buffer */
dma_addr_t tx_buff_dma;
dma_addr_t rx_buff_dma;
__u8 ier; /* Interrupt enable register */
__u8 InterruptID; /* Interrupt ID */
__u8 BusStatus; /* Bus Status */
__u8 LineStatus; /* Line Status */
unsigned char rcvFramesOverflow;
struct timeval stamp;
struct timeval now;
spinlock_t lock; /* For serializing operations */
__u32 new_speed;
int index; /* Instance index */
unsigned char fifo_opti_buf;
struct pm_dev *dev;
};
static inline void switch_bank(int iobase, int bank)
{
outb(bank, iobase+FIR_MCR);
}
#endif /* ALI_IRCC_H */

127
drivers/net/irda/au1000_ircc.h Arquivo normal
Ver arquivo

@@ -0,0 +1,127 @@
/*
*
* BRIEF MODULE DESCRIPTION
* Au1000 IrDA driver.
*
* Copyright 2001 MontaVista Software Inc.
* Author: MontaVista Software, Inc.
* ppopov@mvista.com or source@mvista.com
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* 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.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef AU1000_IRCC_H
#define AU1000_IRCC_H
#include <linux/time.h>
#include <linux/spinlock.h>
#include <linux/pm.h>
#include <asm/io.h>
#define NUM_IR_IFF 1
#define NUM_IR_DESC 64
#define RING_SIZE_4 0x0
#define RING_SIZE_16 0x3
#define RING_SIZE_64 0xF
#define MAX_NUM_IR_DESC 64
#define MAX_BUF_SIZE 2048
#define BPS_115200 0
#define BPS_57600 1
#define BPS_38400 2
#define BPS_19200 5
#define BPS_9600 11
#define BPS_2400 47
/* Ring descriptor flags */
#define AU_OWN (1<<7) /* tx,rx */
#define IR_DIS_CRC (1<<6) /* tx */
#define IR_BAD_CRC (1<<5) /* tx */
#define IR_NEED_PULSE (1<<4) /* tx */
#define IR_FORCE_UNDER (1<<3) /* tx */
#define IR_DISABLE_TX (1<<2) /* tx */
#define IR_HW_UNDER (1<<0) /* tx */
#define IR_TX_ERROR (IR_DIS_CRC|IR_BAD_CRC|IR_HW_UNDER)
#define IR_PHY_ERROR (1<<6) /* rx */
#define IR_CRC_ERROR (1<<5) /* rx */
#define IR_MAX_LEN (1<<4) /* rx */
#define IR_FIFO_OVER (1<<3) /* rx */
#define IR_SIR_ERROR (1<<2) /* rx */
#define IR_RX_ERROR (IR_PHY_ERROR|IR_CRC_ERROR| \
IR_MAX_LEN|IR_FIFO_OVER|IR_SIR_ERROR)
typedef struct db_dest {
struct db_dest *pnext;
volatile u32 *vaddr;
dma_addr_t dma_addr;
} db_dest_t;
typedef struct ring_desc {
u8 count_0; /* 7:0 */
u8 count_1; /* 12:8 */
u8 reserved;
u8 flags;
u8 addr_0; /* 7:0 */
u8 addr_1; /* 15:8 */
u8 addr_2; /* 23:16 */
u8 addr_3; /* 31:24 */
} ring_dest_t;
/* Private data for each instance */
struct au1k_private {
db_dest_t *pDBfree;
db_dest_t db[2*NUM_IR_DESC];
volatile ring_dest_t *rx_ring[NUM_IR_DESC];
volatile ring_dest_t *tx_ring[NUM_IR_DESC];
db_dest_t *rx_db_inuse[NUM_IR_DESC];
db_dest_t *tx_db_inuse[NUM_IR_DESC];
u32 rx_head;
u32 tx_head;
u32 tx_tail;
u32 tx_full;
iobuff_t rx_buff;
struct net_device *netdev;
struct net_device_stats stats;
struct timeval stamp;
struct timeval now;
struct qos_info qos;
struct irlap_cb *irlap;
u8 open;
u32 speed;
u32 newspeed;
u32 intr_work_done; /* number of Rx and Tx pkts processed in the isr */
struct timer_list timer;
spinlock_t lock; /* For serializing operations */
struct pm_dev *dev;
};
#endif /* AU1000_IRCC_H */

851
drivers/net/irda/au1k_ir.c Arquivo normal
Ver arquivo

@@ -0,0 +1,851 @@
/*
* Alchemy Semi Au1000 IrDA driver
*
* Copyright 2001 MontaVista Software Inc.
* Author: MontaVista Software, Inc.
* ppopov@mvista.com or source@mvista.com
*
* This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License (Version 2) as
* published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/netdevice.h>
#include <linux/slab.h>
#include <linux/rtnetlink.h>
#include <linux/interrupt.h>
#include <linux/pm.h>
#include <linux/bitops.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/au1000.h>
#if defined(CONFIG_MIPS_PB1000) || defined(CONFIG_MIPS_PB1100)
#include <asm/pb1000.h>
#elif defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_DB1100)
#include <asm/db1x00.h>
#else
#error au1k_ir: unsupported board
#endif
#include <net/irda/irda.h>
#include <net/irda/irmod.h>
#include <net/irda/wrapper.h>
#include <net/irda/irda_device.h>
#include "au1000_ircc.h"
static int au1k_irda_net_init(struct net_device *);
static int au1k_irda_start(struct net_device *);
static int au1k_irda_stop(struct net_device *dev);
static int au1k_irda_hard_xmit(struct sk_buff *, struct net_device *);
static int au1k_irda_rx(struct net_device *);
static void au1k_irda_interrupt(int, void *, struct pt_regs *);
static void au1k_tx_timeout(struct net_device *);
static struct net_device_stats *au1k_irda_stats(struct net_device *);
static int au1k_irda_ioctl(struct net_device *, struct ifreq *, int);
static int au1k_irda_set_speed(struct net_device *dev, int speed);
static void *dma_alloc(size_t, dma_addr_t *);
static void dma_free(void *, size_t);
static int qos_mtt_bits = 0x07; /* 1 ms or more */
static struct net_device *ir_devs[NUM_IR_IFF];
static char version[] __devinitdata =
"au1k_ircc:1.2 ppopov@mvista.com\n";
#define RUN_AT(x) (jiffies + (x))
#if defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_DB1100)
static BCSR * const bcsr = (BCSR *)0xAE000000;
#endif
static DEFINE_SPINLOCK(ir_lock);
/*
* IrDA peripheral bug. You have to read the register
* twice to get the right value.
*/
u32 read_ir_reg(u32 addr)
{
readl(addr);
return readl(addr);
}
/*
* Buffer allocation/deallocation routines. The buffer descriptor returned
* has the virtual and dma address of a buffer suitable for
* both, receive and transmit operations.
*/
static db_dest_t *GetFreeDB(struct au1k_private *aup)
{
db_dest_t *pDB;
pDB = aup->pDBfree;
if (pDB) {
aup->pDBfree = pDB->pnext;
}
return pDB;
}
static void ReleaseDB(struct au1k_private *aup, db_dest_t *pDB)
{
db_dest_t *pDBfree = aup->pDBfree;
if (pDBfree)
pDBfree->pnext = pDB;
aup->pDBfree = pDB;
}
/*
DMA memory allocation, derived from pci_alloc_consistent.
However, the Au1000 data cache is coherent (when programmed
so), therefore we return KSEG0 address, not KSEG1.
*/
static void *dma_alloc(size_t size, dma_addr_t * dma_handle)
{
void *ret;
int gfp = GFP_ATOMIC | GFP_DMA;
ret = (void *) __get_free_pages(gfp, get_order(size));
if (ret != NULL) {
memset(ret, 0, size);
*dma_handle = virt_to_bus(ret);
ret = (void *)KSEG0ADDR(ret);
}
return ret;
}
static void dma_free(void *vaddr, size_t size)
{
vaddr = (void *)KSEG0ADDR(vaddr);
free_pages((unsigned long) vaddr, get_order(size));
}
static void
setup_hw_rings(struct au1k_private *aup, u32 rx_base, u32 tx_base)
{
int i;
for (i=0; i<NUM_IR_DESC; i++) {
aup->rx_ring[i] = (volatile ring_dest_t *)
(rx_base + sizeof(ring_dest_t)*i);
}
for (i=0; i<NUM_IR_DESC; i++) {
aup->tx_ring[i] = (volatile ring_dest_t *)
(tx_base + sizeof(ring_dest_t)*i);
}
}
static int au1k_irda_init(void)
{
static unsigned version_printed = 0;
struct au1k_private *aup;
struct net_device *dev;
int err;
if (version_printed++ == 0) printk(version);
dev = alloc_irdadev(sizeof(struct au1k_private));
if (!dev)
return -ENOMEM;
dev->irq = AU1000_IRDA_RX_INT; /* TX has its own interrupt */
err = au1k_irda_net_init(dev);
if (err)
goto out;
err = register_netdev(dev);
if (err)
goto out1;
ir_devs[0] = dev;
printk(KERN_INFO "IrDA: Registered device %s\n", dev->name);
return 0;
out1:
aup = netdev_priv(dev);
dma_free((void *)aup->db[0].vaddr,
MAX_BUF_SIZE * 2*NUM_IR_DESC);
dma_free((void *)aup->rx_ring[0],
2 * MAX_NUM_IR_DESC*(sizeof(ring_dest_t)));
kfree(aup->rx_buff.head);
out:
free_netdev(dev);
return err;
}
static int au1k_irda_init_iobuf(iobuff_t *io, int size)
{
io->head = kmalloc(size, GFP_KERNEL);
if (io->head != NULL) {
io->truesize = size;
io->in_frame = FALSE;
io->state = OUTSIDE_FRAME;
io->data = io->head;
}
return io->head ? 0 : -ENOMEM;
}
static int au1k_irda_net_init(struct net_device *dev)
{
struct au1k_private *aup = netdev_priv(dev);
int i, retval = 0, err;
db_dest_t *pDB, *pDBfree;
dma_addr_t temp;
err = au1k_irda_init_iobuf(&aup->rx_buff, 14384);
if (err)
goto out1;
dev->open = au1k_irda_start;
dev->hard_start_xmit = au1k_irda_hard_xmit;
dev->stop = au1k_irda_stop;
dev->get_stats = au1k_irda_stats;
dev->do_ioctl = au1k_irda_ioctl;
dev->tx_timeout = au1k_tx_timeout;
irda_init_max_qos_capabilies(&aup->qos);
/* The only value we must override it the baudrate */
aup->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
IR_115200|IR_576000 |(IR_4000000 << 8);
aup->qos.min_turn_time.bits = qos_mtt_bits;
irda_qos_bits_to_value(&aup->qos);
retval = -ENOMEM;
/* Tx ring follows rx ring + 512 bytes */
/* we need a 1k aligned buffer */
aup->rx_ring[0] = (ring_dest_t *)
dma_alloc(2*MAX_NUM_IR_DESC*(sizeof(ring_dest_t)), &temp);
if (!aup->rx_ring[0])
goto out2;
/* allocate the data buffers */
aup->db[0].vaddr =
(void *)dma_alloc(MAX_BUF_SIZE * 2*NUM_IR_DESC, &temp);
if (!aup->db[0].vaddr)
goto out3;
setup_hw_rings(aup, (u32)aup->rx_ring[0], (u32)aup->rx_ring[0] + 512);
pDBfree = NULL;
pDB = aup->db;
for (i=0; i<(2*NUM_IR_DESC); i++) {
pDB->pnext = pDBfree;
pDBfree = pDB;
pDB->vaddr =
(u32 *)((unsigned)aup->db[0].vaddr + MAX_BUF_SIZE*i);
pDB->dma_addr = (dma_addr_t)virt_to_bus(pDB->vaddr);
pDB++;
}
aup->pDBfree = pDBfree;
/* attach a data buffer to each descriptor */
for (i=0; i<NUM_IR_DESC; i++) {
pDB = GetFreeDB(aup);
if (!pDB) goto out;
aup->rx_ring[i]->addr_0 = (u8)(pDB->dma_addr & 0xff);
aup->rx_ring[i]->addr_1 = (u8)((pDB->dma_addr>>8) & 0xff);
aup->rx_ring[i]->addr_2 = (u8)((pDB->dma_addr>>16) & 0xff);
aup->rx_ring[i]->addr_3 = (u8)((pDB->dma_addr>>24) & 0xff);
aup->rx_db_inuse[i] = pDB;
}
for (i=0; i<NUM_IR_DESC; i++) {
pDB = GetFreeDB(aup);
if (!pDB) goto out;
aup->tx_ring[i]->addr_0 = (u8)(pDB->dma_addr & 0xff);
aup->tx_ring[i]->addr_1 = (u8)((pDB->dma_addr>>8) & 0xff);
aup->tx_ring[i]->addr_2 = (u8)((pDB->dma_addr>>16) & 0xff);
aup->tx_ring[i]->addr_3 = (u8)((pDB->dma_addr>>24) & 0xff);
aup->tx_ring[i]->count_0 = 0;
aup->tx_ring[i]->count_1 = 0;
aup->tx_ring[i]->flags = 0;
aup->tx_db_inuse[i] = pDB;
}
#if defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_DB1100)
/* power on */
bcsr->resets &= ~BCSR_RESETS_IRDA_MODE_MASK;
bcsr->resets |= BCSR_RESETS_IRDA_MODE_FULL;
au_sync();
#endif
return 0;
out3:
dma_free((void *)aup->rx_ring[0],
2 * MAX_NUM_IR_DESC*(sizeof(ring_dest_t)));
out2:
kfree(aup->rx_buff.head);
out1:
printk(KERN_ERR "au1k_init_module failed. Returns %d\n", retval);
return retval;
}
static int au1k_init(struct net_device *dev)
{
struct au1k_private *aup = netdev_priv(dev);
int i;
u32 control;
u32 ring_address;
/* bring the device out of reset */
control = 0xe; /* coherent, clock enable, one half system clock */
#ifndef CONFIG_CPU_LITTLE_ENDIAN
control |= 1;
#endif
aup->tx_head = 0;
aup->tx_tail = 0;
aup->rx_head = 0;
for (i=0; i<NUM_IR_DESC; i++) {
aup->rx_ring[i]->flags = AU_OWN;
}
writel(control, IR_INTERFACE_CONFIG);
au_sync_delay(10);
writel(read_ir_reg(IR_ENABLE) & ~0x8000, IR_ENABLE); /* disable PHY */
au_sync_delay(1);
writel(MAX_BUF_SIZE, IR_MAX_PKT_LEN);
ring_address = (u32)virt_to_phys((void *)aup->rx_ring[0]);
writel(ring_address >> 26, IR_RING_BASE_ADDR_H);
writel((ring_address >> 10) & 0xffff, IR_RING_BASE_ADDR_L);
writel(RING_SIZE_64<<8 | RING_SIZE_64<<12, IR_RING_SIZE);
writel(1<<2 | IR_ONE_PIN, IR_CONFIG_2); /* 48MHz */
writel(0, IR_RING_ADDR_CMPR);
au1k_irda_set_speed(dev, 9600);
return 0;
}
static int au1k_irda_start(struct net_device *dev)
{
int retval;
char hwname[32];
struct au1k_private *aup = netdev_priv(dev);
if ((retval = au1k_init(dev))) {
printk(KERN_ERR "%s: error in au1k_init\n", dev->name);
return retval;
}
if ((retval = request_irq(AU1000_IRDA_TX_INT, &au1k_irda_interrupt,
0, dev->name, dev))) {
printk(KERN_ERR "%s: unable to get IRQ %d\n",
dev->name, dev->irq);
return retval;
}
if ((retval = request_irq(AU1000_IRDA_RX_INT, &au1k_irda_interrupt,
0, dev->name, dev))) {
free_irq(AU1000_IRDA_TX_INT, dev);
printk(KERN_ERR "%s: unable to get IRQ %d\n",
dev->name, dev->irq);
return retval;
}
/* Give self a hardware name */
sprintf(hwname, "Au1000 SIR/FIR");
aup->irlap = irlap_open(dev, &aup->qos, hwname);
netif_start_queue(dev);
writel(read_ir_reg(IR_CONFIG_2) | 1<<8, IR_CONFIG_2); /* int enable */
aup->timer.expires = RUN_AT((3*HZ));
aup->timer.data = (unsigned long)dev;
return 0;
}
static int au1k_irda_stop(struct net_device *dev)
{
struct au1k_private *aup = netdev_priv(dev);
/* disable interrupts */
writel(read_ir_reg(IR_CONFIG_2) & ~(1<<8), IR_CONFIG_2);
writel(0, IR_CONFIG_1);
writel(0, IR_INTERFACE_CONFIG); /* disable clock */
au_sync();
if (aup->irlap) {
irlap_close(aup->irlap);
aup->irlap = NULL;
}
netif_stop_queue(dev);
del_timer(&aup->timer);
/* disable the interrupt */
free_irq(AU1000_IRDA_TX_INT, dev);
free_irq(AU1000_IRDA_RX_INT, dev);
return 0;
}
static void __exit au1k_irda_exit(void)
{
struct net_device *dev = ir_devs[0];
struct au1k_private *aup = netdev_priv(dev);
unregister_netdev(dev);
dma_free((void *)aup->db[0].vaddr,
MAX_BUF_SIZE * 2*NUM_IR_DESC);
dma_free((void *)aup->rx_ring[0],
2 * MAX_NUM_IR_DESC*(sizeof(ring_dest_t)));
kfree(aup->rx_buff.head);
free_netdev(dev);
}
static inline void
update_tx_stats(struct net_device *dev, u32 status, u32 pkt_len)
{
struct au1k_private *aup = netdev_priv(dev);
struct net_device_stats *ps = &aup->stats;
ps->tx_packets++;
ps->tx_bytes += pkt_len;
if (status & IR_TX_ERROR) {
ps->tx_errors++;
ps->tx_aborted_errors++;
}
}
static void au1k_tx_ack(struct net_device *dev)
{
struct au1k_private *aup = netdev_priv(dev);
volatile ring_dest_t *ptxd;
ptxd = aup->tx_ring[aup->tx_tail];
while (!(ptxd->flags & AU_OWN) && (aup->tx_tail != aup->tx_head)) {
update_tx_stats(dev, ptxd->flags,
ptxd->count_1<<8 | ptxd->count_0);
ptxd->count_0 = 0;
ptxd->count_1 = 0;
au_sync();
aup->tx_tail = (aup->tx_tail + 1) & (NUM_IR_DESC - 1);
ptxd = aup->tx_ring[aup->tx_tail];
if (aup->tx_full) {
aup->tx_full = 0;
netif_wake_queue(dev);
}
}
if (aup->tx_tail == aup->tx_head) {
if (aup->newspeed) {
au1k_irda_set_speed(dev, aup->newspeed);
aup->newspeed = 0;
}
else {
writel(read_ir_reg(IR_CONFIG_1) & ~IR_TX_ENABLE,
IR_CONFIG_1);
au_sync();
writel(read_ir_reg(IR_CONFIG_1) | IR_RX_ENABLE,
IR_CONFIG_1);
writel(0, IR_RING_PROMPT);
au_sync();
}
}
}
/*
* Au1000 transmit routine.
*/
static int au1k_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct au1k_private *aup = netdev_priv(dev);
int speed = irda_get_next_speed(skb);
volatile ring_dest_t *ptxd;
u32 len;
u32 flags;
db_dest_t *pDB;
if (speed != aup->speed && speed != -1) {
aup->newspeed = speed;
}
if ((skb->len == 0) && (aup->newspeed)) {
if (aup->tx_tail == aup->tx_head) {
au1k_irda_set_speed(dev, speed);
aup->newspeed = 0;
}
dev_kfree_skb(skb);
return 0;
}
ptxd = aup->tx_ring[aup->tx_head];
flags = ptxd->flags;
if (flags & AU_OWN) {
printk(KERN_DEBUG "%s: tx_full\n", dev->name);
netif_stop_queue(dev);
aup->tx_full = 1;
return 1;
}
else if (((aup->tx_head + 1) & (NUM_IR_DESC - 1)) == aup->tx_tail) {
printk(KERN_DEBUG "%s: tx_full\n", dev->name);
netif_stop_queue(dev);
aup->tx_full = 1;
return 1;
}
pDB = aup->tx_db_inuse[aup->tx_head];
#if 0
if (read_ir_reg(IR_RX_BYTE_CNT) != 0) {
printk("tx warning: rx byte cnt %x\n",
read_ir_reg(IR_RX_BYTE_CNT));
}
#endif
if (aup->speed == 4000000) {
/* FIR */
memcpy((void *)pDB->vaddr, skb->data, skb->len);
ptxd->count_0 = skb->len & 0xff;
ptxd->count_1 = (skb->len >> 8) & 0xff;
}
else {
/* SIR */
len = async_wrap_skb(skb, (u8 *)pDB->vaddr, MAX_BUF_SIZE);
ptxd->count_0 = len & 0xff;
ptxd->count_1 = (len >> 8) & 0xff;
ptxd->flags |= IR_DIS_CRC;
au_writel(au_readl(0xae00000c) & ~(1<<13), 0xae00000c);
}
ptxd->flags |= AU_OWN;
au_sync();
writel(read_ir_reg(IR_CONFIG_1) | IR_TX_ENABLE, IR_CONFIG_1);
writel(0, IR_RING_PROMPT);
au_sync();
dev_kfree_skb(skb);
aup->tx_head = (aup->tx_head + 1) & (NUM_IR_DESC - 1);
dev->trans_start = jiffies;
return 0;
}
static inline void
update_rx_stats(struct net_device *dev, u32 status, u32 count)
{
struct au1k_private *aup = netdev_priv(dev);
struct net_device_stats *ps = &aup->stats;
ps->rx_packets++;
if (status & IR_RX_ERROR) {
ps->rx_errors++;
if (status & (IR_PHY_ERROR|IR_FIFO_OVER))
ps->rx_missed_errors++;
if (status & IR_MAX_LEN)
ps->rx_length_errors++;
if (status & IR_CRC_ERROR)
ps->rx_crc_errors++;
}
else
ps->rx_bytes += count;
}
/*
* Au1000 receive routine.
*/
static int au1k_irda_rx(struct net_device *dev)
{
struct au1k_private *aup = netdev_priv(dev);
struct sk_buff *skb;
volatile ring_dest_t *prxd;
u32 flags, count;
db_dest_t *pDB;
prxd = aup->rx_ring[aup->rx_head];
flags = prxd->flags;
while (!(flags & AU_OWN)) {
pDB = aup->rx_db_inuse[aup->rx_head];
count = prxd->count_1<<8 | prxd->count_0;
if (!(flags & IR_RX_ERROR)) {
/* good frame */
update_rx_stats(dev, flags, count);
skb=alloc_skb(count+1,GFP_ATOMIC);
if (skb == NULL) {
aup->stats.rx_dropped++;
continue;
}
skb_reserve(skb, 1);
if (aup->speed == 4000000)
skb_put(skb, count);
else
skb_put(skb, count-2);
memcpy(skb->data, (void *)pDB->vaddr, count-2);
skb->dev = dev;
skb->mac.raw = skb->data;
skb->protocol = htons(ETH_P_IRDA);
netif_rx(skb);
prxd->count_0 = 0;
prxd->count_1 = 0;
}
prxd->flags |= AU_OWN;
aup->rx_head = (aup->rx_head + 1) & (NUM_IR_DESC - 1);
writel(0, IR_RING_PROMPT);
au_sync();
/* next descriptor */
prxd = aup->rx_ring[aup->rx_head];
flags = prxd->flags;
dev->last_rx = jiffies;
}
return 0;
}
void au1k_irda_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct net_device *dev = (struct net_device *) dev_id;
if (dev == NULL) {
printk(KERN_ERR "%s: isr: null dev ptr\n", dev->name);
return;
}
writel(0, IR_INT_CLEAR); /* ack irda interrupts */
au1k_irda_rx(dev);
au1k_tx_ack(dev);
}
/*
* The Tx ring has been full longer than the watchdog timeout
* value. The transmitter must be hung?
*/
static void au1k_tx_timeout(struct net_device *dev)
{
u32 speed;
struct au1k_private *aup = netdev_priv(dev);
printk(KERN_ERR "%s: tx timeout\n", dev->name);
speed = aup->speed;
aup->speed = 0;
au1k_irda_set_speed(dev, speed);
aup->tx_full = 0;
netif_wake_queue(dev);
}
/*
* Set the IrDA communications speed.
*/
static int
au1k_irda_set_speed(struct net_device *dev, int speed)
{
unsigned long flags;
struct au1k_private *aup = netdev_priv(dev);
u32 control;
int ret = 0, timeout = 10, i;
volatile ring_dest_t *ptxd;
#if defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_DB1100)
unsigned long irda_resets;
#endif
if (speed == aup->speed)
return ret;
spin_lock_irqsave(&ir_lock, flags);
/* disable PHY first */
writel(read_ir_reg(IR_ENABLE) & ~0x8000, IR_ENABLE);
/* disable RX/TX */
writel(read_ir_reg(IR_CONFIG_1) & ~(IR_RX_ENABLE|IR_TX_ENABLE),
IR_CONFIG_1);
au_sync_delay(1);
while (read_ir_reg(IR_ENABLE) & (IR_RX_STATUS | IR_TX_STATUS)) {
mdelay(1);
if (!timeout--) {
printk(KERN_ERR "%s: rx/tx disable timeout\n",
dev->name);
break;
}
}
/* disable DMA */
writel(read_ir_reg(IR_CONFIG_1) & ~IR_DMA_ENABLE, IR_CONFIG_1);
au_sync_delay(1);
/*
* After we disable tx/rx. the index pointers
* go back to zero.
*/
aup->tx_head = aup->tx_tail = aup->rx_head = 0;
for (i=0; i<NUM_IR_DESC; i++) {
ptxd = aup->tx_ring[i];
ptxd->flags = 0;
ptxd->count_0 = 0;
ptxd->count_1 = 0;
}
for (i=0; i<NUM_IR_DESC; i++) {
ptxd = aup->rx_ring[i];
ptxd->count_0 = 0;
ptxd->count_1 = 0;
ptxd->flags = AU_OWN;
}
if (speed == 4000000) {
#if defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_DB1100)
bcsr->resets |= BCSR_RESETS_FIR_SEL;
#else /* Pb1000 and Pb1100 */
writel(1<<13, CPLD_AUX1);
#endif
}
else {
#if defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_DB1100)
bcsr->resets &= ~BCSR_RESETS_FIR_SEL;
#else /* Pb1000 and Pb1100 */
writel(readl(CPLD_AUX1) & ~(1<<13), CPLD_AUX1);
#endif
}
switch (speed) {
case 9600:
writel(11<<10 | 12<<5, IR_WRITE_PHY_CONFIG);
writel(IR_SIR_MODE, IR_CONFIG_1);
break;
case 19200:
writel(5<<10 | 12<<5, IR_WRITE_PHY_CONFIG);
writel(IR_SIR_MODE, IR_CONFIG_1);
break;
case 38400:
writel(2<<10 | 12<<5, IR_WRITE_PHY_CONFIG);
writel(IR_SIR_MODE, IR_CONFIG_1);
break;
case 57600:
writel(1<<10 | 12<<5, IR_WRITE_PHY_CONFIG);
writel(IR_SIR_MODE, IR_CONFIG_1);
break;
case 115200:
writel(12<<5, IR_WRITE_PHY_CONFIG);
writel(IR_SIR_MODE, IR_CONFIG_1);
break;
case 4000000:
writel(0xF, IR_WRITE_PHY_CONFIG);
writel(IR_FIR|IR_DMA_ENABLE|IR_RX_ENABLE, IR_CONFIG_1);
break;
default:
printk(KERN_ERR "%s unsupported speed %x\n", dev->name, speed);
ret = -EINVAL;
break;
}
aup->speed = speed;
writel(read_ir_reg(IR_ENABLE) | 0x8000, IR_ENABLE);
au_sync();
control = read_ir_reg(IR_ENABLE);
writel(0, IR_RING_PROMPT);
au_sync();
if (control & (1<<14)) {
printk(KERN_ERR "%s: configuration error\n", dev->name);
}
else {
if (control & (1<<11))
printk(KERN_DEBUG "%s Valid SIR config\n", dev->name);
if (control & (1<<12))
printk(KERN_DEBUG "%s Valid MIR config\n", dev->name);
if (control & (1<<13))
printk(KERN_DEBUG "%s Valid FIR config\n", dev->name);
if (control & (1<<10))
printk(KERN_DEBUG "%s TX enabled\n", dev->name);
if (control & (1<<9))
printk(KERN_DEBUG "%s RX enabled\n", dev->name);
}
spin_unlock_irqrestore(&ir_lock, flags);
return ret;
}
static int
au1k_irda_ioctl(struct net_device *dev, struct ifreq *ifreq, int cmd)
{
struct if_irda_req *rq = (struct if_irda_req *)ifreq;
struct au1k_private *aup = netdev_priv(dev);
int ret = -EOPNOTSUPP;
switch (cmd) {
case SIOCSBANDWIDTH:
if (capable(CAP_NET_ADMIN)) {
/*
* We are unable to set the speed if the
* device is not running.
*/
if (aup->open)
ret = au1k_irda_set_speed(dev,
rq->ifr_baudrate);
else {
printk(KERN_ERR "%s ioctl: !netif_running\n",
dev->name);
ret = 0;
}
}
break;
case SIOCSMEDIABUSY:
ret = -EPERM;
if (capable(CAP_NET_ADMIN)) {
irda_device_set_media_busy(dev, TRUE);
ret = 0;
}
break;
case SIOCGRECEIVING:
rq->ifr_receiving = 0;
break;
default:
break;
}
return ret;
}
static struct net_device_stats *au1k_irda_stats(struct net_device *dev)
{
struct au1k_private *aup = netdev_priv(dev);
return &aup->stats;
}
MODULE_AUTHOR("Pete Popov <ppopov@mvista.com>");
MODULE_DESCRIPTION("Au1000 IrDA Device Driver");
module_init(au1k_irda_init);
module_exit(au1k_irda_exit);

1789
drivers/net/irda/donauboe.c Arquivo normal

Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff

363
drivers/net/irda/donauboe.h Arquivo normal
Ver arquivo

@@ -0,0 +1,363 @@
/*********************************************************************
*
* Filename: toshoboe.h
* Version: 2.16
* Description: Driver for the Toshiba OBOE (or type-O or 701)
* FIR Chipset, also supports the DONAUOBOE (type-DO
* or d01) FIR chipset which as far as I know is
* register compatible.
* Status: Experimental.
* Author: James McKenzie <james@fishsoup.dhs.org>
* Created at: Sat May 8 12:35:27 1999
* Modified: 2.16 Martin Lucina <mato@kotelna.sk>
* Modified: 2.16 Sat Jun 22 18:54:29 2002 (sync headers)
* Modified: 2.17 Christian Gennerat <christian.gennerat@polytechnique.org>
* Modified: 2.17 jeu sep 12 08:50:20 2002 (add lock to be used by spinlocks)
*
* Copyright (c) 1999 James McKenzie, All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* Neither James McKenzie nor Cambridge University admit liability nor
* provide warranty for any of this software. This material is
* provided "AS-IS" and at no charge.
*
* Applicable Models : Libretto 100/110CT and many more.
* Toshiba refers to this chip as the type-O IR port,
* or the type-DO IR port.
*
* IrDA chip set list from Toshiba Computer Engineering Corp.
* model method maker controler Version
* Portege 320CT FIR,SIR Toshiba Oboe(Triangle)
* Portege 3010CT FIR,SIR Toshiba Oboe(Sydney)
* Portege 3015CT FIR,SIR Toshiba Oboe(Sydney)
* Portege 3020CT FIR,SIR Toshiba Oboe(Sydney)
* Portege 7020CT FIR,SIR ? ?
*
* Satell. 4090XCDT FIR,SIR ? ?
*
* Libretto 100CT FIR,SIR Toshiba Oboe
* Libretto 1000CT FIR,SIR Toshiba Oboe
*
* TECRA750DVD FIR,SIR Toshiba Oboe(Triangle) REV ID=14h
* TECRA780 FIR,SIR Toshiba Oboe(Sandlot) REV ID=32h,33h
* TECRA750CDT FIR,SIR Toshiba Oboe(Triangle) REV ID=13h,14h
* TECRA8000 FIR,SIR Toshiba Oboe(ISKUR) REV ID=23h
*
********************************************************************/
/* The documentation for this chip is allegedly released */
/* However I have not seen it, not have I managed to contact */
/* anyone who has. HOWEVER the chip bears a striking resemblence */
/* to the IrDA controller in the Toshiba RISC TMPR3922 chip */
/* the documentation for this is freely available at */
/* http://www.toshiba.com/taec/components/Generic/TMPR3922.shtml */
/* The mapping between the registers in that document and the */
/* Registers in the 701 oboe chip are as follows */
/* 3922 reg 701 regs, by bit numbers */
/* 7- 0 15- 8 24-16 31-25 */
/* $28 0x0 0x1 */
/* $2c SEE NOTE 1 */
/* $30 0x6 0x7 */
/* $34 0x8 0x9 SEE NOTE 2 */
/* $38 0x10 0x11 */
/* $3C 0xe SEE NOTE 3 */
/* $40 0x12 0x13 */
/* $44 0x14 0x15 */
/* $48 0x16 0x17 */
/* $4c 0x18 0x19 */
/* $50 0x1a 0x1b */
/* FIXME: could be 0x1b 0x1a here */
/* $54 0x1d 0x1c */
/* $5C 0xf SEE NOTE 4 */
/* $130 SEE NOTE 5 */
/* $134 SEE NOTE 6 */
/* */
/* NOTES: */
/* 1. The pointer to ring is packed in most unceremoniusly */
/* 701 Register Address bits (A9-A0 must be zero) */
/* 0x4: A17 A16 A15 A14 A13 A12 A11 A10 */
/* 0x5: A25 A24 A23 A22 A21 A20 A19 A18 */
/* 0x2: 0 0 A31 A30 A29 A28 A27 A26 */
/* */
/* 2. The M$ drivers do a write 0x1 to 0x9, however the 3922 */
/* documentation would suggest that a write of 0x1 to 0x8 */
/* would be more appropriate. */
/* */
/* 3. This assignment is tenuous at best, register 0xe seems to */
/* have bits arranged 0 0 0 R/W R/W R/W R/W R/W */
/* if either of the lower two bits are set the chip seems to */
/* switch off */
/* */
/* 4. Bits 7-4 seem to be different 4 seems just to be generic */
/* receiver busy flag */
/* */
/* 5. and 6. The IER and ISR have a different bit assignment */
/* The lower three bits of both read back as ones */
/* ISR is register 0xc, IER is register 0xd */
/* 7 6 5 4 3 2 1 0 */
/* 0xc: TxDone RxDone TxUndr RxOver SipRcv 1 1 1 */
/* 0xd: TxDone RxDone TxUndr RxOver SipRcv 1 1 1 */
/* TxDone xmitt done (generated only if generate interrupt bit */
/* is set in the ring) */
/* RxDone recv completed (or other recv condition if you set it */
/* up */
/* TxUnder underflow in Transmit FIFO */
/* RxOver overflow in Recv FIFO */
/* SipRcv received serial gap (or other condition you set) */
/* Interrupts are enabled by writing a one to the IER register */
/* Interrupts are cleared by writting a one to the ISR register */
/* */
/* 6. The remaining registers: 0x6 and 0x3 appear to be */
/* reserved parts of 16 or 32 bit registersthe remainder */
/* 0xa 0xb 0x1e 0x1f could possibly be (by their behaviour) */
/* the Unicast Filter register at $58. */
/* */
/* 7. While the core obviously expects 32 bit accesses all the */
/* M$ drivers do 8 bit accesses, infact the Miniport ones */
/* write and read back the byte serveral times (why?) */
#ifndef TOSHOBOE_H
#define TOSHOBOE_H
/* Registers */
#define OBOE_IO_EXTENT 0x1f
/*Receive and transmit slot pointers */
#define OBOE_REG(i) (i+(self->base))
#define OBOE_RXSLOT OBOE_REG(0x0)
#define OBOE_TXSLOT OBOE_REG(0x1)
#define OBOE_SLOT_MASK 0x3f
#define OBOE_TXRING_OFFSET 0x200
#define OBOE_TXRING_OFFSET_IN_SLOTS 0x40
/*pointer to the ring */
#define OBOE_RING_BASE0 OBOE_REG(0x4)
#define OBOE_RING_BASE1 OBOE_REG(0x5)
#define OBOE_RING_BASE2 OBOE_REG(0x2)
#define OBOE_RING_BASE3 OBOE_REG(0x3)
/*Number of slots in the ring */
#define OBOE_RING_SIZE OBOE_REG(0x7)
#define OBOE_RING_SIZE_RX4 0x00
#define OBOE_RING_SIZE_RX8 0x01
#define OBOE_RING_SIZE_RX16 0x03
#define OBOE_RING_SIZE_RX32 0x07
#define OBOE_RING_SIZE_RX64 0x0f
#define OBOE_RING_SIZE_TX4 0x00
#define OBOE_RING_SIZE_TX8 0x10
#define OBOE_RING_SIZE_TX16 0x30
#define OBOE_RING_SIZE_TX32 0x70
#define OBOE_RING_SIZE_TX64 0xf0
#define OBOE_RING_MAX_SIZE 64
/*Causes the gubbins to re-examine the ring */
#define OBOE_PROMPT OBOE_REG(0x9)
#define OBOE_PROMPT_BIT 0x1
/* Interrupt Status Register */
#define OBOE_ISR OBOE_REG(0xc)
/* Interrupt Enable Register */
#define OBOE_IER OBOE_REG(0xd)
/* Interrupt bits for IER and ISR */
#define OBOE_INT_TXDONE 0x80
#define OBOE_INT_RXDONE 0x40
#define OBOE_INT_TXUNDER 0x20
#define OBOE_INT_RXOVER 0x10
#define OBOE_INT_SIP 0x08
#define OBOE_INT_MASK 0xf8
/*Reset Register */
#define OBOE_CONFIG1 OBOE_REG(0xe)
#define OBOE_CONFIG1_RST 0x01
#define OBOE_CONFIG1_DISABLE 0x02
#define OBOE_CONFIG1_4 0x08
#define OBOE_CONFIG1_8 0x08
#define OBOE_CONFIG1_ON 0x8
#define OBOE_CONFIG1_RESET 0xf
#define OBOE_CONFIG1_OFF 0xe
#define OBOE_STATUS OBOE_REG(0xf)
#define OBOE_STATUS_RXBUSY 0x10
#define OBOE_STATUS_FIRRX 0x04
#define OBOE_STATUS_MIRRX 0x02
#define OBOE_STATUS_SIRRX 0x01
/*Speed control registers */
#define OBOE_CONFIG0L OBOE_REG(0x10)
#define OBOE_CONFIG0H OBOE_REG(0x11)
#define OBOE_CONFIG0H_TXONLOOP 0x80 /*Transmit when looping (dangerous) */
#define OBOE_CONFIG0H_LOOP 0x40 /*Loopback Tx->Rx */
#define OBOE_CONFIG0H_ENTX 0x10 /*Enable Tx */
#define OBOE_CONFIG0H_ENRX 0x08 /*Enable Rx */
#define OBOE_CONFIG0H_ENDMAC 0x04 /*Enable/reset* the DMA controller */
#define OBOE_CONFIG0H_RCVANY 0x02 /*DMA mode 1=bytes, 0=dwords */
#define OBOE_CONFIG0L_CRC16 0x80 /*CRC 1=16 bit 0=32 bit */
#define OBOE_CONFIG0L_ENFIR 0x40 /*Enable FIR */
#define OBOE_CONFIG0L_ENMIR 0x20 /*Enable MIR */
#define OBOE_CONFIG0L_ENSIR 0x10 /*Enable SIR */
#define OBOE_CONFIG0L_ENSIRF 0x08 /*Enable SIR framer */
#define OBOE_CONFIG0L_SIRTEST 0x04 /*Enable SIR framer in MIR and FIR */
#define OBOE_CONFIG0L_INVERTTX 0x02 /*Invert Tx Line */
#define OBOE_CONFIG0L_INVERTRX 0x01 /*Invert Rx Line */
#define OBOE_BOF OBOE_REG(0x12)
#define OBOE_EOF OBOE_REG(0x13)
#define OBOE_ENABLEL OBOE_REG(0x14)
#define OBOE_ENABLEH OBOE_REG(0x15)
#define OBOE_ENABLEH_PHYANDCLOCK 0x80 /*Toggle low to copy config in */
#define OBOE_ENABLEH_CONFIGERR 0x40
#define OBOE_ENABLEH_FIRON 0x20
#define OBOE_ENABLEH_MIRON 0x10
#define OBOE_ENABLEH_SIRON 0x08
#define OBOE_ENABLEH_ENTX 0x04
#define OBOE_ENABLEH_ENRX 0x02
#define OBOE_ENABLEH_CRC16 0x01
#define OBOE_ENABLEL_BROADCAST 0x01
#define OBOE_CURR_PCONFIGL OBOE_REG(0x16) /*Current config */
#define OBOE_CURR_PCONFIGH OBOE_REG(0x17)
#define OBOE_NEW_PCONFIGL OBOE_REG(0x18)
#define OBOE_NEW_PCONFIGH OBOE_REG(0x19)
#define OBOE_PCONFIGH_BAUDMASK 0xfc
#define OBOE_PCONFIGH_WIDTHMASK 0x04
#define OBOE_PCONFIGL_WIDTHMASK 0xe0
#define OBOE_PCONFIGL_PREAMBLEMASK 0x1f
#define OBOE_PCONFIG_BAUDMASK 0xfc00
#define OBOE_PCONFIG_BAUDSHIFT 10
#define OBOE_PCONFIG_WIDTHMASK 0x04e0
#define OBOE_PCONFIG_WIDTHSHIFT 5
#define OBOE_PCONFIG_PREAMBLEMASK 0x001f
#define OBOE_PCONFIG_PREAMBLESHIFT 0
#define OBOE_MAXLENL OBOE_REG(0x1a)
#define OBOE_MAXLENH OBOE_REG(0x1b)
#define OBOE_RXCOUNTH OBOE_REG(0x1c) /*Reset on recipt */
#define OBOE_RXCOUNTL OBOE_REG(0x1d) /*of whole packet */
/* The PCI ID of the OBOE chip */
#ifndef PCI_DEVICE_ID_FIR701
#define PCI_DEVICE_ID_FIR701 0x0701
#endif
#ifndef PCI_DEVICE_ID_FIRD01
#define PCI_DEVICE_ID_FIRD01 0x0d01
#endif
struct OboeSlot
{
__u16 len; /*Tweleve bits of packet length */
__u8 unused;
__u8 control; /*Slot control/status see below */
__u32 address; /*Slot buffer address */
}
__attribute__ ((packed));
#define OBOE_NTASKS OBOE_TXRING_OFFSET_IN_SLOTS
struct OboeRing
{
struct OboeSlot rx[OBOE_NTASKS];
struct OboeSlot tx[OBOE_NTASKS];
};
#define OBOE_RING_LEN (sizeof(struct OboeRing))
#define OBOE_CTL_TX_HW_OWNS 0x80 /*W/R This slot owned by the hardware */
#define OBOE_CTL_TX_DISTX_CRC 0x40 /*W Disable CRC generation for [FM]IR */
#define OBOE_CTL_TX_BAD_CRC 0x20 /*W Generate bad CRC */
#define OBOE_CTL_TX_SIP 0x10 /*W Generate an SIP after xmittion */
#define OBOE_CTL_TX_MKUNDER 0x08 /*W Generate an underrun error */
#define OBOE_CTL_TX_RTCENTX 0x04 /*W Enable receiver and generate TXdone */
/* After this slot is processed */
#define OBOE_CTL_TX_UNDER 0x01 /*R Set by hardware to indicate underrun */
#define OBOE_CTL_RX_HW_OWNS 0x80 /*W/R This slot owned by hardware */
#define OBOE_CTL_RX_PHYERR 0x40 /*R Decoder error on receiption */
#define OBOE_CTL_RX_CRCERR 0x20 /*R CRC error only set for [FM]IR */
#define OBOE_CTL_RX_LENGTH 0x10 /*R Packet > max Rx length */
#define OBOE_CTL_RX_OVER 0x08 /*R set to indicate an overflow */
#define OBOE_CTL_RX_SIRBAD 0x04 /*R SIR had BOF in packet or ABORT sequence */
#define OBOE_CTL_RX_RXEOF 0x02 /*R Finished receiving on this slot */
struct toshoboe_cb
{
struct net_device *netdev; /* Yes! we are some kind of netdevice */
struct net_device_stats stats;
struct tty_driver ttydev;
struct irlap_cb *irlap; /* The link layer we are binded to */
chipio_t io; /* IrDA controller information */
struct qos_info qos; /* QoS capabilities for this device */
__u32 flags; /* Interface flags */
struct pci_dev *pdev; /*PCI device */
int base; /*IO base */
int txpending; /*how many tx's are pending */
int txs, rxs; /*Which slots are we at */
int irdad; /*Driver under control of netdev end */
int async; /*Driver under control of async end */
int stopped; /*Stopped by some or other APM stuff */
int filter; /*In SIR mode do we want to receive
frames or byte ranges */
void *ringbuf; /*The ring buffer */
struct OboeRing *ring; /*The ring */
void *tx_bufs[OBOE_RING_MAX_SIZE]; /*The buffers */
void *rx_bufs[OBOE_RING_MAX_SIZE];
int speed; /*Current setting of the speed */
int new_speed; /*Set to request a speed change */
/* The spinlock protect critical parts of the driver.
* Locking is done like this :
* spin_lock_irqsave(&self->spinlock, flags);
* Releasing the lock :
* spin_unlock_irqrestore(&self->spinlock, flags);
*/
spinlock_t spinlock;
/* Used for the probe and diagnostics code */
int int_rx;
int int_tx;
int int_txunder;
int int_rxover;
int int_sip;
};
#endif

122
drivers/net/irda/ep7211_ir.c Arquivo normal
Ver arquivo

@@ -0,0 +1,122 @@
/*
* IR port driver for the Cirrus Logic EP7211 processor.
*
* Copyright 2001, Blue Mug Inc. All rights reserved.
*/
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/tty.h>
#include <linux/init.h>
#include <net/irda/irda.h>
#include <net/irda/irda_device.h>
#include <asm/io.h>
#include <asm/hardware.h>
#define MIN_DELAY 25 /* 15 us, but wait a little more to be sure */
#define MAX_DELAY 10000 /* 1 ms */
static void ep7211_ir_open(dongle_t *self, struct qos_info *qos);
static void ep7211_ir_close(dongle_t *self);
static int ep7211_ir_change_speed(struct irda_task *task);
static int ep7211_ir_reset(struct irda_task *task);
static struct dongle_reg dongle = {
.type = IRDA_EP7211_IR,
.open = ep7211_ir_open,
.close = ep7211_ir_close,
.reset = ep7211_ir_reset,
.change_speed = ep7211_ir_change_speed,
.owner = THIS_MODULE,
};
static void ep7211_ir_open(dongle_t *self, struct qos_info *qos)
{
unsigned int syscon1, flags;
save_flags(flags); cli();
/* Turn on the SIR encoder. */
syscon1 = clps_readl(SYSCON1);
syscon1 |= SYSCON1_SIREN;
clps_writel(syscon1, SYSCON1);
/* XXX: We should disable modem status interrupts on the first
UART (interrupt #14). */
restore_flags(flags);
}
static void ep7211_ir_close(dongle_t *self)
{
unsigned int syscon1, flags;
save_flags(flags); cli();
/* Turn off the SIR encoder. */
syscon1 = clps_readl(SYSCON1);
syscon1 &= ~SYSCON1_SIREN;
clps_writel(syscon1, SYSCON1);
/* XXX: If we've disabled the modem status interrupts, we should
reset them back to their original state. */
restore_flags(flags);
}
/*
* Function ep7211_ir_change_speed (task)
*
* Change speed of the EP7211 I/R port. We don't really have to do anything
* for the EP7211 as long as the rate is being changed at the serial port
* level.
*/
static int ep7211_ir_change_speed(struct irda_task *task)
{
irda_task_next_state(task, IRDA_TASK_DONE);
return 0;
}
/*
* Function ep7211_ir_reset (task)
*
* Reset the EP7211 I/R. We don't really have to do anything.
*
*/
static int ep7211_ir_reset(struct irda_task *task)
{
irda_task_next_state(task, IRDA_TASK_DONE);
return 0;
}
/*
* Function ep7211_ir_init(void)
*
* Initialize EP7211 I/R module
*
*/
static int __init ep7211_ir_init(void)
{
return irda_device_register_dongle(&dongle);
}
/*
* Function ep7211_ir_cleanup(void)
*
* Cleanup EP7211 I/R module
*
*/
static void __exit ep7211_ir_cleanup(void)
{
irda_device_unregister_dongle(&dongle);
}
MODULE_AUTHOR("Jon McClintock <jonm@bluemug.com>");
MODULE_DESCRIPTION("EP7211 I/R driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("irda-dongle-8"); /* IRDA_EP7211_IR */
module_init(ep7211_ir_init);
module_exit(ep7211_ir_cleanup);

159
drivers/net/irda/esi-sir.c Arquivo normal
Ver arquivo

@@ -0,0 +1,159 @@
/*********************************************************************
*
* Filename: esi.c
* Version: 1.6
* Description: Driver for the Extended Systems JetEye PC dongle
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sat Feb 21 18:54:38 1998
* Modified at: Sun Oct 27 22:01:04 2002
* Modified by: Martin Diehl <mad@mdiehl.de>
*
* Copyright (c) 1999 Dag Brattli, <dagb@cs.uit.no>,
* Copyright (c) 1998 Thomas Davis, <ratbert@radiks.net>,
* Copyright (c) 2002 Martin Diehl, <mad@mdiehl.de>,
* All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
********************************************************************/
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <net/irda/irda.h>
#include "sir-dev.h"
static int esi_open(struct sir_dev *);
static int esi_close(struct sir_dev *);
static int esi_change_speed(struct sir_dev *, unsigned);
static int esi_reset(struct sir_dev *);
static struct dongle_driver esi = {
.owner = THIS_MODULE,
.driver_name = "JetEye PC ESI-9680 PC",
.type = IRDA_ESI_DONGLE,
.open = esi_open,
.close = esi_close,
.reset = esi_reset,
.set_speed = esi_change_speed,
};
static int __init esi_sir_init(void)
{
return irda_register_dongle(&esi);
}
static void __exit esi_sir_cleanup(void)
{
irda_unregister_dongle(&esi);
}
static int esi_open(struct sir_dev *dev)
{
struct qos_info *qos = &dev->qos;
/* Power up and set dongle to 9600 baud */
sirdev_set_dtr_rts(dev, FALSE, TRUE);
qos->baud_rate.bits &= IR_9600|IR_19200|IR_115200;
qos->min_turn_time.bits = 0x01; /* Needs at least 10 ms */
irda_qos_bits_to_value(qos);
/* irda thread waits 50 msec for power settling */
return 0;
}
static int esi_close(struct sir_dev *dev)
{
/* Power off dongle */
sirdev_set_dtr_rts(dev, FALSE, FALSE);
return 0;
}
/*
* Function esi_change_speed (task)
*
* Set the speed for the Extended Systems JetEye PC ESI-9680 type dongle
* Apparently (see old esi-driver) no delays are needed here...
*
*/
static int esi_change_speed(struct sir_dev *dev, unsigned speed)
{
int ret = 0;
int dtr, rts;
switch (speed) {
case 19200:
dtr = TRUE;
rts = FALSE;
break;
case 115200:
dtr = rts = TRUE;
break;
default:
ret = -EINVAL;
speed = 9600;
/* fall through */
case 9600:
dtr = FALSE;
rts = TRUE;
break;
}
/* Change speed of dongle */
sirdev_set_dtr_rts(dev, dtr, rts);
dev->speed = speed;
return ret;
}
/*
* Function esi_reset (task)
*
* Reset dongle;
*
*/
static int esi_reset(struct sir_dev *dev)
{
sirdev_set_dtr_rts(dev, FALSE, FALSE);
/* Hm, the old esi-driver left the dongle unpowered relying on
* the following speed change to repower. This might work for
* the esi because we only need the modem lines. However, now the
* general rule is reset must bring the dongle to some working
* well-known state because speed change might write to registers.
* The old esi-driver didn't any delay here - let's hope it' fine.
*/
sirdev_set_dtr_rts(dev, FALSE, TRUE);
dev->speed = 9600;
return 0;
}
MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
MODULE_DESCRIPTION("Extended Systems JetEye PC dongle driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("irda-dongle-1"); /* IRDA_ESI_DONGLE */
module_init(esi_sir_init);
module_exit(esi_sir_cleanup);

149
drivers/net/irda/esi.c Arquivo normal
Ver arquivo

@@ -0,0 +1,149 @@
/*********************************************************************
*
* Filename: esi.c
* Version: 1.5
* Description: Driver for the Extended Systems JetEye PC dongle
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sat Feb 21 18:54:38 1998
* Modified at: Fri Dec 17 09:14:04 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1999 Dag Brattli, <dagb@cs.uit.no>,
* Copyright (c) 1998 Thomas Davis, <ratbert@radiks.net>,
* All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
********************************************************************/
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/tty.h>
#include <linux/init.h>
#include <net/irda/irda.h>
#include <net/irda/irda_device.h>
static void esi_open(dongle_t *self, struct qos_info *qos);
static void esi_close(dongle_t *self);
static int esi_change_speed(struct irda_task *task);
static int esi_reset(struct irda_task *task);
static struct dongle_reg dongle = {
.type = IRDA_ESI_DONGLE,
.open = esi_open,
.close = esi_close,
.reset = esi_reset,
.change_speed = esi_change_speed,
.owner = THIS_MODULE,
};
static int __init esi_init(void)
{
return irda_device_register_dongle(&dongle);
}
static void __exit esi_cleanup(void)
{
irda_device_unregister_dongle(&dongle);
}
static void esi_open(dongle_t *self, 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 */
}
static void esi_close(dongle_t *dongle)
{
/* Power off dongle */
dongle->set_dtr_rts(dongle->dev, FALSE, FALSE);
}
/*
* Function esi_change_speed (task)
*
* Set the speed for the Extended Systems JetEye PC ESI-9680 type dongle
*
*/
static int esi_change_speed(struct irda_task *task)
{
dongle_t *self = (dongle_t *) task->instance;
__u32 speed = (__u32) task->param;
int dtr, rts;
switch (speed) {
case 19200:
dtr = TRUE;
rts = FALSE;
break;
case 115200:
dtr = rts = TRUE;
break;
case 9600:
default:
dtr = FALSE;
rts = TRUE;
break;
}
/* Change speed of dongle */
self->set_dtr_rts(self->dev, dtr, rts);
self->speed = speed;
irda_task_next_state(task, IRDA_TASK_DONE);
return 0;
}
/*
* Function esi_reset (task)
*
* Reset dongle;
*
*/
static int esi_reset(struct irda_task *task)
{
dongle_t *self = (dongle_t *) task->instance;
self->set_dtr_rts(self->dev, FALSE, FALSE);
irda_task_next_state(task, IRDA_TASK_DONE);
return 0;
}
MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
MODULE_DESCRIPTION("Extended Systems JetEye PC dongle driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("irda-dongle-1"); /* IRDA_ESI_DONGLE */
/*
* Function init_module (void)
*
* Initialize ESI module
*
*/
module_init(esi_init);
/*
* Function cleanup_module (void)
*
* Cleanup ESI module
*
*/
module_exit(esi_cleanup);

258
drivers/net/irda/girbil-sir.c Arquivo normal
Ver arquivo

@@ -0,0 +1,258 @@
/*********************************************************************
*
* Filename: girbil.c
* Version: 1.2
* 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: Fri Dec 17 09:13:20 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1999 Dag Brattli, All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* Neither Dag Brattli nor University of Troms<6D> admit liability nor
* provide warranty for any of this software. This material is
* provided "AS-IS" and at no charge.
*
********************************************************************/
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <net/irda/irda.h>
#include "sir-dev.h"
static int girbil_reset(struct sir_dev *dev);
static int girbil_open(struct sir_dev *dev);
static int girbil_close(struct sir_dev *dev);
static int girbil_change_speed(struct sir_dev *dev, unsigned speed);
/* Control register 1 */
#define GIRBIL_TXEN 0x01 /* Enable transmitter */
#define GIRBIL_RXEN 0x02 /* Enable receiver */
#define GIRBIL_ECAN 0x04 /* Cancel self emmited data */
#define GIRBIL_ECHO 0x08 /* Echo control characters */
/* LED Current Register (0x2) */
#define GIRBIL_HIGH 0x20
#define GIRBIL_MEDIUM 0x21
#define GIRBIL_LOW 0x22
/* Baud register (0x3) */
#define GIRBIL_2400 0x30
#define GIRBIL_4800 0x31
#define GIRBIL_9600 0x32
#define GIRBIL_19200 0x33
#define GIRBIL_38400 0x34
#define GIRBIL_57600 0x35
#define GIRBIL_115200 0x36
/* Mode register (0x4) */
#define GIRBIL_IRDA 0x40
#define GIRBIL_ASK 0x41
/* Control register 2 (0x5) */
#define GIRBIL_LOAD 0x51 /* Load the new baud rate value */
static struct dongle_driver girbil = {
.owner = THIS_MODULE,
.driver_name = "Greenwich GIrBIL",
.type = IRDA_GIRBIL_DONGLE,
.open = girbil_open,
.close = girbil_close,
.reset = girbil_reset,
.set_speed = girbil_change_speed,
};
static int __init girbil_sir_init(void)
{
return irda_register_dongle(&girbil);
}
static void __exit girbil_sir_cleanup(void)
{
irda_unregister_dongle(&girbil);
}
static int girbil_open(struct sir_dev *dev)
{
struct qos_info *qos = &dev->qos;
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
/* Power on dongle */
sirdev_set_dtr_rts(dev, TRUE, TRUE);
qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
qos->min_turn_time.bits = 0x03;
irda_qos_bits_to_value(qos);
/* irda thread waits 50 msec for power settling */
return 0;
}
static int girbil_close(struct sir_dev *dev)
{
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
/* Power off dongle */
sirdev_set_dtr_rts(dev, FALSE, FALSE);
return 0;
}
/*
* Function girbil_change_speed (dev, speed)
*
* Set the speed for the Girbil type dongle.
*
*/
#define GIRBIL_STATE_WAIT_SPEED (SIRDEV_STATE_DONGLE_SPEED + 1)
static int girbil_change_speed(struct sir_dev *dev, unsigned speed)
{
unsigned state = dev->fsm.substate;
unsigned delay = 0;
u8 control[2];
static int ret = 0;
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
/* dongle alread reset - port and dongle at default speed */
switch(state) {
case SIRDEV_STATE_DONGLE_SPEED:
/* Set DTR and Clear RTS to enter command mode */
sirdev_set_dtr_rts(dev, FALSE, TRUE);
udelay(25); /* better wait a little while */
ret = 0;
switch (speed) {
default:
ret = -EINVAL;
/* fall through */
case 9600:
control[0] = GIRBIL_9600;
break;
case 19200:
control[0] = GIRBIL_19200;
break;
case 34800:
control[0] = GIRBIL_38400;
break;
case 57600:
control[0] = GIRBIL_57600;
break;
case 115200:
control[0] = GIRBIL_115200;
break;
}
control[1] = GIRBIL_LOAD;
/* Write control bytes */
sirdev_raw_write(dev, control, 2);
dev->speed = speed;
state = GIRBIL_STATE_WAIT_SPEED;
delay = 100;
break;
case GIRBIL_STATE_WAIT_SPEED:
/* Go back to normal mode */
sirdev_set_dtr_rts(dev, TRUE, TRUE);
udelay(25); /* better wait a little while */
break;
default:
IRDA_ERROR("%s - undefined state %d\n", __FUNCTION__, state);
ret = -EINVAL;
break;
}
dev->fsm.substate = state;
return (delay > 0) ? delay : ret;
}
/*
* Function girbil_reset (driver)
*
* This function resets the girbil dongle.
*
* Algorithm:
* 0. set RTS, and wait at least 5 ms
* 1. clear RTS
*/
#define GIRBIL_STATE_WAIT1_RESET (SIRDEV_STATE_DONGLE_RESET + 1)
#define GIRBIL_STATE_WAIT2_RESET (SIRDEV_STATE_DONGLE_RESET + 2)
#define GIRBIL_STATE_WAIT3_RESET (SIRDEV_STATE_DONGLE_RESET + 3)
static int girbil_reset(struct sir_dev *dev)
{
unsigned state = dev->fsm.substate;
unsigned delay = 0;
u8 control = GIRBIL_TXEN | GIRBIL_RXEN;
int ret = 0;
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
switch (state) {
case SIRDEV_STATE_DONGLE_RESET:
/* Reset dongle */
sirdev_set_dtr_rts(dev, TRUE, FALSE);
/* Sleep at least 5 ms */
delay = 20;
state = GIRBIL_STATE_WAIT1_RESET;
break;
case GIRBIL_STATE_WAIT1_RESET:
/* Set DTR and clear RTS to enter command mode */
sirdev_set_dtr_rts(dev, FALSE, TRUE);
delay = 20;
state = GIRBIL_STATE_WAIT2_RESET;
break;
case GIRBIL_STATE_WAIT2_RESET:
/* Write control byte */
sirdev_raw_write(dev, &control, 1);
delay = 20;
state = GIRBIL_STATE_WAIT3_RESET;
break;
case GIRBIL_STATE_WAIT3_RESET:
/* Go back to normal mode */
sirdev_set_dtr_rts(dev, TRUE, TRUE);
dev->speed = 9600;
break;
default:
IRDA_ERROR("%s(), undefined state %d\n", __FUNCTION__, state);
ret = -1;
break;
}
dev->fsm.substate = state;
return (delay > 0) ? delay : ret;
}
MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
MODULE_DESCRIPTION("Greenwich GIrBIL dongle driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("irda-dongle-4"); /* IRDA_GIRBIL_DONGLE */
module_init(girbil_sir_init);
module_exit(girbil_sir_cleanup);

250
drivers/net/irda/girbil.c Arquivo normal
Ver arquivo

@@ -0,0 +1,250 @@
/*********************************************************************
*
* Filename: girbil.c
* Version: 1.2
* 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: Fri Dec 17 09:13:20 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1999 Dag Brattli, All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* Neither Dag Brattli nor University of Troms<6D> admit liability nor
* provide warranty for any of this software. This material is
* provided "AS-IS" and at no charge.
*
********************************************************************/
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/tty.h>
#include <linux/init.h>
#include <net/irda/irda.h>
#include <net/irda/irda_device.h>
static int girbil_reset(struct irda_task *task);
static void girbil_open(dongle_t *self, struct qos_info *qos);
static void girbil_close(dongle_t *self);
static int girbil_change_speed(struct irda_task *task);
/* Control register 1 */
#define GIRBIL_TXEN 0x01 /* Enable transmitter */
#define GIRBIL_RXEN 0x02 /* Enable receiver */
#define GIRBIL_ECAN 0x04 /* Cancel self emmited data */
#define GIRBIL_ECHO 0x08 /* Echo control characters */
/* LED Current Register (0x2) */
#define GIRBIL_HIGH 0x20
#define GIRBIL_MEDIUM 0x21
#define GIRBIL_LOW 0x22
/* Baud register (0x3) */
#define GIRBIL_2400 0x30
#define GIRBIL_4800 0x31
#define GIRBIL_9600 0x32
#define GIRBIL_19200 0x33
#define GIRBIL_38400 0x34
#define GIRBIL_57600 0x35
#define GIRBIL_115200 0x36
/* Mode register (0x4) */
#define GIRBIL_IRDA 0x40
#define GIRBIL_ASK 0x41
/* Control register 2 (0x5) */
#define GIRBIL_LOAD 0x51 /* Load the new baud rate value */
static struct dongle_reg dongle = {
.type = IRDA_GIRBIL_DONGLE,
.open = girbil_open,
.close = girbil_close,
.reset = girbil_reset,
.change_speed = girbil_change_speed,
.owner = THIS_MODULE,
};
static int __init girbil_init(void)
{
return irda_device_register_dongle(&dongle);
}
static void __exit girbil_cleanup(void)
{
irda_device_unregister_dongle(&dongle);
}
static void girbil_open(dongle_t *self, struct qos_info *qos)
{
qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
qos->min_turn_time.bits = 0x03;
}
static void girbil_close(dongle_t *self)
{
/* Power off dongle */
self->set_dtr_rts(self->dev, FALSE, FALSE);
}
/*
* Function girbil_change_speed (dev, speed)
*
* Set the speed for the Girbil type dongle.
*
*/
static int girbil_change_speed(struct irda_task *task)
{
dongle_t *self = (dongle_t *) task->instance;
__u32 speed = (__u32) task->param;
__u8 control[2];
int ret = 0;
self->speed_task = task;
switch (task->state) {
case IRDA_TASK_INIT:
/* Need to reset the dongle and go to 9600 bps before
programming */
if (irda_task_execute(self, girbil_reset, NULL, task,
(void *) speed))
{
/* Dongle need more time to reset */
irda_task_next_state(task, IRDA_TASK_CHILD_WAIT);
/* Give reset 1 sec to finish */
ret = msecs_to_jiffies(1000);
}
break;
case IRDA_TASK_CHILD_WAIT:
IRDA_WARNING("%s(), resetting dongle timed out!\n",
__FUNCTION__);
ret = -1;
break;
case IRDA_TASK_CHILD_DONE:
/* Set DTR and Clear RTS to enter command mode */
self->set_dtr_rts(self->dev, FALSE, TRUE);
switch (speed) {
case 9600:
default:
control[0] = GIRBIL_9600;
break;
case 19200:
control[0] = GIRBIL_19200;
break;
case 34800:
control[0] = GIRBIL_38400;
break;
case 57600:
control[0] = GIRBIL_57600;
break;
case 115200:
control[0] = GIRBIL_115200;
break;
}
control[1] = GIRBIL_LOAD;
/* Write control bytes */
self->write(self->dev, control, 2);
irda_task_next_state(task, IRDA_TASK_WAIT);
ret = msecs_to_jiffies(100);
break;
case IRDA_TASK_WAIT:
/* Go back to normal mode */
self->set_dtr_rts(self->dev, TRUE, TRUE);
irda_task_next_state(task, IRDA_TASK_DONE);
self->speed_task = NULL;
break;
default:
IRDA_ERROR("%s(), unknown state %d\n",
__FUNCTION__, task->state);
irda_task_next_state(task, IRDA_TASK_DONE);
self->speed_task = NULL;
ret = -1;
break;
}
return ret;
}
/*
* Function girbil_reset (driver)
*
* This function resets the girbil dongle.
*
* Algorithm:
* 0. set RTS, and wait at least 5 ms
* 1. clear RTS
*/
static int girbil_reset(struct irda_task *task)
{
dongle_t *self = (dongle_t *) task->instance;
__u8 control = GIRBIL_TXEN | GIRBIL_RXEN;
int ret = 0;
self->reset_task = task;
switch (task->state) {
case IRDA_TASK_INIT:
/* Reset dongle */
self->set_dtr_rts(self->dev, TRUE, FALSE);
irda_task_next_state(task, IRDA_TASK_WAIT1);
/* Sleep at least 5 ms */
ret = msecs_to_jiffies(20);
break;
case IRDA_TASK_WAIT1:
/* Set DTR and clear RTS to enter command mode */
self->set_dtr_rts(self->dev, FALSE, TRUE);
irda_task_next_state(task, IRDA_TASK_WAIT2);
ret = msecs_to_jiffies(20);
break;
case IRDA_TASK_WAIT2:
/* Write control byte */
self->write(self->dev, &control, 1);
irda_task_next_state(task, IRDA_TASK_WAIT3);
ret = msecs_to_jiffies(20);
break;
case IRDA_TASK_WAIT3:
/* Go back to normal mode */
self->set_dtr_rts(self->dev, TRUE, TRUE);
irda_task_next_state(task, IRDA_TASK_DONE);
self->reset_task = NULL;
break;
default:
IRDA_ERROR("%s(), unknown state %d\n",
__FUNCTION__, task->state);
irda_task_next_state(task, IRDA_TASK_DONE);
self->reset_task = NULL;
ret = -1;
break;
}
return ret;
}
MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
MODULE_DESCRIPTION("Greenwich GIrBIL dongle driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("irda-dongle-4"); /* IRDA_GIRBIL_DONGLE */
/*
* Function init_module (void)
*
* Initialize Girbil module
*
*/
module_init(girbil_init);
/*
* Function cleanup_module (void)
*
* Cleanup Girbil module
*
*/
module_exit(girbil_cleanup);

1602
drivers/net/irda/irda-usb.c Arquivo normal

Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff

163
drivers/net/irda/irda-usb.h Arquivo normal
Ver arquivo

@@ -0,0 +1,163 @@
/*****************************************************************************
*
* Filename: irda-usb.h
* Version: 0.9b
* Description: IrDA-USB Driver
* Status: Experimental
* Author: Dag Brattli <dag@brattli.net>
*
* Copyright (C) 2001, Roman Weissgaerber <weissg@vienna.at>
* Copyright (C) 2000, Dag Brattli <dag@brattli.net>
* Copyright (C) 2001, Jean Tourrilhes <jt@hpl.hp.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*****************************************************************************/
#include <linux/time.h>
#include <net/irda/irda.h>
#include <net/irda/irda_device.h> /* struct irlap_cb */
#define RX_COPY_THRESHOLD 200
#define IRDA_USB_MAX_MTU 2051
#define IRDA_USB_SPEED_MTU 64 /* Weird, but work like this */
/* Maximum number of active URB on the Rx path
* This is the amount of buffers the we keep between the USB harware and the
* IrDA stack.
*
* Note : the network layer does also queue the packets between us and the
* IrDA stack, and is actually pretty fast and efficient in doing that.
* Therefore, we don't need to have a large number of URBs, and we can
* perfectly live happy with only one. We certainly don't need to keep the
* full IrTTP window around here...
* I repeat for those who have trouble to understand : 1 URB is plenty
* good enough to handle back-to-back (brickwalled) frames. I tried it,
* it works (it's the hardware that has trouble doing it).
*
* Having 2 URBs would allow the USB stack to process one URB while we take
* care of the other and then swap the URBs...
* On the other hand, increasing the number of URB will have penalities
* in term of latency and will interact with the link management in IrLAP...
* Jean II */
#define IU_MAX_ACTIVE_RX_URBS 1 /* Don't touch !!! */
/* When a Rx URB is passed back to us, we can't reuse it immediately,
* because it may still be referenced by the USB layer. Therefore we
* need to keep one extra URB in the Rx path.
* Jean II */
#define IU_MAX_RX_URBS (IU_MAX_ACTIVE_RX_URBS + 1)
/* Various ugly stuff to try to workaround generic problems */
/* Send speed command in case of timeout, just for trying to get things sane */
#define IU_BUG_KICK_TIMEOUT
/* Show the USB class descriptor */
#undef IU_DUMP_CLASS_DESC
/* Assume a minimum round trip latency for USB transfer (in us)...
* USB transfer are done in the next USB slot if there is no traffic
* (1/19 msec) and is done at 12 Mb/s :
* Waiting for slot + tx = (53us + 16us) * 2 = 137us minimum.
* Rx notification will only be done at the end of the USB frame period :
* OHCI : frame period = 1ms
* UHCI : frame period = 1ms, but notification can take 2 or 3 ms :-(
* EHCI : frame period = 125us */
#define IU_USB_MIN_RTT 500 /* This should be safe in most cases */
/* Inbound header */
#define MEDIA_BUSY 0x80
#define SPEED_2400 0x01
#define SPEED_9600 0x02
#define SPEED_19200 0x03
#define SPEED_38400 0x04
#define SPEED_57600 0x05
#define SPEED_115200 0x06
#define SPEED_576000 0x07
#define SPEED_1152000 0x08
#define SPEED_4000000 0x09
/* Basic capabilities */
#define IUC_DEFAULT 0x00 /* Basic device compliant with 1.0 spec */
/* Main bugs */
#define IUC_SPEED_BUG 0x01 /* Device doesn't set speed after the frame */
#define IUC_NO_WINDOW 0x02 /* Device doesn't behave with big Rx window */
#define IUC_NO_TURN 0x04 /* Device doesn't do turnaround by itself */
/* Not currently used */
#define IUC_SIR_ONLY 0x08 /* Device doesn't behave at FIR speeds */
#define IUC_SMALL_PKT 0x10 /* Device doesn't behave with big Rx packets */
#define IUC_MAX_WINDOW 0x20 /* Device underestimate the Rx window */
#define IUC_MAX_XBOFS 0x40 /* Device need more xbofs than advertised */
/* USB class definitions */
#define USB_IRDA_HEADER 0x01
#define USB_CLASS_IRDA 0x02 /* USB_CLASS_APP_SPEC subclass */
#define USB_DT_IRDA 0x21
struct irda_class_desc {
__u8 bLength;
__u8 bDescriptorType;
__u16 bcdSpecRevision;
__u8 bmDataSize;
__u8 bmWindowSize;
__u8 bmMinTurnaroundTime;
__u16 wBaudRate;
__u8 bmAdditionalBOFs;
__u8 bIrdaRateSniff;
__u8 bMaxUnicastList;
} __attribute__ ((packed));
/* class specific interface request to get the IrDA-USB class descriptor
* (6.2.5, USB-IrDA class spec 1.0) */
#define IU_REQ_GET_CLASS_DESC 0x06
struct irda_usb_cb {
struct irda_class_desc *irda_desc;
struct usb_device *usbdev; /* init: probe_irda */
struct usb_interface *usbintf; /* init: probe_irda */
int netopen; /* Device is active for network */
int present; /* Device is present on the bus */
__u32 capability; /* Capability of the hardware */
__u8 bulk_in_ep; /* Rx Endpoint assignments */
__u8 bulk_out_ep; /* Tx Endpoint assignments */
__u16 bulk_out_mtu; /* Max Tx packet size in bytes */
__u8 bulk_int_ep; /* Interrupt Endpoint assignments */
wait_queue_head_t wait_q; /* for timeouts */
struct urb *rx_urb[IU_MAX_RX_URBS]; /* URBs used to receive data frames */
struct urb *idle_rx_urb; /* Pointer to idle URB in Rx path */
struct urb *tx_urb; /* URB used to send data frames */
struct urb *speed_urb; /* URB used to send speed commands */
struct net_device *netdev; /* Yes! we are some kind of netdev. */
struct net_device_stats stats;
struct irlap_cb *irlap; /* The link layer we are binded to */
struct qos_info qos;
hashbin_t *tx_list; /* Queued transmit skb's */
char *speed_buff; /* Buffer for speed changes */
struct timeval stamp;
struct timeval now;
spinlock_t lock; /* For serializing operations */
__u16 xbofs; /* Current xbofs setting */
__s16 new_xbofs; /* xbofs we need to set */
__u32 speed; /* Current speed */
__s32 new_speed; /* speed we need to set */
};

1146
drivers/net/irda/irport.c Arquivo normal

Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff

80
drivers/net/irda/irport.h Arquivo normal
Ver arquivo

@@ -0,0 +1,80 @@
/*********************************************************************
*
* Filename: irport.h
* Version: 0.1
* Description: Serial driver for IrDA
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sun Aug 3 13:49:59 1997
* Modified at: Fri Jan 14 10:21:10 2000
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1997, 1998-2000 Dag Brattli <dagb@cs.uit.no>
* All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* Neither Dag Brattli nor University of Troms<6D> admit liability nor
* provide warranty for any of this software. This material is
* provided "AS-IS" and at no charge.
*
********************************************************************/
#ifndef IRPORT_H
#define IRPORT_H
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/types.h>
#include <linux/spinlock.h>
#include <net/irda/irda_device.h>
#define SPEED_DEFAULT 9600
#define SPEED_MAX 115200
/*
* These are the supported serial types.
*/
#define PORT_UNKNOWN 0
#define PORT_8250 1
#define PORT_16450 2
#define PORT_16550 3
#define PORT_16550A 4
#define PORT_CIRRUS 5
#define PORT_16650 6
#define PORT_MAX 6
#define FRAME_MAX_SIZE 2048
struct irport_cb {
struct net_device *netdev; /* Yes! we are some kind of netdevice */
struct net_device_stats stats;
struct irlap_cb *irlap; /* The link layer we are attached to */
chipio_t io; /* IrDA controller information */
iobuff_t tx_buff; /* Transmit buffer */
iobuff_t rx_buff; /* Receive buffer */
struct qos_info qos; /* QoS capabilities for this device */
dongle_t *dongle; /* Dongle driver */
__u32 flags; /* Interface flags */
__u32 new_speed;
int mode;
int index; /* Instance index */
int transmitting; /* Are we transmitting ? */
spinlock_t lock; /* For serializing operations */
/* For piggyback drivers */
void *priv;
void (*change_speed)(void *priv, __u32 speed);
int (*interrupt)(int irq, void *dev_id, struct pt_regs *regs);
};
#endif /* IRPORT_H */

642
drivers/net/irda/irtty-sir.c Arquivo normal
Ver arquivo

@@ -0,0 +1,642 @@
/*********************************************************************
*
* Filename: irtty-sir.c
* Version: 2.0
* Description: IrDA line discipline implementation
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Tue Dec 9 21:18:38 1997
* Modified at: Sun Oct 27 22:13:30 2002
* Modified by: Martin Diehl <mad@mdiehl.de>
* Sources: slip.c by Laurence Culhane, <loz@holmes.demon.co.uk>
* Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
*
* Copyright (c) 1998-2000 Dag Brattli,
* Copyright (c) 2002 Martin Diehl,
* 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<6D> admit liability nor
* provide warranty for any of this software. This material is
* provided "AS-IS" and at no charge.
*
********************************************************************/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/tty.h>
#include <linux/init.h>
#include <asm/uaccess.h>
#include <linux/smp_lock.h>
#include <linux/delay.h>
#include <net/irda/irda.h>
#include <net/irda/irda_device.h>
#include "sir-dev.h"
#include "irtty-sir.h"
static int qos_mtt_bits = 0x03; /* 5 ms or more */
module_param(qos_mtt_bits, int, 0);
MODULE_PARM_DESC(qos_mtt_bits, "Minimum Turn Time");
/* ------------------------------------------------------- */
/* device configuration callbacks always invoked with irda-thread context */
/* find out, how many chars we have in buffers below us
* this is allowed to lie, i.e. return less chars than we
* actually have. The returned value is used to determine
* how long the irdathread should wait before doing the
* real blocking wait_until_sent()
*/
static int irtty_chars_in_buffer(struct sir_dev *dev)
{
struct sirtty_cb *priv = dev->priv;
IRDA_ASSERT(priv != NULL, return -1;);
IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return -1;);
return priv->tty->driver->chars_in_buffer(priv->tty);
}
/* Wait (sleep) until underlaying hardware finished transmission
* i.e. hardware buffers are drained
* this must block and not return before all characters are really sent
*
* If the tty sits on top of a 16550A-like uart, there are typically
* up to 16 bytes in the fifo - f.e. 9600 bps 8N1 needs 16.7 msec
*
* With usbserial the uart-fifo is basically replaced by the converter's
* outgoing endpoint buffer, which can usually hold 64 bytes (at least).
* With pl2303 it appears we are safe with 60msec here.
*
* I really wish all serial drivers would provide
* correct implementation of wait_until_sent()
*/
#define USBSERIAL_TX_DONE_DELAY 60
static void irtty_wait_until_sent(struct sir_dev *dev)
{
struct sirtty_cb *priv = dev->priv;
struct tty_struct *tty;
IRDA_ASSERT(priv != NULL, return;);
IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return;);
tty = priv->tty;
if (tty->driver->wait_until_sent) {
lock_kernel();
tty->driver->wait_until_sent(tty, msecs_to_jiffies(100));
unlock_kernel();
}
else {
msleep(USBSERIAL_TX_DONE_DELAY);
}
}
/*
* Function irtty_change_speed (dev, speed)
*
* Change the speed of the serial port.
*
* This may sleep in set_termios (usbserial driver f.e.) and must
* not be called from interrupt/timer/tasklet therefore.
* All such invocations are deferred to kIrDAd now so we can sleep there.
*/
static int irtty_change_speed(struct sir_dev *dev, unsigned speed)
{
struct sirtty_cb *priv = dev->priv;
struct tty_struct *tty;
struct termios old_termios;
int cflag;
IRDA_ASSERT(priv != NULL, return -1;);
IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return -1;);
tty = priv->tty;
lock_kernel();
old_termios = *(tty->termios);
cflag = tty->termios->c_cflag;
cflag &= ~CBAUD;
IRDA_DEBUG(2, "%s(), Setting speed to %d\n", __FUNCTION__, speed);
switch (speed) {
case 1200:
cflag |= B1200;
break;
case 2400:
cflag |= B2400;
break;
case 4800:
cflag |= B4800;
break;
case 19200:
cflag |= B19200;
break;
case 38400:
cflag |= B38400;
break;
case 57600:
cflag |= B57600;
break;
case 115200:
cflag |= B115200;
break;
case 9600:
default:
cflag |= B9600;
break;
}
tty->termios->c_cflag = cflag;
if (tty->driver->set_termios)
tty->driver->set_termios(tty, &old_termios);
unlock_kernel();
priv->io.speed = speed;
return 0;
}
/*
* Function irtty_set_dtr_rts (dev, dtr, rts)
*
* This function can be used by dongles etc. to set or reset the status
* of the dtr and rts lines
*/
static int irtty_set_dtr_rts(struct sir_dev *dev, int dtr, int rts)
{
struct sirtty_cb *priv = dev->priv;
int set = 0;
int clear = 0;
IRDA_ASSERT(priv != NULL, return -1;);
IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return -1;);
if (rts)
set |= TIOCM_RTS;
else
clear |= TIOCM_RTS;
if (dtr)
set |= TIOCM_DTR;
else
clear |= TIOCM_DTR;
/*
* We can't use ioctl() because it expects a non-null file structure,
* and we don't have that here.
* This function is not yet defined for all tty driver, so
* let's be careful... Jean II
*/
IRDA_ASSERT(priv->tty->driver->tiocmset != NULL, return -1;);
priv->tty->driver->tiocmset(priv->tty, NULL, set, clear);
return 0;
}
/* ------------------------------------------------------- */
/* called from sir_dev when there is more data to send
* context is either netdev->hard_xmit or some transmit-completion bh
* i.e. we are under spinlock here and must not sleep.
*/
static int irtty_do_write(struct sir_dev *dev, const unsigned char *ptr, size_t len)
{
struct sirtty_cb *priv = dev->priv;
struct tty_struct *tty;
int writelen;
IRDA_ASSERT(priv != NULL, return -1;);
IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return -1;);
tty = priv->tty;
if (!tty->driver->write)
return 0;
tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
if (tty->driver->write_room) {
writelen = tty->driver->write_room(tty);
if (writelen > len)
writelen = len;
}
else
writelen = len;
return tty->driver->write(tty, ptr, writelen);
}
/* ------------------------------------------------------- */
/* irda line discipline callbacks */
/*
* Function irtty_receive_buf( tty, cp, count)
*
* Handle the 'receiver data ready' interrupt. This function is called
* by the 'tty_io' module in the kernel when a block of IrDA data has
* been received, which can now be decapsulated and delivered for
* further processing
*
* calling context depends on underlying driver and tty->low_latency!
* for example (low_latency: 1 / 0):
* serial.c: uart-interrupt / softint
* usbserial: urb-complete-interrupt / softint
*/
static void irtty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
char *fp, int count)
{
struct sir_dev *dev;
struct sirtty_cb *priv = tty->disc_data;
int i;
IRDA_ASSERT(priv != NULL, return;);
IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return;);
if (unlikely(count==0)) /* yes, this happens */
return;
dev = priv->dev;
if (!dev) {
IRDA_WARNING("%s(), not ready yet!\n", __FUNCTION__);
return;
}
for (i = 0; i < count; i++) {
/*
* Characters received with a parity error, etc?
*/
if (fp && *fp++) {
IRDA_DEBUG(0, "Framing or parity error!\n");
sirdev_receive(dev, NULL, 0); /* notify sir_dev (updating stats) */
return;
}
}
sirdev_receive(dev, cp, count);
}
/*
* Function irtty_receive_room (tty)
*
* Used by the TTY to find out how much data we can receive at a time
*
*/
static int irtty_receive_room(struct tty_struct *tty)
{
struct sirtty_cb *priv = tty->disc_data;
IRDA_ASSERT(priv != NULL, return 0;);
IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return 0;);
return 65536; /* We can handle an infinite amount of data. :-) */
}
/*
* Function irtty_write_wakeup (tty)
*
* Called by the driver when there's room for more data. If we have
* more packets to send, we send them here.
*
*/
static void irtty_write_wakeup(struct tty_struct *tty)
{
struct sirtty_cb *priv = tty->disc_data;
IRDA_ASSERT(priv != NULL, return;);
IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return;);
tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
if (priv->dev)
sirdev_write_complete(priv->dev);
}
/* ------------------------------------------------------- */
/*
* Function irtty_stop_receiver (tty, stop)
*
*/
static inline void irtty_stop_receiver(struct tty_struct *tty, int stop)
{
struct termios old_termios;
int cflag;
lock_kernel();
old_termios = *(tty->termios);
cflag = tty->termios->c_cflag;
if (stop)
cflag &= ~CREAD;
else
cflag |= CREAD;
tty->termios->c_cflag = cflag;
if (tty->driver->set_termios)
tty->driver->set_termios(tty, &old_termios);
unlock_kernel();
}
/*****************************************************************/
/* serialize ldisc open/close with sir_dev */
static DECLARE_MUTEX(irtty_sem);
/* notifier from sir_dev when irda% device gets opened (ifup) */
static int irtty_start_dev(struct sir_dev *dev)
{
struct sirtty_cb *priv;
struct tty_struct *tty;
/* serialize with ldisc open/close */
down(&irtty_sem);
priv = dev->priv;
if (unlikely(!priv || priv->magic!=IRTTY_MAGIC)) {
up(&irtty_sem);
return -ESTALE;
}
tty = priv->tty;
if (tty->driver->start)
tty->driver->start(tty);
/* Make sure we can receive more data */
irtty_stop_receiver(tty, FALSE);
up(&irtty_sem);
return 0;
}
/* notifier from sir_dev when irda% device gets closed (ifdown) */
static int irtty_stop_dev(struct sir_dev *dev)
{
struct sirtty_cb *priv;
struct tty_struct *tty;
/* serialize with ldisc open/close */
down(&irtty_sem);
priv = dev->priv;
if (unlikely(!priv || priv->magic!=IRTTY_MAGIC)) {
up(&irtty_sem);
return -ESTALE;
}
tty = priv->tty;
/* Make sure we don't receive more data */
irtty_stop_receiver(tty, TRUE);
if (tty->driver->stop)
tty->driver->stop(tty);
up(&irtty_sem);
return 0;
}
/* ------------------------------------------------------- */
static struct sir_driver sir_tty_drv = {
.owner = THIS_MODULE,
.driver_name = "sir_tty",
.start_dev = irtty_start_dev,
.stop_dev = irtty_stop_dev,
.do_write = irtty_do_write,
.chars_in_buffer = irtty_chars_in_buffer,
.wait_until_sent = irtty_wait_until_sent,
.set_speed = irtty_change_speed,
.set_dtr_rts = irtty_set_dtr_rts,
};
/* ------------------------------------------------------- */
/*
* Function irtty_ioctl (tty, file, cmd, arg)
*
* The Swiss army knife of system calls :-)
*
*/
static int irtty_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
{
struct irtty_info { char name[6]; } info;
struct sir_dev *dev;
struct sirtty_cb *priv = tty->disc_data;
int err = 0;
IRDA_ASSERT(priv != NULL, return -ENODEV;);
IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return -EBADR;);
IRDA_DEBUG(3, "%s(cmd=0x%X)\n", __FUNCTION__, cmd);
dev = priv->dev;
IRDA_ASSERT(dev != NULL, return -1;);
switch (cmd) {
case TCGETS:
case TCGETA:
err = n_tty_ioctl(tty, file, cmd, arg);
break;
case IRTTY_IOCTDONGLE:
/* this call blocks for completion */
err = sirdev_set_dongle(dev, (IRDA_DONGLE) arg);
break;
case IRTTY_IOCGET:
IRDA_ASSERT(dev->netdev != NULL, return -1;);
memset(&info, 0, sizeof(info));
strncpy(info.name, dev->netdev->name, sizeof(info.name)-1);
if (copy_to_user((void __user *)arg, &info, sizeof(info)))
err = -EFAULT;
break;
default:
err = -ENOIOCTLCMD;
break;
}
return err;
}
/*
* Function irtty_open(tty)
*
* This function is called by the TTY module when the IrDA line
* discipline is called for. Because we are sure the tty line exists,
* we only have to link it to a free IrDA channel.
*/
static int irtty_open(struct tty_struct *tty)
{
struct sir_dev *dev;
struct sirtty_cb *priv;
int ret = 0;
/* Module stuff handled via irda_ldisc.owner - Jean II */
/* First make sure we're not already connected. */
if (tty->disc_data != NULL) {
priv = tty->disc_data;
if (priv && priv->magic == IRTTY_MAGIC) {
ret = -EEXIST;
goto out;
}
tty->disc_data = NULL; /* ### */
}
/* stop the underlying driver */
irtty_stop_receiver(tty, TRUE);
if (tty->driver->stop)
tty->driver->stop(tty);
if (tty->driver->flush_buffer)
tty->driver->flush_buffer(tty);
/* apply mtt override */
sir_tty_drv.qos_mtt_bits = qos_mtt_bits;
/* get a sir device instance for this driver */
dev = sirdev_get_instance(&sir_tty_drv, tty->name);
if (!dev) {
ret = -ENODEV;
goto out;
}
/* allocate private device info block */
priv = kmalloc(sizeof(*priv), GFP_KERNEL);
if (!priv)
goto out_put;
memset(priv, 0, sizeof(*priv));
priv->magic = IRTTY_MAGIC;
priv->tty = tty;
priv->dev = dev;
/* serialize with start_dev - in case we were racing with ifup */
down(&irtty_sem);
dev->priv = priv;
tty->disc_data = priv;
up(&irtty_sem);
IRDA_DEBUG(0, "%s - %s: irda line discipline opened\n", __FUNCTION__, tty->name);
return 0;
out_put:
sirdev_put_instance(dev);
out:
return ret;
}
/*
* Function irtty_close (tty)
*
* Close down a IrDA channel. This means flushing out any pending queues,
* and then restoring the TTY line discipline to what it was before it got
* hooked to IrDA (which usually is TTY again).
*/
static void irtty_close(struct tty_struct *tty)
{
struct sirtty_cb *priv = tty->disc_data;
IRDA_ASSERT(priv != NULL, return;);
IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return;);
/* Hm, with a dongle attached the dongle driver wants
* to close the dongle - which requires the use of
* some tty write and/or termios or ioctl operations.
* Are we allowed to call those when already requested
* to shutdown the ldisc?
* If not, we should somehow mark the dev being staled.
* Question remains, how to close the dongle in this case...
* For now let's assume we are granted to issue tty driver calls
* until we return here from the ldisc close. I'm just wondering
* how this behaves with hotpluggable serial hardware like
* rs232-pcmcia card or usb-serial...
*
* priv->tty = NULL?;
*/
/* we are dead now */
tty->disc_data = NULL;
sirdev_put_instance(priv->dev);
/* Stop tty */
irtty_stop_receiver(tty, TRUE);
tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
if (tty->driver->stop)
tty->driver->stop(tty);
kfree(priv);
IRDA_DEBUG(0, "%s - %s: irda line discipline closed\n", __FUNCTION__, tty->name);
}
/* ------------------------------------------------------- */
static struct tty_ldisc irda_ldisc = {
.magic = TTY_LDISC_MAGIC,
.name = "irda",
.flags = 0,
.open = irtty_open,
.close = irtty_close,
.read = NULL,
.write = NULL,
.ioctl = irtty_ioctl,
.poll = NULL,
.receive_buf = irtty_receive_buf,
.receive_room = irtty_receive_room,
.write_wakeup = irtty_write_wakeup,
.owner = THIS_MODULE,
};
/* ------------------------------------------------------- */
static int __init irtty_sir_init(void)
{
int err;
if ((err = tty_register_ldisc(N_IRDA, &irda_ldisc)) != 0)
IRDA_ERROR("IrDA: can't register line discipline (err = %d)\n",
err);
return err;
}
static void __exit irtty_sir_cleanup(void)
{
int err;
if ((err = tty_register_ldisc(N_IRDA, NULL))) {
IRDA_ERROR("%s(), can't unregister line discipline (err = %d)\n",
__FUNCTION__, err);
}
}
module_init(irtty_sir_init);
module_exit(irtty_sir_cleanup);
MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
MODULE_DESCRIPTION("IrDA TTY device driver");
MODULE_ALIAS_LDISC(N_IRDA);
MODULE_LICENSE("GPL");

34
drivers/net/irda/irtty-sir.h Arquivo normal
Ver arquivo

@@ -0,0 +1,34 @@
/*********************************************************************
*
* sir_tty.h: definitions for the irtty_sir client driver (former irtty)
*
* Copyright (c) 2002 Martin Diehl
*
* 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.
*
********************************************************************/
#ifndef IRTTYSIR_H
#define IRTTYSIR_H
#include <net/irda/irda.h>
#include <net/irda/irda_device.h> // chipio_t
#define IRTTY_IOC_MAGIC 'e'
#define IRTTY_IOCTDONGLE _IO(IRTTY_IOC_MAGIC, 1)
#define IRTTY_IOCGET _IOR(IRTTY_IOC_MAGIC, 2, struct irtty_info)
#define IRTTY_IOC_MAXNR 2
struct sirtty_cb {
magic_t magic;
struct sir_dev *dev;
struct tty_struct *tty;
chipio_t io; /* IrDA controller information */
};
#endif

209
drivers/net/irda/litelink-sir.c Arquivo normal
Ver arquivo

@@ -0,0 +1,209 @@
/*********************************************************************
*
* Filename: litelink.c
* Version: 1.1
* Description: Driver for the Parallax LiteLink dongle
* Status: Stable
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Fri May 7 12:50:33 1999
* Modified at: Fri Dec 17 09:14:23 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1999 Dag Brattli, All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* 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
*
********************************************************************/
/*
* Modified at: Thu Jan 15 2003
* Modified by: Eugene Crosser <crosser@average.org>
*
* Convert to "new" IRDA infrastructure for kernel 2.6
*/
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <net/irda/irda.h>
#include "sir-dev.h"
#define MIN_DELAY 25 /* 15 us, but wait a little more to be sure */
#define MAX_DELAY 10000 /* 1 ms */
static int litelink_open(struct sir_dev *dev);
static int litelink_close(struct sir_dev *dev);
static int litelink_change_speed(struct sir_dev *dev, unsigned speed);
static int litelink_reset(struct sir_dev *dev);
/* These are the baudrates supported - 9600 must be last one! */
static unsigned baud_rates[] = { 115200, 57600, 38400, 19200, 9600 };
static struct dongle_driver litelink = {
.owner = THIS_MODULE,
.driver_name = "Parallax LiteLink",
.type = IRDA_LITELINK_DONGLE,
.open = litelink_open,
.close = litelink_close,
.reset = litelink_reset,
.set_speed = litelink_change_speed,
};
static int __init litelink_sir_init(void)
{
return irda_register_dongle(&litelink);
}
static void __exit litelink_sir_cleanup(void)
{
irda_unregister_dongle(&litelink);
}
static int litelink_open(struct sir_dev *dev)
{
struct qos_info *qos = &dev->qos;
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
/* Power up dongle */
sirdev_set_dtr_rts(dev, TRUE, TRUE);
/* Set the speeds we can accept */
qos->baud_rate.bits &= IR_115200|IR_57600|IR_38400|IR_19200|IR_9600;
qos->min_turn_time.bits = 0x7f; /* Needs 0.01 ms */
irda_qos_bits_to_value(qos);
/* irda thread waits 50 msec for power settling */
return 0;
}
static int litelink_close(struct sir_dev *dev)
{
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
/* Power off dongle */
sirdev_set_dtr_rts(dev, FALSE, FALSE);
return 0;
}
/*
* Function litelink_change_speed (task)
*
* Change speed of the Litelink dongle. To cycle through the available
* baud rates, pulse RTS low for a few ms.
*/
static int litelink_change_speed(struct sir_dev *dev, unsigned speed)
{
int i;
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
/* dongle already reset by irda-thread - current speed (dongle and
* port) is the default speed (115200 for litelink!)
*/
/* Cycle through avaiable baudrates until we reach the correct one */
for (i = 0; baud_rates[i] != speed; i++) {
/* end-of-list reached due to invalid speed request */
if (baud_rates[i] == 9600)
break;
/* Set DTR, clear RTS */
sirdev_set_dtr_rts(dev, FALSE, TRUE);
/* Sleep a minimum of 15 us */
udelay(MIN_DELAY);
/* Set DTR, Set RTS */
sirdev_set_dtr_rts(dev, TRUE, TRUE);
/* Sleep a minimum of 15 us */
udelay(MIN_DELAY);
}
dev->speed = baud_rates[i];
/* invalid baudrate should not happen - but if, we return -EINVAL and
* the dongle configured for 9600 so the stack has a chance to recover
*/
return (dev->speed == speed) ? 0 : -EINVAL;
}
/*
* Function litelink_reset (task)
*
* Reset the Litelink type dongle.
*
*/
static int litelink_reset(struct sir_dev *dev)
{
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
/* probably the power-up can be dropped here, but with only
* 15 usec delay it's not worth the risk unless somebody with
* the hardware confirms it doesn't break anything...
*/
/* Power on dongle */
sirdev_set_dtr_rts(dev, TRUE, TRUE);
/* Sleep a minimum of 15 us */
udelay(MIN_DELAY);
/* Clear RTS to reset dongle */
sirdev_set_dtr_rts(dev, TRUE, FALSE);
/* Sleep a minimum of 15 us */
udelay(MIN_DELAY);
/* Go back to normal mode */
sirdev_set_dtr_rts(dev, TRUE, TRUE);
/* Sleep a minimum of 15 us */
udelay(MIN_DELAY);
/* This dongles speed defaults to 115200 bps */
dev->speed = 115200;
return 0;
}
MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
MODULE_DESCRIPTION("Parallax Litelink dongle driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("irda-dongle-5"); /* IRDA_LITELINK_DONGLE */
/*
* Function init_module (void)
*
* Initialize Litelink module
*
*/
module_init(litelink_sir_init);
/*
* Function cleanup_module (void)
*
* Cleanup Litelink module
*
*/
module_exit(litelink_sir_cleanup);

179
drivers/net/irda/litelink.c Arquivo normal
Ver arquivo

@@ -0,0 +1,179 @@
/*********************************************************************
*
* Filename: litelink.c
* Version: 1.1
* Description: Driver for the Parallax LiteLink dongle
* Status: Stable
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Fri May 7 12:50:33 1999
* Modified at: Fri Dec 17 09:14:23 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1999 Dag Brattli, All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
********************************************************************/
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/tty.h>
#include <linux/init.h>
#include <net/irda/irda.h>
#include <net/irda/irda_device.h>
#define MIN_DELAY 25 /* 15 us, but wait a little more to be sure */
#define MAX_DELAY 10000 /* 1 ms */
static void litelink_open(dongle_t *self, struct qos_info *qos);
static void litelink_close(dongle_t *self);
static int litelink_change_speed(struct irda_task *task);
static int litelink_reset(struct irda_task *task);
/* These are the baudrates supported */
static __u32 baud_rates[] = { 115200, 57600, 38400, 19200, 9600 };
static struct dongle_reg dongle = {
.type = IRDA_LITELINK_DONGLE,
.open = litelink_open,
.close = litelink_close,
.reset = litelink_reset,
.change_speed = litelink_change_speed,
.owner = THIS_MODULE,
};
static int __init litelink_init(void)
{
return irda_device_register_dongle(&dongle);
}
static void __exit litelink_cleanup(void)
{
irda_device_unregister_dongle(&dongle);
}
static void litelink_open(dongle_t *self, struct qos_info *qos)
{
qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
qos->min_turn_time.bits = 0x7f; /* Needs 0.01 ms */
}
static void litelink_close(dongle_t *self)
{
/* Power off dongle */
self->set_dtr_rts(self->dev, FALSE, FALSE);
}
/*
* Function litelink_change_speed (task)
*
* Change speed of the Litelink dongle. To cycle through the available
* baud rates, pulse RTS low for a few ms.
*/
static int litelink_change_speed(struct irda_task *task)
{
dongle_t *self = (dongle_t *) task->instance;
__u32 speed = (__u32) task->param;
int i;
/* Clear RTS to reset dongle */
self->set_dtr_rts(self->dev, TRUE, FALSE);
/* Sleep a minimum of 15 us */
udelay(MIN_DELAY);
/* Go back to normal mode */
self->set_dtr_rts(self->dev, TRUE, TRUE);
/* Sleep a minimum of 15 us */
udelay(MIN_DELAY);
/* Cycle through avaiable baudrates until we reach the correct one */
for (i=0; i<5 && baud_rates[i] != speed; i++) {
/* Set DTR, clear RTS */
self->set_dtr_rts(self->dev, FALSE, TRUE);
/* Sleep a minimum of 15 us */
udelay(MIN_DELAY);
/* Set DTR, Set RTS */
self->set_dtr_rts(self->dev, TRUE, TRUE);
/* Sleep a minimum of 15 us */
udelay(MIN_DELAY);
}
irda_task_next_state(task, IRDA_TASK_DONE);
return 0;
}
/*
* Function litelink_reset (task)
*
* Reset the Litelink type dongle.
*
*/
static int litelink_reset(struct irda_task *task)
{
dongle_t *self = (dongle_t *) task->instance;
/* Power on dongle */
self->set_dtr_rts(self->dev, TRUE, TRUE);
/* Sleep a minimum of 15 us */
udelay(MIN_DELAY);
/* Clear RTS to reset dongle */
self->set_dtr_rts(self->dev, TRUE, FALSE);
/* Sleep a minimum of 15 us */
udelay(MIN_DELAY);
/* Go back to normal mode */
self->set_dtr_rts(self->dev, TRUE, TRUE);
/* Sleep a minimum of 15 us */
udelay(MIN_DELAY);
/* This dongles speed defaults to 115200 bps */
self->speed = 115200;
irda_task_next_state(task, IRDA_TASK_DONE);
return 0;
}
MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
MODULE_DESCRIPTION("Parallax Litelink dongle driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("irda-dongle-5"); /* IRDA_LITELINK_DONGLE */
/*
* Function init_module (void)
*
* Initialize Litelink module
*
*/
module_init(litelink_init);
/*
* Function cleanup_module (void)
*
* Cleanup Litelink module
*
*/
module_exit(litelink_cleanup);

264
drivers/net/irda/ma600-sir.c Arquivo normal
Ver arquivo

@@ -0,0 +1,264 @@
/*********************************************************************
*
* Filename: ma600.c
* Version: 0.1
* Description: Implementation of the MA600 dongle
* Status: Experimental.
* Author: Leung <95Etwl@alumni.ee.ust.hk> http://www.engsvr.ust/~eetwl95
* Created at: Sat Jun 10 20:02:35 2000
* Modified at: Sat Aug 16 09:34:13 2003
* Modified by: Martin Diehl <mad@mdiehl.de> (modified for new sir_dev)
*
* Note: very thanks to Mr. Maru Wang <maru@mobileaction.com.tw> for providing
* information on the MA600 dongle
*
* Copyright (c) 2000 Leung, All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
********************************************************************/
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <net/irda/irda.h>
#include "sir-dev.h"
static int ma600_open(struct sir_dev *);
static int ma600_close(struct sir_dev *);
static int ma600_change_speed(struct sir_dev *, unsigned);
static int ma600_reset(struct sir_dev *);
/* control byte for MA600 */
#define MA600_9600 0x00
#define MA600_19200 0x01
#define MA600_38400 0x02
#define MA600_57600 0x03
#define MA600_115200 0x04
#define MA600_DEV_ID1 0x05
#define MA600_DEV_ID2 0x06
#define MA600_2400 0x08
static struct dongle_driver ma600 = {
.owner = THIS_MODULE,
.driver_name = "MA600",
.type = IRDA_MA600_DONGLE,
.open = ma600_open,
.close = ma600_close,
.reset = ma600_reset,
.set_speed = ma600_change_speed,
};
static int __init ma600_sir_init(void)
{
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
return irda_register_dongle(&ma600);
}
static void __exit ma600_sir_cleanup(void)
{
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
irda_unregister_dongle(&ma600);
}
/*
Power on:
(0) Clear RTS and DTR for 1 second
(1) Set RTS and DTR for 1 second
(2) 9600 bps now
Note: assume RTS, DTR are clear before
*/
static int ma600_open(struct sir_dev *dev)
{
struct qos_info *qos = &dev->qos;
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
sirdev_set_dtr_rts(dev, TRUE, TRUE);
/* Explicitly set the speeds we can accept */
qos->baud_rate.bits &= IR_2400|IR_9600|IR_19200|IR_38400
|IR_57600|IR_115200;
/* Hm, 0x01 means 10ms - for >= 1ms we would need 0x07 */
qos->min_turn_time.bits = 0x01; /* Needs at least 1 ms */
irda_qos_bits_to_value(qos);
/* irda thread waits 50 msec for power settling */
return 0;
}
static int ma600_close(struct sir_dev *dev)
{
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
/* Power off dongle */
sirdev_set_dtr_rts(dev, FALSE, FALSE);
return 0;
}
static __u8 get_control_byte(__u32 speed)
{
__u8 byte;
switch (speed) {
default:
case 115200:
byte = MA600_115200;
break;
case 57600:
byte = MA600_57600;
break;
case 38400:
byte = MA600_38400;
break;
case 19200:
byte = MA600_19200;
break;
case 9600:
byte = MA600_9600;
break;
case 2400:
byte = MA600_2400;
break;
}
return byte;
}
/*
* Function ma600_change_speed (dev, speed)
*
* Set the speed for the MA600 type dongle.
*
* The dongle has already been reset to a known state (dongle default)
* We cycle through speeds by pulsing RTS low and then high.
*/
/*
* Function ma600_change_speed (dev, speed)
*
* Set the speed for the MA600 type dongle.
*
* Algorithm
* 1. Reset (already done by irda thread state machine)
* 2. clear RTS, set DTR and wait for 1ms
* 3. send Control Byte to the MA600 through TXD to set new baud rate
* wait until the stop bit of Control Byte is sent (for 9600 baud rate,
* it takes about 10 msec)
* 4. set RTS, set DTR (return to NORMAL Operation)
* 5. wait at least 10 ms, new setting (baud rate, etc) takes effect here
* after
*/
/* total delays are only about 20ms - let's just sleep for now to
* avoid the state machine complexity before we get things working
*/
static int ma600_change_speed(struct sir_dev *dev, unsigned speed)
{
u8 byte;
IRDA_DEBUG(2, "%s(), speed=%d (was %d)\n", __FUNCTION__,
speed, dev->speed);
/* dongle already reset, dongle and port at default speed (9600) */
/* Set RTS low for 1 ms */
sirdev_set_dtr_rts(dev, TRUE, FALSE);
mdelay(1);
/* Write control byte */
byte = get_control_byte(speed);
sirdev_raw_write(dev, &byte, sizeof(byte));
/* Wait at least 10ms: fake wait_until_sent - 10 bits at 9600 baud*/
msleep(15); /* old ma600 uses 15ms */
#if 1
/* read-back of the control byte. ma600 is the first dongle driver
* which uses this so there might be some unidentified issues.
* Disable this in case of problems with readback.
*/
sirdev_raw_read(dev, &byte, sizeof(byte));
if (byte != get_control_byte(speed)) {
IRDA_WARNING("%s(): bad control byte read-back %02x != %02x\n",
__FUNCTION__, (unsigned) byte,
(unsigned) get_control_byte(speed));
return -1;
}
else
IRDA_DEBUG(2, "%s() control byte write read OK\n", __FUNCTION__);
#endif
/* Set DTR, Set RTS */
sirdev_set_dtr_rts(dev, TRUE, TRUE);
/* Wait at least 10ms */
msleep(10);
/* dongle is now switched to the new speed */
dev->speed = speed;
return 0;
}
/*
* Function ma600_reset (dev)
*
* This function resets the ma600 dongle.
*
* Algorithm:
* 0. DTR=0, RTS=1 and wait 10 ms
* 1. DTR=1, RTS=1 and wait 10 ms
* 2. 9600 bps now
*/
/* total delays are only about 20ms - let's just sleep for now to
* avoid the state machine complexity before we get things working
*/
int ma600_reset(struct sir_dev *dev)
{
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
/* Reset the dongle : set DTR low for 10 ms */
sirdev_set_dtr_rts(dev, FALSE, TRUE);
msleep(10);
/* Go back to normal mode */
sirdev_set_dtr_rts(dev, TRUE, TRUE);
msleep(10);
dev->speed = 9600; /* That's the dongle-default */
return 0;
}
MODULE_AUTHOR("Leung <95Etwl@alumni.ee.ust.hk> http://www.engsvr.ust/~eetwl95");
MODULE_DESCRIPTION("MA600 dongle driver version 0.1");
MODULE_LICENSE("GPL");
MODULE_ALIAS("irda-dongle-11"); /* IRDA_MA600_DONGLE */
module_init(ma600_sir_init);
module_exit(ma600_sir_cleanup);

354
drivers/net/irda/ma600.c Arquivo normal
Ver arquivo

@@ -0,0 +1,354 @@
/*********************************************************************
*
* Filename: ma600.c
* Version: 0.1
* Description: Implementation of the MA600 dongle
* Status: Experimental.
* Author: Leung <95Etwl@alumni.ee.ust.hk> http://www.engsvr.ust/~eetwl95
* Created at: Sat Jun 10 20:02:35 2000
* Modified at:
* Modified by:
*
* Note: very thanks to Mr. Maru Wang <maru@mobileaction.com.tw> for providing
* information on the MA600 dongle
*
* Copyright (c) 2000 Leung, All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
********************************************************************/
/* define this macro for release version */
//#define NDEBUG
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/tty.h>
#include <linux/init.h>
#include <net/irda/irda.h>
#include <net/irda/irda_device.h>
#ifndef NDEBUG
#undef IRDA_DEBUG
#define IRDA_DEBUG(n, args...) (printk(KERN_DEBUG args))
#undef ASSERT
#define ASSERT(expr, func) \
if(!(expr)) { \
printk( "Assertion failed! %s,%s,%s,line=%d\n",\
#expr,__FILE__,__FUNCTION__,__LINE__); \
func}
#endif
/* convert hex value to ascii hex */
static const char hexTbl[] = "0123456789ABCDEF";
static void ma600_open(dongle_t *self, struct qos_info *qos);
static void ma600_close(dongle_t *self);
static int ma600_change_speed(struct irda_task *task);
static int ma600_reset(struct irda_task *task);
/* control byte for MA600 */
#define MA600_9600 0x00
#define MA600_19200 0x01
#define MA600_38400 0x02
#define MA600_57600 0x03
#define MA600_115200 0x04
#define MA600_DEV_ID1 0x05
#define MA600_DEV_ID2 0x06
#define MA600_2400 0x08
static struct dongle_reg dongle = {
.type = IRDA_MA600_DONGLE,
.open = ma600_open,
.close = ma600_close,
.reset = ma600_reset,
.change_speed = ma600_change_speed,
.owner = THIS_MODULE,
};
static int __init ma600_init(void)
{
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
return irda_device_register_dongle(&dongle);
}
static void __exit ma600_cleanup(void)
{
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
irda_device_unregister_dongle(&dongle);
}
/*
Power on:
(0) Clear RTS and DTR for 1 second
(1) Set RTS and DTR for 1 second
(2) 9600 bps now
Note: assume RTS, DTR are clear before
*/
static void ma600_open(dongle_t *self, struct qos_info *qos)
{
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
qos->baud_rate.bits &= IR_2400|IR_9600|IR_19200|IR_38400
|IR_57600|IR_115200;
qos->min_turn_time.bits = 0x01; /* Needs at least 1 ms */
irda_qos_bits_to_value(qos);
//self->set_dtr_rts(self->dev, FALSE, FALSE);
// should wait 1 second
self->set_dtr_rts(self->dev, TRUE, TRUE);
// should wait 1 second
}
static void ma600_close(dongle_t *self)
{
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
/* Power off dongle */
self->set_dtr_rts(self->dev, FALSE, FALSE);
}
static __u8 get_control_byte(__u32 speed)
{
__u8 byte;
switch (speed) {
default:
case 115200:
byte = MA600_115200;
break;
case 57600:
byte = MA600_57600;
break;
case 38400:
byte = MA600_38400;
break;
case 19200:
byte = MA600_19200;
break;
case 9600:
byte = MA600_9600;
break;
case 2400:
byte = MA600_2400;
break;
}
return byte;
}
/*
* Function ma600_change_speed (dev, state, speed)
*
* Set the speed for the MA600 type dongle. Warning, this
* function must be called with a process context!
*
* Algorithm
* 1. Reset
* 2. clear RTS, set DTR and wait for 1ms
* 3. send Control Byte to the MA600 through TXD to set new baud rate
* wait until the stop bit of Control Byte is sent (for 9600 baud rate,
* it takes about 10 msec)
* 4. set RTS, set DTR (return to NORMAL Operation)
* 5. wait at least 10 ms, new setting (baud rate, etc) takes effect here
* after
*/
static int ma600_change_speed(struct irda_task *task)
{
dongle_t *self = (dongle_t *) task->instance;
__u32 speed = (__u32) task->param;
static __u8 byte;
__u8 byte_echo;
int ret = 0;
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
ASSERT(task != NULL, return -1;);
if (self->speed_task && self->speed_task != task) {
IRDA_DEBUG(0, "%s(), busy!\n", __FUNCTION__);
return msecs_to_jiffies(10);
} else {
self->speed_task = task;
}
switch (task->state) {
case IRDA_TASK_INIT:
case IRDA_TASK_CHILD_INIT:
/*
* Need to reset the dongle and go to 9600 bps before
* programming
*/
if (irda_task_execute(self, ma600_reset, NULL, task,
(void *) speed)) {
/* Dongle need more time to reset */
irda_task_next_state(task, IRDA_TASK_CHILD_WAIT);
/* give 1 second to finish */
ret = msecs_to_jiffies(1000);
} else {
irda_task_next_state(task, IRDA_TASK_CHILD_DONE);
}
break;
case IRDA_TASK_CHILD_WAIT:
IRDA_WARNING("%s(), resetting dongle timed out!\n",
__FUNCTION__);
ret = -1;
break;
case IRDA_TASK_CHILD_DONE:
/* Set DTR, Clear RTS */
self->set_dtr_rts(self->dev, TRUE, FALSE);
ret = msecs_to_jiffies(1); /* Sleep 1 ms */
irda_task_next_state(task, IRDA_TASK_WAIT);
break;
case IRDA_TASK_WAIT:
speed = (__u32) task->param;
byte = get_control_byte(speed);
/* Write control byte */
self->write(self->dev, &byte, sizeof(byte));
irda_task_next_state(task, IRDA_TASK_WAIT1);
/* Wait at least 10 ms */
ret = msecs_to_jiffies(15);
break;
case IRDA_TASK_WAIT1:
/* Read control byte echo */
self->read(self->dev, &byte_echo, sizeof(byte_echo));
if(byte != byte_echo) {
/* if control byte != echo, I don't know what to do */
printk(KERN_WARNING "%s() control byte written != read!\n", __FUNCTION__);
printk(KERN_WARNING "control byte = 0x%c%c\n",
hexTbl[(byte>>4)&0x0f], hexTbl[byte&0x0f]);
printk(KERN_WARNING "byte echo = 0x%c%c\n",
hexTbl[(byte_echo>>4) & 0x0f],
hexTbl[byte_echo & 0x0f]);
#ifndef NDEBUG
} else {
IRDA_DEBUG(2, "%s() control byte write read OK\n", __FUNCTION__);
#endif
}
/* Set DTR, Set RTS */
self->set_dtr_rts(self->dev, TRUE, TRUE);
irda_task_next_state(task, IRDA_TASK_WAIT2);
/* Wait at least 10 ms */
ret = msecs_to_jiffies(10);
break;
case IRDA_TASK_WAIT2:
irda_task_next_state(task, IRDA_TASK_DONE);
self->speed_task = NULL;
break;
default:
IRDA_ERROR("%s(), unknown state %d\n",
__FUNCTION__, task->state);
irda_task_next_state(task, IRDA_TASK_DONE);
self->speed_task = NULL;
ret = -1;
break;
}
return ret;
}
/*
* Function ma600_reset (driver)
*
* This function resets the ma600 dongle. Warning, this function
* must be called with a process context!!
*
* Algorithm:
* 0. DTR=0, RTS=1 and wait 10 ms
* 1. DTR=1, RTS=1 and wait 10 ms
* 2. 9600 bps now
*/
int ma600_reset(struct irda_task *task)
{
dongle_t *self = (dongle_t *) task->instance;
int ret = 0;
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
ASSERT(task != NULL, return -1;);
if (self->reset_task && self->reset_task != task) {
IRDA_DEBUG(0, "%s(), busy!\n", __FUNCTION__);
return msecs_to_jiffies(10);
} else
self->reset_task = task;
switch (task->state) {
case IRDA_TASK_INIT:
/* Clear DTR and Set RTS */
self->set_dtr_rts(self->dev, FALSE, TRUE);
irda_task_next_state(task, IRDA_TASK_WAIT1);
ret = msecs_to_jiffies(10); /* Sleep 10 ms */
break;
case IRDA_TASK_WAIT1:
/* Set DTR and RTS */
self->set_dtr_rts(self->dev, TRUE, TRUE);
irda_task_next_state(task, IRDA_TASK_WAIT2);
ret = msecs_to_jiffies(10); /* Sleep 10 ms */
break;
case IRDA_TASK_WAIT2:
irda_task_next_state(task, IRDA_TASK_DONE);
self->reset_task = NULL;
break;
default:
IRDA_ERROR("%s(), unknown state %d\n",
__FUNCTION__, task->state);
irda_task_next_state(task, IRDA_TASK_DONE);
self->reset_task = NULL;
ret = -1;
}
return ret;
}
MODULE_AUTHOR("Leung <95Etwl@alumni.ee.ust.hk> http://www.engsvr.ust/~eetwl95");
MODULE_DESCRIPTION("MA600 dongle driver version 0.1");
MODULE_LICENSE("GPL");
MODULE_ALIAS("irda-dongle-11"); /* IRDA_MA600_DONGLE */
/*
* Function init_module (void)
*
* Initialize MA600 module
*
*/
module_init(ma600_init);
/*
* Function cleanup_module (void)
*
* Cleanup MA600 module
*
*/
module_exit(ma600_cleanup);

230
drivers/net/irda/mcp2120-sir.c Arquivo normal
Ver arquivo

@@ -0,0 +1,230 @@
/*********************************************************************
*
*
* Filename: mcp2120.c
* Version: 1.0
* Description: Implementation for the MCP2120 (Microchip)
* Status: Experimental.
* Author: Felix Tang (tangf@eyetap.org)
* Created at: Sun Mar 31 19:32:12 EST 2002
* Based on code by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 2002 Felix Tang, 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.
*
********************************************************************/
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <net/irda/irda.h>
#include "sir-dev.h"
static int mcp2120_reset(struct sir_dev *dev);
static int mcp2120_open(struct sir_dev *dev);
static int mcp2120_close(struct sir_dev *dev);
static int mcp2120_change_speed(struct sir_dev *dev, unsigned speed);
#define MCP2120_9600 0x87
#define MCP2120_19200 0x8B
#define MCP2120_38400 0x85
#define MCP2120_57600 0x83
#define MCP2120_115200 0x81
#define MCP2120_COMMIT 0x11
static struct dongle_driver mcp2120 = {
.owner = THIS_MODULE,
.driver_name = "Microchip MCP2120",
.type = IRDA_MCP2120_DONGLE,
.open = mcp2120_open,
.close = mcp2120_close,
.reset = mcp2120_reset,
.set_speed = mcp2120_change_speed,
};
static int __init mcp2120_sir_init(void)
{
return irda_register_dongle(&mcp2120);
}
static void __exit mcp2120_sir_cleanup(void)
{
irda_unregister_dongle(&mcp2120);
}
static int mcp2120_open(struct sir_dev *dev)
{
struct qos_info *qos = &dev->qos;
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
/* seems no explicit power-on required here and reset switching it on anyway */
qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
qos->min_turn_time.bits = 0x01;
irda_qos_bits_to_value(qos);
return 0;
}
static int mcp2120_close(struct sir_dev *dev)
{
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
/* Power off dongle */
/* reset and inhibit mcp2120 */
sirdev_set_dtr_rts(dev, TRUE, TRUE);
// sirdev_set_dtr_rts(dev, FALSE, FALSE);
return 0;
}
/*
* Function mcp2120_change_speed (dev, speed)
*
* Set the speed for the MCP2120.
*
*/
#define MCP2120_STATE_WAIT_SPEED (SIRDEV_STATE_DONGLE_SPEED+1)
static int mcp2120_change_speed(struct sir_dev *dev, unsigned speed)
{
unsigned state = dev->fsm.substate;
unsigned delay = 0;
u8 control[2];
static int ret = 0;
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
switch (state) {
case SIRDEV_STATE_DONGLE_SPEED:
/* Set DTR to enter command mode */
sirdev_set_dtr_rts(dev, TRUE, FALSE);
udelay(500);
ret = 0;
switch (speed) {
default:
speed = 9600;
ret = -EINVAL;
/* fall through */
case 9600:
control[0] = MCP2120_9600;
//printk("mcp2120 9600\n");
break;
case 19200:
control[0] = MCP2120_19200;
//printk("mcp2120 19200\n");
break;
case 34800:
control[0] = MCP2120_38400;
//printk("mcp2120 38400\n");
break;
case 57600:
control[0] = MCP2120_57600;
//printk("mcp2120 57600\n");
break;
case 115200:
control[0] = MCP2120_115200;
//printk("mcp2120 115200\n");
break;
}
control[1] = MCP2120_COMMIT;
/* Write control bytes */
sirdev_raw_write(dev, control, 2);
dev->speed = speed;
state = MCP2120_STATE_WAIT_SPEED;
delay = 100;
//printk("mcp2120_change_speed: dongle_speed\n");
break;
case MCP2120_STATE_WAIT_SPEED:
/* Go back to normal mode */
sirdev_set_dtr_rts(dev, FALSE, FALSE);
//printk("mcp2120_change_speed: mcp_wait\n");
break;
default:
IRDA_ERROR("%s(), undefine state %d\n", __FUNCTION__, state);
ret = -EINVAL;
break;
}
dev->fsm.substate = state;
return (delay > 0) ? delay : ret;
}
/*
* Function mcp2120_reset (driver)
*
* This function resets the mcp2120 dongle.
*
* Info: -set RTS to reset mcp2120
* -set DTR to set mcp2120 software command mode
* -mcp2120 defaults to 9600 baud after reset
*
* Algorithm:
* 0. Set RTS to reset mcp2120.
* 1. Clear RTS and wait for device reset timer of 30 ms (max).
*
*/
#define MCP2120_STATE_WAIT1_RESET (SIRDEV_STATE_DONGLE_RESET+1)
#define MCP2120_STATE_WAIT2_RESET (SIRDEV_STATE_DONGLE_RESET+2)
static int mcp2120_reset(struct sir_dev *dev)
{
unsigned state = dev->fsm.substate;
unsigned delay = 0;
int ret = 0;
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
switch (state) {
case SIRDEV_STATE_DONGLE_RESET:
//printk("mcp2120_reset: dongle_reset\n");
/* Reset dongle by setting RTS*/
sirdev_set_dtr_rts(dev, TRUE, TRUE);
state = MCP2120_STATE_WAIT1_RESET;
delay = 50;
break;
case MCP2120_STATE_WAIT1_RESET:
//printk("mcp2120_reset: mcp2120_wait1\n");
/* clear RTS and wait for at least 30 ms. */
sirdev_set_dtr_rts(dev, FALSE, FALSE);
state = MCP2120_STATE_WAIT2_RESET;
delay = 50;
break;
case MCP2120_STATE_WAIT2_RESET:
//printk("mcp2120_reset mcp2120_wait2\n");
/* Go back to normal mode */
sirdev_set_dtr_rts(dev, FALSE, FALSE);
break;
default:
IRDA_ERROR("%s(), undefined state %d\n", __FUNCTION__, state);
ret = -EINVAL;
break;
}
dev->fsm.substate = state;
return (delay > 0) ? delay : ret;
}
MODULE_AUTHOR("Felix Tang <tangf@eyetap.org>");
MODULE_DESCRIPTION("Microchip MCP2120");
MODULE_LICENSE("GPL");
MODULE_ALIAS("irda-dongle-9"); /* IRDA_MCP2120_DONGLE */
module_init(mcp2120_sir_init);
module_exit(mcp2120_sir_cleanup);

240
drivers/net/irda/mcp2120.c Arquivo normal
Ver arquivo

@@ -0,0 +1,240 @@
/*********************************************************************
*
*
* Filename: mcp2120.c
* Version: 1.0
* Description: Implementation for the MCP2120 (Microchip)
* Status: Experimental.
* Author: Felix Tang (tangf@eyetap.org)
* Created at: Sun Mar 31 19:32:12 EST 2002
* Based on code by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 2002 Felix Tang, 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.
*
********************************************************************/
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/tty.h>
#include <linux/init.h>
#include <net/irda/irda.h>
#include <net/irda/irda_device.h>
static int mcp2120_reset(struct irda_task *task);
static void mcp2120_open(dongle_t *self, struct qos_info *qos);
static void mcp2120_close(dongle_t *self);
static int mcp2120_change_speed(struct irda_task *task);
#define MCP2120_9600 0x87
#define MCP2120_19200 0x8B
#define MCP2120_38400 0x85
#define MCP2120_57600 0x83
#define MCP2120_115200 0x81
#define MCP2120_COMMIT 0x11
static struct dongle_reg dongle = {
.type = IRDA_MCP2120_DONGLE,
.open = mcp2120_open,
.close = mcp2120_close,
.reset = mcp2120_reset,
.change_speed = mcp2120_change_speed,
.owner = THIS_MODULE,
};
static int __init mcp2120_init(void)
{
return irda_device_register_dongle(&dongle);
}
static void __exit mcp2120_cleanup(void)
{
irda_device_unregister_dongle(&dongle);
}
static void mcp2120_open(dongle_t *self, struct qos_info *qos)
{
qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
qos->min_turn_time.bits = 0x01;
}
static void mcp2120_close(dongle_t *self)
{
/* Power off dongle */
/* reset and inhibit mcp2120 */
self->set_dtr_rts(self->dev, TRUE, TRUE);
//self->set_dtr_rts(self->dev, FALSE, FALSE);
}
/*
* Function mcp2120_change_speed (dev, speed)
*
* Set the speed for the MCP2120.
*
*/
static int mcp2120_change_speed(struct irda_task *task)
{
dongle_t *self = (dongle_t *) task->instance;
__u32 speed = (__u32) task->param;
__u8 control[2];
int ret = 0;
self->speed_task = task;
switch (task->state) {
case IRDA_TASK_INIT:
/* Need to reset the dongle and go to 9600 bps before
programming */
//printk("Dmcp2120_change_speed irda_task_init\n");
if (irda_task_execute(self, mcp2120_reset, NULL, task,
(void *) speed))
{
/* Dongle need more time to reset */
irda_task_next_state(task, IRDA_TASK_CHILD_WAIT);
/* Give reset 1 sec to finish */
ret = msecs_to_jiffies(1000);
}
break;
case IRDA_TASK_CHILD_WAIT:
IRDA_WARNING("%s(), resetting dongle timed out!\n",
__FUNCTION__);
ret = -1;
break;
case IRDA_TASK_CHILD_DONE:
/* Set DTR to enter command mode */
self->set_dtr_rts(self->dev, TRUE, FALSE);
udelay(500);
switch (speed) {
case 9600:
default:
control[0] = MCP2120_9600;
//printk("mcp2120 9600\n");
break;
case 19200:
control[0] = MCP2120_19200;
//printk("mcp2120 19200\n");
break;
case 34800:
control[0] = MCP2120_38400;
//printk("mcp2120 38400\n");
break;
case 57600:
control[0] = MCP2120_57600;
//printk("mcp2120 57600\n");
break;
case 115200:
control[0] = MCP2120_115200;
//printk("mcp2120 115200\n");
break;
}
control[1] = MCP2120_COMMIT;
/* Write control bytes */
self->write(self->dev, control, 2);
irda_task_next_state(task, IRDA_TASK_WAIT);
ret = msecs_to_jiffies(100);
//printk("mcp2120_change_speed irda_child_done\n");
break;
case IRDA_TASK_WAIT:
/* Go back to normal mode */
self->set_dtr_rts(self->dev, FALSE, FALSE);
irda_task_next_state(task, IRDA_TASK_DONE);
self->speed_task = NULL;
//printk("mcp2120_change_speed irda_task_wait\n");
break;
default:
IRDA_ERROR("%s(), unknown state %d\n",
__FUNCTION__, task->state);
irda_task_next_state(task, IRDA_TASK_DONE);
self->speed_task = NULL;
ret = -1;
break;
}
return ret;
}
/*
* Function mcp2120_reset (driver)
*
* This function resets the mcp2120 dongle.
*
* Info: -set RTS to reset mcp2120
* -set DTR to set mcp2120 software command mode
* -mcp2120 defaults to 9600 baud after reset
*
* Algorithm:
* 0. Set RTS to reset mcp2120.
* 1. Clear RTS and wait for device reset timer of 30 ms (max).
*
*/
static int mcp2120_reset(struct irda_task *task)
{
dongle_t *self = (dongle_t *) task->instance;
int ret = 0;
self->reset_task = task;
switch (task->state) {
case IRDA_TASK_INIT:
//printk("mcp2120_reset irda_task_init\n");
/* Reset dongle by setting RTS*/
self->set_dtr_rts(self->dev, TRUE, TRUE);
irda_task_next_state(task, IRDA_TASK_WAIT1);
ret = msecs_to_jiffies(50);
break;
case IRDA_TASK_WAIT1:
//printk("mcp2120_reset irda_task_wait1\n");
/* clear RTS and wait for at least 30 ms. */
self->set_dtr_rts(self->dev, FALSE, FALSE);
irda_task_next_state(task, IRDA_TASK_WAIT2);
ret = msecs_to_jiffies(50);
break;
case IRDA_TASK_WAIT2:
//printk("mcp2120_reset irda_task_wait2\n");
/* Go back to normal mode */
self->set_dtr_rts(self->dev, FALSE, FALSE);
irda_task_next_state(task, IRDA_TASK_DONE);
self->reset_task = NULL;
break;
default:
IRDA_ERROR("%s(), unknown state %d\n",
__FUNCTION__, task->state);
irda_task_next_state(task, IRDA_TASK_DONE);
self->reset_task = NULL;
ret = -1;
break;
}
return ret;
}
MODULE_AUTHOR("Felix Tang <tangf@eyetap.org>");
MODULE_DESCRIPTION("Microchip MCP2120");
MODULE_LICENSE("GPL");
MODULE_ALIAS("irda-dongle-9"); /* IRDA_MCP2120_DONGLE */
/*
* Function init_module (void)
*
* Initialize MCP2120 module
*
*/
module_init(mcp2120_init);
/*
* Function cleanup_module (void)
*
* Cleanup MCP2120 module
*
*/
module_exit(mcp2120_cleanup);

2222
drivers/net/irda/nsc-ircc.c Arquivo normal

Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff

280
drivers/net/irda/nsc-ircc.h Arquivo normal
Ver arquivo

@@ -0,0 +1,280 @@
/*********************************************************************
*
* Filename: nsc-ircc.h
* Version:
* Description:
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Fri Nov 13 14:37:40 1998
* Modified at: Sun Jan 23 17:47:00 2000
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1998-2000 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
*
* 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<6D> admit liability nor
* provide warranty for any of this software. This material is
* provided "AS-IS" and at no charge.
*
********************************************************************/
#ifndef NSC_IRCC_H
#define NSC_IRCC_H
#include <linux/time.h>
#include <linux/spinlock.h>
#include <linux/pm.h>
#include <linux/types.h>
#include <asm/io.h>
/* DMA modes needed */
#define DMA_TX_MODE 0x08 /* Mem to I/O, ++, demand. */
#define DMA_RX_MODE 0x04 /* I/O to mem, ++, demand. */
/* Config registers for the '108 */
#define CFG_108_BAIC 0x00
#define CFG_108_CSRT 0x01
#define CFG_108_MCTL 0x02
/* Config registers for the '338 */
#define CFG_338_FER 0x00
#define CFG_338_FAR 0x01
#define CFG_338_PTR 0x02
#define CFG_338_PNP0 0x1b
#define CFG_338_PNP1 0x1c
#define CFG_338_PNP3 0x4f
/* Config registers for the '39x (in the logical device bank) */
#define CFG_39X_LDN 0x07 /* Logical device number (Super I/O bank) */
#define CFG_39X_SIOCF1 0x21 /* SuperI/O Config */
#define CFG_39X_ACT 0x30 /* Device activation */
#define CFG_39X_BASEH 0x60 /* Device base address (high bits) */
#define CFG_39X_BASEL 0x61 /* Device base address (low bits) */
#define CFG_39X_IRQNUM 0x70 /* Interrupt number & wake up enable */
#define CFG_39X_IRQSEL 0x71 /* Interrupt select (edge/level + polarity) */
#define CFG_39X_DMA0 0x74 /* DMA 0 configuration */
#define CFG_39X_DMA1 0x75 /* DMA 1 configuration */
#define CFG_39X_SPC 0xF0 /* Serial port configuration register */
/* Flags for configuration register CRF0 */
#define APEDCRC 0x02
#define ENBNKSEL 0x01
/* Set 0 */
#define TXD 0x00 /* Transmit data port */
#define RXD 0x00 /* Receive data port */
/* Register 1 */
#define IER 0x01 /* Interrupt Enable Register*/
#define IER_RXHDL_IE 0x01 /* Receiver high data level interrupt */
#define IER_TXLDL_IE 0x02 /* Transeiver low data level interrupt */
#define IER_LS_IE 0x04//* Link Status Interrupt */
#define IER_ETXURI 0x04 /* Tx underrun */
#define IER_DMA_IE 0x10 /* DMA finished interrupt */
#define IER_TXEMP_IE 0x20
#define IER_SFIF_IE 0x40 /* Frame status FIFO intr */
#define IER_TMR_IE 0x80 /* Timer event */
#define FCR 0x02 /* (write only) */
#define FCR_FIFO_EN 0x01 /* Enable FIFO's */
#define FCR_RXSR 0x02 /* Rx FIFO soft reset */
#define FCR_TXSR 0x04 /* Tx FIFO soft reset */
#define FCR_RXTH 0x40 /* Rx FIFO threshold (set to 16) */
#define FCR_TXTH 0x20 /* Tx FIFO threshold (set to 17) */
#define EIR 0x02 /* (read only) */
#define EIR_RXHDL_EV 0x01
#define EIR_TXLDL_EV 0x02
#define EIR_LS_EV 0x04
#define EIR_DMA_EV 0x10
#define EIR_TXEMP_EV 0x20
#define EIR_SFIF_EV 0x40
#define EIR_TMR_EV 0x80
#define LCR 0x03 /* Link control register */
#define LCR_WLS_8 0x03 /* 8 bits */
#define BSR 0x03 /* Bank select register */
#define BSR_BKSE 0x80
#define BANK0 LCR_WLS_8 /* Must make sure that we set 8N1 */
#define BANK1 0x80
#define BANK2 0xe0
#define BANK3 0xe4
#define BANK4 0xe8
#define BANK5 0xec
#define BANK6 0xf0
#define BANK7 0xf4
#define MCR 0x04 /* Mode Control Register */
#define MCR_MODE_MASK ~(0xd0)
#define MCR_UART 0x00
#define MCR_RESERVED 0x20
#define MCR_SHARP_IR 0x40
#define MCR_SIR 0x60
#define MCR_MIR 0x80
#define MCR_FIR 0xa0
#define MCR_CEIR 0xb0
#define MCR_IR_PLS 0x10
#define MCR_DMA_EN 0x04
#define MCR_EN_IRQ 0x08
#define MCR_TX_DFR 0x08
#define LSR 0x05 /* Link status register */
#define LSR_RXDA 0x01 /* Receiver data available */
#define LSR_TXRDY 0x20 /* Transmitter ready */
#define LSR_TXEMP 0x40 /* Transmitter empty */
#define ASCR 0x07 /* Auxillary Status and Control Register */
#define ASCR_RXF_TOUT 0x01 /* Rx FIFO timeout */
#define ASCR_FEND_INF 0x02 /* Frame end bytes in rx FIFO */
#define ASCR_S_EOT 0x04 /* Set end of transmission */
#define ASCT_RXBSY 0x20 /* Rx busy */
#define ASCR_TXUR 0x40 /* Transeiver underrun */
#define ASCR_CTE 0x80 /* Clear timer event */
/* Bank 2 */
#define BGDL 0x00 /* Baud Generator Divisor Port (Low Byte) */
#define BGDH 0x01 /* Baud Generator Divisor Port (High Byte) */
#define ECR1 0x02 /* Extended Control Register 1 */
#define ECR1_EXT_SL 0x01 /* Extended Mode Select */
#define ECR1_DMANF 0x02 /* DMA Fairness */
#define ECR1_DMATH 0x04 /* DMA Threshold */
#define ECR1_DMASWP 0x08 /* DMA Swap */
#define EXCR2 0x04
#define EXCR2_TFSIZ 0x01 /* Rx FIFO size = 32 */
#define EXCR2_RFSIZ 0x04 /* Tx FIFO size = 32 */
#define TXFLV 0x06 /* Tx FIFO level */
#define RXFLV 0x07 /* Rx FIFO level */
/* Bank 3 */
#define MID 0x00
/* Bank 4 */
#define TMRL 0x00 /* Timer low byte */
#define TMRH 0x01 /* Timer high byte */
#define IRCR1 0x02 /* Infrared control register 1 */
#define IRCR1_TMR_EN 0x01 /* Timer enable */
#define TFRLL 0x04
#define TFRLH 0x05
#define RFRLL 0x06
#define RFRLH 0x07
/* Bank 5 */
#define IRCR2 0x04 /* Infrared control register 2 */
#define IRCR2_MDRS 0x04 /* MIR data rate select */
#define IRCR2_FEND_MD 0x20 /* */
#define FRM_ST 0x05 /* Frame status FIFO */
#define FRM_ST_VLD 0x80 /* Frame status FIFO data valid */
#define FRM_ST_ERR_MSK 0x5f
#define FRM_ST_LOST_FR 0x40 /* Frame lost */
#define FRM_ST_MAX_LEN 0x10 /* Max frame len exceeded */
#define FRM_ST_PHY_ERR 0x08 /* Physical layer error */
#define FRM_ST_BAD_CRC 0x04
#define FRM_ST_OVR1 0x02 /* Rx FIFO overrun */
#define FRM_ST_OVR2 0x01 /* Frame status FIFO overrun */
#define RFLFL 0x06
#define RFLFH 0x07
/* Bank 6 */
#define IR_CFG2 0x00
#define IR_CFG2_DIS_CRC 0x02
/* Bank 7 */
#define IRM_CR 0x07 /* Infrared module control register */
#define IRM_CR_IRX_MSL 0x40
#define IRM_CR_AF_MNT 0x80 /* Automatic format */
/* NSC chip information */
struct nsc_chip {
char *name; /* Name of chipset */
int cfg[3]; /* Config registers */
u_int8_t cid_index; /* Chip identification index reg */
u_int8_t cid_value; /* Chip identification expected value */
u_int8_t cid_mask; /* Chip identification revision mask */
/* Functions for probing and initializing the specific chip */
int (*probe)(struct nsc_chip *chip, chipio_t *info);
int (*init)(struct nsc_chip *chip, chipio_t *info);
};
typedef struct nsc_chip nsc_chip_t;
/* For storing entries in the status FIFO */
struct st_fifo_entry {
int status;
int len;
};
#define MAX_TX_WINDOW 7
#define MAX_RX_WINDOW 7
struct st_fifo {
struct st_fifo_entry entries[MAX_RX_WINDOW];
int pending_bytes;
int head;
int tail;
int len;
};
struct frame_cb {
void *start; /* Start of frame in DMA mem */
int len; /* Lenght of frame in DMA mem */
};
struct tx_fifo {
struct frame_cb queue[MAX_TX_WINDOW]; /* Info about frames in queue */
int ptr; /* Currently being sent */
int len; /* Lenght of queue */
int free; /* Next free slot */
void *tail; /* Next free start in DMA mem */
};
/* Private data for each instance */
struct nsc_ircc_cb {
struct st_fifo st_fifo; /* Info about received frames */
struct tx_fifo tx_fifo; /* Info about frames to be transmitted */
struct net_device *netdev; /* Yes! we are some kind of netdevice */
struct net_device_stats stats;
struct irlap_cb *irlap; /* The link layer we are binded to */
struct qos_info qos; /* QoS capabilities for this device */
chipio_t io; /* IrDA controller information */
iobuff_t tx_buff; /* Transmit buffer */
iobuff_t rx_buff; /* Receive buffer */
dma_addr_t tx_buff_dma;
dma_addr_t rx_buff_dma;
__u8 ier; /* Interrupt enable register */
struct timeval stamp;
struct timeval now;
spinlock_t lock; /* For serializing operations */
__u32 new_speed;
int index; /* Instance index */
struct pm_dev *dev;
};
static inline void switch_bank(int iobase, int bank)
{
outb(bank, iobase+BSR);
}
#endif /* NSC_IRCC_H */

Ver arquivo

@@ -0,0 +1,156 @@
/*********************************************************************
*
* Filename: old_belkin.c
* Version: 1.1
* Description: Driver for the Belkin (old) SmartBeam dongle
* Status: Experimental...
* Author: Jean Tourrilhes <jt@hpl.hp.com>
* Created at: 22/11/99
* Modified at: Fri Dec 17 09:13:32 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1999 Jean Tourrilhes, All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
********************************************************************/
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <net/irda/irda.h>
// #include <net/irda/irda_device.h>
#include "sir-dev.h"
/*
* Belkin is selling a dongle called the SmartBeam.
* In fact, there is two hardware version of this dongle, of course with
* the same name and looking the exactly same (grrr...).
* I guess that I've got the old one, because inside I don't have
* a jumper for IrDA/ASK...
*
* As far as I can make it from info on their web site, the old dongle
* support only 9600 b/s, which make our life much simpler as far as
* the driver is concerned, but you might not like it very much ;-)
* The new SmartBeam does 115 kb/s, and I've not tested it...
*
* Belkin claim that the correct driver for the old dongle (in Windows)
* is the generic Parallax 9500a driver, but the Linux LiteLink driver
* fails for me (probably because Linux-IrDA doesn't rate fallback),
* so I created this really dumb driver...
*
* In fact, this driver doesn't do much. The only thing it does is to
* prevent Linux-IrDA to use any other speed than 9600 b/s ;-) This
* driver is called "old_belkin" so that when the new SmartBeam is supported
* its driver can be called "belkin" instead of "new_belkin".
*
* Note : this driver was written without any info/help from Belkin,
* so a lot of info here might be totally wrong. Blame me ;-)
*/
static int old_belkin_open(struct sir_dev *dev);
static int old_belkin_close(struct sir_dev *dev);
static int old_belkin_change_speed(struct sir_dev *dev, unsigned speed);
static int old_belkin_reset(struct sir_dev *dev);
static struct dongle_driver old_belkin = {
.owner = THIS_MODULE,
.driver_name = "Old Belkin SmartBeam",
.type = IRDA_OLD_BELKIN_DONGLE,
.open = old_belkin_open,
.close = old_belkin_close,
.reset = old_belkin_reset,
.set_speed = old_belkin_change_speed,
};
static int __init old_belkin_sir_init(void)
{
return irda_register_dongle(&old_belkin);
}
static void __exit old_belkin_sir_cleanup(void)
{
irda_unregister_dongle(&old_belkin);
}
static int old_belkin_open(struct sir_dev *dev)
{
struct qos_info *qos = &dev->qos;
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
/* Power on dongle */
sirdev_set_dtr_rts(dev, TRUE, TRUE);
/* Not too fast, please... */
qos->baud_rate.bits &= IR_9600;
/* Needs at least 10 ms (totally wild guess, can do probably better) */
qos->min_turn_time.bits = 0x01;
irda_qos_bits_to_value(qos);
/* irda thread waits 50 msec for power settling */
return 0;
}
static int old_belkin_close(struct sir_dev *dev)
{
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
/* Power off dongle */
sirdev_set_dtr_rts(dev, FALSE, FALSE);
return 0;
}
/*
* Function old_belkin_change_speed (task)
*
* With only one speed available, not much to do...
*/
static int old_belkin_change_speed(struct sir_dev *dev, unsigned speed)
{
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
dev->speed = 9600;
return (speed==dev->speed) ? 0 : -EINVAL;
}
/*
* Function old_belkin_reset (task)
*
* Reset the Old-Belkin type dongle.
*
*/
static int old_belkin_reset(struct sir_dev *dev)
{
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
/* This dongles speed "defaults" to 9600 bps ;-) */
dev->speed = 9600;
return 0;
}
MODULE_AUTHOR("Jean Tourrilhes <jt@hpl.hp.com>");
MODULE_DESCRIPTION("Belkin (old) SmartBeam dongle driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("irda-dongle-7"); /* IRDA_OLD_BELKIN_DONGLE */
module_init(old_belkin_sir_init);
module_exit(old_belkin_sir_cleanup);

164
drivers/net/irda/old_belkin.c Arquivo normal
Ver arquivo

@@ -0,0 +1,164 @@
/*********************************************************************
*
* Filename: old_belkin.c
* Version: 1.1
* Description: Driver for the Belkin (old) SmartBeam dongle
* Status: Experimental...
* Author: Jean Tourrilhes <jt@hpl.hp.com>
* Created at: 22/11/99
* Modified at: Fri Dec 17 09:13:32 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1999 Jean Tourrilhes, All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
********************************************************************/
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/tty.h>
#include <linux/init.h>
#include <net/irda/irda.h>
#include <net/irda/irda_device.h>
/*
* Belkin is selling a dongle called the SmartBeam.
* In fact, there is two hardware version of this dongle, of course with
* the same name and looking the exactly same (grrr...).
* I guess that I've got the old one, because inside I don't have
* a jumper for IrDA/ASK...
*
* As far as I can make it from info on their web site, the old dongle
* support only 9600 b/s, which make our life much simpler as far as
* the driver is concerned, but you might not like it very much ;-)
* The new SmartBeam does 115 kb/s, and I've not tested it...
*
* Belkin claim that the correct driver for the old dongle (in Windows)
* is the generic Parallax 9500a driver, but the Linux LiteLink driver
* fails for me (probably because Linux-IrDA doesn't rate fallback),
* so I created this really dumb driver...
*
* In fact, this driver doesn't do much. The only thing it does is to
* prevent Linux-IrDA to use any other speed than 9600 b/s ;-) This
* driver is called "old_belkin" so that when the new SmartBeam is supported
* its driver can be called "belkin" instead of "new_belkin".
*
* Note : this driver was written without any info/help from Belkin,
* so a lot of info here might be totally wrong. Blame me ;-)
*/
/* Let's guess */
#define MIN_DELAY 25 /* 15 us, but wait a little more to be sure */
static void old_belkin_open(dongle_t *self, struct qos_info *qos);
static void old_belkin_close(dongle_t *self);
static int old_belkin_change_speed(struct irda_task *task);
static int old_belkin_reset(struct irda_task *task);
/* These are the baudrates supported */
/* static __u32 baud_rates[] = { 9600 }; */
static struct dongle_reg dongle = {
.type = IRDA_OLD_BELKIN_DONGLE,
.open = old_belkin_open,
.close = old_belkin_close,
.reset = old_belkin_reset,
.change_speed = old_belkin_change_speed,
.owner = THIS_MODULE,
};
static int __init old_belkin_init(void)
{
return irda_device_register_dongle(&dongle);
}
static void __exit old_belkin_cleanup(void)
{
irda_device_unregister_dongle(&dongle);
}
static void old_belkin_open(dongle_t *self, struct qos_info *qos)
{
/* Not too fast, please... */
qos->baud_rate.bits &= IR_9600;
/* Needs at least 10 ms (totally wild guess, can do probably better) */
qos->min_turn_time.bits = 0x01;
}
static void old_belkin_close(dongle_t *self)
{
/* Power off dongle */
self->set_dtr_rts(self->dev, FALSE, FALSE);
}
/*
* Function old_belkin_change_speed (task)
*
* With only one speed available, not much to do...
*/
static int old_belkin_change_speed(struct irda_task *task)
{
irda_task_next_state(task, IRDA_TASK_DONE);
return 0;
}
/*
* Function old_belkin_reset (task)
*
* Reset the Old-Belkin type dongle.
*
*/
static int old_belkin_reset(struct irda_task *task)
{
dongle_t *self = (dongle_t *) task->instance;
/* Power on dongle */
self->set_dtr_rts(self->dev, TRUE, TRUE);
/* Sleep a minimum of 15 us */
udelay(MIN_DELAY);
/* This dongles speed "defaults" to 9600 bps ;-) */
self->speed = 9600;
irda_task_next_state(task, IRDA_TASK_DONE);
return 0;
}
MODULE_AUTHOR("Jean Tourrilhes <jt@hpl.hp.com>");
MODULE_DESCRIPTION("Belkin (old) SmartBeam dongle driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("irda-dongle-7"); /* IRDA_OLD_BELKIN_DONGLE */
/*
* Function init_module (void)
*
* Initialize Old-Belkin module
*
*/
module_init(old_belkin_init);
/*
* Function cleanup_module (void)
*
* Cleanup Old-Belkin module
*
*/
module_exit(old_belkin_cleanup);

1045
drivers/net/irda/sa1100_ir.c Arquivo normal

Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff

202
drivers/net/irda/sir-dev.h Arquivo normal
Ver arquivo

@@ -0,0 +1,202 @@
/*********************************************************************
*
* sir.h: include file for irda-sir device abstraction layer
*
* Copyright (c) 2002 Martin Diehl
*
* 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.
*
********************************************************************/
#ifndef IRDA_SIR_H
#define IRDA_SIR_H
#include <linux/netdevice.h>
#include <net/irda/irda.h>
#include <net/irda/irda_device.h> // iobuff_t
/* FIXME: unify irda_request with sir_fsm! */
struct irda_request {
struct list_head lh_request;
unsigned long pending;
void (*func)(void *);
void *data;
struct timer_list timer;
};
struct sir_fsm {
struct semaphore sem;
struct irda_request rq;
unsigned state, substate;
int param;
int result;
};
#define SIRDEV_STATE_WAIT_TX_COMPLETE 0x0100
/* substates for wait_tx_complete */
#define SIRDEV_STATE_WAIT_XMIT 0x0101
#define SIRDEV_STATE_WAIT_UNTIL_SENT 0x0102
#define SIRDEV_STATE_TX_DONE 0x0103
#define SIRDEV_STATE_DONGLE_OPEN 0x0300
/* 0x0301-0x03ff reserved for individual dongle substates */
#define SIRDEV_STATE_DONGLE_CLOSE 0x0400
/* 0x0401-0x04ff reserved for individual dongle substates */
#define SIRDEV_STATE_SET_DTR_RTS 0x0500
#define SIRDEV_STATE_SET_SPEED 0x0700
#define SIRDEV_STATE_DONGLE_CHECK 0x0800
#define SIRDEV_STATE_DONGLE_RESET 0x0900
/* 0x0901-0x09ff reserved for individual dongle substates */
#define SIRDEV_STATE_DONGLE_SPEED 0x0a00
/* 0x0a01-0x0aff reserved for individual dongle substates */
#define SIRDEV_STATE_PORT_SPEED 0x0b00
#define SIRDEV_STATE_DONE 0x0c00
#define SIRDEV_STATE_ERROR 0x0d00
#define SIRDEV_STATE_COMPLETE 0x0e00
#define SIRDEV_STATE_DEAD 0xffff
struct sir_dev;
struct dongle_driver {
struct module *owner;
const char *driver_name;
IRDA_DONGLE type;
int (*open)(struct sir_dev *dev);
int (*close)(struct sir_dev *dev);
int (*reset)(struct sir_dev *dev);
int (*set_speed)(struct sir_dev *dev, unsigned speed);
struct list_head dongle_list;
};
struct sir_driver {
struct module *owner;
const char *driver_name;
int qos_mtt_bits;
int (*chars_in_buffer)(struct sir_dev *dev);
void (*wait_until_sent)(struct sir_dev *dev);
int (*set_speed)(struct sir_dev *dev, unsigned speed);
int (*set_dtr_rts)(struct sir_dev *dev, int dtr, int rts);
int (*do_write)(struct sir_dev *dev, const unsigned char *ptr, size_t len);
int (*start_dev)(struct sir_dev *dev);
int (*stop_dev)(struct sir_dev *dev);
};
/* exported */
extern int irda_register_dongle(struct dongle_driver *new);
extern int irda_unregister_dongle(struct dongle_driver *drv);
extern struct sir_dev * sirdev_get_instance(const struct sir_driver *drv, const char *name);
extern int sirdev_put_instance(struct sir_dev *self);
extern int sirdev_set_dongle(struct sir_dev *dev, IRDA_DONGLE type);
extern void sirdev_write_complete(struct sir_dev *dev);
extern int sirdev_receive(struct sir_dev *dev, const unsigned char *cp, size_t count);
/* low level helpers for SIR device/dongle setup */
extern int sirdev_raw_write(struct sir_dev *dev, const char *buf, int len);
extern int sirdev_raw_read(struct sir_dev *dev, char *buf, int len);
extern int sirdev_set_dtr_rts(struct sir_dev *dev, int dtr, int rts);
/* not exported */
extern int sirdev_get_dongle(struct sir_dev *self, IRDA_DONGLE type);
extern int sirdev_put_dongle(struct sir_dev *self);
extern void sirdev_enable_rx(struct sir_dev *dev);
extern int sirdev_schedule_request(struct sir_dev *dev, int state, unsigned param);
extern int __init irda_thread_create(void);
extern void __exit irda_thread_join(void);
/* inline helpers */
static inline int sirdev_schedule_speed(struct sir_dev *dev, unsigned speed)
{
return sirdev_schedule_request(dev, SIRDEV_STATE_SET_SPEED, speed);
}
static inline int sirdev_schedule_dongle_open(struct sir_dev *dev, int dongle_id)
{
return sirdev_schedule_request(dev, SIRDEV_STATE_DONGLE_OPEN, dongle_id);
}
static inline int sirdev_schedule_dongle_close(struct sir_dev *dev)
{
return sirdev_schedule_request(dev, SIRDEV_STATE_DONGLE_CLOSE, 0);
}
static inline int sirdev_schedule_dtr_rts(struct sir_dev *dev, int dtr, int rts)
{
int dtrrts;
dtrrts = ((dtr) ? 0x02 : 0x00) | ((rts) ? 0x01 : 0x00);
return sirdev_schedule_request(dev, SIRDEV_STATE_SET_DTR_RTS, dtrrts);
}
#if 0
static inline int sirdev_schedule_mode(struct sir_dev *dev, int mode)
{
return sirdev_schedule_request(dev, SIRDEV_STATE_SET_MODE, mode);
}
#endif
struct sir_dev {
struct net_device *netdev;
struct net_device_stats stats;
struct irlap_cb *irlap;
struct qos_info qos;
char hwname[32];
struct sir_fsm fsm;
atomic_t enable_rx;
int raw_tx;
spinlock_t tx_lock;
u32 new_speed;
u32 flags;
unsigned speed;
iobuff_t tx_buff; /* Transmit buffer */
iobuff_t rx_buff; /* Receive buffer */
struct sk_buff *tx_skb;
const struct dongle_driver * dongle_drv;
const struct sir_driver * drv;
void *priv;
};
#endif /* IRDA_SIR_H */

56
drivers/net/irda/sir_core.c Arquivo normal
Ver arquivo

@@ -0,0 +1,56 @@
/*********************************************************************
*
* sir_core.c: module core for irda-sir abstraction layer
*
* Copyright (c) 2002 Martin Diehl
*
* 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.
*
********************************************************************/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <net/irda/irda.h>
#include "sir-dev.h"
/***************************************************************************/
MODULE_AUTHOR("Martin Diehl <info@mdiehl.de>");
MODULE_DESCRIPTION("IrDA SIR core");
MODULE_LICENSE("GPL");
/***************************************************************************/
EXPORT_SYMBOL(irda_register_dongle);
EXPORT_SYMBOL(irda_unregister_dongle);
EXPORT_SYMBOL(sirdev_get_instance);
EXPORT_SYMBOL(sirdev_put_instance);
EXPORT_SYMBOL(sirdev_set_dongle);
EXPORT_SYMBOL(sirdev_write_complete);
EXPORT_SYMBOL(sirdev_receive);
EXPORT_SYMBOL(sirdev_raw_write);
EXPORT_SYMBOL(sirdev_raw_read);
EXPORT_SYMBOL(sirdev_set_dtr_rts);
static int __init sir_core_init(void)
{
return irda_thread_create();
}
static void __exit sir_core_exit(void)
{
irda_thread_join();
}
module_init(sir_core_init);
module_exit(sir_core_exit);

677
drivers/net/irda/sir_dev.c Arquivo normal
Ver arquivo

@@ -0,0 +1,677 @@
/*********************************************************************
*
* sir_dev.c: irda sir network device
*
* Copyright (c) 2002 Martin Diehl
*
* 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.
*
********************************************************************/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/smp_lock.h>
#include <linux/delay.h>
#include <net/irda/irda.h>
#include <net/irda/wrapper.h>
#include <net/irda/irda_device.h>
#include "sir-dev.h"
/***************************************************************************/
void sirdev_enable_rx(struct sir_dev *dev)
{
if (unlikely(atomic_read(&dev->enable_rx)))
return;
/* flush rx-buffer - should also help in case of problems with echo cancelation */
dev->rx_buff.data = dev->rx_buff.head;
dev->rx_buff.len = 0;
dev->rx_buff.in_frame = FALSE;
dev->rx_buff.state = OUTSIDE_FRAME;
atomic_set(&dev->enable_rx, 1);
}
static int sirdev_is_receiving(struct sir_dev *dev)
{
if (!atomic_read(&dev->enable_rx))
return 0;
return (dev->rx_buff.state != OUTSIDE_FRAME);
}
int sirdev_set_dongle(struct sir_dev *dev, IRDA_DONGLE type)
{
int err;
IRDA_DEBUG(3, "%s : requesting dongle %d.\n", __FUNCTION__, type);
err = sirdev_schedule_dongle_open(dev, type);
if (unlikely(err))
return err;
down(&dev->fsm.sem); /* block until config change completed */
err = dev->fsm.result;
up(&dev->fsm.sem);
return err;
}
/* used by dongle drivers for dongle programming */
int sirdev_raw_write(struct sir_dev *dev, const char *buf, int len)
{
unsigned long flags;
int ret;
if (unlikely(len > dev->tx_buff.truesize))
return -ENOSPC;
spin_lock_irqsave(&dev->tx_lock, flags); /* serialize with other tx operations */
while (dev->tx_buff.len > 0) { /* wait until tx idle */
spin_unlock_irqrestore(&dev->tx_lock, flags);
msleep(10);
spin_lock_irqsave(&dev->tx_lock, flags);
}
dev->tx_buff.data = dev->tx_buff.head;
memcpy(dev->tx_buff.data, buf, len);
dev->tx_buff.len = len;
ret = dev->drv->do_write(dev, dev->tx_buff.data, dev->tx_buff.len);
if (ret > 0) {
IRDA_DEBUG(3, "%s(), raw-tx started\n", __FUNCTION__);
dev->tx_buff.data += ret;
dev->tx_buff.len -= ret;
dev->raw_tx = 1;
ret = len; /* all data is going to be sent */
}
spin_unlock_irqrestore(&dev->tx_lock, flags);
return ret;
}
/* seems some dongle drivers may need this */
int sirdev_raw_read(struct sir_dev *dev, char *buf, int len)
{
int count;
if (atomic_read(&dev->enable_rx))
return -EIO; /* fail if we expect irda-frames */
count = (len < dev->rx_buff.len) ? len : dev->rx_buff.len;
if (count > 0) {
memcpy(buf, dev->rx_buff.data, count);
dev->rx_buff.data += count;
dev->rx_buff.len -= count;
}
/* remaining stuff gets flushed when re-enabling normal rx */
return count;
}
int sirdev_set_dtr_rts(struct sir_dev *dev, int dtr, int rts)
{
int ret = -ENXIO;
if (dev->drv->set_dtr_rts != 0)
ret = dev->drv->set_dtr_rts(dev, dtr, rts);
return ret;
}
/**********************************************************************/
/* called from client driver - likely with bh-context - to indicate
* it made some progress with transmission. Hence we send the next
* chunk, if any, or complete the skb otherwise
*/
void sirdev_write_complete(struct sir_dev *dev)
{
unsigned long flags;
struct sk_buff *skb;
int actual = 0;
int err;
spin_lock_irqsave(&dev->tx_lock, flags);
IRDA_DEBUG(3, "%s() - dev->tx_buff.len = %d\n",
__FUNCTION__, dev->tx_buff.len);
if (likely(dev->tx_buff.len > 0)) {
/* Write data left in transmit buffer */
actual = dev->drv->do_write(dev, dev->tx_buff.data, dev->tx_buff.len);
if (likely(actual>0)) {
dev->tx_buff.data += actual;
dev->tx_buff.len -= actual;
}
else if (unlikely(actual<0)) {
/* could be dropped later when we have tx_timeout to recover */
IRDA_ERROR("%s: drv->do_write failed (%d)\n",
__FUNCTION__, actual);
if ((skb=dev->tx_skb) != NULL) {
dev->tx_skb = NULL;
dev_kfree_skb_any(skb);
dev->stats.tx_errors++;
dev->stats.tx_dropped++;
}
dev->tx_buff.len = 0;
}
if (dev->tx_buff.len > 0)
goto done; /* more data to send later */
}
if (unlikely(dev->raw_tx != 0)) {
/* in raw mode we are just done now after the buffer was sent
* completely. Since this was requested by some dongle driver
* running under the control of the irda-thread we must take
* care here not to re-enable the queue. The queue will be
* restarted when the irda-thread has completed the request.
*/
IRDA_DEBUG(3, "%s(), raw-tx done\n", __FUNCTION__);
dev->raw_tx = 0;
goto done; /* no post-frame handling in raw mode */
}
/* we have finished now sending this skb.
* update statistics and free the skb.
* finally we check and trigger a pending speed change, if any.
* if not we switch to rx mode and wake the queue for further
* packets.
* note the scheduled speed request blocks until the lower
* client driver and the corresponding hardware has really
* finished sending all data (xmit fifo drained f.e.)
* before the speed change gets finally done and the queue
* re-activated.
*/
IRDA_DEBUG(5, "%s(), finished with frame!\n", __FUNCTION__);
if ((skb=dev->tx_skb) != NULL) {
dev->tx_skb = NULL;
dev->stats.tx_packets++;
dev->stats.tx_bytes += skb->len;
dev_kfree_skb_any(skb);
}
if (unlikely(dev->new_speed > 0)) {
IRDA_DEBUG(5, "%s(), Changing speed!\n", __FUNCTION__);
err = sirdev_schedule_speed(dev, dev->new_speed);
if (unlikely(err)) {
/* should never happen
* forget the speed change and hope the stack recovers
*/
IRDA_ERROR("%s - schedule speed change failed: %d\n",
__FUNCTION__, err);
netif_wake_queue(dev->netdev);
}
/* else: success
* speed change in progress now
* on completion dev->new_speed gets cleared,
* rx-reenabled and the queue restarted
*/
}
else {
sirdev_enable_rx(dev);
netif_wake_queue(dev->netdev);
}
done:
spin_unlock_irqrestore(&dev->tx_lock, flags);
}
/* called from client driver - likely with bh-context - to give us
* some more received bytes. We put them into the rx-buffer,
* normally unwrapping and building LAP-skb's (unless rx disabled)
*/
int sirdev_receive(struct sir_dev *dev, const unsigned char *cp, size_t count)
{
if (!dev || !dev->netdev) {
IRDA_WARNING("%s(), not ready yet!\n", __FUNCTION__);
return -1;
}
if (!dev->irlap) {
IRDA_WARNING("%s - too early: %p / %zd!\n",
__FUNCTION__, cp, count);
return -1;
}
if (cp==NULL) {
/* error already at lower level receive
* just update stats and set media busy
*/
irda_device_set_media_busy(dev->netdev, TRUE);
dev->stats.rx_dropped++;
IRDA_DEBUG(0, "%s; rx-drop: %zd\n", __FUNCTION__, count);
return 0;
}
/* Read the characters into the buffer */
if (likely(atomic_read(&dev->enable_rx))) {
while (count--)
/* Unwrap and destuff one byte */
async_unwrap_char(dev->netdev, &dev->stats,
&dev->rx_buff, *cp++);
} else {
while (count--) {
/* rx not enabled: save the raw bytes and never
* trigger any netif_rx. The received bytes are flushed
* later when we re-enable rx but might be read meanwhile
* by the dongle driver.
*/
dev->rx_buff.data[dev->rx_buff.len++] = *cp++;
/* What should we do when the buffer is full? */
if (unlikely(dev->rx_buff.len == dev->rx_buff.truesize))
dev->rx_buff.len = 0;
}
}
return 0;
}
/**********************************************************************/
/* callbacks from network layer */
static struct net_device_stats *sirdev_get_stats(struct net_device *ndev)
{
struct sir_dev *dev = ndev->priv;
return (dev) ? &dev->stats : NULL;
}
static int sirdev_hard_xmit(struct sk_buff *skb, struct net_device *ndev)
{
struct sir_dev *dev = ndev->priv;
unsigned long flags;
int actual = 0;
int err;
s32 speed;
IRDA_ASSERT(dev != NULL, return 0;);
netif_stop_queue(ndev);
IRDA_DEBUG(3, "%s(), skb->len = %d\n", __FUNCTION__, skb->len);
speed = irda_get_next_speed(skb);
if ((speed != dev->speed) && (speed != -1)) {
if (!skb->len) {
err = sirdev_schedule_speed(dev, speed);
if (unlikely(err == -EWOULDBLOCK)) {
/* Failed to initiate the speed change, likely the fsm
* is still busy (pretty unlikely, but...)
* We refuse to accept the skb and return with the queue
* stopped so the network layer will retry after the
* fsm completes and wakes the queue.
*/
return 1;
}
else if (unlikely(err)) {
/* other fatal error - forget the speed change and
* hope the stack will recover somehow
*/
netif_start_queue(ndev);
}
/* else: success
* speed change in progress now
* on completion the queue gets restarted
*/
dev_kfree_skb_any(skb);
return 0;
} else
dev->new_speed = speed;
}
/* Init tx buffer*/
dev->tx_buff.data = dev->tx_buff.head;
/* Check problems */
if(spin_is_locked(&dev->tx_lock)) {
IRDA_DEBUG(3, "%s(), write not completed\n", __FUNCTION__);
}
/* serialize with write completion */
spin_lock_irqsave(&dev->tx_lock, flags);
/* Copy skb to tx_buff while wrapping, stuffing and making CRC */
dev->tx_buff.len = async_wrap_skb(skb, dev->tx_buff.data, dev->tx_buff.truesize);
/* transmission will start now - disable receive.
* if we are just in the middle of an incoming frame,
* treat it as collision. probably it's a good idea to
* reset the rx_buf OUTSIDE_FRAME in this case too?
*/
atomic_set(&dev->enable_rx, 0);
if (unlikely(sirdev_is_receiving(dev)))
dev->stats.collisions++;
actual = dev->drv->do_write(dev, dev->tx_buff.data, dev->tx_buff.len);
if (likely(actual > 0)) {
dev->tx_skb = skb;
ndev->trans_start = jiffies;
dev->tx_buff.data += actual;
dev->tx_buff.len -= actual;
}
else if (unlikely(actual < 0)) {
/* could be dropped later when we have tx_timeout to recover */
IRDA_ERROR("%s: drv->do_write failed (%d)\n",
__FUNCTION__, actual);
dev_kfree_skb_any(skb);
dev->stats.tx_errors++;
dev->stats.tx_dropped++;
netif_wake_queue(ndev);
}
spin_unlock_irqrestore(&dev->tx_lock, flags);
return 0;
}
/* called from network layer with rtnl hold */
static int sirdev_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
{
struct if_irda_req *irq = (struct if_irda_req *) rq;
struct sir_dev *dev = ndev->priv;
int ret = 0;
IRDA_ASSERT(dev != NULL, return -1;);
IRDA_DEBUG(3, "%s(), %s, (cmd=0x%X)\n", __FUNCTION__, ndev->name, cmd);
switch (cmd) {
case SIOCSBANDWIDTH: /* Set bandwidth */
if (!capable(CAP_NET_ADMIN))
ret = -EPERM;
else
ret = sirdev_schedule_speed(dev, irq->ifr_baudrate);
/* cannot sleep here for completion
* we are called from network layer with rtnl hold
*/
break;
case SIOCSDONGLE: /* Set dongle */
if (!capable(CAP_NET_ADMIN))
ret = -EPERM;
else
ret = sirdev_schedule_dongle_open(dev, irq->ifr_dongle);
/* cannot sleep here for completion
* we are called from network layer with rtnl hold
*/
break;
case SIOCSMEDIABUSY: /* Set media busy */
if (!capable(CAP_NET_ADMIN))
ret = -EPERM;
else
irda_device_set_media_busy(dev->netdev, TRUE);
break;
case SIOCGRECEIVING: /* Check if we are receiving right now */
irq->ifr_receiving = sirdev_is_receiving(dev);
break;
case SIOCSDTRRTS:
if (!capable(CAP_NET_ADMIN))
ret = -EPERM;
else
ret = sirdev_schedule_dtr_rts(dev, irq->ifr_dtr, irq->ifr_rts);
/* cannot sleep here for completion
* we are called from network layer with rtnl hold
*/
break;
case SIOCSMODE:
#if 0
if (!capable(CAP_NET_ADMIN))
ret = -EPERM;
else
ret = sirdev_schedule_mode(dev, irq->ifr_mode);
/* cannot sleep here for completion
* we are called from network layer with rtnl hold
*/
break;
#endif
default:
ret = -EOPNOTSUPP;
}
return ret;
}
/* ----------------------------------------------------------------------------- */
#define SIRBUF_ALLOCSIZE 4269 /* worst case size of a wrapped IrLAP frame */
static int sirdev_alloc_buffers(struct sir_dev *dev)
{
dev->tx_buff.truesize = SIRBUF_ALLOCSIZE;
dev->rx_buff.truesize = IRDA_SKB_MAX_MTU;
/* Bootstrap ZeroCopy Rx */
dev->rx_buff.skb = __dev_alloc_skb(dev->rx_buff.truesize, GFP_KERNEL);
if (dev->rx_buff.skb == NULL)
return -ENOMEM;
skb_reserve(dev->rx_buff.skb, 1);
dev->rx_buff.head = dev->rx_buff.skb->data;
dev->tx_buff.head = kmalloc(dev->tx_buff.truesize, GFP_KERNEL);
if (dev->tx_buff.head == NULL) {
kfree_skb(dev->rx_buff.skb);
dev->rx_buff.skb = NULL;
dev->rx_buff.head = NULL;
return -ENOMEM;
}
dev->tx_buff.data = dev->tx_buff.head;
dev->rx_buff.data = dev->rx_buff.head;
dev->tx_buff.len = 0;
dev->rx_buff.len = 0;
dev->rx_buff.in_frame = FALSE;
dev->rx_buff.state = OUTSIDE_FRAME;
return 0;
};
static void sirdev_free_buffers(struct sir_dev *dev)
{
if (dev->rx_buff.skb)
kfree_skb(dev->rx_buff.skb);
if (dev->tx_buff.head)
kfree(dev->tx_buff.head);
dev->rx_buff.head = dev->tx_buff.head = NULL;
dev->rx_buff.skb = NULL;
}
static int sirdev_open(struct net_device *ndev)
{
struct sir_dev *dev = ndev->priv;
const struct sir_driver *drv = dev->drv;
if (!drv)
return -ENODEV;
/* increase the reference count of the driver module before doing serious stuff */
if (!try_module_get(drv->owner))
return -ESTALE;
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
if (sirdev_alloc_buffers(dev))
goto errout_dec;
if (!dev->drv->start_dev || dev->drv->start_dev(dev))
goto errout_free;
sirdev_enable_rx(dev);
dev->raw_tx = 0;
netif_start_queue(ndev);
dev->irlap = irlap_open(ndev, &dev->qos, dev->hwname);
if (!dev->irlap)
goto errout_stop;
netif_wake_queue(ndev);
IRDA_DEBUG(2, "%s - done, speed = %d\n", __FUNCTION__, dev->speed);
return 0;
errout_stop:
atomic_set(&dev->enable_rx, 0);
if (dev->drv->stop_dev)
dev->drv->stop_dev(dev);
errout_free:
sirdev_free_buffers(dev);
errout_dec:
module_put(drv->owner);
return -EAGAIN;
}
static int sirdev_close(struct net_device *ndev)
{
struct sir_dev *dev = ndev->priv;
const struct sir_driver *drv;
// IRDA_DEBUG(0, "%s\n", __FUNCTION__);
netif_stop_queue(ndev);
down(&dev->fsm.sem); /* block on pending config completion */
atomic_set(&dev->enable_rx, 0);
if (unlikely(!dev->irlap))
goto out;
irlap_close(dev->irlap);
dev->irlap = NULL;
drv = dev->drv;
if (unlikely(!drv || !dev->priv))
goto out;
if (drv->stop_dev)
drv->stop_dev(dev);
sirdev_free_buffers(dev);
module_put(drv->owner);
out:
dev->speed = 0;
up(&dev->fsm.sem);
return 0;
}
/* ----------------------------------------------------------------------------- */
struct sir_dev * sirdev_get_instance(const struct sir_driver *drv, const char *name)
{
struct net_device *ndev;
struct sir_dev *dev;
IRDA_DEBUG(0, "%s - %s\n", __FUNCTION__, name);
/* instead of adding tests to protect against drv->do_write==NULL
* at several places we refuse to create a sir_dev instance for
* drivers which don't implement do_write.
*/
if (!drv || !drv->do_write)
return NULL;
/*
* Allocate new instance of the device
*/
ndev = alloc_irdadev(sizeof(*dev));
if (ndev == NULL) {
IRDA_ERROR("%s - Can't allocate memory for IrDA control block!\n", __FUNCTION__);
goto out;
}
dev = ndev->priv;
irda_init_max_qos_capabilies(&dev->qos);
dev->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
dev->qos.min_turn_time.bits = drv->qos_mtt_bits;
irda_qos_bits_to_value(&dev->qos);
strncpy(dev->hwname, name, sizeof(dev->hwname)-1);
atomic_set(&dev->enable_rx, 0);
dev->tx_skb = NULL;
spin_lock_init(&dev->tx_lock);
init_MUTEX(&dev->fsm.sem);
INIT_LIST_HEAD(&dev->fsm.rq.lh_request);
dev->fsm.rq.pending = 0;
init_timer(&dev->fsm.rq.timer);
dev->drv = drv;
dev->netdev = ndev;
SET_MODULE_OWNER(ndev);
/* Override the network functions we need to use */
ndev->hard_start_xmit = sirdev_hard_xmit;
ndev->open = sirdev_open;
ndev->stop = sirdev_close;
ndev->get_stats = sirdev_get_stats;
ndev->do_ioctl = sirdev_ioctl;
if (register_netdev(ndev)) {
IRDA_ERROR("%s(), register_netdev() failed!\n", __FUNCTION__);
goto out_freenetdev;
}
return dev;
out_freenetdev:
free_netdev(ndev);
out:
return NULL;
}
int sirdev_put_instance(struct sir_dev *dev)
{
int err = 0;
IRDA_DEBUG(0, "%s\n", __FUNCTION__);
atomic_set(&dev->enable_rx, 0);
netif_carrier_off(dev->netdev);
netif_device_detach(dev->netdev);
if (dev->dongle_drv)
err = sirdev_schedule_dongle_close(dev);
if (err)
IRDA_ERROR("%s - error %d\n", __FUNCTION__, err);
sirdev_close(dev->netdev);
down(&dev->fsm.sem);
dev->fsm.state = SIRDEV_STATE_DEAD; /* mark staled */
dev->dongle_drv = NULL;
dev->priv = NULL;
up(&dev->fsm.sem);
/* Remove netdevice */
unregister_netdev(dev->netdev);
free_netdev(dev->netdev);
return 0;
}

134
drivers/net/irda/sir_dongle.c Arquivo normal
Ver arquivo

@@ -0,0 +1,134 @@
/*********************************************************************
*
* sir_dongle.c: manager for serial dongle protocol drivers
*
* Copyright (c) 2002 Martin Diehl
*
* 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.
*
********************************************************************/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/smp_lock.h>
#include <linux/kmod.h>
#include <net/irda/irda.h>
#include "sir-dev.h"
/**************************************************************************
*
* dongle registration and attachment
*
*/
static LIST_HEAD(dongle_list); /* list of registered dongle drivers */
static DECLARE_MUTEX(dongle_list_lock); /* protects the list */
int irda_register_dongle(struct dongle_driver *new)
{
struct list_head *entry;
struct dongle_driver *drv;
IRDA_DEBUG(0, "%s : registering dongle \"%s\" (%d).\n",
__FUNCTION__, new->driver_name, new->type);
down(&dongle_list_lock);
list_for_each(entry, &dongle_list) {
drv = list_entry(entry, struct dongle_driver, dongle_list);
if (new->type == drv->type) {
up(&dongle_list_lock);
return -EEXIST;
}
}
list_add(&new->dongle_list, &dongle_list);
up(&dongle_list_lock);
return 0;
}
int irda_unregister_dongle(struct dongle_driver *drv)
{
down(&dongle_list_lock);
list_del(&drv->dongle_list);
up(&dongle_list_lock);
return 0;
}
int sirdev_get_dongle(struct sir_dev *dev, IRDA_DONGLE type)
{
struct list_head *entry;
const struct dongle_driver *drv = NULL;
int err = -EINVAL;
#ifdef CONFIG_KMOD
request_module("irda-dongle-%d", type);
#endif
if (dev->dongle_drv != NULL)
return -EBUSY;
/* serialize access to the list of registered dongles */
down(&dongle_list_lock);
list_for_each(entry, &dongle_list) {
drv = list_entry(entry, struct dongle_driver, dongle_list);
if (drv->type == type)
break;
else
drv = NULL;
}
if (!drv) {
err = -ENODEV;
goto out_unlock; /* no such dongle */
}
/* handling of SMP races with dongle module removal - three cases:
* 1) dongle driver was already unregistered - then we haven't found the
* requested dongle above and are already out here
* 2) the module is already marked deleted but the driver is still
* registered - then the try_module_get() below will fail
* 3) the try_module_get() below succeeds before the module is marked
* deleted - then sys_delete_module() fails and prevents the removal
* because the module is in use.
*/
if (!try_module_get(drv->owner)) {
err = -ESTALE;
goto out_unlock; /* rmmod already pending */
}
dev->dongle_drv = drv;
if (!drv->open || (err=drv->open(dev))!=0)
goto out_reject; /* failed to open driver */
up(&dongle_list_lock);
return 0;
out_reject:
dev->dongle_drv = NULL;
module_put(drv->owner);
out_unlock:
up(&dongle_list_lock);
return err;
}
int sirdev_put_dongle(struct sir_dev *dev)
{
const struct dongle_driver *drv = dev->dongle_drv;
if (drv) {
if (drv->close)
drv->close(dev); /* close this dongle instance */
dev->dongle_drv = NULL; /* unlink the dongle driver */
module_put(drv->owner);/* decrement driver's module refcount */
}
return 0;
}

502
drivers/net/irda/sir_kthread.c Arquivo normal
Ver arquivo

@@ -0,0 +1,502 @@
/*********************************************************************
*
* sir_kthread.c: dedicated thread to process scheduled
* sir device setup requests
*
* Copyright (c) 2002 Martin Diehl
*
* 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.
*
********************************************************************/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/init.h>
#include <linux/smp_lock.h>
#include <linux/completion.h>
#include <linux/delay.h>
#include <net/irda/irda.h>
#include "sir-dev.h"
/**************************************************************************
*
* kIrDAd kernel thread and config state machine
*
*/
struct irda_request_queue {
struct list_head request_list;
spinlock_t lock;
task_t *thread;
struct completion exit;
wait_queue_head_t kick, done;
atomic_t num_pending;
};
static struct irda_request_queue irda_rq_queue;
static int irda_queue_request(struct irda_request *rq)
{
int ret = 0;
unsigned long flags;
if (!test_and_set_bit(0, &rq->pending)) {
spin_lock_irqsave(&irda_rq_queue.lock, flags);
list_add_tail(&rq->lh_request, &irda_rq_queue.request_list);
wake_up(&irda_rq_queue.kick);
atomic_inc(&irda_rq_queue.num_pending);
spin_unlock_irqrestore(&irda_rq_queue.lock, flags);
ret = 1;
}
return ret;
}
static void irda_request_timer(unsigned long data)
{
struct irda_request *rq = (struct irda_request *)data;
unsigned long flags;
spin_lock_irqsave(&irda_rq_queue.lock, flags);
list_add_tail(&rq->lh_request, &irda_rq_queue.request_list);
wake_up(&irda_rq_queue.kick);
spin_unlock_irqrestore(&irda_rq_queue.lock, flags);
}
static int irda_queue_delayed_request(struct irda_request *rq, unsigned long delay)
{
int ret = 0;
struct timer_list *timer = &rq->timer;
if (!test_and_set_bit(0, &rq->pending)) {
timer->expires = jiffies + delay;
timer->function = irda_request_timer;
timer->data = (unsigned long)rq;
atomic_inc(&irda_rq_queue.num_pending);
add_timer(timer);
ret = 1;
}
return ret;
}
static void run_irda_queue(void)
{
unsigned long flags;
struct list_head *entry, *tmp;
struct irda_request *rq;
spin_lock_irqsave(&irda_rq_queue.lock, flags);
list_for_each_safe(entry, tmp, &irda_rq_queue.request_list) {
rq = list_entry(entry, struct irda_request, lh_request);
list_del_init(entry);
spin_unlock_irqrestore(&irda_rq_queue.lock, flags);
clear_bit(0, &rq->pending);
rq->func(rq->data);
if (atomic_dec_and_test(&irda_rq_queue.num_pending))
wake_up(&irda_rq_queue.done);
spin_lock_irqsave(&irda_rq_queue.lock, flags);
}
spin_unlock_irqrestore(&irda_rq_queue.lock, flags);
}
static int irda_thread(void *startup)
{
DECLARE_WAITQUEUE(wait, current);
daemonize("kIrDAd");
irda_rq_queue.thread = current;
complete((struct completion *)startup);
while (irda_rq_queue.thread != NULL) {
/* We use TASK_INTERRUPTIBLE, rather than
* TASK_UNINTERRUPTIBLE. Andrew Morton made this
* change ; he told me that it is safe, because "signal
* blocking is now handled in daemonize()", he added
* that the problem is that "uninterruptible sleep
* contributes to load average", making user worry.
* Jean II */
set_task_state(current, TASK_INTERRUPTIBLE);
add_wait_queue(&irda_rq_queue.kick, &wait);
if (list_empty(&irda_rq_queue.request_list))
schedule();
else
__set_task_state(current, TASK_RUNNING);
remove_wait_queue(&irda_rq_queue.kick, &wait);
/* make swsusp happy with our thread */
if (current->flags & PF_FREEZE)
refrigerator(PF_FREEZE);
run_irda_queue();
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,35)
reparent_to_init();
#endif
complete_and_exit(&irda_rq_queue.exit, 0);
/* never reached */
return 0;
}
static void flush_irda_queue(void)
{
if (atomic_read(&irda_rq_queue.num_pending)) {
DECLARE_WAITQUEUE(wait, current);
if (!list_empty(&irda_rq_queue.request_list))
run_irda_queue();
set_task_state(current, TASK_UNINTERRUPTIBLE);
add_wait_queue(&irda_rq_queue.done, &wait);
if (atomic_read(&irda_rq_queue.num_pending))
schedule();
else
__set_task_state(current, TASK_RUNNING);
remove_wait_queue(&irda_rq_queue.done, &wait);
}
}
/* substate handler of the config-fsm to handle the cases where we want
* to wait for transmit completion before changing the port configuration
*/
static int irda_tx_complete_fsm(struct sir_dev *dev)
{
struct sir_fsm *fsm = &dev->fsm;
unsigned next_state, delay;
unsigned bytes_left;
do {
next_state = fsm->substate; /* default: stay in current substate */
delay = 0;
switch(fsm->substate) {
case SIRDEV_STATE_WAIT_XMIT:
if (dev->drv->chars_in_buffer)
bytes_left = dev->drv->chars_in_buffer(dev);
else
bytes_left = 0;
if (!bytes_left) {
next_state = SIRDEV_STATE_WAIT_UNTIL_SENT;
break;
}
if (dev->speed > 115200)
delay = (bytes_left*8*10000) / (dev->speed/100);
else if (dev->speed > 0)
delay = (bytes_left*10*10000) / (dev->speed/100);
else
delay = 0;
/* expected delay (usec) until remaining bytes are sent */
if (delay < 100) {
udelay(delay);
delay = 0;
break;
}
/* sleep some longer delay (msec) */
delay = (delay+999) / 1000;
break;
case SIRDEV_STATE_WAIT_UNTIL_SENT:
/* block until underlaying hardware buffer are empty */
if (dev->drv->wait_until_sent)
dev->drv->wait_until_sent(dev);
next_state = SIRDEV_STATE_TX_DONE;
break;
case SIRDEV_STATE_TX_DONE:
return 0;
default:
IRDA_ERROR("%s - undefined state\n", __FUNCTION__);
return -EINVAL;
}
fsm->substate = next_state;
} while (delay == 0);
return delay;
}
/*
* Function irda_config_fsm
*
* State machine to handle the configuration of the device (and attached dongle, if any).
* This handler is scheduled for execution in kIrDAd context, so we can sleep.
* however, kIrDAd is shared by all sir_dev devices so we better don't sleep there too
* long. Instead, for longer delays we start a timer to reschedule us later.
* On entry, fsm->sem is always locked and the netdev xmit queue stopped.
* Both must be unlocked/restarted on completion - but only on final exit.
*/
static void irda_config_fsm(void *data)
{
struct sir_dev *dev = data;
struct sir_fsm *fsm = &dev->fsm;
int next_state;
int ret = -1;
unsigned delay;
IRDA_DEBUG(2, "%s(), <%ld>\n", __FUNCTION__, jiffies);
do {
IRDA_DEBUG(3, "%s - state=0x%04x / substate=0x%04x\n",
__FUNCTION__, fsm->state, fsm->substate);
next_state = fsm->state;
delay = 0;
switch(fsm->state) {
case SIRDEV_STATE_DONGLE_OPEN:
if (dev->dongle_drv != NULL) {
ret = sirdev_put_dongle(dev);
if (ret) {
fsm->result = -EINVAL;
next_state = SIRDEV_STATE_ERROR;
break;
}
}
/* Initialize dongle */
ret = sirdev_get_dongle(dev, fsm->param);
if (ret) {
fsm->result = ret;
next_state = SIRDEV_STATE_ERROR;
break;
}
/* Dongles are powered through the modem control lines which
* were just set during open. Before resetting, let's wait for
* the power to stabilize. This is what some dongle drivers did
* in open before, while others didn't - should be safe anyway.
*/
delay = 50;
fsm->substate = SIRDEV_STATE_DONGLE_RESET;
next_state = SIRDEV_STATE_DONGLE_RESET;
fsm->param = 9600;
break;
case SIRDEV_STATE_DONGLE_CLOSE:
/* shouldn't we just treat this as success=? */
if (dev->dongle_drv == NULL) {
fsm->result = -EINVAL;
next_state = SIRDEV_STATE_ERROR;
break;
}
ret = sirdev_put_dongle(dev);
if (ret) {
fsm->result = ret;
next_state = SIRDEV_STATE_ERROR;
break;
}
next_state = SIRDEV_STATE_DONE;
break;
case SIRDEV_STATE_SET_DTR_RTS:
ret = sirdev_set_dtr_rts(dev,
(fsm->param&0x02) ? TRUE : FALSE,
(fsm->param&0x01) ? TRUE : FALSE);
next_state = SIRDEV_STATE_DONE;
break;
case SIRDEV_STATE_SET_SPEED:
fsm->substate = SIRDEV_STATE_WAIT_XMIT;
next_state = SIRDEV_STATE_DONGLE_CHECK;
break;
case SIRDEV_STATE_DONGLE_CHECK:
ret = irda_tx_complete_fsm(dev);
if (ret < 0) {
fsm->result = ret;
next_state = SIRDEV_STATE_ERROR;
break;
}
if ((delay=ret) != 0)
break;
if (dev->dongle_drv) {
fsm->substate = SIRDEV_STATE_DONGLE_RESET;
next_state = SIRDEV_STATE_DONGLE_RESET;
}
else {
dev->speed = fsm->param;
next_state = SIRDEV_STATE_PORT_SPEED;
}
break;
case SIRDEV_STATE_DONGLE_RESET:
if (dev->dongle_drv->reset) {
ret = dev->dongle_drv->reset(dev);
if (ret < 0) {
fsm->result = ret;
next_state = SIRDEV_STATE_ERROR;
break;
}
}
else
ret = 0;
if ((delay=ret) == 0) {
/* set serial port according to dongle default speed */
if (dev->drv->set_speed)
dev->drv->set_speed(dev, dev->speed);
fsm->substate = SIRDEV_STATE_DONGLE_SPEED;
next_state = SIRDEV_STATE_DONGLE_SPEED;
}
break;
case SIRDEV_STATE_DONGLE_SPEED:
if (dev->dongle_drv->reset) {
ret = dev->dongle_drv->set_speed(dev, fsm->param);
if (ret < 0) {
fsm->result = ret;
next_state = SIRDEV_STATE_ERROR;
break;
}
}
else
ret = 0;
if ((delay=ret) == 0)
next_state = SIRDEV_STATE_PORT_SPEED;
break;
case SIRDEV_STATE_PORT_SPEED:
/* Finally we are ready to change the serial port speed */
if (dev->drv->set_speed)
dev->drv->set_speed(dev, dev->speed);
dev->new_speed = 0;
next_state = SIRDEV_STATE_DONE;
break;
case SIRDEV_STATE_DONE:
/* Signal network layer so it can send more frames */
netif_wake_queue(dev->netdev);
next_state = SIRDEV_STATE_COMPLETE;
break;
default:
IRDA_ERROR("%s - undefined state\n", __FUNCTION__);
fsm->result = -EINVAL;
/* fall thru */
case SIRDEV_STATE_ERROR:
IRDA_ERROR("%s - error: %d\n", __FUNCTION__, fsm->result);
#if 0 /* don't enable this before we have netdev->tx_timeout to recover */
netif_stop_queue(dev->netdev);
#else
netif_wake_queue(dev->netdev);
#endif
/* fall thru */
case SIRDEV_STATE_COMPLETE:
/* config change finished, so we are not busy any longer */
sirdev_enable_rx(dev);
up(&fsm->sem);
return;
}
fsm->state = next_state;
} while(!delay);
irda_queue_delayed_request(&fsm->rq, msecs_to_jiffies(delay));
}
/* schedule some device configuration task for execution by kIrDAd
* on behalf of the above state machine.
* can be called from process or interrupt/tasklet context.
*/
int sirdev_schedule_request(struct sir_dev *dev, int initial_state, unsigned param)
{
struct sir_fsm *fsm = &dev->fsm;
int xmit_was_down;
IRDA_DEBUG(2, "%s - state=0x%04x / param=%u\n", __FUNCTION__, initial_state, param);
if (down_trylock(&fsm->sem)) {
if (in_interrupt() || in_atomic() || irqs_disabled()) {
IRDA_DEBUG(1, "%s(), state machine busy!\n", __FUNCTION__);
return -EWOULDBLOCK;
} else
down(&fsm->sem);
}
if (fsm->state == SIRDEV_STATE_DEAD) {
/* race with sirdev_close should never happen */
IRDA_ERROR("%s(), instance staled!\n", __FUNCTION__);
up(&fsm->sem);
return -ESTALE; /* or better EPIPE? */
}
xmit_was_down = netif_queue_stopped(dev->netdev);
netif_stop_queue(dev->netdev);
atomic_set(&dev->enable_rx, 0);
fsm->state = initial_state;
fsm->param = param;
fsm->result = 0;
INIT_LIST_HEAD(&fsm->rq.lh_request);
fsm->rq.pending = 0;
fsm->rq.func = irda_config_fsm;
fsm->rq.data = dev;
if (!irda_queue_request(&fsm->rq)) { /* returns 0 on error! */
atomic_set(&dev->enable_rx, 1);
if (!xmit_was_down)
netif_wake_queue(dev->netdev);
up(&fsm->sem);
return -EAGAIN;
}
return 0;
}
int __init irda_thread_create(void)
{
struct completion startup;
int pid;
spin_lock_init(&irda_rq_queue.lock);
irda_rq_queue.thread = NULL;
INIT_LIST_HEAD(&irda_rq_queue.request_list);
init_waitqueue_head(&irda_rq_queue.kick);
init_waitqueue_head(&irda_rq_queue.done);
atomic_set(&irda_rq_queue.num_pending, 0);
init_completion(&startup);
pid = kernel_thread(irda_thread, &startup, CLONE_FS|CLONE_FILES);
if (pid <= 0)
return -EAGAIN;
else
wait_for_completion(&startup);
return 0;
}
void __exit irda_thread_join(void)
{
if (irda_rq_queue.thread) {
flush_irda_queue();
init_completion(&irda_rq_queue.exit);
irda_rq_queue.thread = NULL;
wake_up(&irda_rq_queue.kick);
wait_for_completion(&irda_rq_queue.exit);
}
}

2396
drivers/net/irda/smsc-ircc2.c Arquivo normal

Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff

194
drivers/net/irda/smsc-ircc2.h Arquivo normal
Ver arquivo

@@ -0,0 +1,194 @@
/*********************************************************************
* $Id: smsc-ircc2.h,v 1.12.2.1 2002/10/27 10:52:37 dip Exp $
*
* Description: Definitions for the SMC IrCC chipset
* Status: Experimental.
* Author: Daniele Peri (peri@csai.unipa.it)
*
* Copyright (c) 2002 Daniele Peri
* All Rights Reserved.
*
* Based on smc-ircc.h:
*
* Copyright (c) 1999-2000, Dag Brattli <dagb@cs.uit.no>
* Copyright (c) 1998-1999, Thomas Davis (tadavis@jps.net>
* All Rights Reserved
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* 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
*
********************************************************************/
#ifndef SMSC_IRCC2_H
#define SMSC_IRCC2_H
/* DMA modes needed */
#define DMA_TX_MODE 0x08 /* Mem to I/O, ++, demand. */
#define DMA_RX_MODE 0x04 /* I/O to mem, ++, demand. */
/* Master Control Register */
#define IRCC_MASTER 0x07
#define IRCC_MASTER_POWERDOWN 0x80
#define IRCC_MASTER_RESET 0x40
#define IRCC_MASTER_INT_EN 0x20
#define IRCC_MASTER_ERROR_RESET 0x10
/* Register block 0 */
/* Interrupt Identification */
#define IRCC_IIR 0x01
#define IRCC_IIR_ACTIVE_FRAME 0x80
#define IRCC_IIR_EOM 0x40
#define IRCC_IIR_RAW_MODE 0x20
#define IRCC_IIR_FIFO 0x10
/* Interrupt Enable */
#define IRCC_IER 0x02
#define IRCC_IER_ACTIVE_FRAME 0x80
#define IRCC_IER_EOM 0x40
#define IRCC_IER_RAW_MODE 0x20
#define IRCC_IER_FIFO 0x10
/* Line Status Register */
#define IRCC_LSR 0x03
#define IRCC_LSR_UNDERRUN 0x80
#define IRCC_LSR_OVERRUN 0x40
#define IRCC_LSR_FRAME_ERROR 0x20
#define IRCC_LSR_SIZE_ERROR 0x10
#define IRCC_LSR_CRC_ERROR 0x80
#define IRCC_LSR_FRAME_ABORT 0x40
/* Line Status Address Register */
#define IRCC_LSAR 0x03
#define IRCC_LSAR_ADDRESS_MASK 0x07
/* Line Control Register A */
#define IRCC_LCR_A 0x04
#define IRCC_LCR_A_FIFO_RESET 0x80
#define IRCC_LCR_A_FAST 0x40
#define IRCC_LCR_A_GP_DATA 0x20
#define IRCC_LCR_A_RAW_TX 0x10
#define IRCC_LCR_A_RAW_RX 0x08
#define IRCC_LCR_A_ABORT 0x04
#define IRCC_LCR_A_DATA_DONE 0x02
/* Line Control Register B */
#define IRCC_LCR_B 0x05
#define IRCC_LCR_B_SCE_DISABLED 0x00
#define IRCC_LCR_B_SCE_TRANSMIT 0x40
#define IRCC_LCR_B_SCE_RECEIVE 0x80
#define IRCC_LCR_B_SCE_UNDEFINED 0xc0
#define IRCC_LCR_B_SIP_ENABLE 0x20
#define IRCC_LCR_B_BRICK_WALL 0x10
/* Bus Status Register */
#define IRCC_BSR 0x06
#define IRCC_BSR_NOT_EMPTY 0x80
#define IRCC_BSR_FIFO_FULL 0x40
#define IRCC_BSR_TIMEOUT 0x20
/* Register block 1 */
#define IRCC_FIFO_THRESHOLD 0x02
#define IRCC_SCE_CFGA 0x00
#define IRCC_CFGA_AUX_IR 0x80
#define IRCC_CFGA_HALF_DUPLEX 0x04
#define IRCC_CFGA_TX_POLARITY 0x02
#define IRCC_CFGA_RX_POLARITY 0x01
#define IRCC_CFGA_COM 0x00
#define IRCC_SCE_CFGA_BLOCK_CTRL_BITS_MASK 0x87
#define IRCC_CFGA_IRDA_SIR_A 0x08
#define IRCC_CFGA_ASK_SIR 0x10
#define IRCC_CFGA_IRDA_SIR_B 0x18
#define IRCC_CFGA_IRDA_HDLC 0x20
#define IRCC_CFGA_IRDA_4PPM 0x28
#define IRCC_CFGA_CONSUMER 0x30
#define IRCC_CFGA_RAW_IR 0x38
#define IRCC_CFGA_OTHER 0x40
#define IRCC_IR_HDLC 0x04
#define IRCC_IR_4PPM 0x01
#define IRCC_IR_CONSUMER 0x02
#define IRCC_SCE_CFGB 0x01
#define IRCC_CFGB_LOOPBACK 0x20
#define IRCC_CFGB_LPBCK_TX_CRC 0x10
#define IRCC_CFGB_NOWAIT 0x08
#define IRCC_CFGB_STRING_MOVE 0x04
#define IRCC_CFGB_DMA_BURST 0x02
#define IRCC_CFGB_DMA_ENABLE 0x01
#define IRCC_CFGB_MUX_COM 0x00
#define IRCC_CFGB_MUX_IR 0x40
#define IRCC_CFGB_MUX_AUX 0x80
#define IRCC_CFGB_MUX_INACTIVE 0xc0
/* Register block 3 - Identification Registers! */
#define IRCC_ID_HIGH 0x00 /* 0x10 */
#define IRCC_ID_LOW 0x01 /* 0xB8 */
#define IRCC_CHIP_ID 0x02 /* 0xF1 */
#define IRCC_VERSION 0x03 /* 0x01 */
#define IRCC_INTERFACE 0x04 /* low 4 = DMA, high 4 = IRQ */
#define IRCC_INTERFACE_DMA_MASK 0x0F /* low 4 = DMA, high 4 = IRQ */
#define IRCC_INTERFACE_IRQ_MASK 0xF0 /* low 4 = DMA, high 4 = IRQ */
/* Register block 4 - IrDA */
#define IRCC_CONTROL 0x00
#define IRCC_BOF_COUNT_LO 0x01 /* Low byte */
#define IRCC_BOF_COUNT_HI 0x00 /* High nibble (bit 0-3) */
#define IRCC_BRICKWALL_CNT_LO 0x02 /* Low byte */
#define IRCC_BRICKWALL_CNT_HI 0x03 /* High nibble (bit 4-7) */
#define IRCC_TX_SIZE_LO 0x04 /* Low byte */
#define IRCC_TX_SIZE_HI 0x03 /* High nibble (bit 0-3) */
#define IRCC_RX_SIZE_HI 0x05 /* High nibble (bit 0-3) */
#define IRCC_RX_SIZE_LO 0x06 /* Low byte */
#define IRCC_1152 0x80
#define IRCC_CRC 0x40
/* Register block 5 - IrDA */
#define IRCC_ATC 0x00
#define IRCC_ATC_nPROGREADY 0x80
#define IRCC_ATC_SPEED 0x40
#define IRCC_ATC_ENABLE 0x20
#define IRCC_ATC_MASK 0xE0
#define IRCC_IRHALFDUPLEX_TIMEOUT 0x01
#define IRCC_SCE_TX_DELAY_TIMER 0x02
/*
* Other definitions
*/
#define SMSC_IRCC2_MAX_SIR_SPEED 115200
#define SMSC_IRCC2_FIR_CHIP_IO_EXTENT 8
#define SMSC_IRCC2_SIR_CHIP_IO_EXTENT 8
#define SMSC_IRCC2_FIFO_SIZE 16
#define SMSC_IRCC2_FIFO_THRESHOLD 64
/* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */
#define SMSC_IRCC2_RX_BUFF_TRUESIZE 14384
#define SMSC_IRCC2_TX_BUFF_TRUESIZE 14384
#define SMSC_IRCC2_MIN_TURN_TIME 0x07
#define SMSC_IRCC2_WINDOW_SIZE 0x07
/* Maximum wait for hw transmitter to finish */
#define SMSC_IRCC2_HW_TRANSMITTER_TIMEOUT_US 1000 /* 1 ms */
/* Maximum wait for ATC transceiver programming to finish */
#define SMSC_IRCC2_ATC_PROGRAMMING_TIMEOUT_JIFFIES 1
#endif /* SMSC_IRCC2_H */

100
drivers/net/irda/smsc-sio.h Arquivo normal
Ver arquivo

@@ -0,0 +1,100 @@
#ifndef SMSC_SIO_H
#define SMSC_SIO_H
/******************************************
Keys. They should work with every SMsC SIO
******************************************/
#define SMSCSIO_CFGACCESSKEY 0x55
#define SMSCSIO_CFGEXITKEY 0xaa
/*****************************
* Generic SIO Flat (!?) *
*****************************/
/* Register 0x0d */
#define SMSCSIOFLAT_DEVICEID_REG 0x0d
/* Register 0x0c */
#define SMSCSIOFLAT_UARTMODE0C_REG 0x0c
#define SMSCSIOFLAT_UART2MODE_MASK 0x38
#define SMSCSIOFLAT_UART2MODE_VAL_COM 0x00
#define SMSCSIOFLAT_UART2MODE_VAL_IRDA 0x08
#define SMSCSIOFLAT_UART2MODE_VAL_ASKIR 0x10
/* Register 0x25 */
#define SMSCSIOFLAT_UART2BASEADDR_REG 0x25
/* Register 0x2b */
#define SMSCSIOFLAT_FIRBASEADDR_REG 0x2b
/* Register 0x2c */
#define SMSCSIOFLAT_FIRDMASELECT_REG 0x2c
#define SMSCSIOFLAT_FIRDMASELECT_MASK 0x0f
/* Register 0x28 */
#define SMSCSIOFLAT_UARTIRQSELECT_REG 0x28
#define SMSCSIOFLAT_UART2IRQSELECT_MASK 0x0f
#define SMSCSIOFLAT_UART1IRQSELECT_MASK 0xf0
#define SMSCSIOFLAT_UARTIRQSELECT_VAL_NONE 0x00
/*********************
* LPC47N227 *
*********************/
#define LPC47N227_CFGACCESSKEY 0x55
#define LPC47N227_CFGEXITKEY 0xaa
/* Register 0x00 */
#define LPC47N227_FDCPOWERVALIDCONF_REG 0x00
#define LPC47N227_FDCPOWER_MASK 0x08
#define LPC47N227_VALID_MASK 0x80
/* Register 0x02 */
#define LPC47N227_UART12POWER_REG 0x02
#define LPC47N227_UART1POWERDOWN_MASK 0x08
#define LPC47N227_UART2POWERDOWN_MASK 0x80
/* Register 0x07 */
#define LPC47N227_APMBOOTDRIVE_REG 0x07
#define LPC47N227_PARPORT2AUTOPWRDOWN_MASK 0x10 /* auto power down on if set */
#define LPC47N227_UART2AUTOPWRDOWN_MASK 0x20 /* auto power down on if set */
#define LPC47N227_UART1AUTOPWRDOWN_MASK 0x40 /* auto power down on if set */
/* Register 0x0c */
#define LPC47N227_UARTMODE0C_REG 0x0c
#define LPC47N227_UART2MODE_MASK 0x38
#define LPC47N227_UART2MODE_VAL_COM 0x00
#define LPC47N227_UART2MODE_VAL_IRDA 0x08
#define LPC47N227_UART2MODE_VAL_ASKIR 0x10
/* Register 0x0d */
#define LPC47N227_DEVICEID_REG 0x0d
#define LPC47N227_DEVICEID_DEFVAL 0x5a
/* Register 0x0e */
#define LPC47N227_REVISIONID_REG 0x0e
/* Register 0x25 */
#define LPC47N227_UART2BASEADDR_REG 0x25
/* Register 0x28 */
#define LPC47N227_UARTIRQSELECT_REG 0x28
#define LPC47N227_UART2IRQSELECT_MASK 0x0f
#define LPC47N227_UART1IRQSELECT_MASK 0xf0
#define LPC47N227_UARTIRQSELECT_VAL_NONE 0x00
/* Register 0x2b */
#define LPC47N227_FIRBASEADDR_REG 0x2b
/* Register 0x2c */
#define LPC47N227_FIRDMASELECT_REG 0x2c
#define LPC47N227_FIRDMASELECT_MASK 0x0f
#define LPC47N227_FIRDMASELECT_VAL_DMA1 0x01 /* 47n227 has three dma channels */
#define LPC47N227_FIRDMASELECT_VAL_DMA2 0x02
#define LPC47N227_FIRDMASELECT_VAL_DMA3 0x03
#define LPC47N227_FIRDMASELECT_VAL_NONE 0x0f
#endif

1184
drivers/net/irda/stir4200.c Arquivo normal

Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff

232
drivers/net/irda/tekram-sir.c Arquivo normal
Ver arquivo

@@ -0,0 +1,232 @@
/*********************************************************************
*
* Filename: tekram.c
* Version: 1.3
* 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: Sun Oct 27 22:02:38 2002
* Modified by: Martin Diehl <mad@mdiehl.de>
*
* Copyright (c) 1998-1999 Dag Brattli,
* Copyright (c) 2002 Martin Diehl,
* 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<6D> admit liability nor
* provide warranty for any of this software. This material is
* provided "AS-IS" and at no charge.
*
********************************************************************/
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <net/irda/irda.h>
#include "sir-dev.h"
static int tekram_delay = 150; /* default is 150 ms */
module_param(tekram_delay, int, 0);
MODULE_PARM_DESC(tekram_delay, "tekram dongle write complete delay");
static int tekram_open(struct sir_dev *);
static int tekram_close(struct sir_dev *);
static int tekram_change_speed(struct sir_dev *, unsigned);
static int tekram_reset(struct sir_dev *);
#define TEKRAM_115200 0x00
#define TEKRAM_57600 0x01
#define TEKRAM_38400 0x02
#define TEKRAM_19200 0x03
#define TEKRAM_9600 0x04
#define TEKRAM_PW 0x10 /* Pulse select bit */
static struct dongle_driver tekram = {
.owner = THIS_MODULE,
.driver_name = "Tekram IR-210B",
.type = IRDA_TEKRAM_DONGLE,
.open = tekram_open,
.close = tekram_close,
.reset = tekram_reset,
.set_speed = tekram_change_speed,
};
static int __init tekram_sir_init(void)
{
if (tekram_delay < 1 || tekram_delay > 500)
tekram_delay = 200;
IRDA_DEBUG(1, "%s - using %d ms delay\n",
tekram.driver_name, tekram_delay);
return irda_register_dongle(&tekram);
}
static void __exit tekram_sir_cleanup(void)
{
irda_unregister_dongle(&tekram);
}
static int tekram_open(struct sir_dev *dev)
{
struct qos_info *qos = &dev->qos;
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
sirdev_set_dtr_rts(dev, TRUE, TRUE);
qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
qos->min_turn_time.bits = 0x01; /* Needs at least 10 ms */
irda_qos_bits_to_value(qos);
/* irda thread waits 50 msec for power settling */
return 0;
}
static int tekram_close(struct sir_dev *dev)
{
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
/* Power off dongle */
sirdev_set_dtr_rts(dev, FALSE, FALSE);
return 0;
}
/*
* Function tekram_change_speed (dev, state, speed)
*
* Set the speed for the Tekram IRMate 210 type dongle. Warning, this
* function must be called with a process context!
*
* Algorithm
* 1. clear DTR
* 2. set RTS, and wait at least 7 us
* 3. send Control Byte to the IR-210 through TXD to set new baud rate
* wait until the stop bit of Control Byte is sent (for 9600 baud rate,
* it takes about 100 msec)
*
* [oops, why 100 msec? sending 1 byte (10 bits) takes 1.05 msec
* - is this probably to compensate for delays in tty layer?]
*
* 5. clear RTS (return to NORMAL Operation)
* 6. wait at least 50 us, new setting (baud rate, etc) takes effect here
* after
*/
#define TEKRAM_STATE_WAIT_SPEED (SIRDEV_STATE_DONGLE_SPEED + 1)
static int tekram_change_speed(struct sir_dev *dev, unsigned speed)
{
unsigned state = dev->fsm.substate;
unsigned delay = 0;
u8 byte;
static int ret = 0;
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
switch(state) {
case SIRDEV_STATE_DONGLE_SPEED:
switch (speed) {
default:
speed = 9600;
ret = -EINVAL;
/* fall thru */
case 9600:
byte = TEKRAM_PW|TEKRAM_9600;
break;
case 19200:
byte = TEKRAM_PW|TEKRAM_19200;
break;
case 38400:
byte = TEKRAM_PW|TEKRAM_38400;
break;
case 57600:
byte = TEKRAM_PW|TEKRAM_57600;
break;
case 115200:
byte = TEKRAM_115200;
break;
}
/* Set DTR, Clear RTS */
sirdev_set_dtr_rts(dev, TRUE, FALSE);
/* Wait at least 7us */
udelay(14);
/* Write control byte */
sirdev_raw_write(dev, &byte, 1);
dev->speed = speed;
state = TEKRAM_STATE_WAIT_SPEED;
delay = tekram_delay;
break;
case TEKRAM_STATE_WAIT_SPEED:
/* Set DTR, Set RTS */
sirdev_set_dtr_rts(dev, TRUE, TRUE);
udelay(50);
break;
default:
IRDA_ERROR("%s - undefined state %d\n", __FUNCTION__, state);
ret = -EINVAL;
break;
}
dev->fsm.substate = state;
return (delay > 0) ? delay : ret;
}
/*
* Function tekram_reset (driver)
*
* This function resets the tekram dongle. Warning, this function
* must be called with a process context!!
*
* Algorithm:
* 0. Clear RTS and DTR, and wait 50 ms (power off the IR-210 )
* 1. clear RTS
* 2. set DTR, and wait at least 1 ms
* 3. clear DTR to SPACE state, wait at least 50 us for further
* operation
*/
static int tekram_reset(struct sir_dev *dev)
{
IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
/* Clear DTR, Set RTS */
sirdev_set_dtr_rts(dev, FALSE, TRUE);
/* Should sleep 1 ms */
msleep(1);
/* Set DTR, Set RTS */
sirdev_set_dtr_rts(dev, TRUE, TRUE);
/* Wait at least 50 us */
udelay(75);
dev->speed = 9600;
return 0;
}
MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
MODULE_DESCRIPTION("Tekram IrMate IR-210B dongle driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("irda-dongle-0"); /* IRDA_TEKRAM_DONGLE */
module_init(tekram_sir_init);
module_exit(tekram_sir_cleanup);

282
drivers/net/irda/tekram.c Arquivo normal
Ver arquivo

@@ -0,0 +1,282 @@
/*********************************************************************
*
* Filename: tekram.c
* 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: Fri Dec 17 09:13:09 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* 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
* 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<6D> admit liability nor
* provide warranty for any of this software. This material is
* provided "AS-IS" and at no charge.
*
********************************************************************/
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/tty.h>
#include <linux/init.h>
#include <net/irda/irda.h>
#include <net/irda/irda_device.h>
static void tekram_open(dongle_t *self, struct qos_info *qos);
static void tekram_close(dongle_t *self);
static int tekram_change_speed(struct irda_task *task);
static int tekram_reset(struct irda_task *task);
#define TEKRAM_115200 0x00
#define TEKRAM_57600 0x01
#define TEKRAM_38400 0x02
#define TEKRAM_19200 0x03
#define TEKRAM_9600 0x04
#define TEKRAM_PW 0x10 /* Pulse select bit */
static struct dongle_reg dongle = {
.type = IRDA_TEKRAM_DONGLE,
.open = tekram_open,
.close = tekram_close,
.reset = tekram_reset,
.change_speed = tekram_change_speed,
.owner = THIS_MODULE,
};
static int __init tekram_init(void)
{
return irda_device_register_dongle(&dongle);
}
static void __exit tekram_cleanup(void)
{
irda_device_unregister_dongle(&dongle);
}
static void tekram_open(dongle_t *self, struct qos_info *qos)
{
IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
qos->min_turn_time.bits = 0x01; /* Needs at least 10 ms */
irda_qos_bits_to_value(qos);
}
static void tekram_close(dongle_t *self)
{
IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
/* Power off dongle */
self->set_dtr_rts(self->dev, FALSE, FALSE);
if (self->reset_task)
irda_task_delete(self->reset_task);
if (self->speed_task)
irda_task_delete(self->speed_task);
}
/*
* Function tekram_change_speed (dev, state, speed)
*
* Set the speed for the Tekram IRMate 210 type dongle. Warning, this
* function must be called with a process context!
*
* Algorithm
* 1. clear DTR
* 2. set RTS, and wait at least 7 us
* 3. send Control Byte to the IR-210 through TXD to set new baud rate
* wait until the stop bit of Control Byte is sent (for 9600 baud rate,
* it takes about 100 msec)
* 5. clear RTS (return to NORMAL Operation)
* 6. wait at least 50 us, new setting (baud rate, etc) takes effect here
* after
*/
static int tekram_change_speed(struct irda_task *task)
{
dongle_t *self = (dongle_t *) task->instance;
__u32 speed = (__u32) task->param;
__u8 byte;
int ret = 0;
IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
IRDA_ASSERT(task != NULL, return -1;);
if (self->speed_task && self->speed_task != task) {
IRDA_DEBUG(0, "%s(), busy!\n", __FUNCTION__ );
return msecs_to_jiffies(10);
} else
self->speed_task = task;
switch (speed) {
default:
case 9600:
byte = TEKRAM_PW|TEKRAM_9600;
break;
case 19200:
byte = TEKRAM_PW|TEKRAM_19200;
break;
case 38400:
byte = TEKRAM_PW|TEKRAM_38400;
break;
case 57600:
byte = TEKRAM_PW|TEKRAM_57600;
break;
case 115200:
byte = TEKRAM_115200;
break;
}
switch (task->state) {
case IRDA_TASK_INIT:
case IRDA_TASK_CHILD_INIT:
/*
* Need to reset the dongle and go to 9600 bps before
* programming
*/
if (irda_task_execute(self, tekram_reset, NULL, task,
(void *) speed))
{
/* Dongle need more time to reset */
irda_task_next_state(task, IRDA_TASK_CHILD_WAIT);
/* Give reset 1 sec to finish */
ret = msecs_to_jiffies(1000);
} else
irda_task_next_state(task, IRDA_TASK_CHILD_DONE);
break;
case IRDA_TASK_CHILD_WAIT:
IRDA_WARNING("%s(), resetting dongle timed out!\n",
__FUNCTION__);
ret = -1;
break;
case IRDA_TASK_CHILD_DONE:
/* Set DTR, Clear RTS */
self->set_dtr_rts(self->dev, TRUE, FALSE);
/* Wait at least 7us */
udelay(14);
/* Write control byte */
self->write(self->dev, &byte, 1);
irda_task_next_state(task, IRDA_TASK_WAIT);
/* Wait at least 100 ms */
ret = msecs_to_jiffies(150);
break;
case IRDA_TASK_WAIT:
/* Set DTR, Set RTS */
self->set_dtr_rts(self->dev, TRUE, TRUE);
irda_task_next_state(task, IRDA_TASK_DONE);
self->speed_task = NULL;
break;
default:
IRDA_ERROR("%s(), unknown state %d\n",
__FUNCTION__, task->state);
irda_task_next_state(task, IRDA_TASK_DONE);
self->speed_task = NULL;
ret = -1;
break;
}
return ret;
}
/*
* Function tekram_reset (driver)
*
* This function resets the tekram dongle. Warning, this function
* must be called with a process context!!
*
* Algorithm:
* 0. Clear RTS and DTR, and wait 50 ms (power off the IR-210 )
* 1. clear RTS
* 2. set DTR, and wait at least 1 ms
* 3. clear DTR to SPACE state, wait at least 50 us for further
* operation
*/
int tekram_reset(struct irda_task *task)
{
dongle_t *self = (dongle_t *) task->instance;
int ret = 0;
IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
IRDA_ASSERT(task != NULL, return -1;);
if (self->reset_task && self->reset_task != task) {
IRDA_DEBUG(0, "%s(), busy!\n", __FUNCTION__ );
return msecs_to_jiffies(10);
} else
self->reset_task = task;
/* Power off dongle */
//self->set_dtr_rts(self->dev, FALSE, FALSE);
self->set_dtr_rts(self->dev, TRUE, TRUE);
switch (task->state) {
case IRDA_TASK_INIT:
irda_task_next_state(task, IRDA_TASK_WAIT1);
/* Sleep 50 ms */
ret = msecs_to_jiffies(50);
break;
case IRDA_TASK_WAIT1:
/* Clear DTR, Set RTS */
self->set_dtr_rts(self->dev, FALSE, TRUE);
irda_task_next_state(task, IRDA_TASK_WAIT2);
/* Should sleep 1 ms */
ret = msecs_to_jiffies(1);
break;
case IRDA_TASK_WAIT2:
/* Set DTR, Set RTS */
self->set_dtr_rts(self->dev, TRUE, TRUE);
/* Wait at least 50 us */
udelay(75);
irda_task_next_state(task, IRDA_TASK_DONE);
self->reset_task = NULL;
break;
default:
IRDA_ERROR("%s(), unknown state %d\n",
__FUNCTION__, task->state);
irda_task_next_state(task, IRDA_TASK_DONE);
self->reset_task = NULL;
ret = -1;
}
return ret;
}
MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
MODULE_DESCRIPTION("Tekram IrMate IR-210B dongle driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("irda-dongle-0"); /* IRDA_TEKRAM_DONGLE */
/*
* Function init_module (void)
*
* Initialize Tekram module
*
*/
module_init(tekram_init);
/*
* Function cleanup_module (void)
*
* Cleanup Tekram module
*
*/
module_exit(tekram_cleanup);

1676
drivers/net/irda/via-ircc.c Arquivo normal

Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff

853
drivers/net/irda/via-ircc.h Arquivo normal
Ver arquivo

@@ -0,0 +1,853 @@
/*********************************************************************
*
* Filename: via-ircc.h
* Version: 1.0
* Description: Driver for the VIA VT8231/VT8233 IrDA chipsets
* Author: VIA Technologies, inc
* Date : 08/06/2003
Copyright (c) 1998-2003 VIA Technologies, Inc.
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, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTIES OR REPRESENTATIONS; 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.
* Comment:
* jul/08/2002 : Rx buffer length should use Rx ring ptr.
* Oct/28/2002 : Add SB id for 3147 and 3177.
* jul/09/2002 : only implement two kind of dongle currently.
* Oct/02/2002 : work on VT8231 and VT8233 .
* Aug/06/2003 : change driver format to pci driver .
********************************************************************/
#ifndef via_IRCC_H
#define via_IRCC_H
#include <linux/time.h>
#include <linux/spinlock.h>
#include <linux/pm.h>
#include <linux/types.h>
#include <asm/io.h>
#define MAX_TX_WINDOW 7
#define MAX_RX_WINDOW 7
struct st_fifo_entry {
int status;
int len;
};
struct st_fifo {
struct st_fifo_entry entries[MAX_RX_WINDOW + 2];
int pending_bytes;
int head;
int tail;
int len;
};
struct frame_cb {
void *start; /* Start of frame in DMA mem */
int len; /* Lenght of frame in DMA mem */
};
struct tx_fifo {
struct frame_cb queue[MAX_TX_WINDOW + 2]; /* Info about frames in queue */
int ptr; /* Currently being sent */
int len; /* Lenght of queue */
int free; /* Next free slot */
void *tail; /* Next free start in DMA mem */
};
struct eventflag // for keeping track of Interrupt Events
{
//--------tx part
unsigned char TxFIFOUnderRun;
unsigned char EOMessage;
unsigned char TxFIFOReady;
unsigned char EarlyEOM;
//--------rx part
unsigned char PHYErr;
unsigned char CRCErr;
unsigned char RxFIFOOverRun;
unsigned char EOPacket;
unsigned char RxAvail;
unsigned char TooLargePacket;
unsigned char SIRBad;
//--------unknown
unsigned char Unknown;
//----------
unsigned char TimeOut;
unsigned char RxDMATC;
unsigned char TxDMATC;
};
/* Private data for each instance */
struct via_ircc_cb {
struct st_fifo st_fifo; /* Info about received frames */
struct tx_fifo tx_fifo; /* Info about frames to be transmitted */
struct net_device *netdev; /* Yes! we are some kind of netdevice */
struct net_device_stats stats;
struct irlap_cb *irlap; /* The link layer we are binded to */
struct qos_info qos; /* QoS capabilities for this device */
chipio_t io; /* IrDA controller information */
iobuff_t tx_buff; /* Transmit buffer */
iobuff_t rx_buff; /* Receive buffer */
dma_addr_t tx_buff_dma;
dma_addr_t rx_buff_dma;
__u8 ier; /* Interrupt enable register */
struct timeval stamp;
struct timeval now;
spinlock_t lock; /* For serializing operations */
__u32 flags; /* Interface flags */
__u32 new_speed;
int index; /* Instance index */
struct eventflag EventFlag;
struct pm_dev *dev;
unsigned int chip_id; /* to remember chip id */
unsigned int RetryCount;
unsigned int RxDataReady;
unsigned int RxLastCount;
};
//---------I=Infrared, H=Host, M=Misc, T=Tx, R=Rx, ST=Status,
// CF=Config, CT=Control, L=Low, H=High, C=Count
#define I_CF_L_0 0x10
#define I_CF_H_0 0x11
#define I_SIR_BOF 0x12
#define I_SIR_EOF 0x13
#define I_ST_CT_0 0x15
#define I_ST_L_1 0x16
#define I_ST_H_1 0x17
#define I_CF_L_1 0x18
#define I_CF_H_1 0x19
#define I_CF_L_2 0x1a
#define I_CF_H_2 0x1b
#define I_CF_3 0x1e
#define H_CT 0x20
#define H_ST 0x21
#define M_CT 0x22
#define TX_CT_1 0x23
#define TX_CT_2 0x24
#define TX_ST 0x25
#define RX_CT 0x26
#define RX_ST 0x27
#define RESET 0x28
#define P_ADDR 0x29
#define RX_C_L 0x2a
#define RX_C_H 0x2b
#define RX_P_L 0x2c
#define RX_P_H 0x2d
#define TX_C_L 0x2e
#define TX_C_H 0x2f
#define TIMER 0x32
#define I_CF_4 0x33
#define I_T_C_L 0x34
#define I_T_C_H 0x35
#define VERSION 0x3f
//-------------------------------
#define StartAddr 0x10 // the first register address
#define EndAddr 0x3f // the last register address
#define GetBit(val,bit) val = (unsigned char) ((val>>bit) & 0x1)
// Returns the bit
#define SetBit(val,bit) val= (unsigned char ) (val | (0x1 << bit))
// Sets bit to 1
#define ResetBit(val,bit) val= (unsigned char ) (val & ~(0x1 << bit))
// Sets bit to 0
#define OFF 0
#define ON 1
#define DMA_TX_MODE 0x08
#define DMA_RX_MODE 0x04
#define DMA1 0
#define DMA2 0xc0
#define MASK1 DMA1+0x0a
#define MASK2 DMA2+0x14
#define Clk_bit 0x40
#define Tx_bit 0x01
#define Rd_Valid 0x08
#define RxBit 0x08
static void DisableDmaChannel(unsigned int channel)
{
switch (channel) { // 8 Bit DMA channels DMAC1
case 0:
outb(4, MASK1); //mask channel 0
break;
case 1:
outb(5, MASK1); //Mask channel 1
break;
case 2:
outb(6, MASK1); //Mask channel 2
break;
case 3:
outb(7, MASK1); //Mask channel 3
break;
case 5:
outb(5, MASK2); //Mask channel 5
break;
case 6:
outb(6, MASK2); //Mask channel 6
break;
case 7:
outb(7, MASK2); //Mask channel 7
break;
default:
break;
}; //Switch
}
static unsigned char ReadLPCReg(int iRegNum)
{
unsigned char iVal;
outb(0x87, 0x2e);
outb(0x87, 0x2e);
outb(iRegNum, 0x2e);
iVal = inb(0x2f);
outb(0xaa, 0x2e);
return iVal;
}
static void WriteLPCReg(int iRegNum, unsigned char iVal)
{
outb(0x87, 0x2e);
outb(0x87, 0x2e);
outb(iRegNum, 0x2e);
outb(iVal, 0x2f);
outb(0xAA, 0x2e);
}
static __u8 ReadReg(unsigned int BaseAddr, int iRegNum)
{
return ((__u8) inb(BaseAddr + iRegNum));
}
static void WriteReg(unsigned int BaseAddr, int iRegNum, unsigned char iVal)
{
outb(iVal, BaseAddr + iRegNum);
}
static int WriteRegBit(unsigned int BaseAddr, unsigned char RegNum,
unsigned char BitPos, unsigned char value)
{
__u8 Rtemp, Wtemp;
if (BitPos > 7) {
return -1;
}
if ((RegNum < StartAddr) || (RegNum > EndAddr))
return -1;
Rtemp = ReadReg(BaseAddr, RegNum);
if (value == 0)
Wtemp = ResetBit(Rtemp, BitPos);
else {
if (value == 1)
Wtemp = SetBit(Rtemp, BitPos);
else
return -1;
}
WriteReg(BaseAddr, RegNum, Wtemp);
return 0;
}
static __u8 CheckRegBit(unsigned int BaseAddr, unsigned char RegNum,
unsigned char BitPos)
{
__u8 temp;
if (BitPos > 7)
return 0xff;
if ((RegNum < StartAddr) || (RegNum > EndAddr)) {
// printf("what is the register %x!\n",RegNum);
}
temp = ReadReg(BaseAddr, RegNum);
return GetBit(temp, BitPos);
}
static void SetMaxRxPacketSize(__u16 iobase, __u16 size)
{
__u16 low, high;
if ((size & 0xe000) == 0) {
low = size & 0x00ff;
high = (size & 0x1f00) >> 8;
WriteReg(iobase, I_CF_L_2, low);
WriteReg(iobase, I_CF_H_2, high);
}
}
//for both Rx and Tx
static void SetFIFO(__u16 iobase, __u16 value)
{
switch (value) {
case 128:
WriteRegBit(iobase, 0x11, 0, 0);
WriteRegBit(iobase, 0x11, 7, 1);
break;
case 64:
WriteRegBit(iobase, 0x11, 0, 0);
WriteRegBit(iobase, 0x11, 7, 0);
break;
case 32:
WriteRegBit(iobase, 0x11, 0, 1);
WriteRegBit(iobase, 0x11, 7, 0);
break;
default:
WriteRegBit(iobase, 0x11, 0, 0);
WriteRegBit(iobase, 0x11, 7, 0);
}
}
#define CRC16(BaseAddr,val) WriteRegBit(BaseAddr,I_CF_L_0,7,val) //0 for 32 CRC
/*
#define SetVFIR(BaseAddr,val) WriteRegBit(BaseAddr,I_CF_H_0,5,val)
#define SetFIR(BaseAddr,val) WriteRegBit(BaseAddr,I_CF_L_0,6,val)
#define SetMIR(BaseAddr,val) WriteRegBit(BaseAddr,I_CF_L_0,5,val)
#define SetSIR(BaseAddr,val) WriteRegBit(BaseAddr,I_CF_L_0,4,val)
*/
#define SIRFilter(BaseAddr,val) WriteRegBit(BaseAddr,I_CF_L_0,3,val)
#define Filter(BaseAddr,val) WriteRegBit(BaseAddr,I_CF_L_0,2,val)
#define InvertTX(BaseAddr,val) WriteRegBit(BaseAddr,I_CF_L_0,1,val)
#define InvertRX(BaseAddr,val) WriteRegBit(BaseAddr,I_CF_L_0,0,val)
//****************************I_CF_H_0
#define EnableTX(BaseAddr,val) WriteRegBit(BaseAddr,I_CF_H_0,4,val)
#define EnableRX(BaseAddr,val) WriteRegBit(BaseAddr,I_CF_H_0,3,val)
#define EnableDMA(BaseAddr,val) WriteRegBit(BaseAddr,I_CF_H_0,2,val)
#define SIRRecvAny(BaseAddr,val) WriteRegBit(BaseAddr,I_CF_H_0,1,val)
#define DiableTrans(BaseAddr,val) WriteRegBit(BaseAddr,I_CF_H_0,0,val)
//***************************I_SIR_BOF,I_SIR_EOF
#define SetSIRBOF(BaseAddr,val) WriteReg(BaseAddr,I_SIR_BOF,val)
#define SetSIREOF(BaseAddr,val) WriteReg(BaseAddr,I_SIR_EOF,val)
#define GetSIRBOF(BaseAddr) ReadReg(BaseAddr,I_SIR_BOF)
#define GetSIREOF(BaseAddr) ReadReg(BaseAddr,I_SIR_EOF)
//*******************I_ST_CT_0
#define EnPhys(BaseAddr,val) WriteRegBit(BaseAddr,I_ST_CT_0,7,val)
#define IsModeError(BaseAddr) CheckRegBit(BaseAddr,I_ST_CT_0,6) //RO
#define IsVFIROn(BaseAddr) CheckRegBit(BaseAddr,0x14,0) //RO for VT1211 only
#define IsFIROn(BaseAddr) CheckRegBit(BaseAddr,I_ST_CT_0,5) //RO
#define IsMIROn(BaseAddr) CheckRegBit(BaseAddr,I_ST_CT_0,4) //RO
#define IsSIROn(BaseAddr) CheckRegBit(BaseAddr,I_ST_CT_0,3) //RO
#define IsEnableTX(BaseAddr) CheckRegBit(BaseAddr,I_ST_CT_0,2) //RO
#define IsEnableRX(BaseAddr) CheckRegBit(BaseAddr,I_ST_CT_0,1) //RO
#define Is16CRC(BaseAddr) CheckRegBit(BaseAddr,I_ST_CT_0,0) //RO
//***************************I_CF_3
#define DisableAdjacentPulseWidth(BaseAddr,val) WriteRegBit(BaseAddr,I_CF_3,5,val) //1 disable
#define DisablePulseWidthAdjust(BaseAddr,val) WriteRegBit(BaseAddr,I_CF_3,4,val) //1 disable
#define UseOneRX(BaseAddr,val) WriteRegBit(BaseAddr,I_CF_3,1,val) //0 use two RX
#define SlowIRRXLowActive(BaseAddr,val) WriteRegBit(BaseAddr,I_CF_3,0,val) //0 show RX high=1 in SIR
//***************************H_CT
#define EnAllInt(BaseAddr,val) WriteRegBit(BaseAddr,H_CT,7,val)
#define TXStart(BaseAddr,val) WriteRegBit(BaseAddr,H_CT,6,val)
#define RXStart(BaseAddr,val) WriteRegBit(BaseAddr,H_CT,5,val)
#define ClearRXInt(BaseAddr,val) WriteRegBit(BaseAddr,H_CT,4,val) // 1 clear
//*****************H_ST
#define IsRXInt(BaseAddr) CheckRegBit(BaseAddr,H_ST,4)
#define GetIntIndentify(BaseAddr) ((ReadReg(BaseAddr,H_ST)&0xf1) >>1)
#define IsHostBusy(BaseAddr) CheckRegBit(BaseAddr,H_ST,0)
#define GetHostStatus(BaseAddr) ReadReg(BaseAddr,H_ST) //RO
//**************************M_CT
#define EnTXDMA(BaseAddr,val) WriteRegBit(BaseAddr,M_CT,7,val)
#define EnRXDMA(BaseAddr,val) WriteRegBit(BaseAddr,M_CT,6,val)
#define SwapDMA(BaseAddr,val) WriteRegBit(BaseAddr,M_CT,5,val)
#define EnInternalLoop(BaseAddr,val) WriteRegBit(BaseAddr,M_CT,4,val)
#define EnExternalLoop(BaseAddr,val) WriteRegBit(BaseAddr,M_CT,3,val)
//**************************TX_CT_1
#define EnTXFIFOHalfLevelInt(BaseAddr,val) WriteRegBit(BaseAddr,TX_CT_1,4,val) //half empty int (1 half)
#define EnTXFIFOUnderrunEOMInt(BaseAddr,val) WriteRegBit(BaseAddr,TX_CT_1,5,val)
#define EnTXFIFOReadyInt(BaseAddr,val) WriteRegBit(BaseAddr,TX_CT_1,6,val) //int when reach it threshold (setting by bit 4)
//**************************TX_CT_2
#define ForceUnderrun(BaseAddr,val) WriteRegBit(BaseAddr,TX_CT_2,7,val) // force an underrun int
#define EnTXCRC(BaseAddr,val) WriteRegBit(BaseAddr,TX_CT_2,6,val) //1 for FIR,MIR...0 (not SIR)
#define ForceBADCRC(BaseAddr,val) WriteRegBit(BaseAddr,TX_CT_2,5,val) //force an bad CRC
#define SendSIP(BaseAddr,val) WriteRegBit(BaseAddr,TX_CT_2,4,val) //send indication pulse for prevent SIR disturb
#define ClearEnTX(BaseAddr,val) WriteRegBit(BaseAddr,TX_CT_2,3,val) // opposite to EnTX
//*****************TX_ST
#define GetTXStatus(BaseAddr) ReadReg(BaseAddr,TX_ST) //RO
//**************************RX_CT
#define EnRXSpecInt(BaseAddr,val) WriteRegBit(BaseAddr,RX_CT,0,val)
#define EnRXFIFOReadyInt(BaseAddr,val) WriteRegBit(BaseAddr,RX_CT,1,val) //enable int when reach it threshold (setting by bit 7)
#define EnRXFIFOHalfLevelInt(BaseAddr,val) WriteRegBit(BaseAddr,RX_CT,7,val) //enable int when (1) half full...or (0) just not full
//*****************RX_ST
#define GetRXStatus(BaseAddr) ReadReg(BaseAddr,RX_ST) //RO
//***********************P_ADDR
#define SetPacketAddr(BaseAddr,addr) WriteReg(BaseAddr,P_ADDR,addr)
//***********************I_CF_4
#define EnGPIOtoRX2(BaseAddr,val) WriteRegBit(BaseAddr,I_CF_4,7,val)
#define EnTimerInt(BaseAddr,val) WriteRegBit(BaseAddr,I_CF_4,1,val)
#define ClearTimerInt(BaseAddr,val) WriteRegBit(BaseAddr,I_CF_4,0,val)
//***********************I_T_C_L
#define WriteGIO(BaseAddr,val) WriteRegBit(BaseAddr,I_T_C_L,7,val)
#define ReadGIO(BaseAddr) CheckRegBit(BaseAddr,I_T_C_L,7)
#define ReadRX(BaseAddr) CheckRegBit(BaseAddr,I_T_C_L,3) //RO
#define WriteTX(BaseAddr,val) WriteRegBit(BaseAddr,I_T_C_L,0,val)
//***********************I_T_C_H
#define EnRX2(BaseAddr,val) WriteRegBit(BaseAddr,I_T_C_H,7,val)
#define ReadRX2(BaseAddr) CheckRegBit(BaseAddr,I_T_C_H,7)
//**********************Version
#define GetFIRVersion(BaseAddr) ReadReg(BaseAddr,VERSION)
static void SetTimer(__u16 iobase, __u8 count)
{
EnTimerInt(iobase, OFF);
WriteReg(iobase, TIMER, count);
EnTimerInt(iobase, ON);
}
static void SetSendByte(__u16 iobase, __u32 count)
{
__u32 low, high;
if ((count & 0xf000) == 0) {
low = count & 0x00ff;
high = (count & 0x0f00) >> 8;
WriteReg(iobase, TX_C_L, low);
WriteReg(iobase, TX_C_H, high);
}
}
static void ResetChip(__u16 iobase, __u8 type)
{
__u8 value;
value = (type + 2) << 4;
WriteReg(iobase, RESET, type);
}
static int CkRxRecv(__u16 iobase, struct via_ircc_cb *self)
{
__u8 low, high;
__u16 wTmp = 0, wTmp1 = 0, wTmp_new = 0;
low = ReadReg(iobase, RX_C_L);
high = ReadReg(iobase, RX_C_H);
wTmp1 = high;
wTmp = (wTmp1 << 8) | low;
udelay(10);
low = ReadReg(iobase, RX_C_L);
high = ReadReg(iobase, RX_C_H);
wTmp1 = high;
wTmp_new = (wTmp1 << 8) | low;
if (wTmp_new != wTmp)
return 1;
else
return 0;
}
static __u16 RxCurCount(__u16 iobase, struct via_ircc_cb * self)
{
__u8 low, high;
__u16 wTmp = 0, wTmp1 = 0;
low = ReadReg(iobase, RX_P_L);
high = ReadReg(iobase, RX_P_H);
wTmp1 = high;
wTmp = (wTmp1 << 8) | low;
return wTmp;
}
/* This Routine can only use in recevie_complete
* for it will update last count.
*/
static __u16 GetRecvByte(__u16 iobase, struct via_ircc_cb * self)
{
__u8 low, high;
__u16 wTmp, wTmp1, ret;
low = ReadReg(iobase, RX_P_L);
high = ReadReg(iobase, RX_P_H);
wTmp1 = high;
wTmp = (wTmp1 << 8) | low;
if (wTmp >= self->RxLastCount)
ret = wTmp - self->RxLastCount;
else
ret = (0x8000 - self->RxLastCount) + wTmp;
self->RxLastCount = wTmp;
/* RX_P is more actually the RX_C
low=ReadReg(iobase,RX_C_L);
high=ReadReg(iobase,RX_C_H);
if(!(high&0xe000)) {
temp=(high<<8)+low;
return temp;
}
else return 0;
*/
return ret;
}
static void Sdelay(__u16 scale)
{
__u8 bTmp;
int i, j;
for (j = 0; j < scale; j++) {
for (i = 0; i < 0x20; i++) {
bTmp = inb(0xeb);
outb(bTmp, 0xeb);
}
}
}
static void Tdelay(__u16 scale)
{
__u8 bTmp;
int i, j;
for (j = 0; j < scale; j++) {
for (i = 0; i < 0x50; i++) {
bTmp = inb(0xeb);
outb(bTmp, 0xeb);
}
}
}
static void ActClk(__u16 iobase, __u8 value)
{
__u8 bTmp;
bTmp = ReadReg(iobase, 0x34);
if (value)
WriteReg(iobase, 0x34, bTmp | Clk_bit);
else
WriteReg(iobase, 0x34, bTmp & ~Clk_bit);
}
static void ClkTx(__u16 iobase, __u8 Clk, __u8 Tx)
{
__u8 bTmp;
bTmp = ReadReg(iobase, 0x34);
if (Clk == 0)
bTmp &= ~Clk_bit;
else {
if (Clk == 1)
bTmp |= Clk_bit;
}
WriteReg(iobase, 0x34, bTmp);
Sdelay(1);
if (Tx == 0)
bTmp &= ~Tx_bit;
else {
if (Tx == 1)
bTmp |= Tx_bit;
}
WriteReg(iobase, 0x34, bTmp);
}
static void Wr_Byte(__u16 iobase, __u8 data)
{
__u8 bData = data;
// __u8 btmp;
int i;
ClkTx(iobase, 0, 1);
Tdelay(2);
ActClk(iobase, 1);
Tdelay(1);
for (i = 0; i < 8; i++) { //LDN
if ((bData >> i) & 0x01) {
ClkTx(iobase, 0, 1); //bit data = 1;
} else {
ClkTx(iobase, 0, 0); //bit data = 1;
}
Tdelay(2);
Sdelay(1);
ActClk(iobase, 1); //clk hi
Tdelay(1);
}
}
static __u8 Rd_Indx(__u16 iobase, __u8 addr, __u8 index)
{
__u8 data = 0, bTmp, data_bit;
int i;
bTmp = addr | (index << 1) | 0;
ClkTx(iobase, 0, 0);
Tdelay(2);
ActClk(iobase, 1);
udelay(1);
Wr_Byte(iobase, bTmp);
Sdelay(1);
ClkTx(iobase, 0, 0);
Tdelay(2);
for (i = 0; i < 10; i++) {
ActClk(iobase, 1);
Tdelay(1);
ActClk(iobase, 0);
Tdelay(1);
ClkTx(iobase, 0, 1);
Tdelay(1);
bTmp = ReadReg(iobase, 0x34);
if (!(bTmp & Rd_Valid))
break;
}
if (!(bTmp & Rd_Valid)) {
for (i = 0; i < 8; i++) {
ActClk(iobase, 1);
Tdelay(1);
ActClk(iobase, 0);
bTmp = ReadReg(iobase, 0x34);
data_bit = 1 << i;
if (bTmp & RxBit)
data |= data_bit;
else
data &= ~data_bit;
Tdelay(2);
}
} else {
for (i = 0; i < 2; i++) {
ActClk(iobase, 1);
Tdelay(1);
ActClk(iobase, 0);
Tdelay(2);
}
bTmp = ReadReg(iobase, 0x34);
}
for (i = 0; i < 1; i++) {
ActClk(iobase, 1);
Tdelay(1);
ActClk(iobase, 0);
Tdelay(2);
}
ClkTx(iobase, 0, 0);
Tdelay(1);
for (i = 0; i < 3; i++) {
ActClk(iobase, 1);
Tdelay(1);
ActClk(iobase, 0);
Tdelay(2);
}
return data;
}
static void Wr_Indx(__u16 iobase, __u8 addr, __u8 index, __u8 data)
{
int i;
__u8 bTmp;
ClkTx(iobase, 0, 0);
udelay(2);
ActClk(iobase, 1);
udelay(1);
bTmp = addr | (index << 1) | 1;
Wr_Byte(iobase, bTmp);
Wr_Byte(iobase, data);
for (i = 0; i < 2; i++) {
ClkTx(iobase, 0, 0);
Tdelay(2);
ActClk(iobase, 1);
Tdelay(1);
}
ActClk(iobase, 0);
}
static void ResetDongle(__u16 iobase)
{
int i;
ClkTx(iobase, 0, 0);
Tdelay(1);
for (i = 0; i < 30; i++) {
ActClk(iobase, 1);
Tdelay(1);
ActClk(iobase, 0);
Tdelay(1);
}
ActClk(iobase, 0);
}
static void SetSITmode(__u16 iobase)
{
__u8 bTmp;
bTmp = ReadLPCReg(0x28);
WriteLPCReg(0x28, bTmp | 0x10); //select ITMOFF
bTmp = ReadReg(iobase, 0x35);
WriteReg(iobase, 0x35, bTmp | 0x40); // Driver ITMOFF
WriteReg(iobase, 0x28, bTmp | 0x80); // enable All interrupt
}
static void SI_SetMode(__u16 iobase, int mode)
{
//__u32 dTmp;
__u8 bTmp;
WriteLPCReg(0x28, 0x70); // S/W Reset
SetSITmode(iobase);
ResetDongle(iobase);
udelay(10);
Wr_Indx(iobase, 0x40, 0x0, 0x17); //RX ,APEN enable,Normal power
Wr_Indx(iobase, 0x40, 0x1, mode); //Set Mode
Wr_Indx(iobase, 0x40, 0x2, 0xff); //Set power to FIR VFIR > 1m
bTmp = Rd_Indx(iobase, 0x40, 1);
}
static void InitCard(__u16 iobase)
{
ResetChip(iobase, 5);
WriteReg(iobase, I_ST_CT_0, 0x00); // open CHIP on
SetSIRBOF(iobase, 0xc0); // hardware default value
SetSIREOF(iobase, 0xc1);
}
static void CommonInit(__u16 iobase)
{
// EnTXCRC(iobase,0);
SwapDMA(iobase, OFF);
SetMaxRxPacketSize(iobase, 0x0fff); //set to max:4095
EnRXFIFOReadyInt(iobase, OFF);
EnRXFIFOHalfLevelInt(iobase, OFF);
EnTXFIFOHalfLevelInt(iobase, OFF);
EnTXFIFOUnderrunEOMInt(iobase, ON);
// EnTXFIFOReadyInt(iobase,ON);
InvertTX(iobase, OFF);
InvertRX(iobase, OFF);
// WriteLPCReg(0xF0,0); //(if VT1211 then do this)
if (IsSIROn(iobase)) {
SIRFilter(iobase, ON);
SIRRecvAny(iobase, ON);
} else {
SIRFilter(iobase, OFF);
SIRRecvAny(iobase, OFF);
}
EnRXSpecInt(iobase, ON);
WriteReg(iobase, I_ST_CT_0, 0x80);
EnableDMA(iobase, ON);
}
static void SetBaudRate(__u16 iobase, __u32 rate)
{
__u8 value = 11, temp;
if (IsSIROn(iobase)) {
switch (rate) {
case (__u32) (2400L):
value = 47;
break;
case (__u32) (9600L):
value = 11;
break;
case (__u32) (19200L):
value = 5;
break;
case (__u32) (38400L):
value = 2;
break;
case (__u32) (57600L):
value = 1;
break;
case (__u32) (115200L):
value = 0;
break;
default:
break;
};
} else if (IsMIROn(iobase)) {
value = 0; // will automatically be fixed in 1.152M
} else if (IsFIROn(iobase)) {
value = 0; // will automatically be fixed in 4M
}
temp = (ReadReg(iobase, I_CF_H_1) & 0x03);
temp |= value << 2;
WriteReg(iobase, I_CF_H_1, temp);
}
static void SetPulseWidth(__u16 iobase, __u8 width)
{
__u8 temp, temp1, temp2;
temp = (ReadReg(iobase, I_CF_L_1) & 0x1f);
temp1 = (ReadReg(iobase, I_CF_H_1) & 0xfc);
temp2 = (width & 0x07) << 5;
temp |= temp2;
temp2 = (width & 0x18) >> 3;
temp1 |= temp2;
WriteReg(iobase, I_CF_L_1, temp);
WriteReg(iobase, I_CF_H_1, temp1);
}
static void SetSendPreambleCount(__u16 iobase, __u8 count)
{
__u8 temp;
temp = ReadReg(iobase, I_CF_L_1) & 0xe0;
temp |= count;
WriteReg(iobase, I_CF_L_1, temp);
}
static void SetVFIR(__u16 BaseAddr, __u8 val)
{
__u8 tmp;
tmp = ReadReg(BaseAddr, I_CF_L_0);
WriteReg(BaseAddr, I_CF_L_0, tmp & 0x8f);
WriteRegBit(BaseAddr, I_CF_H_0, 5, val);
}
static void SetFIR(__u16 BaseAddr, __u8 val)
{
__u8 tmp;
WriteRegBit(BaseAddr, I_CF_H_0, 5, 0);
tmp = ReadReg(BaseAddr, I_CF_L_0);
WriteReg(BaseAddr, I_CF_L_0, tmp & 0x8f);
WriteRegBit(BaseAddr, I_CF_L_0, 6, val);
}
static void SetMIR(__u16 BaseAddr, __u8 val)
{
__u8 tmp;
WriteRegBit(BaseAddr, I_CF_H_0, 5, 0);
tmp = ReadReg(BaseAddr, I_CF_L_0);
WriteReg(BaseAddr, I_CF_L_0, tmp & 0x8f);
WriteRegBit(BaseAddr, I_CF_L_0, 5, val);
}
static void SetSIR(__u16 BaseAddr, __u8 val)
{
__u8 tmp;
WriteRegBit(BaseAddr, I_CF_H_0, 5, 0);
tmp = ReadReg(BaseAddr, I_CF_L_0);
WriteReg(BaseAddr, I_CF_L_0, tmp & 0x8f);
WriteRegBit(BaseAddr, I_CF_L_0, 4, val);
}
#endif /* via_IRCC_H */

1912
drivers/net/irda/vlsi_ir.c Arquivo normal

Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff

798
drivers/net/irda/vlsi_ir.h Arquivo normal
Ver arquivo

@@ -0,0 +1,798 @@
/*********************************************************************
*
* vlsi_ir.h: VLSI82C147 PCI IrDA controller driver for Linux
*
* Version: 0.5
*
* Copyright (c) 2001-2003 Martin Diehl
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
********************************************************************/
#ifndef IRDA_VLSI_FIR_H
#define IRDA_VLSI_FIR_H
/* ================================================================
* compatibility stuff
*/
/* definitions not present in pci_ids.h */
#ifndef PCI_CLASS_WIRELESS_IRDA
#define PCI_CLASS_WIRELESS_IRDA 0x0d00
#endif
#ifndef PCI_CLASS_SUBCLASS_MASK
#define PCI_CLASS_SUBCLASS_MASK 0xffff
#endif
/* in recent 2.5 interrupt handlers have non-void return value */
#ifndef IRQ_RETVAL
typedef void irqreturn_t;
#define IRQ_NONE
#define IRQ_HANDLED
#define IRQ_RETVAL(x)
#endif
/* some stuff need to check kernelversion. Not all 2.5 stuff was present
* in early 2.5.x - the test is merely to separate 2.4 from 2.5
*/
#include <linux/version.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
/* PDE() introduced in 2.5.4 */
#ifdef CONFIG_PROC_FS
#define PDE(inode) ((inode)->u.generic_ip)
#endif
/* irda crc16 calculation exported in 2.5.42 */
#define irda_calc_crc16(fcs,buf,len) (GOOD_FCS)
/* we use this for unified pci device name access */
#define PCIDEV_NAME(pdev) ((pdev)->name)
#else /* 2.5 or later */
/* recent 2.5/2.6 stores pci device names at varying places ;-) */
#ifdef CONFIG_PCI_NAMES
/* human readable name */
#define PCIDEV_NAME(pdev) ((pdev)->pretty_name)
#else
/* whatever we get from the associated struct device - bus:slot:dev.fn id */
#define PCIDEV_NAME(pdev) (pci_name(pdev))
#endif
#endif
/* ================================================================ */
/* non-standard PCI registers */
enum vlsi_pci_regs {
VLSI_PCI_CLKCTL = 0x40, /* chip clock input control */
VLSI_PCI_MSTRPAGE = 0x41, /* addr [31:24] for all busmaster cycles */
VLSI_PCI_IRMISC = 0x42 /* mainly legacy UART related */
};
/* ------------------------------------------ */
/* VLSI_PCI_CLKCTL: Clock Control Register (u8, rw) */
/* Three possible clock sources: either on-chip 48MHz PLL or
* external clock applied to EXTCLK pin. External clock may
* be either 48MHz or 40MHz, which is indicated by XCKSEL.
* CLKSTP controls whether the selected clock source gets
* connected to the IrDA block.
*
* On my HP OB-800 the BIOS sets external 40MHz clock as source
* when IrDA enabled and I've never detected any PLL lock success.
* Apparently the 14.3...MHz OSC input required for the PLL to work
* is not connected and the 40MHz EXTCLK is provided externally.
* At least this is what makes the driver working for me.
*/
enum vlsi_pci_clkctl {
/* PLL control */
CLKCTL_PD_INV = 0x04, /* PD#: inverted power down signal,
* i.e. PLL is powered, if PD_INV set */
CLKCTL_LOCK = 0x40, /* (ro) set, if PLL is locked */
/* clock source selection */
CLKCTL_EXTCLK = 0x20, /* set to select external clock input, not PLL */
CLKCTL_XCKSEL = 0x10, /* set to indicate EXTCLK is 40MHz, not 48MHz */
/* IrDA block control */
CLKCTL_CLKSTP = 0x80, /* set to disconnect from selected clock source */
CLKCTL_WAKE = 0x08 /* set to enable wakeup feature: whenever IR activity
* is detected, PD_INV gets set(?) and CLKSTP cleared */
};
/* ------------------------------------------ */
/* VLSI_PCI_MSTRPAGE: Master Page Register (u8, rw) and busmastering stuff */
#define DMA_MASK_USED_BY_HW 0xffffffff
#define DMA_MASK_MSTRPAGE 0x00ffffff
#define MSTRPAGE_VALUE (DMA_MASK_MSTRPAGE >> 24)
/* PCI busmastering is somewhat special for this guy - in short:
*
* We select to operate using fixed MSTRPAGE=0, use ISA DMA
* address restrictions to make the PCI BM api aware of this,
* but ensure the hardware is dealing with real 32bit access.
*
* In detail:
* The chip executes normal 32bit busmaster cycles, i.e.
* drives all 32 address lines. These addresses however are
* composed of [0:23] taken from various busaddr-pointers
* and [24:31] taken from the MSTRPAGE register in the VLSI82C147
* config space. Therefore _all_ busmastering must be
* targeted to/from one single 16MB (busaddr-) superpage!
* The point is to make sure all the allocations for memory
* locations with busmaster access (ring descriptors, buffers)
* are indeed bus-mappable to the same 16MB range (for x86 this
* means they must reside in the same 16MB physical memory address
* range). The only constraint we have which supports "several objects
* mappable to common 16MB range" paradigma, is the old ISA DMA
* restriction to the first 16MB of physical address range.
* Hence the approach here is to enable PCI busmaster support using
* the correct 32bit dma-mask used by the chip. Afterwards the device's
* dma-mask gets restricted to 24bit, which must be honoured somehow by
* all allocations for memory areas to be exposed to the chip ...
*
* Note:
* Don't be surprised to get "Setting latency timer..." messages every
* time when PCI busmastering is enabled for the chip.
* The chip has its PCI latency timer RO fixed at 0 - which is not a
* problem here, because it is never requesting _burst_ transactions.
*/
/* ------------------------------------------ */
/* VLSI_PCIIRMISC: IR Miscellaneous Register (u8, rw) */
/* legacy UART emulation - not used by this driver - would require:
* (see below for some register-value definitions)
*
* - IRMISC_UARTEN must be set to enable UART address decoding
* - IRMISC_UARTSEL configured
* - IRCFG_MASTER must be cleared
* - IRCFG_SIR must be set
* - IRENABLE_PHYANDCLOCK must be asserted 0->1 (and hence IRENABLE_SIR_ON)
*/
enum vlsi_pci_irmisc {
/* IR transceiver control */
IRMISC_IRRAIL = 0x40, /* (ro?) IR rail power indication (and control?)
* 0=3.3V / 1=5V. Probably set during power-on?
* unclear - not touched by driver */
IRMISC_IRPD = 0x08, /* transceiver power down, if set */
/* legacy UART control */
IRMISC_UARTTST = 0x80, /* UART test mode - "always write 0" */
IRMISC_UARTEN = 0x04, /* enable UART address decoding */
/* bits [1:0] IRMISC_UARTSEL to select legacy UART address */
IRMISC_UARTSEL_3f8 = 0x00,
IRMISC_UARTSEL_2f8 = 0x01,
IRMISC_UARTSEL_3e8 = 0x02,
IRMISC_UARTSEL_2e8 = 0x03
};
/* ================================================================ */
/* registers mapped to 32 byte PCI IO space */
/* note: better access all registers at the indicated u8/u16 size
* although some of them contain only 1 byte of information.
* some of them (particaluarly PROMPT and IRCFG) ignore
* access when using the wrong addressing mode!
*/
enum vlsi_pio_regs {
VLSI_PIO_IRINTR = 0x00, /* interrupt enable/request (u8, rw) */
VLSI_PIO_RINGPTR = 0x02, /* rx/tx ring pointer (u16, ro) */
VLSI_PIO_RINGBASE = 0x04, /* [23:10] of ring address (u16, rw) */
VLSI_PIO_RINGSIZE = 0x06, /* rx/tx ring size (u16, rw) */
VLSI_PIO_PROMPT = 0x08, /* triggers ring processing (u16, wo) */
/* 0x0a-0x0f: reserved / duplicated UART regs */
VLSI_PIO_IRCFG = 0x10, /* configuration select (u16, rw) */
VLSI_PIO_SIRFLAG = 0x12, /* BOF/EOF for filtered SIR (u16, ro) */
VLSI_PIO_IRENABLE = 0x14, /* enable and status register (u16, rw/ro) */
VLSI_PIO_PHYCTL = 0x16, /* physical layer current status (u16, ro) */
VLSI_PIO_NPHYCTL = 0x18, /* next physical layer select (u16, rw) */
VLSI_PIO_MAXPKT = 0x1a, /* [11:0] max len for packet receive (u16, rw) */
VLSI_PIO_RCVBCNT = 0x1c /* current receive-FIFO byte count (u16, ro) */
/* 0x1e-0x1f: reserved / duplicated UART regs */
};
/* ------------------------------------------ */
/* VLSI_PIO_IRINTR: Interrupt Register (u8, rw) */
/* enable-bits:
* 1 = enable / 0 = disable
* interrupt condition bits:
* set according to corresponding interrupt source
* (regardless of the state of the enable bits)
* enable bit status indicates whether interrupt gets raised
* write-to-clear
* note: RPKTINT and TPKTINT behave different in legacy UART mode (which we don't use :-)
*/
enum vlsi_pio_irintr {
IRINTR_ACTEN = 0x80, /* activity interrupt enable */
IRINTR_ACTIVITY = 0x40, /* activity monitor (traffic detected) */
IRINTR_RPKTEN = 0x20, /* receive packet interrupt enable*/
IRINTR_RPKTINT = 0x10, /* rx-packet transfered from fifo to memory finished */
IRINTR_TPKTEN = 0x08, /* transmit packet interrupt enable */
IRINTR_TPKTINT = 0x04, /* last bit of tx-packet+crc shifted to ir-pulser */
IRINTR_OE_EN = 0x02, /* UART rx fifo overrun error interrupt enable */
IRINTR_OE_INT = 0x01 /* UART rx fifo overrun error (read LSR to clear) */
};
/* we use this mask to check whether the (shared PCI) interrupt is ours */
#define IRINTR_INT_MASK (IRINTR_ACTIVITY|IRINTR_RPKTINT|IRINTR_TPKTINT)
/* ------------------------------------------ */
/* VLSI_PIO_RINGPTR: Ring Pointer Read-Back Register (u16, ro) */
/* _both_ ring pointers are indices relative to the _entire_ rx,tx-ring!
* i.e. the referenced descriptor is located
* at RINGBASE + PTR * sizeof(descr) for rx and tx
* therefore, the tx-pointer has offset MAX_RING_DESCR
*/
#define MAX_RING_DESCR 64 /* tx, rx rings may contain up to 64 descr each */
#define RINGPTR_RX_MASK (MAX_RING_DESCR-1)
#define RINGPTR_TX_MASK ((MAX_RING_DESCR-1)<<8)
#define RINGPTR_GET_RX(p) ((p)&RINGPTR_RX_MASK)
#define RINGPTR_GET_TX(p) (((p)&RINGPTR_TX_MASK)>>8)
/* ------------------------------------------ */
/* VLSI_PIO_RINGBASE: Ring Pointer Base Address Register (u16, ro) */
/* Contains [23:10] part of the ring base (bus-) address
* which must be 1k-alinged. [31:24] is taken from
* VLSI_PCI_MSTRPAGE above.
* The controller initiates non-burst PCI BM cycles to
* fetch and update the descriptors in the ring.
* Once fetched, the descriptor remains cached onchip
* until it gets closed and updated due to the ring
* processing state machine.
* The entire ring area is split in rx and tx areas with each
* area consisting of 64 descriptors of 8 bytes each.
* The rx(tx) ring is located at ringbase+0 (ringbase+64*8).
*/
#define BUS_TO_RINGBASE(p) (((p)>>10)&0x3fff)
/* ------------------------------------------ */
/* VLSI_PIO_RINGSIZE: Ring Size Register (u16, rw) */
/* bit mask to indicate the ring size to be used for rx and tx.
* possible values encoded bits
* 4 0000
* 8 0001
* 16 0011
* 32 0111
* 64 1111
* located at [15:12] for tx and [11:8] for rx ([7:0] unused)
*
* note: probably a good idea to have IRCFG_MSTR cleared when writing
* this so the state machines are stopped and the RINGPTR is reset!
*/
#define SIZE_TO_BITS(num) ((((num)-1)>>2)&0x0f)
#define TX_RX_TO_RINGSIZE(tx,rx) ((SIZE_TO_BITS(tx)<<12)|(SIZE_TO_BITS(rx)<<8))
#define RINGSIZE_TO_RXSIZE(rs) ((((rs)&0x0f00)>>6)+4)
#define RINGSIZE_TO_TXSIZE(rs) ((((rs)&0xf000)>>10)+4)
/* ------------------------------------------ */
/* VLSI_PIO_PROMPT: Ring Prompting Register (u16, write-to-start) */
/* writing any value kicks the ring processing state machines
* for both tx, rx rings as follows:
* - active rings (currently owning an active descriptor)
* ignore the prompt and continue
* - idle rings fetch the next descr from the ring and start
* their processing
*/
/* ------------------------------------------ */
/* VLSI_PIO_IRCFG: IR Config Register (u16, rw) */
/* notes:
* - not more than one SIR/MIR/FIR bit must be set at any time
* - SIR, MIR, FIR and CRC16 select the configuration which will
* be applied on next 0->1 transition of IRENABLE_PHYANDCLOCK (see below).
* - besides allowing the PCI interface to execute busmaster cycles
* and therefore the ring SM to operate, the MSTR bit has side-effects:
* when MSTR is cleared, the RINGPTR's get reset and the legacy UART mode
* (in contrast to busmaster access mode) gets enabled.
* - clearing ENRX or setting ENTX while data is received may stall the
* receive fifo until ENRX reenabled _and_ another packet arrives
* - SIRFILT means the chip performs the required unwrapping of hardware
* headers (XBOF's, BOF/EOF) and un-escaping in the _receive_ direction.
* Only the resulting IrLAP payload is copied to the receive buffers -
* but with the 16bit FCS still encluded. Question remains, whether it
* was already checked or we should do it before passing the packet to IrLAP?
*/
enum vlsi_pio_ircfg {
IRCFG_LOOP = 0x4000, /* enable loopback test mode */
IRCFG_ENTX = 0x1000, /* transmit enable */
IRCFG_ENRX = 0x0800, /* receive enable */
IRCFG_MSTR = 0x0400, /* master enable */
IRCFG_RXANY = 0x0200, /* receive any packet */
IRCFG_CRC16 = 0x0080, /* 16bit (not 32bit) CRC select for MIR/FIR */
IRCFG_FIR = 0x0040, /* FIR 4PPM encoding mode enable */
IRCFG_MIR = 0x0020, /* MIR HDLC encoding mode enable */
IRCFG_SIR = 0x0010, /* SIR encoding mode enable */
IRCFG_SIRFILT = 0x0008, /* enable SIR decode filter (receiver unwrapping) */
IRCFG_SIRTEST = 0x0004, /* allow SIR decode filter when not in SIR mode */
IRCFG_TXPOL = 0x0002, /* invert tx polarity when set */
IRCFG_RXPOL = 0x0001 /* invert rx polarity when set */
};
/* ------------------------------------------ */
/* VLSI_PIO_SIRFLAG: SIR Flag Register (u16, ro) */
/* register contains hardcoded BOF=0xc0 at [7:0] and EOF=0xc1 at [15:8]
* which is used for unwrapping received frames in SIR decode-filter mode
*/
/* ------------------------------------------ */
/* VLSI_PIO_IRENABLE: IR Enable Register (u16, rw/ro) */
/* notes:
* - IREN acts as gate for latching the configured IR mode information
* from IRCFG and IRPHYCTL when IREN=reset and applying them when
* IREN gets set afterwards.
* - ENTXST reflects IRCFG_ENTX
* - ENRXST = IRCFG_ENRX && (!IRCFG_ENTX || IRCFG_LOOP)
*/
enum vlsi_pio_irenable {
IRENABLE_PHYANDCLOCK = 0x8000, /* enable IR phy and gate the mode config (rw) */
IRENABLE_CFGER = 0x4000, /* mode configuration error (ro) */
IRENABLE_FIR_ON = 0x2000, /* FIR on status (ro) */
IRENABLE_MIR_ON = 0x1000, /* MIR on status (ro) */
IRENABLE_SIR_ON = 0x0800, /* SIR on status (ro) */
IRENABLE_ENTXST = 0x0400, /* transmit enable status (ro) */
IRENABLE_ENRXST = 0x0200, /* Receive enable status (ro) */
IRENABLE_CRC16_ON = 0x0100 /* 16bit (not 32bit) CRC enabled status (ro) */
};
#define IRENABLE_MASK 0xff00 /* Read mask */
/* ------------------------------------------ */
/* VLSI_PIO_PHYCTL: IR Physical Layer Current Control Register (u16, ro) */
/* read-back of the currently applied physical layer status.
* applied from VLSI_PIO_NPHYCTL at rising edge of IRENABLE_PHYANDCLOCK
* contents identical to VLSI_PIO_NPHYCTL (see below)
*/
/* ------------------------------------------ */
/* VLSI_PIO_NPHYCTL: IR Physical Layer Next Control Register (u16, rw) */
/* latched during IRENABLE_PHYANDCLOCK=0 and applied at 0-1 transition
*
* consists of BAUD[15:10], PLSWID[9:5] and PREAMB[4:0] bits defined as follows:
*
* SIR-mode: BAUD = (115.2kHz / baudrate) - 1
* PLSWID = (pulsetime * freq / (BAUD+1)) - 1
* where pulsetime is the requested IrPHY pulse width
* and freq is 8(16)MHz for 40(48)MHz primary input clock
* PREAMB: don't care for SIR
*
* The nominal SIR pulse width is 3/16 bit time so we have PLSWID=12
* fixed for all SIR speeds at 40MHz input clock (PLSWID=24 at 48MHz).
* IrPHY also allows shorter pulses down to the nominal pulse duration
* at 115.2kbaud (minus some tolerance) which is 1.41 usec.
* Using the expression PLSWID = 12/(BAUD+1)-1 (multiplied by two for 48MHz)
* we get the minimum acceptable PLSWID values according to the VLSI
* specification, which provides 1.5 usec pulse width for all speeds (except
* for 2.4kbaud getting 6usec). This is fine with IrPHY v1.3 specs and
* reduces the transceiver power which drains the battery. At 9.6kbaud for
* example this amounts to more than 90% battery power saving!
*
* MIR-mode: BAUD = 0
* PLSWID = 9(10) for 40(48) MHz input clock
* to get nominal MIR pulse width
* PREAMB = 1
*
* FIR-mode: BAUD = 0
* PLSWID: don't care
* PREAMB = 15
*/
#define PHYCTL_BAUD_SHIFT 10
#define PHYCTL_BAUD_MASK 0xfc00
#define PHYCTL_PLSWID_SHIFT 5
#define PHYCTL_PLSWID_MASK 0x03e0
#define PHYCTL_PREAMB_SHIFT 0
#define PHYCTL_PREAMB_MASK 0x001f
#define PHYCTL_TO_BAUD(bwp) (((bwp)&PHYCTL_BAUD_MASK)>>PHYCTL_BAUD_SHIFT)
#define PHYCTL_TO_PLSWID(bwp) (((bwp)&PHYCTL_PLSWID_MASK)>>PHYCTL_PLSWID_SHIFT)
#define PHYCTL_TO_PREAMB(bwp) (((bwp)&PHYCTL_PREAMB_MASK)>>PHYCTL_PREAMB_SHIFT)
#define BWP_TO_PHYCTL(b,w,p) ((((b)<<PHYCTL_BAUD_SHIFT)&PHYCTL_BAUD_MASK) \
| (((w)<<PHYCTL_PLSWID_SHIFT)&PHYCTL_PLSWID_MASK) \
| (((p)<<PHYCTL_PREAMB_SHIFT)&PHYCTL_PREAMB_MASK))
#define BAUD_BITS(br) ((115200/(br))-1)
static inline unsigned
calc_width_bits(unsigned baudrate, unsigned widthselect, unsigned clockselect)
{
unsigned tmp;
if (widthselect) /* nominal 3/16 puls width */
return (clockselect) ? 12 : 24;
tmp = ((clockselect) ? 12 : 24) / (BAUD_BITS(baudrate)+1);
/* intermediate result of integer division needed here */
return (tmp>0) ? (tmp-1) : 0;
}
#define PHYCTL_SIR(br,ws,cs) BWP_TO_PHYCTL(BAUD_BITS(br),calc_width_bits((br),(ws),(cs)),0)
#define PHYCTL_MIR(cs) BWP_TO_PHYCTL(0,((cs)?9:10),1)
#define PHYCTL_FIR BWP_TO_PHYCTL(0,0,15)
/* quite ugly, I know. But implementing these calculations here avoids
* having magic numbers in the code and allows some playing with pulsewidths
* without risk to violate the standards.
* FWIW, here is the table for reference:
*
* baudrate BAUD min-PLSWID nom-PLSWID PREAMB
* 2400 47 0(0) 12(24) 0
* 9600 11 0(0) 12(24) 0
* 19200 5 1(2) 12(24) 0
* 38400 2 3(6) 12(24) 0
* 57600 1 5(10) 12(24) 0
* 115200 0 11(22) 12(24) 0
* MIR 0 - 9(10) 1
* FIR 0 - 0 15
*
* note: x(y) means x-value for 40MHz / y-value for 48MHz primary input clock
*/
/* ------------------------------------------ */
/* VLSI_PIO_MAXPKT: Maximum Packet Length register (u16, rw) */
/* maximum acceptable length for received packets */
/* hw imposed limitation - register uses only [11:0] */
#define MAX_PACKET_LENGTH 0x0fff
/* IrLAP I-field (apparently not defined elsewhere) */
#define IRDA_MTU 2048
/* complete packet consists of A(1)+C(1)+I(<=IRDA_MTU) */
#define IRLAP_SKB_ALLOCSIZE (1+1+IRDA_MTU)
/* the buffers we use to exchange frames with the hardware need to be
* larger than IRLAP_SKB_ALLOCSIZE because we may have up to 4 bytes FCS
* appended and, in SIR mode, a lot of frame wrapping bytes. The worst
* case appears to be a SIR packet with I-size==IRDA_MTU and all bytes
* requiring to be escaped to provide transparency. Furthermore, the peer
* might ask for quite a number of additional XBOFs:
* up to 115+48 XBOFS 163
* regular BOF 1
* A-field 1
* C-field 1
* I-field, IRDA_MTU, all escaped 4096
* FCS (16 bit at SIR, escaped) 4
* EOF 1
* AFAICS nothing in IrLAP guarantees A/C field not to need escaping
* (f.e. 0xc0/0xc1 - i.e. BOF/EOF - are legal values there) so in the
* worst case we have 4269 bytes total frame size.
* However, the VLSI uses 12 bits only for all buffer length values,
* which limits the maximum useable buffer size <= 4095.
* Note this is not a limitation in the receive case because we use
* the SIR filtering mode where the hw unwraps the frame and only the
* bare packet+fcs is stored into the buffer - in contrast to the SIR
* tx case where we have to pass frame-wrapped packets to the hw.
* If this would ever become an issue in real life, the only workaround
* I see would be using the legacy UART emulation in SIR mode.
*/
#define XFER_BUF_SIZE MAX_PACKET_LENGTH
/* ------------------------------------------ */
/* VLSI_PIO_RCVBCNT: Receive Byte Count Register (u16, ro) */
/* receive packet counter gets incremented on every non-filtered
* byte which was put in the receive fifo and reset for each
* new packet. Used to decide whether we are just in the middle
* of receiving
*/
/* better apply the [11:0] mask when reading, as some docs say the
* reserved [15:12] would return 1 when reading - which is wrong AFAICS
*/
#define RCVBCNT_MASK 0x0fff
/******************************************************************/
/* descriptors for rx/tx ring
*
* accessed by hardware - don't change!
*
* the descriptor is owned by hardware, when the ACTIVE status bit
* is set and nothing (besides reading status to test the bit)
* shall be done. The bit gets cleared by hw, when the descriptor
* gets closed. Premature reaping of descriptors owned be the chip
* can be achieved by disabling IRCFG_MSTR
*
* Attention: Writing addr overwrites status!
*
* ### FIXME: depends on endianess (but there ain't no non-i586 ob800 ;-)
*/
struct ring_descr_hw {
volatile u16 rd_count; /* tx/rx count [11:0] */
u16 reserved;
union {
u32 addr; /* [23:0] of the buffer's busaddress */
struct {
u8 addr_res[3];
volatile u8 status; /* descriptor status */
} rd_s __attribute__((packed));
} rd_u __attribute((packed));
} __attribute__ ((packed));
#define rd_addr rd_u.addr
#define rd_status rd_u.rd_s.status
/* ring descriptor status bits */
#define RD_ACTIVE 0x80 /* descriptor owned by hw (both TX,RX) */
/* TX ring descriptor status */
#define RD_TX_DISCRC 0x40 /* do not send CRC (for SIR) */
#define RD_TX_BADCRC 0x20 /* force a bad CRC */
#define RD_TX_PULSE 0x10 /* send indication pulse after this frame (MIR/FIR) */
#define RD_TX_FRCEUND 0x08 /* force underrun */
#define RD_TX_CLRENTX 0x04 /* clear ENTX after this frame */
#define RD_TX_UNDRN 0x01 /* TX fifo underrun (probably PCI problem) */
/* RX ring descriptor status */
#define RD_RX_PHYERR 0x40 /* physical encoding error */
#define RD_RX_CRCERR 0x20 /* CRC error (MIR/FIR) */
#define RD_RX_LENGTH 0x10 /* frame exceeds buffer length */
#define RD_RX_OVER 0x08 /* RX fifo overrun (probably PCI problem) */
#define RD_RX_SIRBAD 0x04 /* EOF missing: BOF follows BOF (SIR, filtered) */
#define RD_RX_ERROR 0x7c /* any error in received frame */
/* the memory required to hold the 2 descriptor rings */
#define HW_RING_AREA_SIZE (2 * MAX_RING_DESCR * sizeof(struct ring_descr_hw))
/******************************************************************/
/* sw-ring descriptors consists of a bus-mapped transfer buffer with
* associated skb and a pointer to the hw entry descriptor
*/
struct ring_descr {
struct ring_descr_hw *hw;
struct sk_buff *skb;
void *buf;
};
/* wrappers for operations on hw-exposed ring descriptors
* access to the hw-part of the descriptors must use these.
*/
static inline int rd_is_active(struct ring_descr *rd)
{
return ((rd->hw->rd_status & RD_ACTIVE) != 0);
}
static inline void rd_activate(struct ring_descr *rd)
{
rd->hw->rd_status |= RD_ACTIVE;
}
static inline void rd_set_status(struct ring_descr *rd, u8 s)
{
rd->hw->rd_status = s; /* may pass ownership to the hardware */
}
static inline void rd_set_addr_status(struct ring_descr *rd, dma_addr_t a, u8 s)
{
/* order is important for two reasons:
* - overlayed: writing addr overwrites status
* - we want to write status last so we have valid address in
* case status has RD_ACTIVE set
*/
if ((a & ~DMA_MASK_MSTRPAGE)>>24 != MSTRPAGE_VALUE) {
IRDA_ERROR("%s: pci busaddr inconsistency!\n", __FUNCTION__);
dump_stack();
return;
}
a &= DMA_MASK_MSTRPAGE; /* clear highbyte to make sure we won't write
* to status - just in case MSTRPAGE_VALUE!=0
*/
rd->hw->rd_addr = cpu_to_le32(a);
wmb();
rd_set_status(rd, s); /* may pass ownership to the hardware */
}
static inline void rd_set_count(struct ring_descr *rd, u16 c)
{
rd->hw->rd_count = cpu_to_le16(c);
}
static inline u8 rd_get_status(struct ring_descr *rd)
{
return rd->hw->rd_status;
}
static inline dma_addr_t rd_get_addr(struct ring_descr *rd)
{
dma_addr_t a;
a = le32_to_cpu(rd->hw->rd_addr);
return (a & DMA_MASK_MSTRPAGE) | (MSTRPAGE_VALUE << 24);
}
static inline u16 rd_get_count(struct ring_descr *rd)
{
return le16_to_cpu(rd->hw->rd_count);
}
/******************************************************************/
/* sw descriptor rings for rx, tx:
*
* operations follow producer-consumer paradigm, with the hw
* in the middle doing the processing.
* ring size must be power of two.
*
* producer advances r->tail after inserting for processing
* consumer advances r->head after removing processed rd
* ring is empty if head==tail / full if (tail+1)==head
*/
struct vlsi_ring {
struct pci_dev *pdev;
int dir;
unsigned len;
unsigned size;
unsigned mask;
atomic_t head, tail;
struct ring_descr *rd;
};
/* ring processing helpers */
static inline struct ring_descr *ring_last(struct vlsi_ring *r)
{
int t;
t = atomic_read(&r->tail) & r->mask;
return (((t+1) & r->mask) == (atomic_read(&r->head) & r->mask)) ? NULL : &r->rd[t];
}
static inline struct ring_descr *ring_put(struct vlsi_ring *r)
{
atomic_inc(&r->tail);
return ring_last(r);
}
static inline struct ring_descr *ring_first(struct vlsi_ring *r)
{
int h;
h = atomic_read(&r->head) & r->mask;
return (h == (atomic_read(&r->tail) & r->mask)) ? NULL : &r->rd[h];
}
static inline struct ring_descr *ring_get(struct vlsi_ring *r)
{
atomic_inc(&r->head);
return ring_first(r);
}
/******************************************************************/
/* our private compound VLSI-PCI-IRDA device information */
typedef struct vlsi_irda_dev {
struct pci_dev *pdev;
struct net_device_stats stats;
struct irlap_cb *irlap;
struct qos_info qos;
unsigned mode;
int baud, new_baud;
dma_addr_t busaddr;
void *virtaddr;
struct vlsi_ring *tx_ring, *rx_ring;
struct timeval last_rx;
spinlock_t lock;
struct semaphore sem;
u8 resume_ok;
struct proc_dir_entry *proc_entry;
} vlsi_irda_dev_t;
/********************************************************/
/* the remapped error flags we use for returning from frame
* post-processing in vlsi_process_tx/rx() after it was completed
* by the hardware. These functions either return the >=0 number
* of transfered bytes in case of success or the negative (-)
* of the or'ed error flags.
*/
#define VLSI_TX_DROP 0x0001
#define VLSI_TX_FIFO 0x0002
#define VLSI_RX_DROP 0x0100
#define VLSI_RX_OVER 0x0200
#define VLSI_RX_LENGTH 0x0400
#define VLSI_RX_FRAME 0x0800
#define VLSI_RX_CRC 0x1000
/********************************************************/
#endif /* IRDA_VLSI_FIR_H */

53
drivers/net/irda/w83977af.h Arquivo normal
Ver arquivo

@@ -0,0 +1,53 @@
#ifndef W83977AF_H
#define W83977AF_H
#define W977_EFIO_BASE 0x370
#define W977_EFIO2_BASE 0x3f0
#define W977_DEVICE_IR 0x06
/*
* Enter extended function mode
*/
static inline void w977_efm_enter(unsigned int efio)
{
outb(0x87, efio);
outb(0x87, efio);
}
/*
* Select a device to configure
*/
static inline void w977_select_device(__u8 devnum, unsigned int efio)
{
outb(0x07, efio);
outb(devnum, efio+1);
}
/*
* Write a byte to a register
*/
static inline void w977_write_reg(__u8 reg, __u8 value, unsigned int efio)
{
outb(reg, efio);
outb(value, efio+1);
}
/*
* read a byte from a register
*/
static inline __u8 w977_read_reg(__u8 reg, unsigned int efio)
{
outb(reg, efio);
return inb(efio+1);
}
/*
* Exit extended function mode
*/
static inline void w977_efm_exit(unsigned int efio)
{
outb(0xAA, efio);
}
#endif

1379
drivers/net/irda/w83977af_ir.c Arquivo normal

Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff

199
drivers/net/irda/w83977af_ir.h Arquivo normal
Ver arquivo

@@ -0,0 +1,199 @@
/*********************************************************************
*
* Filename: w83977af_ir.h
* Version:
* Description:
* Status: Experimental.
* Author: Paul VanderSpek
* Created at: Thu Nov 19 13:55:34 1998
* Modified at: Tue Jan 11 13:08:19 2000
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1998-2000 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<6D> admit liability nor
* provide warranty for any of this software. This material is
* provided "AS-IS" and at no charge.
*
********************************************************************/
#ifndef W83977AF_IR_H
#define W83977AF_IR_H
#include <asm/io.h>
#include <linux/types.h>
/* Flags for configuration register CRF0 */
#define ENBNKSEL 0x01
#define APEDCRC 0x02
#define TXW4C 0x04
#define RXW4C 0x08
/* Bank 0 */
#define RBR 0x00 /* Receiver buffer register */
#define TBR 0x00 /* Transmitter buffer register */
#define ICR 0x01 /* Interrupt configuration register */
#define ICR_ERBRI 0x01 /* Receiver buffer register interrupt */
#define ICR_ETBREI 0x02 /* Transeiver empty interrupt */
#define ICR_EUSRI 0x04//* IR status interrupt */
#define ICR_EHSRI 0x04
#define ICR_ETXURI 0x04 /* Tx underrun */
#define ICR_EDMAI 0x10 /* DMA interrupt */
#define ICR_ETXTHI 0x20 /* Transmitter threshold interrupt */
#define ICR_EFSFI 0x40 /* Frame status FIFO interrupt */
#define ICR_ETMRI 0x80 /* Timer interrupt */
#define UFR 0x02 /* FIFO control register */
#define UFR_EN_FIFO 0x01 /* Enable FIFO's */
#define UFR_RXF_RST 0x02 /* Reset Rx FIFO */
#define UFR_TXF_RST 0x04 /* Reset Tx FIFO */
#define UFR_RXTL 0x80 /* Rx FIFO threshold (set to 16) */
#define UFR_TXTL 0x20 /* Tx FIFO threshold (set to 17) */
#define ISR 0x02 /* Interrupt status register */
#define ISR_RXTH_I 0x01 /* Receive threshold interrupt */
#define ISR_TXEMP_I 0x02 /* Transmitter empty interrupt */
#define ISR_FEND_I 0x04
#define ISR_DMA_I 0x10
#define ISR_TXTH_I 0x20 /* Transmitter threshold interrupt */
#define ISR_FSF_I 0x40
#define ISR_TMR_I 0x80 /* Timer interrupt */
#define UCR 0x03 /* Uart control register */
#define UCR_DLS8 0x03 /* 8N1 */
#define SSR 0x03 /* Sets select register */
#define SET0 UCR_DLS8 /* Make sure we keep 8N1 */
#define SET1 (0x80|UCR_DLS8) /* Make sure we keep 8N1 */
#define SET2 0xE0
#define SET3 0xE4
#define SET4 0xE8
#define SET5 0xEC
#define SET6 0xF0
#define SET7 0xF4
#define HCR 0x04
#define HCR_MODE_MASK ~(0xD0)
#define HCR_SIR 0x60
#define HCR_MIR_576 0x20
#define HCR_MIR_1152 0x80
#define HCR_FIR 0xA0
#define HCR_EN_DMA 0x04
#define HCR_EN_IRQ 0x08
#define HCR_TX_WT 0x08
#define USR 0x05 /* IR status register */
#define USR_RDR 0x01 /* Receive data ready */
#define USR_TSRE 0x40 /* Transmitter empty? */
#define AUDR 0x07
#define AUDR_SFEND 0x08 /* Set a frame end */
#define AUDR_RXBSY 0x20 /* Rx busy */
#define AUDR_UNDR 0x40 /* Transeiver underrun */
/* Set 2 */
#define ABLL 0x00 /* Advanced baud rate divisor latch (low byte) */
#define ABHL 0x01 /* Advanced baud rate divisor latch (high byte) */
#define ADCR1 0x02
#define ADCR1_ADV_SL 0x01
#define ADCR1_D_CHSW 0x08 /* the specs are wrong. its bit 3, not 4 */
#define ADCR1_DMA_F 0x02
#define ADCR2 0x04
#define ADCR2_TXFS32 0x01
#define ADCR2_RXFS32 0x04
#define RXFDTH 0x07
/* Set 3 */
#define AUID 0x00
/* Set 4 */
#define TMRL 0x00 /* Timer value register (low byte) */
#define TMRH 0x01 /* Timer value register (high byte) */
#define IR_MSL 0x02 /* Infrared mode select */
#define IR_MSL_EN_TMR 0x01 /* Enable timer */
#define TFRLL 0x04 /* Transmitter frame length (low byte) */
#define TFRLH 0x05 /* Transmitter frame length (high byte) */
#define RFRLL 0x06 /* Receiver frame length (low byte) */
#define RFRLH 0x07 /* Receiver frame length (high byte) */
/* Set 5 */
#define FS_FO 0x05 /* Frame status FIFO */
#define FS_FO_FSFDR 0x80 /* Frame status FIFO data ready */
#define FS_FO_LST_FR 0x40 /* Frame lost */
#define FS_FO_MX_LEX 0x10 /* Max frame len exceeded */
#define FS_FO_PHY_ERR 0x08 /* Physical layer error */
#define FS_FO_CRC_ERR 0x04
#define FS_FO_RX_OV 0x02 /* Receive overrun */
#define FS_FO_FSF_OV 0x01 /* Frame status FIFO overrun */
#define FS_FO_ERR_MSK 0x5f /* Error mask */
#define RFLFL 0x06
#define RFLFH 0x07
/* Set 6 */
#define IR_CFG2 0x00
#define IR_CFG2_DIS_CRC 0x02
/* Set 7 */
#define IRM_CR 0x07 /* Infrared module control register */
#define IRM_CR_IRX_MSL 0x40
#define IRM_CR_AF_MNT 0x80 /* Automatic format */
/* For storing entries in the status FIFO */
struct st_fifo_entry {
int status;
int len;
};
struct st_fifo {
struct st_fifo_entry entries[10];
int head;
int tail;
int len;
};
/* Private data for each instance */
struct w83977af_ir {
struct st_fifo st_fifo;
int tx_buff_offsets[10]; /* Offsets between frames in tx_buff */
int tx_len; /* Number of frames in tx_buff */
struct net_device *netdev; /* Yes! we are some kind of netdevice */
struct net_device_stats stats;
struct irlap_cb *irlap; /* The link layer we are binded to */
struct qos_info qos; /* QoS capabilities for this device */
chipio_t io; /* IrDA controller information */
iobuff_t tx_buff; /* Transmit buffer */
iobuff_t rx_buff; /* Receive buffer */
dma_addr_t tx_buff_dma;
dma_addr_t rx_buff_dma;
/* Note : currently locking is *very* incomplete, but this
* will get you started. Check in nsc-ircc.c for a proper
* locking strategy. - Jean II */
spinlock_t lock; /* For serializing operations */
__u32 new_speed;
};
static inline void switch_bank( int iobase, int set)
{
outb(set, iobase+SSR);
}
#endif