diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-08-27 18:03:32 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-08-29 02:42:57 +0300 |
commit | 6c391ff758eb9f41e11c6143fd5bdb3b3324bf9f (patch) | |
tree | 95ee8f47eacb698ecb3de600e73f07bde3f0d404 /drivers/net/irda | |
parent | 1ca163afb6fd569b6efdc221954177cba5a02cbc (diff) | |
download | linux-6c391ff758eb9f41e11c6143fd5bdb3b3324bf9f.tar.xz |
irda: move drivers/net/irda to drivers/staging/irda/drivers
Move the irda drivers from drivers/net/irda/ to
drivers/staging/irda/drivers as they will be deleted in a future kernel
release.
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/irda')
47 files changed, 0 insertions, 33483 deletions
diff --git a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig deleted file mode 100644 index e070e1222733..000000000000 --- a/drivers/net/irda/Kconfig +++ /dev/null @@ -1,398 +0,0 @@ -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 && TTY - 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. - -config BFIN_SIR - tristate "Blackfin SIR on UART" - depends on BLACKFIN && IRDA - default n - help - Say Y here if your want to enable SIR function on Blackfin UART - devices. - - To activate this driver you can start irattach like: - "irattach irda0 -s" - - Saying M, it will be built as a module named bfin_sir. - - Note that you need to turn off one of the serial drivers for SIR - to use that UART. - -config BFIN_SIR0 - bool "Blackfin SIR on UART0" - depends on BFIN_SIR && !SERIAL_BFIN_UART0 - -config BFIN_SIR1 - bool "Blackfin SIR on UART1" - depends on BFIN_SIR && !SERIAL_BFIN_UART1 && (!BF531 && !BF532 && !BF533 && !BF561) - -config BFIN_SIR2 - bool "Blackfin SIR on UART2" - depends on BFIN_SIR && !SERIAL_BFIN_UART2 && (BF54x || BF538 || BF539) - -config BFIN_SIR3 - bool "Blackfin SIR on UART3" - depends on BFIN_SIR && !SERIAL_BFIN_UART3 && (BF54x) - -choice - prompt "SIR Mode" - depends on BFIN_SIR - default SIR_BFIN_DMA - -config SIR_BFIN_DMA - bool "DMA mode" - depends on !DMA_UNCACHED_NONE - -config SIR_BFIN_PIO - bool "PIO mode" -endchoice - -config SH_SIR - tristate "SuperH SIR on UART" - depends on IRDA && SUPERH && \ - (CPU_SUBTYPE_SH7722 || CPU_SUBTYPE_SH7723 || \ - CPU_SUBTYPE_SH7724) - default n - help - Say Y here if your want to enable SIR function on SuperH UART - devices. - -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 IRTTY_SIR && 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 IRTTY_SIR && 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 IRTTY_SIR && 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 TOIM3232_DONGLE - tristate "TOIM3232 IrDa dongle" - depends on IRTTY_SIR && DONGLE && IRDA - help - Say Y here if you want to build support for the Vishay/Temic - TOIM3232 and TOIM4232 based dongles. - To compile it as a module, choose M here. - -config LITELINK_DONGLE - tristate "Parallax LiteLink dongle" - depends on IRTTY_SIR && 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 IRTTY_SIR && DONGLE && 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 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 IRTTY_SIR && DONGLE && IRDA - 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 IRTTY_SIR && DONGLE && IRDA - 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 IRTTY_SIR && DONGLE && IRDA - 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-sir.c>. - -config ACT200L_DONGLE - tristate "ACTiSYS IR-200L dongle" - depends on IRTTY_SIR && DONGLE && IRDA - 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". - -config KINGSUN_DONGLE - tristate "KingSun/DonShine DS-620 IrDA-USB dongle" - depends on IRDA && USB - help - Say Y or M here if you want to build support for the KingSun/DonShine - DS-620 IrDA-USB bridge device driver. - - This USB bridge does not conform to the IrDA-USB device class - specification, and therefore needs its own specific driver. This - dongle supports SIR speed only (9600 bps). - - To compile it as a module, choose M here: the module will be called - kingsun-sir. - -config KSDAZZLE_DONGLE - tristate "KingSun Dazzle IrDA-USB dongle" - depends on IRDA && USB - help - Say Y or M here if you want to build support for the KingSun Dazzle - IrDA-USB bridge device driver. - - This USB bridge does not conform to the IrDA-USB device class - specification, and therefore needs its own specific driver. This - dongle supports SIR speeds only (9600 through 115200 bps). - - To compile it as a module, choose M here: the module will be called - ksdazzle-sir. - -config KS959_DONGLE - tristate "KingSun KS-959 IrDA-USB dongle" - depends on IRDA && USB - help - Say Y or M here if you want to build support for the KingSun KS-959 - IrDA-USB bridge device driver. - - This USB bridge does not conform to the IrDA-USB device class - specification, and therefore needs its own specific driver. This - dongle supports SIR speeds only (9600 through 57600 bps). - - To compile it as a module, choose M here: the module will be called - ks959-sir. - -comment "FIR device drivers" - -config USB_IRDA - tristate "IrDA USB dongles" - depends on IRDA && USB - select FW_LOADER - ---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 peculiarities. 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" - depends on IRDA && USB - 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_DMA_API - 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_DMA_API - 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 && VIRT_TO_BUS - 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 IrDA SIR/FIR" - depends on IRDA && MIPS_ALCHEMY - help - Say Y/M here to build support the IrDA peripheral on the - Alchemy Au1000 and Au1100 SoCs. - Say M to build a module; it will be called au1k_ir.ko - -config SMC_IRCC_FIR - tristate "SMSC IrCC" - depends on IRDA && ISA_DMA_API - 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" - depends on IRDA && ISA_DMA_API - 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 South 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" - depends on 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 && DMA_SA11X0 - -config VIA_FIR - tristate "VIA VT8231/VT1211 SIR/MIR/FIR" - depends on IRDA && ISA_DMA_API - 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 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. - -config PXA_FICP - tristate "Intel PXA2xx Internal FICP" - depends on ARCH_PXA && IRDA - help - Say Y or M here if you want to build support for the PXA2xx - built-in IRDA interface which can support both SIR and FIR. - This driver relies on platform specific helper routines so - available capabilities may vary from one PXA2xx target to - another. - -config MCS_FIR - tristate "MosChip MCS7780 IrDA-USB dongle" - depends on IRDA && USB - select CRC32 - help - Say Y or M here if you want to build support for the MosChip - MCS7780 IrDA-USB bridge device driver. - - USB bridge based on the MosChip MCS7780 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 - mcs7780. - -endmenu - diff --git a/drivers/net/irda/Makefile b/drivers/net/irda/Makefile deleted file mode 100644 index 4c344433dae5..000000000000 --- a/drivers/net/irda/Makefile +++ /dev/null @@ -1,42 +0,0 @@ -# -# 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. -# - -# 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 -obj-$(CONFIG_PXA_FICP) += pxaficp_ir.o -obj-$(CONFIG_MCS_FIR) += mcs7780.o -obj-$(CONFIG_AU1000_FIR) += au1k_ir.o -# SIR drivers -obj-$(CONFIG_IRTTY_SIR) += irtty-sir.o sir-dev.o -obj-$(CONFIG_BFIN_SIR) += bfin_sir.o -obj-$(CONFIG_SH_SIR) += sh_sir.o -# dongle drivers for 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 -obj-$(CONFIG_TOIM3232_DONGLE) += toim3232-sir.o -obj-$(CONFIG_KINGSUN_DONGLE) += kingsun-sir.o -obj-$(CONFIG_KSDAZZLE_DONGLE) += ksdazzle-sir.o -obj-$(CONFIG_KS959_DONGLE) += ks959-sir.o - -# The SIR helper module -sir-dev-objs := sir_dev.o sir_dongle.o diff --git a/drivers/net/irda/act200l-sir.c b/drivers/net/irda/act200l-sir.c deleted file mode 100644 index e8917511e1aa..000000000000 --- a/drivers/net/irda/act200l-sir.c +++ /dev/null @@ -1,250 +0,0 @@ -/********************************************************************* - * - * 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; - - /* 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) -{ - /* 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; - - /* 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; - static const 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; - - 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: - net_err_ratelimited("%s(), unknown state %d\n", - __func__, 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); diff --git a/drivers/net/irda/actisys-sir.c b/drivers/net/irda/actisys-sir.c deleted file mode 100644 index e224b8b99517..000000000000 --- a/drivers/net/irda/actisys-sir.c +++ /dev/null @@ -1,245 +0,0 @@ -/********************************************************************* - * - * 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ø 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 ARRAY_SIZE(baud_rates) - -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; - - pr_debug("%s(), speed=%d (was %d)\n", __func__, 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); diff --git a/drivers/net/irda/ali-ircc.c b/drivers/net/irda/ali-ircc.c deleted file mode 100644 index 35f198d83701..000000000000 --- a/drivers/net/irda/ali-ircc.c +++ /dev/null @@ -1,2218 +0,0 @@ -/********************************************************************* - * - * 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:55PM - * Modified by: Benjamin Kong <benjamin_kong@ali.com.tw> - * Modified at: 2003/11/6 and support for ALi south-bridge chipsets M1563 - * Modified by: Clear Zhang <clear_zhang@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. - * - ********************************************************************/ - -#include <linux/module.h> -#include <linux/gfp.h> - -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/skbuff.h> -#include <linux/netdevice.h> -#include <linux/ioport.h> -#include <linux/delay.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/rtnetlink.h> -#include <linux/serial_reg.h> -#include <linux/dma-mapping.h> -#include <linux/platform_device.h> - -#include <asm/io.h> -#include <asm/dma.h> -#include <asm/byteorder.h> - -#include <net/irda/wrapper.h> -#include <net/irda/irda.h> -#include <net/irda/irda_device.h> - -#include "ali-ircc.h" - -#define CHIP_IO_EXTENT 8 -#define BROKEN_DONGLE_ID - -#define ALI_IRCC_DRIVER_NAME "ali-ircc" - -/* Power Management */ -static int ali_ircc_suspend(struct platform_device *dev, pm_message_t state); -static int ali_ircc_resume(struct platform_device *dev); - -static struct platform_driver ali_ircc_driver = { - .suspend = ali_ircc_suspend, - .resume = ali_ircc_resume, - .driver = { - .name = ALI_IRCC_DRIVER_NAME, - }, -}; - -/* Module parameters */ -static int qos_mtt_bits = 0x07; /* 1 ms or more */ - -/* Use BIOS settions by default, but user may supply module parameters */ -static unsigned int io[] = { ~0, ~0, ~0, ~0 }; -static unsigned int irq[] = { 0, 0, 0, 0 }; -static unsigned int dma[] = { 0, 0, 0, 0 }; - -static int ali_ircc_probe_53(ali_chip_t *chip, chipio_t *info); -static int ali_ircc_init_43(ali_chip_t *chip, chipio_t *info); -static int ali_ircc_init_53(ali_chip_t *chip, chipio_t *info); - -/* These are the currently known ALi south-bridge chipsets, the only one difference - * is that M1543C doesn't support HP HDSL-3600 - */ -static ali_chip_t chips[] = -{ - { "M1543", { 0x3f0, 0x370 }, 0x51, 0x23, 0x20, 0x43, ali_ircc_probe_53, ali_ircc_init_43 }, - { "M1535", { 0x3f0, 0x370 }, 0x51, 0x23, 0x20, 0x53, ali_ircc_probe_53, ali_ircc_init_53 }, - { "M1563", { 0x3f0, 0x370 }, 0x51, 0x23, 0x20, 0x63, ali_ircc_probe_53, ali_ircc_init_53 }, - { NULL } -}; - -/* Max 4 instances for now */ -static struct ali_ircc_cb *dev_self[] = { NULL, NULL, NULL, NULL }; - -/* Dongle Types */ -static char *dongle_types[] = { - "TFDS6000", - "HP HSDL-3600", - "HP HSDL-1100", - "No dongle connected", -}; - -/* Some prototypes */ -static int ali_ircc_open(int i, chipio_t *info); - -static int ali_ircc_close(struct ali_ircc_cb *self); - -static int ali_ircc_setup(chipio_t *info); -static int ali_ircc_is_receiving(struct ali_ircc_cb *self); -static int ali_ircc_net_open(struct net_device *dev); -static int ali_ircc_net_close(struct net_device *dev); -static int ali_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); -static void ali_ircc_change_speed(struct ali_ircc_cb *self, __u32 baud); - -/* SIR function */ -static netdev_tx_t ali_ircc_sir_hard_xmit(struct sk_buff *skb, - struct net_device *dev); -static irqreturn_t ali_ircc_sir_interrupt(struct ali_ircc_cb *self); -static void ali_ircc_sir_receive(struct ali_ircc_cb *self); -static void ali_ircc_sir_write_wakeup(struct ali_ircc_cb *self); -static int ali_ircc_sir_write(int iobase, int fifo_size, __u8 *buf, int len); -static void ali_ircc_sir_change_speed(struct ali_ircc_cb *priv, __u32 speed); - -/* FIR function */ -static netdev_tx_t ali_ircc_fir_hard_xmit(struct sk_buff *skb, - struct net_device *dev); -static void ali_ircc_fir_change_speed(struct ali_ircc_cb *priv, __u32 speed); -static irqreturn_t ali_ircc_fir_interrupt(struct ali_ircc_cb *self); -static int ali_ircc_dma_receive(struct ali_ircc_cb *self); -static int ali_ircc_dma_receive_complete(struct ali_ircc_cb *self); -static int ali_ircc_dma_xmit_complete(struct ali_ircc_cb *self); -static void ali_ircc_dma_xmit(struct ali_ircc_cb *self); - -/* My Function */ -static int ali_ircc_read_dongle_id (int i, chipio_t *info); -static void ali_ircc_change_dongle_speed(struct ali_ircc_cb *priv, int speed); - -/* ALi chip function */ -static void SIR2FIR(int iobase); -static void FIR2SIR(int iobase); -static void SetCOMInterrupts(struct ali_ircc_cb *self , unsigned char enable); - -/* - * Function ali_ircc_init () - * - * Initialize chip. Find out whay kinds of chips we are dealing with - * and their configuration registers address - */ -static int __init ali_ircc_init(void) -{ - ali_chip_t *chip; - chipio_t info; - int ret; - int cfg, cfg_base; - int reg, revision; - int i = 0; - - ret = platform_driver_register(&ali_ircc_driver); - if (ret) { - net_err_ratelimited("%s, Can't register driver!\n", - ALI_IRCC_DRIVER_NAME); - return ret; - } - - ret = -ENODEV; - - /* Probe for all the ALi chipsets we know about */ - for (chip= chips; chip->name; chip++, i++) - { - pr_debug("%s(), Probing for %s ...\n", __func__, chip->name); - - /* Try all config registers for this chip */ - for (cfg=0; cfg<2; cfg++) - { - cfg_base = chip->cfg[cfg]; - if (!cfg_base) - continue; - - memset(&info, 0, sizeof(chipio_t)); - info.cfg_base = cfg_base; - info.fir_base = io[i]; - info.dma = dma[i]; - info.irq = irq[i]; - - - /* Enter Configuration */ - outb(chip->entr1, cfg_base); - outb(chip->entr2, cfg_base); - - /* Select Logical Device 5 Registers (UART2) */ - outb(0x07, cfg_base); - outb(0x05, cfg_base+1); - - /* Read Chip Identification Register */ - outb(chip->cid_index, cfg_base); - reg = inb(cfg_base+1); - - if (reg == chip->cid_value) - { - pr_debug("%s(), Chip found at 0x%03x\n", - __func__, cfg_base); - - outb(0x1F, cfg_base); - revision = inb(cfg_base+1); - pr_debug("%s(), Found %s chip, revision=%d\n", - __func__, chip->name, revision); - - /* - * If the user supplies the base address, then - * we init the chip, if not we probe the values - * set by the BIOS - */ - if (io[i] < 2000) - { - chip->init(chip, &info); - } - else - { - chip->probe(chip, &info); - } - - if (ali_ircc_open(i, &info) == 0) - ret = 0; - i++; - } - else - { - pr_debug("%s(), No %s chip at 0x%03x\n", - __func__, chip->name, cfg_base); - } - /* Exit configuration */ - outb(0xbb, cfg_base); - } - } - - if (ret) - platform_driver_unregister(&ali_ircc_driver); - - return ret; -} - -/* - * Function ali_ircc_cleanup () - * - * Close all configured chips - * - */ -static void __exit ali_ircc_cleanup(void) -{ - int i; - - for (i=0; i < ARRAY_SIZE(dev_self); i++) { - if (dev_self[i]) - ali_ircc_close(dev_self[i]); - } - - platform_driver_unregister(&ali_ircc_driver); - -} - -static const struct net_device_ops ali_ircc_sir_ops = { - .ndo_open = ali_ircc_net_open, - .ndo_stop = ali_ircc_net_close, - .ndo_start_xmit = ali_ircc_sir_hard_xmit, - .ndo_do_ioctl = ali_ircc_net_ioctl, -}; - -static const struct net_device_ops ali_ircc_fir_ops = { - .ndo_open = ali_ircc_net_open, - .ndo_stop = ali_ircc_net_close, - .ndo_start_xmit = ali_ircc_fir_hard_xmit, - .ndo_do_ioctl = ali_ircc_net_ioctl, -}; - -/* - * Function ali_ircc_open (int i, chipio_t *inf) - * - * Open driver instance - * - */ -static int ali_ircc_open(int i, chipio_t *info) -{ - struct net_device *dev; - struct ali_ircc_cb *self; - int dongle_id; - int err; - - if (i >= ARRAY_SIZE(dev_self)) { - net_err_ratelimited("%s(), maximum number of supported chips reached!\n", - __func__); - return -ENOMEM; - } - - /* Set FIR FIFO and DMA Threshold */ - if ((ali_ircc_setup(info)) == -1) - return -1; - - dev = alloc_irdadev(sizeof(*self)); - if (dev == NULL) { - net_err_ratelimited("%s(), can't allocate memory for control block!\n", - __func__); - return -ENOMEM; - } - - self = netdev_priv(dev); - self->netdev = dev; - spin_lock_init(&self->lock); - - /* Need to store self somewhere */ - dev_self[i] = self; - self->index = i; - - /* Initialize IO */ - self->io.cfg_base = info->cfg_base; /* In ali_ircc_probe_53 assign */ - self->io.fir_base = info->fir_base; /* info->sir_base = info->fir_base */ - self->io.sir_base = info->sir_base; /* ALi SIR and FIR use the same address */ - self->io.irq = info->irq; - self->io.fir_ext = CHIP_IO_EXTENT; - self->io.dma = info->dma; - self->io.fifo_size = 16; /* SIR: 16, FIR: 32 Benjamin 2000/11/1 */ - - /* Reserve the ioports that we need */ - if (!request_region(self->io.fir_base, self->io.fir_ext, - ALI_IRCC_DRIVER_NAME)) { - net_warn_ratelimited("%s(), can't get iobase of 0x%03x\n", - __func__, self->io.fir_base); - err = -ENODEV; - goto err_out1; - } - - /* Initialize QoS for this device */ - irda_init_max_qos_capabilies(&self->qos); - - /* The only value we must override it the baudrate */ - self->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600| - IR_115200|IR_576000|IR_1152000|(IR_4000000 << 8); // benjamin 2000/11/8 05:27PM - - self->qos.min_turn_time.bits = qos_mtt_bits; - - irda_qos_bits_to_value(&self->qos); - - /* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */ - self->rx_buff.truesize = 14384; - self->tx_buff.truesize = 14384; - - /* Allocate memory if needed */ - self->rx_buff.head = - dma_zalloc_coherent(NULL, self->rx_buff.truesize, - &self->rx_buff_dma, GFP_KERNEL); - if (self->rx_buff.head == NULL) { - err = -ENOMEM; - goto err_out2; - } - - self->tx_buff.head = - dma_zalloc_coherent(NULL, self->tx_buff.truesize, - &self->tx_buff_dma, GFP_KERNEL); - if (self->tx_buff.head == NULL) { - err = -ENOMEM; - goto err_out3; - } - - self->rx_buff.in_frame = FALSE; - self->rx_buff.state = OUTSIDE_FRAME; - self->tx_buff.data = self->tx_buff.head; - self->rx_buff.data = self->rx_buff.head; - - /* Reset Tx queue info */ - self->tx_fifo.len = self->tx_fifo.ptr = self->tx_fifo.free = 0; - self->tx_fifo.tail = self->tx_buff.head; - - /* Override the network functions we need to use */ - dev->netdev_ops = &ali_ircc_sir_ops; - - err = register_netdev(dev); - if (err) { - net_err_ratelimited("%s(), register_netdev() failed!\n", - __func__); - goto err_out4; - } - net_info_ratelimited("IrDA: Registered device %s\n", dev->name); - - /* Check dongle id */ - dongle_id = ali_ircc_read_dongle_id(i, info); - net_info_ratelimited("%s(), %s, Found dongle: %s\n", - __func__, ALI_IRCC_DRIVER_NAME, - dongle_types[dongle_id]); - - self->io.dongle_id = dongle_id; - - - return 0; - - err_out4: - dma_free_coherent(NULL, self->tx_buff.truesize, - self->tx_buff.head, self->tx_buff_dma); - err_out3: - dma_free_coherent(NULL, self->rx_buff.truesize, - self->rx_buff.head, self->rx_buff_dma); - err_out2: - release_region(self->io.fir_base, self->io.fir_ext); - err_out1: - dev_self[i] = NULL; - free_netdev(dev); - return err; -} - - -/* - * Function ali_ircc_close (self) - * - * Close driver instance - * - */ -static int __exit ali_ircc_close(struct ali_ircc_cb *self) -{ - int iobase; - - IRDA_ASSERT(self != NULL, return -1;); - - iobase = self->io.fir_base; - - /* Remove netdevice */ - unregister_netdev(self->netdev); - - /* Release the PORT that this driver is using */ - pr_debug("%s(), Releasing Region %03x\n", __func__, self->io.fir_base); - release_region(self->io.fir_base, self->io.fir_ext); - - if (self->tx_buff.head) - dma_free_coherent(NULL, self->tx_buff.truesize, - self->tx_buff.head, self->tx_buff_dma); - - if (self->rx_buff.head) - dma_free_coherent(NULL, self->rx_buff.truesize, - self->rx_buff.head, self->rx_buff_dma); - - dev_self[self->index] = NULL; - free_netdev(self->netdev); - - - return 0; -} - -/* - * Function ali_ircc_init_43 (chip, info) - * - * Initialize the ALi M1543 chip. - */ -static int ali_ircc_init_43(ali_chip_t *chip, chipio_t *info) -{ - /* All controller information like I/O address, DMA channel, IRQ - * are set by BIOS - */ - - return 0; -} - -/* - * Function ali_ircc_init_53 (chip, info) - * - * Initialize the ALi M1535 chip. - */ -static int ali_ircc_init_53(ali_chip_t *chip, chipio_t *info) -{ - /* All controller information like I/O address, DMA channel, IRQ - * are set by BIOS - */ - - return 0; -} - -/* - * Function ali_ircc_probe_53 (chip, info) - * - * Probes for the ALi M1535D or M1535 - */ -static int ali_ircc_probe_53(ali_chip_t *chip, chipio_t *info) -{ - int cfg_base = info->cfg_base; - int hi, low, reg; - - - /* Enter Configuration */ - outb(chip->entr1, cfg_base); - outb(chip->entr2, cfg_base); - - /* Select Logical Device 5 Registers (UART2) */ - outb(0x07, cfg_base); - outb(0x05, cfg_base+1); - - /* Read address control register */ - outb(0x60, cfg_base); - hi = inb(cfg_base+1); - outb(0x61, cfg_base); - low = inb(cfg_base+1); - info->fir_base = (hi<<8) + low; - - info->sir_base = info->fir_base; - - pr_debug("%s(), probing fir_base=0x%03x\n", __func__, info->fir_base); - - /* Read IRQ control register */ - outb(0x70, cfg_base); - reg = inb(cfg_base+1); - info->irq = reg & 0x0f; - pr_debug("%s(), probing irq=%d\n", __func__, info->irq); - - /* Read DMA channel */ - outb(0x74, cfg_base); - reg = inb(cfg_base+1); - info->dma = reg & 0x07; - - if(info->dma == 0x04) - net_warn_ratelimited("%s(), No DMA channel assigned !\n", - __func__); - else - pr_debug("%s(), probing dma=%d\n", __func__, info->dma); - - /* Read Enabled Status */ - outb(0x30, cfg_base); - reg = inb(cfg_base+1); - info->enabled = (reg & 0x80) && (reg & 0x01); - pr_debug("%s(), probing enabled=%d\n", __func__, info->enabled); - - /* Read Power Status */ - outb(0x22, cfg_base); - reg = inb(cfg_base+1); - info->suspended = (reg & 0x20); - pr_debug("%s(), probing suspended=%d\n", __func__, info->suspended); - - /* Exit configuration */ - outb(0xbb, cfg_base); - - - return 0; -} - -/* - * Function ali_ircc_setup (info) - * - * Set FIR FIFO and DMA Threshold - * Returns non-negative on success. - * - */ -static int ali_ircc_setup(chipio_t *info) -{ - unsigned char tmp; - int version; - int iobase = info->fir_base; - - - /* Locking comments : - * Most operations here need to be protected. We are called before - * the device instance is created in ali_ircc_open(), therefore - * nobody can bother us - Jean II */ - - /* Switch to FIR space */ - SIR2FIR(iobase); - - /* Master Reset */ - outb(0x40, iobase+FIR_MCR); // benjamin 2000/11/30 11:45AM - - /* Read FIR ID Version Register */ - switch_bank(iobase, BANK3); - version = inb(iobase+FIR_ID_VR); - - /* Should be 0x00 in the M1535/M1535D */ - if(version != 0x00) - { - net_err_ratelimited("%s, Wrong chip version %02x\n", - ALI_IRCC_DRIVER_NAME, version); - return -1; - } - - /* Set FIR FIFO Threshold Register */ - switch_bank(iobase, BANK1); - outb(RX_FIFO_Threshold, iobase+FIR_FIFO_TR); - - /* Set FIR DMA Threshold Register */ - outb(RX_DMA_Threshold, iobase+FIR_DMA_TR); - - /* CRC enable */ - switch_bank(iobase, BANK2); - outb(inb(iobase+FIR_IRDA_CR) | IRDA_CR_CRC, iobase+FIR_IRDA_CR); - - /* NDIS driver set TX Length here BANK2 Alias 3, Alias4*/ - - /* Switch to Bank 0 */ - switch_bank(iobase, BANK0); - - tmp = inb(iobase+FIR_LCR_B); - tmp &=~0x20; // disable SIP - tmp |= 0x80; // these two steps make RX mode - tmp &= 0xbf; - outb(tmp, iobase+FIR_LCR_B); - - /* Disable Interrupt */ - outb(0x00, iobase+FIR_IER); - - - /* Switch to SIR space */ - FIR2SIR(iobase); - - net_info_ratelimited("%s, driver loaded (Benjamin Kong)\n", - ALI_IRCC_DRIVER_NAME); - - /* Enable receive interrupts */ - // outb(UART_IER_RDI, iobase+UART_IER); //benjamin 2000/11/23 01:25PM - // Turn on the interrupts in ali_ircc_net_open - - - return 0; -} - -/* - * Function ali_ircc_read_dongle_id (int index, info) - * - * Try to read dongle identification. This procedure needs to be executed - * once after power-on/reset. It also needs to be used whenever you suspect - * that the user may have plugged/unplugged the IrDA Dongle. - */ -static int ali_ircc_read_dongle_id (int i, chipio_t *info) -{ - int dongle_id, reg; - int cfg_base = info->cfg_base; - - - /* Enter Configuration */ - outb(chips[i].entr1, cfg_base); - outb(chips[i].entr2, cfg_base); - - /* Select Logical Device 5 Registers (UART2) */ - outb(0x07, cfg_base); - outb(0x05, cfg_base+1); - - /* Read Dongle ID */ - outb(0xf0, cfg_base); - reg = inb(cfg_base+1); - dongle_id = ((reg>>6)&0x02) | ((reg>>5)&0x01); - pr_debug("%s(), probing dongle_id=%d, dongle_types=%s\n", - __func__, dongle_id, dongle_types[dongle_id]); - - /* Exit configuration */ - outb(0xbb, cfg_base); - - - return dongle_id; -} - -/* - * Function ali_ircc_interrupt (irq, dev_id, regs) - * - * An interrupt from the chip has arrived. Time to do some work - * - */ -static irqreturn_t ali_ircc_interrupt(int irq, void *dev_id) -{ - struct net_device *dev = dev_id; - struct ali_ircc_cb *self; - int ret; - - - self = netdev_priv(dev); - - spin_lock(&self->lock); - - /* Dispatch interrupt handler for the current speed */ - if (self->io.speed > 115200) - ret = ali_ircc_fir_interrupt(self); - else - ret = ali_ircc_sir_interrupt(self); - - spin_unlock(&self->lock); - - return ret; -} -/* - * Function ali_ircc_fir_interrupt(irq, struct ali_ircc_cb *self) - * - * Handle MIR/FIR interrupt - * - */ -static irqreturn_t ali_ircc_fir_interrupt(struct ali_ircc_cb *self) -{ - __u8 eir, OldMessageCount; - int iobase, tmp; - - - iobase = self->io.fir_base; - - switch_bank(iobase, BANK0); - self->InterruptID = inb(iobase+FIR_IIR); - self->BusStatus = inb(iobase+FIR_BSR); - - OldMessageCount = (self->LineStatus + 1) & 0x07; - self->LineStatus = inb(iobase+FIR_LSR); - //self->ier = inb(iobase+FIR_IER); 2000/12/1 04:32PM - eir = self->InterruptID & self->ier; /* Mask out the interesting ones */ - - pr_debug("%s(), self->InterruptID = %x\n", __func__, self->InterruptID); - pr_debug("%s(), self->LineStatus = %x\n", __func__, self->LineStatus); - pr_debug("%s(), self->ier = %x\n", __func__, self->ier); - pr_debug("%s(), eir = %x\n", __func__, eir); - - /* Disable interrupts */ - SetCOMInterrupts(self, FALSE); - - /* Tx or Rx Interrupt */ - - if (eir & IIR_EOM) - { - if (self->io.direction == IO_XMIT) /* TX */ - { - pr_debug("%s(), ******* IIR_EOM (Tx) *******\n", - __func__); - - if(ali_ircc_dma_xmit_complete(self)) - { - if (irda_device_txqueue_empty(self->netdev)) - { - /* Prepare for receive */ - ali_ircc_dma_receive(self); - self->ier = IER_EOM; - } - } - else - { - self->ier = IER_EOM; - } - - } - else /* RX */ - { - pr_debug("%s(), ******* IIR_EOM (Rx) *******\n", - __func__); - - if(OldMessageCount > ((self->LineStatus+1) & 0x07)) - { - self->rcvFramesOverflow = TRUE; - pr_debug("%s(), ******* self->rcvFramesOverflow = TRUE ********\n", - __func__); - } - - if (ali_ircc_dma_receive_complete(self)) - { - pr_debug("%s(), ******* receive complete ********\n", - __func__); - - self->ier = IER_EOM; - } - else - { - pr_debug("%s(), ******* Not receive complete ********\n", - __func__); - - self->ier = IER_EOM | IER_TIMER; - } - - } - } - /* Timer Interrupt */ - else if (eir & IIR_TIMER) - { - if(OldMessageCount > ((self->LineStatus+1) & 0x07)) - { - self->rcvFramesOverflow = TRUE; - pr_debug("%s(), ******* self->rcvFramesOverflow = TRUE *******\n", - __func__); - } - /* Disable Timer */ - switch_bank(iobase, BANK1); - tmp = inb(iobase+FIR_CR); - outb( tmp& ~CR_TIMER_EN, iobase+FIR_CR); - - /* Check if this is a Tx timer interrupt */ - if (self->io.direction == IO_XMIT) - { - ali_ircc_dma_xmit(self); - - /* Interrupt on EOM */ - self->ier = IER_EOM; - - } - else /* Rx */ - { - if(ali_ircc_dma_receive_complete(self)) - { - self->ier = IER_EOM; - } - else - { - self->ier = IER_EOM | IER_TIMER; - } - } - } - - /* Restore Interrupt */ - SetCOMInterrupts(self, TRUE); - - return IRQ_RETVAL(eir); -} - -/* - * Function ali_ircc_sir_interrupt (irq, self, eir) - * - * Handle SIR interrupt - * - */ -static irqreturn_t ali_ircc_sir_interrupt(struct ali_ircc_cb *self) -{ - int iobase; - int iir, lsr; - - - iobase = self->io.sir_base; - - iir = inb(iobase+UART_IIR) & UART_IIR_ID; - if (iir) { - /* Clear interrupt */ - lsr = inb(iobase+UART_LSR); - - pr_debug("%s(), iir=%02x, lsr=%02x, iobase=%#x\n", - __func__, iir, lsr, iobase); - - switch (iir) - { - case UART_IIR_RLSI: - pr_debug("%s(), RLSI\n", __func__); - break; - case UART_IIR_RDI: - /* Receive interrupt */ - ali_ircc_sir_receive(self); - break; - case UART_IIR_THRI: - if (lsr & UART_LSR_THRE) - { - /* Transmitter ready for data */ - ali_ircc_sir_write_wakeup(self); - } - break; - default: - pr_debug("%s(), unhandled IIR=%#x\n", - __func__, iir); - break; - } - - } - - - return IRQ_RETVAL(iir); -} - - -/* - * Function ali_ircc_sir_receive (self) - * - * Receive one frame from the infrared port - * - */ -static void ali_ircc_sir_receive(struct ali_ircc_cb *self) -{ - int boguscount = 0; - int iobase; - - IRDA_ASSERT(self != NULL, return;); - - iobase = self->io.sir_base; - - /* - * Receive all characters in Rx FIFO, unwrap and unstuff them. - * async_unwrap_char will deliver all found frames - */ - do { - async_unwrap_char(self->netdev, &self->netdev->stats, &self->rx_buff, - inb(iobase+UART_RX)); - - /* Make sure we don't stay here too long */ - if (boguscount++ > 32) { - pr_debug("%s(), breaking!\n", __func__); - break; - } - } while (inb(iobase+UART_LSR) & UART_LSR_DR); - -} - -/* - * Function ali_ircc_sir_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 ali_ircc_sir_write_wakeup(struct ali_ircc_cb *self) -{ - int actual = 0; - int iobase; - - IRDA_ASSERT(self != NULL, return;); - - - iobase = self->io.sir_base; - - /* Finished with frame? */ - if (self->tx_buff.len > 0) - { - /* Write data left in transmit buffer */ - actual = ali_ircc_sir_write(iobase, self->io.fifo_size, - self->tx_buff.data, self->tx_buff.len); - self->tx_buff.data += actual; - self->tx_buff.len -= actual; - } - else - { - if (self->new_speed) - { - /* We must wait until all data are gone */ - while(!(inb(iobase+UART_LSR) & UART_LSR_TEMT)) - pr_debug("%s(), UART_LSR_THRE\n", __func__); - - pr_debug("%s(), Changing speed! self->new_speed = %d\n", - __func__, self->new_speed); - ali_ircc_change_speed(self, self->new_speed); - self->new_speed = 0; - - // benjamin 2000/11/10 06:32PM - if (self->io.speed > 115200) - { - pr_debug("%s(), ali_ircc_change_speed from UART_LSR_TEMT\n", - __func__); - - self->ier = IER_EOM; - // SetCOMInterrupts(self, TRUE); - return; - } - } - else - { - netif_wake_queue(self->netdev); - } - - self->netdev->stats.tx_packets++; - - /* Turn on receive interrupts */ - outb(UART_IER_RDI, iobase+UART_IER); - } - -} - -static void ali_ircc_change_speed(struct ali_ircc_cb *self, __u32 baud) -{ - struct net_device *dev = self->netdev; - int iobase; - - - pr_debug("%s(), setting speed = %d\n", __func__, baud); - - /* This function *must* be called with irq off and spin-lock. - * - Jean II */ - - iobase = self->io.fir_base; - - SetCOMInterrupts(self, FALSE); // 2000/11/24 11:43AM - - /* Go to MIR, FIR Speed */ - if (baud > 115200) - { - - - ali_ircc_fir_change_speed(self, baud); - - /* Install FIR xmit handler*/ - dev->netdev_ops = &ali_ircc_fir_ops; - - /* Enable Interuupt */ - self->ier = IER_EOM; // benjamin 2000/11/20 07:24PM - - /* Be ready for incoming frames */ - ali_ircc_dma_receive(self); // benajmin 2000/11/8 07:46PM not complete - } - /* Go to SIR Speed */ - else - { - ali_ircc_sir_change_speed(self, baud); - - /* Install SIR xmit handler*/ - dev->netdev_ops = &ali_ircc_sir_ops; - } - - - SetCOMInterrupts(self, TRUE); // 2000/11/24 11:43AM - - netif_wake_queue(self->netdev); - -} - -static void ali_ircc_fir_change_speed(struct ali_ircc_cb *priv, __u32 baud) -{ - - int iobase; - struct ali_ircc_cb *self = priv; - struct net_device *dev; - - - IRDA_ASSERT(self != NULL, return;); - - dev = self->netdev; - iobase = self->io.fir_base; - - pr_debug("%s(), self->io.speed = %d, change to speed = %d\n", - __func__, self->io.speed, baud); - - /* Come from SIR speed */ - if(self->io.speed <=115200) - { - SIR2FIR(iobase); - } - - /* Update accounting for new speed */ - self->io.speed = baud; - - // Set Dongle Speed mode - ali_ircc_change_dongle_speed(self, baud); - -} - -/* - * Function ali_sir_change_speed (self, speed) - * - * Set speed of IrDA port to specified baudrate - * - */ -static void ali_ircc_sir_change_speed(struct ali_ircc_cb *priv, __u32 speed) -{ - struct ali_ircc_cb *self = priv; - int iobase; - int fcr; /* FIFO control reg */ - int lcr; /* Line control reg */ - int divisor; - - - pr_debug("%s(), Setting speed to: %d\n", __func__, speed); - - IRDA_ASSERT(self != NULL, return;); - - iobase = self->io.sir_base; - - /* Come from MIR or FIR speed */ - if(self->io.speed >115200) - { - // Set Dongle Speed mode first - ali_ircc_change_dongle_speed(self, speed); - - FIR2SIR(iobase); - } - - // Clear Line and Auxiluary status registers 2000/11/24 11:47AM - - inb(iobase+UART_LSR); - inb(iobase+UART_SCR); - - /* Update accounting for new speed */ - self->io.speed = speed; - - divisor = 115200/speed; - - fcr = UART_FCR_ENABLE_FIFO; - - /* - * Use trigger level 1 to avoid 3 ms. timeout delay at 9600 bps, and - * almost 1,7 ms at 19200 bps. At speeds above that we can just forget - * about this timeout since it will always be fast enough. - */ - if (self->io.speed < 38400) - fcr |= UART_FCR_TRIGGER_1; - else - fcr |= UART_FCR_TRIGGER_14; - - /* IrDA ports use 8N1 */ - lcr = UART_LCR_WLEN8; - - outb(UART_LCR_DLAB | lcr, iobase+UART_LCR); /* Set DLAB */ - outb(divisor & 0xff, iobase+UART_DLL); /* Set speed */ - outb(divisor >> 8, iobase+UART_DLM); - outb(lcr, iobase+UART_LCR); /* Set 8N1 */ - outb(fcr, iobase+UART_FCR); /* Enable FIFO's */ - - /* without this, the connection will be broken after come back from FIR speed, - but with this, the SIR connection is harder to established */ - outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), iobase+UART_MCR); -} - -static void ali_ircc_change_dongle_speed(struct ali_ircc_cb *priv, int speed) -{ - - struct ali_ircc_cb *self = priv; - int iobase,dongle_id; - int tmp = 0; - - - iobase = self->io.fir_base; /* or iobase = self->io.sir_base; */ - dongle_id = self->io.dongle_id; - - /* We are already locked, no need to do it again */ - - pr_debug("%s(), Set Speed for %s , Speed = %d\n", - __func__, dongle_types[dongle_id], speed); - - switch_bank(iobase, BANK2); - tmp = inb(iobase+FIR_IRDA_CR); - - /* IBM type dongle */ - if(dongle_id == 0) - { - if(speed == 4000000) - { - // __ __ - // SD/MODE __| |__ __ - // __ __ - // IRTX __ __| |__ - // T1 T2 T3 T4 T5 - - tmp &= ~IRDA_CR_HDLC; // HDLC=0 - tmp |= IRDA_CR_CRC; // CRC=1 - - switch_bank(iobase, BANK2); - outb(tmp, iobase+FIR_IRDA_CR); - - // T1 -> SD/MODE:0 IRTX:0 - tmp &= ~0x09; - tmp |= 0x02; - outb(tmp, iobase+FIR_IRDA_CR); - udelay(2); - - // T2 -> SD/MODE:1 IRTX:0 - tmp &= ~0x01; - tmp |= 0x0a; - outb(tmp, iobase+FIR_IRDA_CR); - udelay(2); - - // T3 -> SD/MODE:1 IRTX:1 - tmp |= 0x0b; - outb(tmp, iobase+FIR_IRDA_CR); - udelay(2); - - // T4 -> SD/MODE:0 IRTX:1 - tmp &= ~0x08; - tmp |= 0x03; - outb(tmp, iobase+FIR_IRDA_CR); - udelay(2); - - // T5 -> SD/MODE:0 IRTX:0 - tmp &= ~0x09; - tmp |= 0x02; - outb(tmp, iobase+FIR_IRDA_CR); - udelay(2); - - // reset -> Normal TX output Signal - outb(tmp & ~0x02, iobase+FIR_IRDA_CR); - } - else /* speed <=1152000 */ - { - // __ - // SD/MODE __| |__ - // - // IRTX ________ - // T1 T2 T3 - - /* MIR 115200, 57600 */ - if (speed==1152000) - { - tmp |= 0xA0; //HDLC=1, 1.152Mbps=1 - } - else - { - tmp &=~0x80; //HDLC 0.576Mbps - tmp |= 0x20; //HDLC=1, - } - - tmp |= IRDA_CR_CRC; // CRC=1 - - switch_bank(iobase, BANK2); - outb(tmp, iobase+FIR_IRDA_CR); - - /* MIR 115200, 57600 */ - - //switch_bank(iobase, BANK2); - // T1 -> SD/MODE:0 IRTX:0 - tmp &= ~0x09; - tmp |= 0x02; - outb(tmp, iobase+FIR_IRDA_CR); - udelay(2); - - // T2 -> SD/MODE:1 IRTX:0 - tmp &= ~0x01; - tmp |= 0x0a; - outb(tmp, iobase+FIR_IRDA_CR); - - // T3 -> SD/MODE:0 IRTX:0 - tmp &= ~0x09; - tmp |= 0x02; - outb(tmp, iobase+FIR_IRDA_CR); - udelay(2); - - // reset -> Normal TX output Signal - outb(tmp & ~0x02, iobase+FIR_IRDA_CR); - } - } - else if (dongle_id == 1) /* HP HDSL-3600 */ - { - switch(speed) - { - case 4000000: - tmp &= ~IRDA_CR_HDLC; // HDLC=0 - break; - - case 1152000: - tmp |= 0xA0; // HDLC=1, 1.152Mbps=1 - break; - - case 576000: - tmp &=~0x80; // HDLC 0.576Mbps - tmp |= 0x20; // HDLC=1, - break; - } - - tmp |= IRDA_CR_CRC; // CRC=1 - - switch_bank(iobase, BANK2); - outb(tmp, iobase+FIR_IRDA_CR); - } - else /* HP HDSL-1100 */ - { - if(speed <= 115200) /* SIR */ - { - - tmp &= ~IRDA_CR_FIR_SIN; // HP sin select = 0 - - switch_bank(iobase, BANK2); - outb(tmp, iobase+FIR_IRDA_CR); - } - else /* MIR FIR */ - { - - switch(speed) - { - case 4000000: - tmp &= ~IRDA_CR_HDLC; // HDLC=0 - break; - - case 1152000: - tmp |= 0xA0; // HDLC=1, 1.152Mbps=1 - break; - - case 576000: - tmp &=~0x80; // HDLC 0.576Mbps - tmp |= 0x20; // HDLC=1, - break; - } - - tmp |= IRDA_CR_CRC; // CRC=1 - tmp |= IRDA_CR_FIR_SIN; // HP sin select = 1 - - switch_bank(iobase, BANK2); - outb(tmp, iobase+FIR_IRDA_CR); - } - } - - switch_bank(iobase, BANK0); - -} - -/* - * Function ali_ircc_sir_write (driver) - * - * Fill Tx FIFO with transmit data - * - */ -static int ali_ircc_sir_write(int iobase, int fifo_size, __u8 *buf, int len) -{ - int actual = 0; - - - /* Tx FIFO should be empty! */ - if (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) { - pr_debug("%s(), failed, fifo not empty!\n", __func__); - return 0; - } - - /* Fill FIFO with current frame */ - while ((fifo_size-- > 0) && (actual < len)) { - /* Transmit next byte */ - outb(buf[actual], iobase+UART_TX); - - actual++; - } - - return actual; -} - -/* - * Function ali_ircc_net_open (dev) - * - * Start the device - * - */ -static int ali_ircc_net_open(struct net_device *dev) -{ - struct ali_ircc_cb *self; - int iobase; - char hwname[32]; - - - IRDA_ASSERT(dev != NULL, return -1;); - - self = netdev_priv(dev); - - IRDA_ASSERT(self != NULL, return 0;); - - iobase = self->io.fir_base; - - /* Request IRQ and install Interrupt Handler */ - if (request_irq(self->io.irq, ali_ircc_interrupt, 0, dev->name, dev)) - { - net_warn_ratelimited("%s, unable to allocate irq=%d\n", - ALI_IRCC_DRIVER_NAME, self->io.irq); - return -EAGAIN; - } - - /* - * Always allocate the DMA channel after the IRQ, and clean up on - * failure. - */ - if (request_dma(self->io.dma, dev->name)) { - net_warn_ratelimited("%s, unable to allocate dma=%d\n", - ALI_IRCC_DRIVER_NAME, self->io.dma); - free_irq(self->io.irq, dev); - return -EAGAIN; - } - - /* Turn on interrups */ - outb(UART_IER_RDI , iobase+UART_IER); - - /* Ready to play! */ - netif_start_queue(dev); //benjamin by irport - - /* Give self a hardware name */ - sprintf(hwname, "ALI-FIR @ 0x%03x", self->io.fir_base); - - /* - * Open new IrLAP layer instance, now that everything should be - * initialized properly - */ - self->irlap = irlap_open(dev, &self->qos, hwname); - - - return 0; -} - -/* - * Function ali_ircc_net_close (dev) - * - * Stop the device - * - */ -static int ali_ircc_net_close(struct net_device *dev) -{ - - struct ali_ircc_cb *self; - //int iobase; - - - IRDA_ASSERT(dev != NULL, return -1;); - - self = netdev_priv(dev); - IRDA_ASSERT(self != NULL, return 0;); - - /* Stop device */ - netif_stop_queue(dev); - - /* Stop and remove instance of IrLAP */ - if (self->irlap) - irlap_close(self->irlap); - self->irlap = NULL; - - disable_dma(self->io.dma); - - /* Disable interrupts */ - SetCOMInterrupts(self, FALSE); - - free_irq(self->io.irq, dev); - free_dma(self->io.dma); - - - return 0; -} - -/* - * Function ali_ircc_fir_hard_xmit (skb, dev) - * - * Transmit the frame - * - */ -static netdev_tx_t ali_ircc_fir_hard_xmit(struct sk_buff *skb, - struct net_device *dev) -{ - struct ali_ircc_cb *self; - unsigned long flags; - int iobase; - __u32 speed; - int mtt, diff; - - - self = netdev_priv(dev); - iobase = self->io.fir_base; - - netif_stop_queue(dev); - - /* Make sure tests *& speed change are atomic */ - spin_lock_irqsave(&self->lock, flags); - - /* Note : you should make sure that speed changes are not going - * to corrupt any outgoing frame. Look at nsc-ircc for the gory - * details - Jean II */ - - /* Check if we need to change the speed */ - speed = irda_get_next_speed(skb); - if ((speed != self->io.speed) && (speed != -1)) { - /* Check for empty frame */ - if (!skb->len) { - ali_ircc_change_speed(self, speed); - netif_trans_update(dev); - spin_unlock_irqrestore(&self->lock, flags); - dev_kfree_skb(skb); - return NETDEV_TX_OK; - } else - self->new_speed = speed; - } - - /* Register and copy this frame to DMA memory */ - self->tx_fifo.queue[self->tx_fifo.free].start = self->tx_fifo.tail; - self->tx_fifo.queue[self->tx_fifo.free].len = skb->len; - self->tx_fifo.tail += skb->len; - - dev->stats.tx_bytes += skb->len; - - skb_copy_from_linear_data(skb, self->tx_fifo.queue[self->tx_fifo.free].start, - skb->len); - self->tx_fifo.len++; - self->tx_fifo.free++; - - /* Start transmit only if there is currently no transmit going on */ - if (self->tx_fifo.len == 1) - { - /* Check if we must wait the min turn time or not */ - mtt = irda_get_mtt(skb); - - if (mtt) - { - /* Check how much time we have used already */ - diff = ktime_us_delta(ktime_get(), self->stamp); - /* self->stamp is set from ali_ircc_dma_receive_complete() */ - - pr_debug("%s(), ******* diff = %d *******\n", - __func__, diff); - - /* Check if the mtt is larger than the time we have - * already used by all the protocol processing - */ - if (mtt > diff) - { - mtt -= diff; - - /* - * Use timer if delay larger than 1000 us, and - * use udelay for smaller values which should - * be acceptable - */ - if (mtt > 500) - { - /* Adjust for timer resolution */ - mtt = (mtt+250) / 500; /* 4 discard, 5 get advanced, Let's round off */ - - pr_debug("%s(), ************** mtt = %d ***********\n", - __func__, mtt); - - /* Setup timer */ - if (mtt == 1) /* 500 us */ - { - switch_bank(iobase, BANK1); - outb(TIMER_IIR_500, iobase+FIR_TIMER_IIR); - } - else if (mtt == 2) /* 1 ms */ - { - switch_bank(iobase, BANK1); - outb(TIMER_IIR_1ms, iobase+FIR_TIMER_IIR); - } - else /* > 2ms -> 4ms */ - { - switch_bank(iobase, BANK1); - outb(TIMER_IIR_2ms, iobase+FIR_TIMER_IIR); - } - - - /* Start timer */ - outb(inb(iobase+FIR_CR) | CR_TIMER_EN, iobase+FIR_CR); - self->io.direction = IO_XMIT; - - /* Enable timer interrupt */ - self->ier = IER_TIMER; - SetCOMInterrupts(self, TRUE); - - /* Timer will take care of the rest */ - goto out; - } - else - udelay(mtt); - } // if (if (mtt > diff) - }// if (mtt) - - /* Enable EOM interrupt */ - self->ier = IER_EOM; - SetCOMInterrupts(self, TRUE); - - /* Transmit frame */ - ali_ircc_dma_xmit(self); - } // if (self->tx_fifo.len == 1) - - out: - - /* Not busy transmitting anymore if window is not full */ - if (self->tx_fifo.free < MAX_TX_WINDOW) - netif_wake_queue(self->netdev); - - /* Restore bank register */ - switch_bank(iobase, BANK0); - - netif_trans_update(dev); - spin_unlock_irqrestore(&self->lock, flags); - dev_kfree_skb(skb); - - return NETDEV_TX_OK; -} - - -static void ali_ircc_dma_xmit(struct ali_ircc_cb *self) -{ - int iobase, tmp; - unsigned char FIFO_OPTI, Hi, Lo; - - - - iobase = self->io.fir_base; - - /* FIFO threshold , this method comes from NDIS5 code */ - - if(self->tx_fifo.queue[self->tx_fifo.ptr].len < TX_FIFO_Threshold) - FIFO_OPTI = self->tx_fifo.queue[self->tx_fifo.ptr].len-1; - else - FIFO_OPTI = TX_FIFO_Threshold; - - /* Disable DMA */ - switch_bank(iobase, BANK1); - outb(inb(iobase+FIR_CR) & ~CR_DMA_EN, iobase+FIR_CR); - - self->io.direction = IO_XMIT; - - irda_setup_dma(self->io.dma, - ((u8 *)self->tx_fifo.queue[self->tx_fifo.ptr].start - - self->tx_buff.head) + self->tx_buff_dma, - self->tx_fifo.queue[self->tx_fifo.ptr].len, - DMA_TX_MODE); - - /* Reset Tx FIFO */ - switch_bank(iobase, BANK0); - outb(LCR_A_FIFO_RESET, iobase+FIR_LCR_A); - - /* Set Tx FIFO threshold */ - if (self->fifo_opti_buf!=FIFO_OPTI) - { - switch_bank(iobase, BANK1); - outb(FIFO_OPTI, iobase+FIR_FIFO_TR) ; - self->fifo_opti_buf=FIFO_OPTI; - } - - /* Set Tx DMA threshold */ - switch_bank(iobase, BANK1); - outb(TX_DMA_Threshold, iobase+FIR_DMA_TR); - - /* Set max Tx frame size */ - Hi = (self->tx_fifo.queue[self->tx_fifo.ptr].len >> 8) & 0x0f; - Lo = self->tx_fifo.queue[self->tx_fifo.ptr].len & 0xff; - switch_bank(iobase, BANK2); - outb(Hi, iobase+FIR_TX_DSR_HI); - outb(Lo, iobase+FIR_TX_DSR_LO); - - /* Disable SIP , Disable Brick Wall (we don't support in TX mode), Change to TX mode */ - switch_bank(iobase, BANK0); - tmp = inb(iobase+FIR_LCR_B); - tmp &= ~0x20; // Disable SIP - outb(((unsigned char)(tmp & 0x3f) | LCR_B_TX_MODE) & ~LCR_B_BW, iobase+FIR_LCR_B); - pr_debug("%s(), *** Change to TX mode: FIR_LCR_B = 0x%x ***\n", - __func__, inb(iobase + FIR_LCR_B)); - - outb(0, iobase+FIR_LSR); - - /* Enable DMA and Burst Mode */ - switch_bank(iobase, BANK1); - outb(inb(iobase+FIR_CR) | CR_DMA_EN | CR_DMA_BURST, iobase+FIR_CR); - - switch_bank(iobase, BANK0); - -} - -static int ali_ircc_dma_xmit_complete(struct ali_ircc_cb *self) -{ - int iobase; - int ret = TRUE; - - - iobase = self->io.fir_base; - - /* Disable DMA */ - switch_bank(iobase, BANK1); - outb(inb(iobase+FIR_CR) & ~CR_DMA_EN, iobase+FIR_CR); - - /* Check for underrun! */ - switch_bank(iobase, BANK0); - if((inb(iobase+FIR_LSR) & LSR_FRAME_ABORT) == LSR_FRAME_ABORT) - - { - net_err_ratelimited("%s(), ********* LSR_FRAME_ABORT *********\n", - __func__); - self->netdev->stats.tx_errors++; - self->netdev->stats.tx_fifo_errors++; - } - else - { - self->netdev->stats.tx_packets++; - } - - /* Check if we need to change the speed */ - if (self->new_speed) - { - ali_ircc_change_speed(self, self->new_speed); - self->new_speed = 0; - } - - /* Finished with this frame, so prepare for next */ - self->tx_fifo.ptr++; - self->tx_fifo.len--; - - /* Any frames to be sent back-to-back? */ - if (self->tx_fifo.len) - { - ali_ircc_dma_xmit(self); - - /* Not finished yet! */ - ret = FALSE; - } - else - { /* Reset Tx FIFO info */ - self->tx_fifo.len = self->tx_fifo.ptr = self->tx_fifo.free = 0; - self->tx_fifo.tail = self->tx_buff.head; - } - - /* Make sure we have room for more frames */ - if (self->tx_fifo.free < MAX_TX_WINDOW) { - /* Not busy transmitting anymore */ - /* Tell the network layer, that we can accept more frames */ - netif_wake_queue(self->netdev); - } - - switch_bank(iobase, BANK0); - - return ret; -} - -/* - * Function ali_ircc_dma_receive (self) - * - * Get ready for receiving a frame. The device will initiate a DMA - * if it starts to receive a frame. - * - */ -static int ali_ircc_dma_receive(struct ali_ircc_cb *self) -{ - int iobase, tmp; - - - iobase = self->io.fir_base; - - /* Reset Tx FIFO info */ - self->tx_fifo.len = self->tx_fifo.ptr = self->tx_fifo.free = 0; - self->tx_fifo.tail = self->tx_buff.head; - - /* Disable DMA */ - switch_bank(iobase, BANK1); - outb(inb(iobase+FIR_CR) & ~CR_DMA_EN, iobase+FIR_CR); - - /* Reset Message Count */ - switch_bank(iobase, BANK0); - outb(0x07, iobase+FIR_LSR); - - self->rcvFramesOverflow = FALSE; - - self->LineStatus = inb(iobase+FIR_LSR) ; - - /* Reset Rx FIFO info */ - self->io.direction = IO_RECV; - self->rx_buff.data = self->rx_buff.head; - - /* Reset Rx FIFO */ - // switch_bank(iobase, BANK0); - outb(LCR_A_FIFO_RESET, iobase+FIR_LCR_A); - - self->st_fifo.len = self->st_fifo.pending_bytes = 0; - self->st_fifo.tail = self->st_fifo.head = 0; - - irda_setup_dma(self->io.dma, self->rx_buff_dma, self->rx_buff.truesize, - DMA_RX_MODE); - - /* Set Receive Mode,Brick Wall */ - //switch_bank(iobase, BANK0); - tmp = inb(iobase+FIR_LCR_B); - outb((unsigned char)(tmp &0x3f) | LCR_B_RX_MODE | LCR_B_BW , iobase + FIR_LCR_B); // 2000/12/1 05:16PM - pr_debug("%s(), *** Change To RX mode: FIR_LCR_B = 0x%x ***\n", - __func__, inb(iobase + FIR_LCR_B)); - - /* Set Rx Threshold */ - switch_bank(iobase, BANK1); - outb(RX_FIFO_Threshold, iobase+FIR_FIFO_TR); - outb(RX_DMA_Threshold, iobase+FIR_DMA_TR); - - /* Enable DMA and Burst Mode */ - // switch_bank(iobase, BANK1); - outb(CR_DMA_EN | CR_DMA_BURST, iobase+FIR_CR); - - switch_bank(iobase, BANK0); - return 0; -} - -static int ali_ircc_dma_receive_complete(struct ali_ircc_cb *self) -{ - struct st_fifo *st_fifo; - struct sk_buff *skb; - __u8 status, MessageCount; - int len, i, iobase, val; - - st_fifo = &self->st_fifo; - iobase = self->io.fir_base; - - switch_bank(iobase, BANK0); - MessageCount = inb(iobase+ FIR_LSR)&0x07; - - if (MessageCount > 0) - pr_debug("%s(), Message count = %d\n", __func__, MessageCount); - - for (i=0; i<=MessageCount; i++) - { - /* Bank 0 */ - switch_bank(iobase, BANK0); - status = inb(iobase+FIR_LSR); - - switch_bank(iobase, BANK2); - len = inb(iobase+FIR_RX_DSR_HI) & 0x0f; - len = len << 8; - len |= inb(iobase+FIR_RX_DSR_LO); - - pr_debug("%s(), RX Length = 0x%.2x,\n", __func__ , len); - pr_debug("%s(), RX Status = 0x%.2x,\n", __func__ , status); - - if (st_fifo->tail >= MAX_RX_WINDOW) { - pr_debug("%s(), window is full!\n", __func__); - continue; - } - - st_fifo->entries[st_fifo->tail].status = status; - st_fifo->entries[st_fifo->tail].len = len; - st_fifo->pending_bytes += len; - st_fifo->tail++; - st_fifo->len++; - } - - for (i=0; i<=MessageCount; i++) - { - /* Get first entry */ - status = st_fifo->entries[st_fifo->head].status; - len = st_fifo->entries[st_fifo->head].len; - st_fifo->pending_bytes -= len; - st_fifo->head++; - st_fifo->len--; - - /* Check for errors */ - if ((status & 0xd8) || self->rcvFramesOverflow || (len==0)) - { - pr_debug("%s(), ************* RX Errors ************\n", - __func__); - - /* Skip frame */ - self->netdev->stats.rx_errors++; - - self->rx_buff.data += len; - - if (status & LSR_FIFO_UR) - { - self->netdev->stats.rx_frame_errors++; - pr_debug("%s(), ************* FIFO Errors ************\n", - __func__); - } - if (status & LSR_FRAME_ERROR) - { - self->netdev->stats.rx_frame_errors++; - pr_debug("%s(), ************* FRAME Errors ************\n", - __func__); - } - - if (status & LSR_CRC_ERROR) - { - self->netdev->stats.rx_crc_errors++; - pr_debug("%s(), ************* CRC Errors ************\n", - __func__); - } - - if(self->rcvFramesOverflow) - { - self->netdev->stats.rx_frame_errors++; - pr_debug("%s(), ************* Overran DMA buffer ************\n", - __func__); - } - if(len == 0) - { - self->netdev->stats.rx_frame_errors++; - pr_debug("%s(), ********** Receive Frame Size = 0 *********\n", - __func__); - } - } - else - { - - if (st_fifo->pending_bytes < 32) - { - switch_bank(iobase, BANK0); - val = inb(iobase+FIR_BSR); - if ((val& BSR_FIFO_NOT_EMPTY)== 0x80) - { - pr_debug("%s(), ************* BSR_FIFO_NOT_EMPTY ************\n", - __func__); - - /* Put this entry back in fifo */ - st_fifo->head--; - st_fifo->len++; - st_fifo->pending_bytes += len; - st_fifo->entries[st_fifo->head].status = status; - st_fifo->entries[st_fifo->head].len = len; - - /* - * DMA not finished yet, so try again - * later, set timer value, resolution - * 500 us - */ - - switch_bank(iobase, BANK1); - outb(TIMER_IIR_500, iobase+FIR_TIMER_IIR); // 2001/1/2 05:07PM - - /* Enable Timer */ - outb(inb(iobase+FIR_CR) | CR_TIMER_EN, iobase+FIR_CR); - - return FALSE; /* I'll be back! */ - } - } - - /* - * Remember the time we received this frame, so we can - * reduce the min turn time a bit since we will know - * how much time we have used for protocol processing - */ - self->stamp = ktime_get(); - - skb = dev_alloc_skb(len+1); - if (skb == NULL) - { - self->netdev->stats.rx_dropped++; - - return FALSE; - } - - /* Make sure IP header gets aligned */ - skb_reserve(skb, 1); - - /* Copy frame without CRC, CRC is removed by hardware*/ - skb_put(skb, len); - skb_copy_to_linear_data(skb, self->rx_buff.data, len); - - /* Move to next frame */ - self->rx_buff.data += len; - self->netdev->stats.rx_bytes += len; - self->netdev->stats.rx_packets++; - - skb->dev = self->netdev; - skb_reset_mac_header(skb); - skb->protocol = htons(ETH_P_IRDA); - netif_rx(skb); - } - } - - switch_bank(iobase, BANK0); - - return TRUE; -} - - - -/* - * Function ali_ircc_sir_hard_xmit (skb, dev) - * - * Transmit the frame! - * - */ -static netdev_tx_t ali_ircc_sir_hard_xmit(struct sk_buff *skb, - struct net_device *dev) -{ - struct ali_ircc_cb *self; - unsigned long flags; - int iobase; - __u32 speed; - - - IRDA_ASSERT(dev != NULL, return NETDEV_TX_OK;); - - self = netdev_priv(dev); - IRDA_ASSERT(self != NULL, return NETDEV_TX_OK;); - - iobase = self->io.sir_base; - - netif_stop_queue(dev); - - /* Make sure tests *& speed change are atomic */ - spin_lock_irqsave(&self->lock, flags); - - /* Note : you should make sure that speed changes are not going - * to corrupt any outgoing frame. Look at nsc-ircc for the gory - * details - Jean II */ - - /* Check if we need to change the speed */ - speed = irda_get_next_speed(skb); - if ((speed != self->io.speed) && (speed != -1)) { - /* Check for empty frame */ - if (!skb->len) { - ali_ircc_change_speed(self, speed); - netif_trans_update(dev); - spin_unlock_irqrestore(&self->lock, flags); - dev_kfree_skb(skb); - return NETDEV_TX_OK; - } else - self->new_speed = speed; - } - - /* Init tx buffer */ - self->tx_buff.data = self->tx_buff.head; - - /* Copy skb to tx_buff while wrapping, stuffing and making CRC */ - self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data, - self->tx_buff.truesize); - - self->netdev->stats.tx_bytes += self->tx_buff.len; - - /* Turn on transmit finished interrupt. Will fire immediately! */ - outb(UART_IER_THRI, iobase+UART_IER); - - netif_trans_update(dev); - spin_unlock_irqrestore(&self->lock, flags); - - dev_kfree_skb(skb); - - - return NETDEV_TX_OK; -} - - -/* - * Function ali_ircc_net_ioctl (dev, rq, cmd) - * - * Process IOCTL commands for this device - * - */ -static int ali_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct if_irda_req *irq = (struct if_irda_req *) rq; - struct ali_ircc_cb *self; - unsigned long flags; - int ret = 0; - - - IRDA_ASSERT(dev != NULL, return -1;); - - self = netdev_priv(dev); - - IRDA_ASSERT(self != NULL, return -1;); - - pr_debug("%s(), %s, (cmd=0x%X)\n", __func__ , dev->name, cmd); - - switch (cmd) { - case SIOCSBANDWIDTH: /* Set bandwidth */ - pr_debug("%s(), SIOCSBANDWIDTH\n", __func__); - /* - * This function will also be used by IrLAP to change the - * speed, so we still must allow for speed change within - * interrupt context. - */ - if (!in_interrupt() && !capable(CAP_NET_ADMIN)) - return -EPERM; - - spin_lock_irqsave(&self->lock, flags); - ali_ircc_change_speed(self, irq->ifr_baudrate); - spin_unlock_irqrestore(&self->lock, flags); - break; - case SIOCSMEDIABUSY: /* Set media busy */ - pr_debug("%s(), SIOCSMEDIABUSY\n", __func__); - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - irda_device_set_media_busy(self->netdev, TRUE); - break; - case SIOCGRECEIVING: /* Check if we are receiving right now */ - pr_debug("%s(), SIOCGRECEIVING\n", __func__); - /* This is protected */ - irq->ifr_receiving = ali_ircc_is_receiving(self); - break; - default: - ret = -EOPNOTSUPP; - } - - - return ret; -} - -/* - * Function ali_ircc_is_receiving (self) - * - * Return TRUE is we are currently receiving a frame - * - */ -static int ali_ircc_is_receiving(struct ali_ircc_cb *self) -{ - unsigned long flags; - int status = FALSE; - int iobase; - - - IRDA_ASSERT(self != NULL, return FALSE;); - - spin_lock_irqsave(&self->lock, flags); - - if (self->io.speed > 115200) - { - iobase = self->io.fir_base; - - switch_bank(iobase, BANK1); - if((inb(iobase+FIR_FIFO_FR) & 0x3f) != 0) - { - /* We are receiving something */ - pr_debug("%s(), We are receiving something\n", - __func__); - status = TRUE; - } - switch_bank(iobase, BANK0); - } - else - { - status = (self->rx_buff.state != OUTSIDE_FRAME); - } - - spin_unlock_irqrestore(&self->lock, flags); - - - return status; -} - -static int ali_ircc_suspend(struct platform_device *dev, pm_message_t state) -{ - struct ali_ircc_cb *self = platform_get_drvdata(dev); - - net_info_ratelimited("%s, Suspending\n", ALI_IRCC_DRIVER_NAME); - - if (self->io.suspended) - return 0; - - ali_ircc_net_close(self->netdev); - - self->io.suspended = 1; - - return 0; -} - -static int ali_ircc_resume(struct platform_device *dev) -{ - struct ali_ircc_cb *self = platform_get_drvdata(dev); - - if (!self->io.suspended) - return 0; - - ali_ircc_net_open(self->netdev); - - net_info_ratelimited("%s, Waking up\n", ALI_IRCC_DRIVER_NAME); - - self->io.suspended = 0; - - return 0; -} - -/* ALi Chip Function */ - -static void SetCOMInterrupts(struct ali_ircc_cb *self , unsigned char enable) -{ - - unsigned char newMask; - - int iobase = self->io.fir_base; /* or sir_base */ - - pr_debug("%s(), -------- Start -------- ( Enable = %d )\n", - __func__, enable); - - /* Enable the interrupt which we wish to */ - if (enable){ - if (self->io.direction == IO_XMIT) - { - if (self->io.speed > 115200) /* FIR, MIR */ - { - newMask = self->ier; - } - else /* SIR */ - { - newMask = UART_IER_THRI | UART_IER_RDI; - } - } - else { - if (self->io.speed > 115200) /* FIR, MIR */ - { - newMask = self->ier; - } - else /* SIR */ - { - newMask = UART_IER_RDI; - } - } - } - else /* Disable all the interrupts */ - { - newMask = 0x00; - - } - - //SIR and FIR has different registers - if (self->io.speed > 115200) - { - switch_bank(iobase, BANK0); - outb(newMask, iobase+FIR_IER); - } - else - outb(newMask, iobase+UART_IER); - -} - -static void SIR2FIR(int iobase) -{ - //unsigned char tmp; - - - /* Already protected (change_speed() or setup()), no need to lock. - * Jean II */ - - outb(0x28, iobase+UART_MCR); - outb(0x68, iobase+UART_MCR); - outb(0x88, iobase+UART_MCR); - - outb(0x60, iobase+FIR_MCR); /* Master Reset */ - outb(0x20, iobase+FIR_MCR); /* Master Interrupt Enable */ - - //tmp = inb(iobase+FIR_LCR_B); /* SIP enable */ - //tmp |= 0x20; - //outb(tmp, iobase+FIR_LCR_B); - -} - -static void FIR2SIR(int iobase) -{ - unsigned char val; - - - /* Already protected (change_speed() or setup()), no need to lock. - * Jean II */ - - outb(0x20, iobase+FIR_MCR); /* IRQ to low */ - outb(0x00, iobase+UART_IER); - - outb(0xA0, iobase+FIR_MCR); /* Don't set master reset */ - outb(0x00, iobase+UART_FCR); - outb(0x07, iobase+UART_FCR); - - val = inb(iobase+UART_RX); - val = inb(iobase+UART_LSR); - val = inb(iobase+UART_MSR); - -} - -MODULE_AUTHOR("Benjamin Kong <benjamin_kong@ali.com.tw>"); -MODULE_DESCRIPTION("ALi FIR Controller Driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:" ALI_IRCC_DRIVER_NAME); - - -module_param_hw_array(io, int, ioport, NULL, 0); -MODULE_PARM_DESC(io, "Base I/O addresses"); -module_param_hw_array(irq, int, irq, NULL, 0); -MODULE_PARM_DESC(irq, "IRQ lines"); -module_param_hw_array(dma, int, dma, NULL, 0); -MODULE_PARM_DESC(dma, "DMA channels"); - -module_init(ali_ircc_init); -module_exit(ali_ircc_cleanup); diff --git a/drivers/net/irda/ali-ircc.h b/drivers/net/irda/ali-ircc.h deleted file mode 100644 index c2d9747a5108..000000000000 --- a/drivers/net/irda/ali-ircc.h +++ /dev/null @@ -1,227 +0,0 @@ -/********************************************************************* - * - * 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/ktime.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; /* Length 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; /* Length 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 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; - - ktime_t stamp; - - spinlock_t lock; /* For serializing operations */ - - __u32 new_speed; - int index; /* Instance index */ - - unsigned char fifo_opti_buf; -}; - -static inline void switch_bank(int iobase, int bank) -{ - outb(bank, iobase+FIR_MCR); -} - -#endif /* ALI_IRCC_H */ diff --git a/drivers/net/irda/au1k_ir.c b/drivers/net/irda/au1k_ir.c deleted file mode 100644 index be4ea6aa57a9..000000000000 --- a/drivers/net/irda/au1k_ir.c +++ /dev/null @@ -1,989 +0,0 @@ -/* - * 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, see <http://www.gnu.org/licenses/>. - */ - -#include <linux/clk.h> -#include <linux/module.h> -#include <linux/netdevice.h> -#include <linux/interrupt.h> -#include <linux/platform_device.h> -#include <linux/slab.h> -#include <linux/types.h> - -#include <net/irda/irda.h> -#include <net/irda/irmod.h> -#include <net/irda/wrapper.h> -#include <net/irda/irda_device.h> -#include <asm/mach-au1x00/au1000.h> - -/* registers */ -#define IR_RING_PTR_STATUS 0x00 -#define IR_RING_BASE_ADDR_H 0x04 -#define IR_RING_BASE_ADDR_L 0x08 -#define IR_RING_SIZE 0x0C -#define IR_RING_PROMPT 0x10 -#define IR_RING_ADDR_CMPR 0x14 -#define IR_INT_CLEAR 0x18 -#define IR_CONFIG_1 0x20 -#define IR_SIR_FLAGS 0x24 -#define IR_STATUS 0x28 -#define IR_READ_PHY_CONFIG 0x2C -#define IR_WRITE_PHY_CONFIG 0x30 -#define IR_MAX_PKT_LEN 0x34 -#define IR_RX_BYTE_CNT 0x38 -#define IR_CONFIG_2 0x3C -#define IR_ENABLE 0x40 - -/* Config1 */ -#define IR_RX_INVERT_LED (1 << 0) -#define IR_TX_INVERT_LED (1 << 1) -#define IR_ST (1 << 2) -#define IR_SF (1 << 3) -#define IR_SIR (1 << 4) -#define IR_MIR (1 << 5) -#define IR_FIR (1 << 6) -#define IR_16CRC (1 << 7) -#define IR_TD (1 << 8) -#define IR_RX_ALL (1 << 9) -#define IR_DMA_ENABLE (1 << 10) -#define IR_RX_ENABLE (1 << 11) -#define IR_TX_ENABLE (1 << 12) -#define IR_LOOPBACK (1 << 14) -#define IR_SIR_MODE (IR_SIR | IR_DMA_ENABLE | \ - IR_RX_ALL | IR_RX_ENABLE | IR_SF | \ - IR_16CRC) - -/* ir_status */ -#define IR_RX_STATUS (1 << 9) -#define IR_TX_STATUS (1 << 10) -#define IR_PHYEN (1 << 15) - -/* ir_write_phy_config */ -#define IR_BR(x) (((x) & 0x3f) << 10) /* baud rate */ -#define IR_PW(x) (((x) & 0x1f) << 5) /* pulse width */ -#define IR_P(x) ((x) & 0x1f) /* preamble bits */ - -/* Config2 */ -#define IR_MODE_INV (1 << 0) -#define IR_ONE_PIN (1 << 1) -#define IR_PHYCLK_40MHZ (0 << 2) -#define IR_PHYCLK_48MHZ (1 << 2) -#define IR_PHYCLK_56MHZ (2 << 2) -#define IR_PHYCLK_64MHZ (3 << 2) -#define IR_DP (1 << 4) -#define IR_DA (1 << 5) -#define IR_FLT_HIGH (0 << 6) -#define IR_FLT_MEDHI (1 << 6) -#define IR_FLT_MEDLO (2 << 6) -#define IR_FLT_LO (3 << 6) -#define IR_IEN (1 << 8) - -/* ir_enable */ -#define IR_HC (1 << 3) /* divide SBUS clock by 2 */ -#define IR_CE (1 << 2) /* clock enable */ -#define IR_C (1 << 1) /* coherency bit */ -#define IR_BE (1 << 0) /* set in big endian mode */ - -#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 - -/* 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) - -struct db_dest { - struct db_dest *pnext; - volatile u32 *vaddr; - dma_addr_t dma_addr; -}; - -struct ring_dest { - 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 */ -}; - -/* Private data for each instance */ -struct au1k_private { - void __iomem *iobase; - int irq_rx, irq_tx; - - struct db_dest *pDBfree; - struct db_dest db[2 * NUM_IR_DESC]; - volatile struct ring_dest *rx_ring[NUM_IR_DESC]; - volatile struct ring_dest *tx_ring[NUM_IR_DESC]; - struct db_dest *rx_db_inuse[NUM_IR_DESC]; - struct db_dest *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 qos_info qos; - struct irlap_cb *irlap; - - u8 open; - u32 speed; - u32 newspeed; - - struct resource *ioarea; - struct au1k_irda_platform_data *platdata; - struct clk *irda_clk; -}; - -static int qos_mtt_bits = 0x07; /* 1 ms or more */ - -static void au1k_irda_plat_set_phy_mode(struct au1k_private *p, int mode) -{ - if (p->platdata && p->platdata->set_phy_mode) - p->platdata->set_phy_mode(mode); -} - -static inline unsigned long irda_read(struct au1k_private *p, - unsigned long ofs) -{ - /* - * IrDA peripheral bug. You have to read the register - * twice to get the right value. - */ - (void)__raw_readl(p->iobase + ofs); - return __raw_readl(p->iobase + ofs); -} - -static inline void irda_write(struct au1k_private *p, unsigned long ofs, - unsigned long val) -{ - __raw_writel(val, p->iobase + ofs); - wmb(); -} - -/* - * 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 struct db_dest *GetFreeDB(struct au1k_private *aup) -{ - struct db_dest *db; - db = aup->pDBfree; - - if (db) - aup->pDBfree = db->pnext; - return db; -} - -/* - 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 struct ring_dest *) - (rx_base + sizeof(struct ring_dest) * i); - } - for (i = 0; i < NUM_IR_DESC; i++) { - aup->tx_ring[i] = (volatile struct ring_dest *) - (tx_base + sizeof(struct ring_dest) * i); - } -} - -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; -} - -/* - * Set the IrDA communications speed. - */ -static int au1k_irda_set_speed(struct net_device *dev, int speed) -{ - struct au1k_private *aup = netdev_priv(dev); - volatile struct ring_dest *ptxd; - unsigned long control; - int ret = 0, timeout = 10, i; - - if (speed == aup->speed) - return ret; - - /* disable PHY first */ - au1k_irda_plat_set_phy_mode(aup, AU1000_IRDA_PHY_MODE_OFF); - irda_write(aup, IR_STATUS, irda_read(aup, IR_STATUS) & ~IR_PHYEN); - - /* disable RX/TX */ - irda_write(aup, IR_CONFIG_1, - irda_read(aup, IR_CONFIG_1) & ~(IR_RX_ENABLE | IR_TX_ENABLE)); - msleep(20); - while (irda_read(aup, IR_STATUS) & (IR_RX_STATUS | IR_TX_STATUS)) { - msleep(20); - if (!timeout--) { - printk(KERN_ERR "%s: rx/tx disable timeout\n", - dev->name); - break; - } - } - - /* disable DMA */ - irda_write(aup, IR_CONFIG_1, - irda_read(aup, IR_CONFIG_1) & ~IR_DMA_ENABLE); - msleep(20); - - /* 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) - au1k_irda_plat_set_phy_mode(aup, AU1000_IRDA_PHY_MODE_FIR); - else - au1k_irda_plat_set_phy_mode(aup, AU1000_IRDA_PHY_MODE_SIR); - - switch (speed) { - case 9600: - irda_write(aup, IR_WRITE_PHY_CONFIG, IR_BR(11) | IR_PW(12)); - irda_write(aup, IR_CONFIG_1, IR_SIR_MODE); - break; - case 19200: - irda_write(aup, IR_WRITE_PHY_CONFIG, IR_BR(5) | IR_PW(12)); - irda_write(aup, IR_CONFIG_1, IR_SIR_MODE); - break; - case 38400: - irda_write(aup, IR_WRITE_PHY_CONFIG, IR_BR(2) | IR_PW(12)); - irda_write(aup, IR_CONFIG_1, IR_SIR_MODE); - break; - case 57600: - irda_write(aup, IR_WRITE_PHY_CONFIG, IR_BR(1) | IR_PW(12)); - irda_write(aup, IR_CONFIG_1, IR_SIR_MODE); - break; - case 115200: - irda_write(aup, IR_WRITE_PHY_CONFIG, IR_PW(12)); - irda_write(aup, IR_CONFIG_1, IR_SIR_MODE); - break; - case 4000000: - irda_write(aup, IR_WRITE_PHY_CONFIG, IR_P(15)); - irda_write(aup, IR_CONFIG_1, IR_FIR | IR_DMA_ENABLE | - IR_RX_ENABLE); - break; - default: - printk(KERN_ERR "%s unsupported speed %x\n", dev->name, speed); - ret = -EINVAL; - break; - } - - aup->speed = speed; - irda_write(aup, IR_STATUS, irda_read(aup, IR_STATUS) | IR_PHYEN); - - control = irda_read(aup, IR_STATUS); - irda_write(aup, IR_RING_PROMPT, 0); - - 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); - } - - return ret; -} - -static void update_rx_stats(struct net_device *dev, u32 status, u32 count) -{ - struct net_device_stats *ps = &dev->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; -} - -static void update_tx_stats(struct net_device *dev, u32 status, u32 pkt_len) -{ - struct net_device_stats *ps = &dev->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 struct ring_dest *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; - wmb(); - 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 { - irda_write(aup, IR_CONFIG_1, - irda_read(aup, IR_CONFIG_1) & ~IR_TX_ENABLE); - irda_write(aup, IR_CONFIG_1, - irda_read(aup, IR_CONFIG_1) | IR_RX_ENABLE); - irda_write(aup, IR_RING_PROMPT, 0); - } - } -} - -static int au1k_irda_rx(struct net_device *dev) -{ - struct au1k_private *aup = netdev_priv(dev); - volatile struct ring_dest *prxd; - struct sk_buff *skb; - struct db_dest *pDB; - u32 flags, count; - - 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) { - dev->stats.rx_dropped++; - continue; - } - skb_reserve(skb, 1); - if (aup->speed == 4000000) - skb_put(skb, count); - else - skb_put(skb, count - 2); - skb_copy_to_linear_data(skb, (void *)pDB->vaddr, - count - 2); - skb->dev = dev; - skb_reset_mac_header(skb); - 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); - irda_write(aup, IR_RING_PROMPT, 0); - - /* next descriptor */ - prxd = aup->rx_ring[aup->rx_head]; - flags = prxd->flags; - - } - return 0; -} - -static irqreturn_t au1k_irda_interrupt(int dummy, void *dev_id) -{ - struct net_device *dev = dev_id; - struct au1k_private *aup = netdev_priv(dev); - - irda_write(aup, IR_INT_CLEAR, 0); /* ack irda interrupts */ - - au1k_irda_rx(dev); - au1k_tx_ack(dev); - - return IRQ_HANDLED; -} - -static int au1k_init(struct net_device *dev) -{ - struct au1k_private *aup = netdev_priv(dev); - u32 enable, ring_address, phyck; - struct clk *c; - int i; - - c = clk_get(NULL, "irda_clk"); - if (IS_ERR(c)) - return PTR_ERR(c); - i = clk_prepare_enable(c); - if (i) { - clk_put(c); - return i; - } - - switch (clk_get_rate(c)) { - case 40000000: - phyck = IR_PHYCLK_40MHZ; - break; - case 48000000: - phyck = IR_PHYCLK_48MHZ; - break; - case 56000000: - phyck = IR_PHYCLK_56MHZ; - break; - case 64000000: - phyck = IR_PHYCLK_64MHZ; - break; - default: - clk_disable_unprepare(c); - clk_put(c); - return -EINVAL; - } - aup->irda_clk = c; - - enable = IR_HC | IR_CE | IR_C; -#ifndef CONFIG_CPU_LITTLE_ENDIAN - enable |= IR_BE; -#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; - - irda_write(aup, IR_ENABLE, enable); - msleep(20); - - /* disable PHY */ - au1k_irda_plat_set_phy_mode(aup, AU1000_IRDA_PHY_MODE_OFF); - irda_write(aup, IR_STATUS, irda_read(aup, IR_STATUS) & ~IR_PHYEN); - msleep(20); - - irda_write(aup, IR_MAX_PKT_LEN, MAX_BUF_SIZE); - - ring_address = (u32)virt_to_phys((void *)aup->rx_ring[0]); - irda_write(aup, IR_RING_BASE_ADDR_H, ring_address >> 26); - irda_write(aup, IR_RING_BASE_ADDR_L, (ring_address >> 10) & 0xffff); - - irda_write(aup, IR_RING_SIZE, - (RING_SIZE_64 << 8) | (RING_SIZE_64 << 12)); - - irda_write(aup, IR_CONFIG_2, phyck | IR_ONE_PIN); - irda_write(aup, IR_RING_ADDR_CMPR, 0); - - au1k_irda_set_speed(dev, 9600); - return 0; -} - -static int au1k_irda_start(struct net_device *dev) -{ - struct au1k_private *aup = netdev_priv(dev); - char hwname[32]; - int retval; - - retval = au1k_init(dev); - if (retval) { - printk(KERN_ERR "%s: error in au1k_init\n", dev->name); - return retval; - } - - retval = request_irq(aup->irq_tx, &au1k_irda_interrupt, 0, - dev->name, dev); - if (retval) { - printk(KERN_ERR "%s: unable to get IRQ %d\n", - dev->name, dev->irq); - return retval; - } - retval = request_irq(aup->irq_rx, &au1k_irda_interrupt, 0, - dev->name, dev); - if (retval) { - free_irq(aup->irq_tx, 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); - - /* int enable */ - irda_write(aup, IR_CONFIG_2, irda_read(aup, IR_CONFIG_2) | IR_IEN); - - /* power up */ - au1k_irda_plat_set_phy_mode(aup, AU1000_IRDA_PHY_MODE_SIR); - - return 0; -} - -static int au1k_irda_stop(struct net_device *dev) -{ - struct au1k_private *aup = netdev_priv(dev); - - au1k_irda_plat_set_phy_mode(aup, AU1000_IRDA_PHY_MODE_OFF); - - /* disable interrupts */ - irda_write(aup, IR_CONFIG_2, irda_read(aup, IR_CONFIG_2) & ~IR_IEN); - irda_write(aup, IR_CONFIG_1, 0); - irda_write(aup, IR_ENABLE, 0); /* disable clock */ - - if (aup->irlap) { - irlap_close(aup->irlap); - aup->irlap = NULL; - } - - netif_stop_queue(dev); - - /* disable the interrupt */ - free_irq(aup->irq_tx, dev); - free_irq(aup->irq_rx, dev); - - clk_disable_unprepare(aup->irda_clk); - clk_put(aup->irda_clk); - - return 0; -} - -/* - * 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 struct ring_dest *ptxd; - struct db_dest *pDB; - u32 len, flags; - - 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 NETDEV_TX_OK; - } - - 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 (irda_read(aup, IR_RX_BYTE_CNT) != 0) { - printk(KERN_DEBUG "tx warning: rx byte cnt %x\n", - irda_read(aup, IR_RX_BYTE_CNT)); - } -#endif - - if (aup->speed == 4000000) { - /* FIR */ - skb_copy_from_linear_data(skb, (void *)pDB->vaddr, 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; - } - ptxd->flags |= AU_OWN; - wmb(); - - irda_write(aup, IR_CONFIG_1, - irda_read(aup, IR_CONFIG_1) | IR_TX_ENABLE); - irda_write(aup, IR_RING_PROMPT, 0); - - dev_kfree_skb(skb); - aup->tx_head = (aup->tx_head + 1) & (NUM_IR_DESC - 1); - return NETDEV_TX_OK; -} - -/* - * 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); -} - -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 const struct net_device_ops au1k_irda_netdev_ops = { - .ndo_open = au1k_irda_start, - .ndo_stop = au1k_irda_stop, - .ndo_start_xmit = au1k_irda_hard_xmit, - .ndo_tx_timeout = au1k_tx_timeout, - .ndo_do_ioctl = au1k_irda_ioctl, -}; - -static int au1k_irda_net_init(struct net_device *dev) -{ - struct au1k_private *aup = netdev_priv(dev); - struct db_dest *pDB, *pDBfree; - int i, err, retval = 0; - dma_addr_t temp; - - err = au1k_irda_init_iobuf(&aup->rx_buff, 14384); - if (err) - goto out1; - - dev->netdev_ops = &au1k_irda_netdev_ops; - - 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] = (struct ring_dest *) - dma_alloc(2 * MAX_NUM_IR_DESC * (sizeof(struct ring_dest)), - &temp); - if (!aup->rx_ring[0]) - goto out2; - - /* allocate the data buffers */ - aup->db[0].vaddr = - 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 out3; - 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 out3; - 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; - } - - return 0; - -out3: - dma_free((void *)aup->rx_ring[0], - 2 * MAX_NUM_IR_DESC * (sizeof(struct ring_dest))); -out2: - kfree(aup->rx_buff.head); -out1: - printk(KERN_ERR "au1k_irda_net_init() failed. Returns %d\n", retval); - return retval; -} - -static int au1k_irda_probe(struct platform_device *pdev) -{ - struct au1k_private *aup; - struct net_device *dev; - struct resource *r; - struct clk *c; - int err; - - dev = alloc_irdadev(sizeof(struct au1k_private)); - if (!dev) - return -ENOMEM; - - aup = netdev_priv(dev); - - aup->platdata = pdev->dev.platform_data; - - err = -EINVAL; - r = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!r) - goto out; - - aup->irq_tx = r->start; - - r = platform_get_resource(pdev, IORESOURCE_IRQ, 1); - if (!r) - goto out; - - aup->irq_rx = r->start; - - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!r) - goto out; - - err = -EBUSY; - aup->ioarea = request_mem_region(r->start, resource_size(r), - pdev->name); - if (!aup->ioarea) - goto out; - - /* bail out early if clock doesn't exist */ - c = clk_get(NULL, "irda_clk"); - if (IS_ERR(c)) { - err = PTR_ERR(c); - goto out; - } - clk_put(c); - - aup->iobase = ioremap_nocache(r->start, resource_size(r)); - if (!aup->iobase) - goto out2; - - dev->irq = aup->irq_rx; - - err = au1k_irda_net_init(dev); - if (err) - goto out3; - err = register_netdev(dev); - if (err) - goto out4; - - platform_set_drvdata(pdev, dev); - - printk(KERN_INFO "IrDA: Registered device %s\n", dev->name); - return 0; - -out4: - 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(struct ring_dest))); - kfree(aup->rx_buff.head); -out3: - iounmap(aup->iobase); -out2: - release_resource(aup->ioarea); - kfree(aup->ioarea); -out: - free_netdev(dev); - return err; -} - -static int au1k_irda_remove(struct platform_device *pdev) -{ - struct net_device *dev = platform_get_drvdata(pdev); - 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(struct ring_dest))); - kfree(aup->rx_buff.head); - - iounmap(aup->iobase); - release_resource(aup->ioarea); - kfree(aup->ioarea); - - free_netdev(dev); - - return 0; -} - -static struct platform_driver au1k_irda_driver = { - .driver = { - .name = "au1000-irda", - }, - .probe = au1k_irda_probe, - .remove = au1k_irda_remove, -}; - -module_platform_driver(au1k_irda_driver); - -MODULE_AUTHOR("Pete Popov <ppopov@mvista.com>"); -MODULE_DESCRIPTION("Au1000 IrDA Device Driver"); diff --git a/drivers/net/irda/bfin_sir.c b/drivers/net/irda/bfin_sir.c deleted file mode 100644 index 3151b580dbd6..000000000000 --- a/drivers/net/irda/bfin_sir.c +++ /dev/null @@ -1,817 +0,0 @@ -/* - * Blackfin Infra-red Driver - * - * Copyright 2006-2009 Analog Devices Inc. - * - * Enter bugs at http://blackfin.uclinux.org/ - * - * Licensed under the GPL-2 or later. - * - */ -#include "bfin_sir.h" - -#ifdef CONFIG_SIR_BFIN_DMA -#define DMA_SIR_RX_XCNT 10 -#define DMA_SIR_RX_YCNT (PAGE_SIZE / DMA_SIR_RX_XCNT) -#define DMA_SIR_RX_FLUSH_JIFS (HZ * 4 / 250) -#endif - -#if ANOMALY_05000447 -static int max_rate = 57600; -#else -static int max_rate = 115200; -#endif - -static void turnaround_delay(int mtt) -{ - long ticks; - - mtt = mtt < 10000 ? 10000 : mtt; - ticks = 1 + mtt / (USEC_PER_SEC / HZ); - schedule_timeout_uninterruptible(ticks); -} - -static void bfin_sir_init_ports(struct bfin_sir_port *sp, struct platform_device *pdev) -{ - int i; - struct resource *res; - - for (i = 0; i < pdev->num_resources; i++) { - res = &pdev->resource[i]; - switch (res->flags) { - case IORESOURCE_MEM: - sp->membase = (void __iomem *)res->start; - break; - case IORESOURCE_IRQ: - sp->irq = res->start; - break; - case IORESOURCE_DMA: - sp->rx_dma_channel = res->start; - sp->tx_dma_channel = res->end; - break; - default: - break; - } - } - - sp->clk = get_sclk(); -#ifdef CONFIG_SIR_BFIN_DMA - sp->tx_done = 1; - init_timer(&(sp->rx_dma_timer)); -#endif -} - -static void bfin_sir_stop_tx(struct bfin_sir_port *port) -{ -#ifdef CONFIG_SIR_BFIN_DMA - disable_dma(port->tx_dma_channel); -#endif - - while (!(UART_GET_LSR(port) & THRE)) { - cpu_relax(); - continue; - } - - UART_CLEAR_IER(port, ETBEI); -} - -static void bfin_sir_enable_tx(struct bfin_sir_port *port) -{ - UART_SET_IER(port, ETBEI); -} - -static void bfin_sir_stop_rx(struct bfin_sir_port *port) -{ - UART_CLEAR_IER(port, ERBFI); -} - -static void bfin_sir_enable_rx(struct bfin_sir_port *port) -{ - UART_SET_IER(port, ERBFI); -} - -static int bfin_sir_set_speed(struct bfin_sir_port *port, int speed) -{ - int ret = -EINVAL; - unsigned int quot; - unsigned short val, lsr, lcr; - static int utime; - int count = 10; - - lcr = WLS(8); - - switch (speed) { - case 9600: - case 19200: - case 38400: - case 57600: - case 115200: - - /* - * IRDA is not affected by anomaly 05000230, so there is no - * need to tweak the divisor like he UART driver (which will - * slightly speed up the baud rate on us). - */ - quot = (port->clk + (8 * speed)) / (16 * speed); - - do { - udelay(utime); - lsr = UART_GET_LSR(port); - } while (!(lsr & TEMT) && count--); - - /* The useconds for 1 bits to transmit */ - utime = 1000000 / speed + 1; - - /* Clear UCEN bit to reset the UART state machine - * and control registers - */ - val = UART_GET_GCTL(port); - val &= ~UCEN; - UART_PUT_GCTL(port, val); - - /* Set DLAB in LCR to Access THR RBR IER */ - UART_SET_DLAB(port); - SSYNC(); - - UART_PUT_DLL(port, quot & 0xFF); - UART_PUT_DLH(port, (quot >> 8) & 0xFF); - SSYNC(); - - /* Clear DLAB in LCR */ - UART_CLEAR_DLAB(port); - SSYNC(); - - UART_PUT_LCR(port, lcr); - - val = UART_GET_GCTL(port); - val |= UCEN; - UART_PUT_GCTL(port, val); - - ret = 0; - break; - default: - printk(KERN_WARNING "bfin_sir: Invalid speed %d\n", speed); - break; - } - - val = UART_GET_GCTL(port); - /* If not add the 'RPOLC', we can't catch the receive interrupt. - * It's related with the HW layout and the IR transiver. - */ - val |= UMOD_IRDA | RPOLC; - UART_PUT_GCTL(port, val); - return ret; -} - -static int bfin_sir_is_receiving(struct net_device *dev) -{ - struct bfin_sir_self *self = netdev_priv(dev); - struct bfin_sir_port *port = self->sir_port; - - if (!(UART_GET_IER(port) & ERBFI)) - return 0; - return self->rx_buff.state != OUTSIDE_FRAME; -} - -#ifdef CONFIG_SIR_BFIN_PIO -static void bfin_sir_tx_chars(struct net_device *dev) -{ - unsigned int chr; - struct bfin_sir_self *self = netdev_priv(dev); - struct bfin_sir_port *port = self->sir_port; - - if (self->tx_buff.len != 0) { - chr = *(self->tx_buff.data); - UART_PUT_CHAR(port, chr); - self->tx_buff.data++; - self->tx_buff.len--; - } else { - self->stats.tx_packets++; - self->stats.tx_bytes += self->tx_buff.data - self->tx_buff.head; - if (self->newspeed) { - bfin_sir_set_speed(port, self->newspeed); - self->speed = self->newspeed; - self->newspeed = 0; - } - bfin_sir_stop_tx(port); - bfin_sir_enable_rx(port); - /* I'm hungry! */ - netif_wake_queue(dev); - } -} - -static void bfin_sir_rx_chars(struct net_device *dev) -{ - struct bfin_sir_self *self = netdev_priv(dev); - struct bfin_sir_port *port = self->sir_port; - unsigned char ch; - - UART_CLEAR_LSR(port); - ch = UART_GET_CHAR(port); - async_unwrap_char(dev, &self->stats, &self->rx_buff, ch); -} - -static irqreturn_t bfin_sir_rx_int(int irq, void *dev_id) -{ - struct net_device *dev = dev_id; - struct bfin_sir_self *self = netdev_priv(dev); - struct bfin_sir_port *port = self->sir_port; - - spin_lock(&self->lock); - while ((UART_GET_LSR(port) & DR)) - bfin_sir_rx_chars(dev); - spin_unlock(&self->lock); - - return IRQ_HANDLED; -} - -static irqreturn_t bfin_sir_tx_int(int irq, void *dev_id) -{ - struct net_device *dev = dev_id; - struct bfin_sir_self *self = netdev_priv(dev); - struct bfin_sir_port *port = self->sir_port; - - spin_lock(&self->lock); - if (UART_GET_LSR(port) & THRE) - bfin_sir_tx_chars(dev); - spin_unlock(&self->lock); - - return IRQ_HANDLED; -} -#endif /* CONFIG_SIR_BFIN_PIO */ - -#ifdef CONFIG_SIR_BFIN_DMA -static void bfin_sir_dma_tx_chars(struct net_device *dev) -{ - struct bfin_sir_self *self = netdev_priv(dev); - struct bfin_sir_port *port = self->sir_port; - - if (!port->tx_done) - return; - port->tx_done = 0; - - if (self->tx_buff.len == 0) { - self->stats.tx_packets++; - if (self->newspeed) { - bfin_sir_set_speed(port, self->newspeed); - self->speed = self->newspeed; - self->newspeed = 0; - } - bfin_sir_enable_rx(port); - port->tx_done = 1; - netif_wake_queue(dev); - return; - } - - blackfin_dcache_flush_range((unsigned long)(self->tx_buff.data), - (unsigned long)(self->tx_buff.data+self->tx_buff.len)); - set_dma_config(port->tx_dma_channel, - set_bfin_dma_config(DIR_READ, DMA_FLOW_STOP, - INTR_ON_BUF, DIMENSION_LINEAR, DATA_SIZE_8, - DMA_SYNC_RESTART)); - set_dma_start_addr(port->tx_dma_channel, - (unsigned long)(self->tx_buff.data)); - set_dma_x_count(port->tx_dma_channel, self->tx_buff.len); - set_dma_x_modify(port->tx_dma_channel, 1); - enable_dma(port->tx_dma_channel); -} - -static irqreturn_t bfin_sir_dma_tx_int(int irq, void *dev_id) -{ - struct net_device *dev = dev_id; - struct bfin_sir_self *self = netdev_priv(dev); - struct bfin_sir_port *port = self->sir_port; - - spin_lock(&self->lock); - if (!(get_dma_curr_irqstat(port->tx_dma_channel) & DMA_RUN)) { - clear_dma_irqstat(port->tx_dma_channel); - bfin_sir_stop_tx(port); - - self->stats.tx_packets++; - self->stats.tx_bytes += self->tx_buff.len; - self->tx_buff.len = 0; - if (self->newspeed) { - bfin_sir_set_speed(port, self->newspeed); - self->speed = self->newspeed; - self->newspeed = 0; - } - bfin_sir_enable_rx(port); - /* I'm hungry! */ - netif_wake_queue(dev); - port->tx_done = 1; - } - spin_unlock(&self->lock); - - return IRQ_HANDLED; -} - -static void bfin_sir_dma_rx_chars(struct net_device *dev) -{ - struct bfin_sir_self *self = netdev_priv(dev); - struct bfin_sir_port *port = self->sir_port; - int i; - - UART_CLEAR_LSR(port); - - for (i = port->rx_dma_buf.head; i < port->rx_dma_buf.tail; i++) - async_unwrap_char(dev, &self->stats, &self->rx_buff, port->rx_dma_buf.buf[i]); -} - -void bfin_sir_rx_dma_timeout(struct net_device *dev) -{ - struct bfin_sir_self *self = netdev_priv(dev); - struct bfin_sir_port *port = self->sir_port; - int x_pos, pos; - unsigned long flags; - - spin_lock_irqsave(&self->lock, flags); - x_pos = DMA_SIR_RX_XCNT - get_dma_curr_xcount(port->rx_dma_channel); - if (x_pos == DMA_SIR_RX_XCNT) - x_pos = 0; - - pos = port->rx_dma_nrows * DMA_SIR_RX_XCNT + x_pos; - - if (pos > port->rx_dma_buf.tail) { - port->rx_dma_buf.tail = pos; - bfin_sir_dma_rx_chars(dev); - port->rx_dma_buf.head = port->rx_dma_buf.tail; - } - spin_unlock_irqrestore(&self->lock, flags); -} - -static irqreturn_t bfin_sir_dma_rx_int(int irq, void *dev_id) -{ - struct net_device *dev = dev_id; - struct bfin_sir_self *self = netdev_priv(dev); - struct bfin_sir_port *port = self->sir_port; - unsigned short irqstat; - - spin_lock(&self->lock); - - port->rx_dma_nrows++; - port->rx_dma_buf.tail = DMA_SIR_RX_XCNT * port->rx_dma_nrows; - bfin_sir_dma_rx_chars(dev); - if (port->rx_dma_nrows >= DMA_SIR_RX_YCNT) { - port->rx_dma_nrows = 0; - port->rx_dma_buf.tail = 0; - } - port->rx_dma_buf.head = port->rx_dma_buf.tail; - - irqstat = get_dma_curr_irqstat(port->rx_dma_channel); - clear_dma_irqstat(port->rx_dma_channel); - spin_unlock(&self->lock); - - mod_timer(&port->rx_dma_timer, jiffies + DMA_SIR_RX_FLUSH_JIFS); - return IRQ_HANDLED; -} -#endif /* CONFIG_SIR_BFIN_DMA */ - -static int bfin_sir_startup(struct bfin_sir_port *port, struct net_device *dev) -{ -#ifdef CONFIG_SIR_BFIN_DMA - dma_addr_t dma_handle; -#endif /* CONFIG_SIR_BFIN_DMA */ - - if (request_dma(port->rx_dma_channel, "BFIN_UART_RX") < 0) { - dev_warn(&dev->dev, "Unable to attach SIR RX DMA channel\n"); - return -EBUSY; - } - - if (request_dma(port->tx_dma_channel, "BFIN_UART_TX") < 0) { - dev_warn(&dev->dev, "Unable to attach SIR TX DMA channel\n"); - free_dma(port->rx_dma_channel); - return -EBUSY; - } - -#ifdef CONFIG_SIR_BFIN_DMA - - set_dma_callback(port->rx_dma_channel, bfin_sir_dma_rx_int, dev); - set_dma_callback(port->tx_dma_channel, bfin_sir_dma_tx_int, dev); - - port->rx_dma_buf.buf = dma_alloc_coherent(NULL, PAGE_SIZE, - &dma_handle, GFP_DMA); - port->rx_dma_buf.head = 0; - port->rx_dma_buf.tail = 0; - port->rx_dma_nrows = 0; - - set_dma_config(port->rx_dma_channel, - set_bfin_dma_config(DIR_WRITE, DMA_FLOW_AUTO, - INTR_ON_ROW, DIMENSION_2D, - DATA_SIZE_8, DMA_SYNC_RESTART)); - set_dma_x_count(port->rx_dma_channel, DMA_SIR_RX_XCNT); - set_dma_x_modify(port->rx_dma_channel, 1); - set_dma_y_count(port->rx_dma_channel, DMA_SIR_RX_YCNT); - set_dma_y_modify(port->rx_dma_channel, 1); - set_dma_start_addr(port->rx_dma_channel, (unsigned long)port->rx_dma_buf.buf); - enable_dma(port->rx_dma_channel); - - port->rx_dma_timer.data = (unsigned long)(dev); - port->rx_dma_timer.function = (void *)bfin_sir_rx_dma_timeout; - -#else - - if (request_irq(port->irq, bfin_sir_rx_int, 0, "BFIN_SIR_RX", dev)) { - dev_warn(&dev->dev, "Unable to attach SIR RX interrupt\n"); - return -EBUSY; - } - - if (request_irq(port->irq+1, bfin_sir_tx_int, 0, "BFIN_SIR_TX", dev)) { - dev_warn(&dev->dev, "Unable to attach SIR TX interrupt\n"); - free_irq(port->irq, dev); - return -EBUSY; - } -#endif - - return 0; -} - -static void bfin_sir_shutdown(struct bfin_sir_port *port, struct net_device *dev) -{ - unsigned short val; - - bfin_sir_stop_rx(port); - - val = UART_GET_GCTL(port); - val &= ~(UCEN | UMOD_MASK | RPOLC); - UART_PUT_GCTL(port, val); - -#ifdef CONFIG_SIR_BFIN_DMA - disable_dma(port->tx_dma_channel); - disable_dma(port->rx_dma_channel); - del_timer(&(port->rx_dma_timer)); - dma_free_coherent(NULL, PAGE_SIZE, port->rx_dma_buf.buf, 0); -#else - free_irq(port->irq+1, dev); - free_irq(port->irq, dev); -#endif - free_dma(port->tx_dma_channel); - free_dma(port->rx_dma_channel); -} - -#ifdef CONFIG_PM -static int bfin_sir_suspend(struct platform_device *pdev, pm_message_t state) -{ - struct bfin_sir_port *sir_port; - struct net_device *dev; - struct bfin_sir_self *self; - - sir_port = platform_get_drvdata(pdev); - if (!sir_port) - return 0; - - dev = sir_port->dev; - self = netdev_priv(dev); - if (self->open) { - flush_work(&self->work); - bfin_sir_shutdown(self->sir_port, dev); - netif_device_detach(dev); - } - - return 0; -} -static int bfin_sir_resume(struct platform_device *pdev) -{ - struct bfin_sir_port *sir_port; - struct net_device *dev; - struct bfin_sir_self *self; - struct bfin_sir_port *port; - - sir_port = platform_get_drvdata(pdev); - if (!sir_port) - return 0; - - dev = sir_port->dev; - self = netdev_priv(dev); - port = self->sir_port; - if (self->open) { - if (self->newspeed) { - self->speed = self->newspeed; - self->newspeed = 0; - } - bfin_sir_startup(port, dev); - bfin_sir_set_speed(port, 9600); - bfin_sir_enable_rx(port); - netif_device_attach(dev); - } - return 0; -} -#else -#define bfin_sir_suspend NULL -#define bfin_sir_resume NULL -#endif - -static void bfin_sir_send_work(struct work_struct *work) -{ - struct bfin_sir_self *self = container_of(work, struct bfin_sir_self, work); - struct net_device *dev = self->sir_port->dev; - struct bfin_sir_port *port = self->sir_port; - unsigned short val; - int tx_cnt = 10; - - while (bfin_sir_is_receiving(dev) && --tx_cnt) - turnaround_delay(self->mtt); - - bfin_sir_stop_rx(port); - - /* To avoid losting RX interrupt, we reset IR function before - * sending data. We also can set the speed, which will - * reset all the UART. - */ - val = UART_GET_GCTL(port); - val &= ~(UMOD_MASK | RPOLC); - UART_PUT_GCTL(port, val); - SSYNC(); - val |= UMOD_IRDA | RPOLC; - UART_PUT_GCTL(port, val); - SSYNC(); - /* bfin_sir_set_speed(port, self->speed); */ - -#ifdef CONFIG_SIR_BFIN_DMA - bfin_sir_dma_tx_chars(dev); -#endif - bfin_sir_enable_tx(port); - netif_trans_update(dev); -} - -static int bfin_sir_hard_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct bfin_sir_self *self = netdev_priv(dev); - int speed = irda_get_next_speed(skb); - - netif_stop_queue(dev); - - self->mtt = irda_get_mtt(skb); - - if (speed != self->speed && speed != -1) - self->newspeed = speed; - - self->tx_buff.data = self->tx_buff.head; - if (skb->len == 0) - self->tx_buff.len = 0; - else - self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data, self->tx_buff.truesize); - - schedule_work(&self->work); - dev_kfree_skb(skb); - - return 0; -} - -static int bfin_sir_ioctl(struct net_device *dev, struct ifreq *ifreq, int cmd) -{ - struct if_irda_req *rq = (struct if_irda_req *)ifreq; - struct bfin_sir_self *self = netdev_priv(dev); - struct bfin_sir_port *port = self->sir_port; - int ret = 0; - - switch (cmd) { - case SIOCSBANDWIDTH: - if (capable(CAP_NET_ADMIN)) { - if (self->open) { - ret = bfin_sir_set_speed(port, rq->ifr_baudrate); - bfin_sir_enable_rx(port); - } else { - dev_warn(&dev->dev, "SIOCSBANDWIDTH: !netif_running\n"); - 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 = bfin_sir_is_receiving(dev); - break; - - default: - ret = -EOPNOTSUPP; - break; - } - - return ret; -} - -static struct net_device_stats *bfin_sir_stats(struct net_device *dev) -{ - struct bfin_sir_self *self = netdev_priv(dev); - - return &self->stats; -} - -static int bfin_sir_open(struct net_device *dev) -{ - struct bfin_sir_self *self = netdev_priv(dev); - struct bfin_sir_port *port = self->sir_port; - int err; - - self->newspeed = 0; - self->speed = 9600; - - spin_lock_init(&self->lock); - - err = bfin_sir_startup(port, dev); - if (err) - goto err_startup; - - bfin_sir_set_speed(port, 9600); - - self->irlap = irlap_open(dev, &self->qos, DRIVER_NAME); - if (!self->irlap) { - err = -ENOMEM; - goto err_irlap; - } - - INIT_WORK(&self->work, bfin_sir_send_work); - - /* - * Now enable the interrupt then start the queue - */ - self->open = 1; - bfin_sir_enable_rx(port); - - netif_start_queue(dev); - - return 0; - -err_irlap: - self->open = 0; - bfin_sir_shutdown(port, dev); -err_startup: - return err; -} - -static int bfin_sir_stop(struct net_device *dev) -{ - struct bfin_sir_self *self = netdev_priv(dev); - - flush_work(&self->work); - bfin_sir_shutdown(self->sir_port, dev); - - if (self->rxskb) { - dev_kfree_skb(self->rxskb); - self->rxskb = NULL; - } - - /* Stop IrLAP */ - if (self->irlap) { - irlap_close(self->irlap); - self->irlap = NULL; - } - - netif_stop_queue(dev); - self->open = 0; - - return 0; -} - -static int bfin_sir_init_iobuf(iobuff_t *io, int size) -{ - io->head = kmalloc(size, GFP_KERNEL); - if (!io->head) - return -ENOMEM; - io->truesize = size; - io->in_frame = FALSE; - io->state = OUTSIDE_FRAME; - io->data = io->head; - return 0; -} - -static const struct net_device_ops bfin_sir_ndo = { - .ndo_open = bfin_sir_open, - .ndo_stop = bfin_sir_stop, - .ndo_start_xmit = bfin_sir_hard_xmit, - .ndo_do_ioctl = bfin_sir_ioctl, - .ndo_get_stats = bfin_sir_stats, -}; - -static int bfin_sir_probe(struct platform_device *pdev) -{ - struct net_device *dev; - struct bfin_sir_self *self; - unsigned int baudrate_mask; - struct bfin_sir_port *sir_port; - int err; - - if (pdev->id >= 0 && pdev->id < ARRAY_SIZE(per) && \ - per[pdev->id][3] == pdev->id) { - err = peripheral_request_list(per[pdev->id], DRIVER_NAME); - if (err) - return err; - } else { - dev_err(&pdev->dev, "Invalid pdev id, please check board file\n"); - return -ENODEV; - } - - err = -ENOMEM; - sir_port = kmalloc(sizeof(*sir_port), GFP_KERNEL); - if (!sir_port) - goto err_mem_0; - - bfin_sir_init_ports(sir_port, pdev); - - dev = alloc_irdadev(sizeof(*self)); - if (!dev) - goto err_mem_1; - - self = netdev_priv(dev); - self->dev = &pdev->dev; - self->sir_port = sir_port; - sir_port->dev = dev; - - err = bfin_sir_init_iobuf(&self->rx_buff, IRDA_SKB_MAX_MTU); - if (err) - goto err_mem_2; - err = bfin_sir_init_iobuf(&self->tx_buff, IRDA_SIR_MAX_FRAME); - if (err) - goto err_mem_3; - - dev->netdev_ops = &bfin_sir_ndo; - dev->irq = sir_port->irq; - - irda_init_max_qos_capabilies(&self->qos); - - baudrate_mask = IR_9600; - - switch (max_rate) { - case 115200: - baudrate_mask |= IR_115200; - case 57600: - baudrate_mask |= IR_57600; - case 38400: - baudrate_mask |= IR_38400; - case 19200: - baudrate_mask |= IR_19200; - case 9600: - break; - default: - dev_warn(&pdev->dev, "Invalid maximum baud rate, using 9600\n"); - } - - self->qos.baud_rate.bits &= baudrate_mask; - - self->qos.min_turn_time.bits = 1; /* 10 ms or more */ - - irda_qos_bits_to_value(&self->qos); - - err = register_netdev(dev); - - if (err) { - kfree(self->tx_buff.head); -err_mem_3: - kfree(self->rx_buff.head); -err_mem_2: - free_netdev(dev); -err_mem_1: - kfree(sir_port); -err_mem_0: - peripheral_free_list(per[pdev->id]); - } else - platform_set_drvdata(pdev, sir_port); - - return err; -} - -static int bfin_sir_remove(struct platform_device *pdev) -{ - struct bfin_sir_port *sir_port; - struct net_device *dev = NULL; - struct bfin_sir_self *self; - - sir_port = platform_get_drvdata(pdev); - if (!sir_port) - return 0; - dev = sir_port->dev; - self = netdev_priv(dev); - unregister_netdev(dev); - kfree(self->tx_buff.head); - kfree(self->rx_buff.head); - free_netdev(dev); - kfree(sir_port); - - return 0; -} - -static struct platform_driver bfin_ir_driver = { - .probe = bfin_sir_probe, - .remove = bfin_sir_remove, - .suspend = bfin_sir_suspend, - .resume = bfin_sir_resume, - .driver = { - .name = DRIVER_NAME, - }, -}; - -module_platform_driver(bfin_ir_driver); - -module_param(max_rate, int, 0); -MODULE_PARM_DESC(max_rate, "Maximum baud rate (115200, 57600, 38400, 19200, 9600)"); - -MODULE_AUTHOR("Graf Yang <graf.yang@analog.com>"); -MODULE_DESCRIPTION("Blackfin IrDA driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/net/irda/bfin_sir.h b/drivers/net/irda/bfin_sir.h deleted file mode 100644 index d47cf14bb4a5..000000000000 --- a/drivers/net/irda/bfin_sir.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Blackfin Infra-red Driver - * - * Copyright 2006-2009 Analog Devices Inc. - * - * Enter bugs at http://blackfin.uclinux.org/ - * - * Licensed under the GPL-2 or later. - * - */ - -#include <linux/serial.h> -#include <linux/module.h> -#include <linux/netdevice.h> -#include <linux/interrupt.h> -#include <linux/delay.h> -#include <linux/platform_device.h> -#include <linux/dma-mapping.h> -#include <linux/slab.h> - -#include <net/irda/irda.h> -#include <net/irda/wrapper.h> -#include <net/irda/irda_device.h> - -#include <asm/irq.h> -#include <asm/cacheflush.h> -#include <asm/dma.h> -#include <asm/portmux.h> -#undef DRIVER_NAME - -#ifdef CONFIG_SIR_BFIN_DMA -struct dma_rx_buf { - char *buf; - int head; - int tail; -}; -#endif - -struct bfin_sir_port { - unsigned char __iomem *membase; - unsigned int irq; - unsigned int lsr; - unsigned long clk; - struct net_device *dev; -#ifdef CONFIG_SIR_BFIN_DMA - int tx_done; - struct dma_rx_buf rx_dma_buf; - struct timer_list rx_dma_timer; - int rx_dma_nrows; -#endif - unsigned int tx_dma_channel; - unsigned int rx_dma_channel; -}; - -struct bfin_sir_port_res { - unsigned long base_addr; - int irq; - unsigned int rx_dma_channel; - unsigned int tx_dma_channel; -}; - -struct bfin_sir_self { - struct bfin_sir_port *sir_port; - spinlock_t lock; - unsigned int open; - int speed; - int newspeed; - - struct sk_buff *txskb; - struct sk_buff *rxskb; - struct net_device_stats stats; - struct device *dev; - struct irlap_cb *irlap; - struct qos_info qos; - - iobuff_t tx_buff; - iobuff_t rx_buff; - - struct work_struct work; - int mtt; -}; - -#define DRIVER_NAME "bfin_sir" - -#include <asm/bfin_serial.h> - -static const unsigned short per[][4] = { - /* rx pin tx pin NULL uart_number */ - {P_UART0_RX, P_UART0_TX, 0, 0}, - {P_UART1_RX, P_UART1_TX, 0, 1}, - {P_UART2_RX, P_UART2_TX, 0, 2}, - {P_UART3_RX, P_UART3_TX, 0, 3}, -}; diff --git a/drivers/net/irda/donauboe.c b/drivers/net/irda/donauboe.c deleted file mode 100644 index b337e6d23a88..000000000000 --- a/drivers/net/irda/donauboe.c +++ /dev/null @@ -1,1732 +0,0 @@ -/***************************************************************** - * - * Filename: donauboe.c - * Version: 2.17 - * 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. - * Documentation: http://libxg.free.fr/irda/lib-irda.html - * Status: Experimental. - * Author: James McKenzie <james@fishsoup.dhs.org> - * Created at: Sat May 8 12:35:27 1999 - * Modified: Paul Bristow <paul.bristow@technologist.com> - * Modified: Mon Nov 11 19:10:05 1999 - * Modified: James McKenzie <james@fishsoup.dhs.org> - * Modified: Thu Mar 16 12:49:00 2000 (Substantial rewrite) - * Modified: Sat Apr 29 00:23:03 2000 (Added DONAUOBOE support) - * Modified: Wed May 24 23:45:02 2000 (Fixed chipio_t structure) - * Modified: 2.13 Christian Gennerat <christian.gennerat@polytechnique.org> - * Modified: 2.13 dim jan 07 21:57:39 2001 (tested with kernel 2.4 & irnet/ppp) - * Modified: 2.14 Christian Gennerat <christian.gennerat@polytechnique.org> - * Modified: 2.14 lun fev 05 17:55:59 2001 (adapted to patch-2.4.1-pre8-irda1) - * Modified: 2.15 Martin Lucina <mato@kotelna.sk> - * Modified: 2.15 Fri Jun 21 20:40:59 2002 (sync with 2.4.18, substantial fixes) - * Modified: 2.16 Martin Lucina <mato@kotelna.sk> - * Modified: 2.16 Sat Jun 22 18:54:29 2002 (fix freeregion, default to verbose) - * Modified: 2.17 Christian Gennerat <christian.gennerat@polytechnique.org> - * Modified: 2.17 jeu sep 12 08:50:20 2002 (save_flags();cli(); replaced by spinlocks) - * Modified: 2.18 Christian Gennerat <christian.gennerat@polytechnique.org> - * Modified: 2.18 ven jan 10 03:14:16 2003 Change probe default options - * - * 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. - * - ********************************************************************/ - -/* Look at toshoboe.h (currently in include/net/irda) for details of */ -/* Where to get documentation on the chip */ - -/* See below for a description of the logic in this driver */ - -/* User servicable parts */ -/* USE_PROBE Create the code which probes the chip and does a few tests */ -/* do_probe module parameter Enable this code */ -/* Probe code is very useful for understanding how the hardware works */ -/* Use it with various combinations of TT_LEN, RX_LEN */ -/* Strongly recommended, disable if the probe fails on your machine */ -/* and send me <james@fishsoup.dhs.org> the output of dmesg */ -#define USE_PROBE 1 -#undef USE_PROBE - -/* Trace Transmit ring, interrupts, Receive ring or not ? */ -#define PROBE_VERBOSE 1 - -/* Debug option, examine sent and received raw data */ -/* Irdadump is better, but does not see all packets. enable it if you want. */ -#undef DUMP_PACKETS - -/* MIR mode has not been tested. Some behaviour is different */ -/* Seems to work against an Ericsson R520 for me. -Martin */ -#define USE_MIR - -/* Schedule back to back hardware transmits wherever possible, otherwise */ -/* we need an interrupt for every frame, unset if oboe works for a bit and */ -/* then hangs */ -#define OPTIMIZE_TX - -/* Set the number of slots in the rings */ -/* If you get rx/tx fifo overflows at high bitrates, you can try increasing */ -/* these */ - -#define RING_SIZE (OBOE_RING_SIZE_RX8 | OBOE_RING_SIZE_TX8) -#define TX_SLOTS 8 -#define RX_SLOTS 8 - - -/* Less user servicable parts below here */ - -/* Test, Transmit and receive buffer sizes, adjust at your peril */ -/* remarks: nfs usually needs 1k blocks */ -/* remarks: in SIR mode, CRC is received, -> RX_LEN=TX_LEN+2 */ -/* remarks: test accepts large blocks. Standard is 0x80 */ -/* When TT_LEN > RX_LEN (SIR mode) data is stored in successive slots. */ -/* When 3 or more slots are needed for each test packet, */ -/* data received in the first slots is overwritten, even */ -/* if OBOE_CTL_RX_HW_OWNS is not set, without any error! */ -#define TT_LEN 0x80 -#define TX_LEN 0xc00 -#define RX_LEN 0xc04 -/* Real transmitted length (SIR mode) is about 14+(2%*TX_LEN) more */ -/* long than user-defined length (see async_wrap_skb) and is less then 4K */ -/* Real received length is (max RX_LEN) differs from user-defined */ -/* length only b the CRC (2 or 4 bytes) */ -#define BUF_SAFETY 0x7a -#define RX_BUF_SZ (RX_LEN) -#define TX_BUF_SZ (TX_LEN+BUF_SAFETY) - - -/* Logic of the netdev part of this driver */ - -/* The RX ring is filled with buffers, when a packet arrives */ -/* it is DMA'd into the buffer which is marked used and RxDone called */ -/* RxDone forms an skb (and checks the CRC if in SIR mode) and ships */ -/* the packet off upstairs */ - -/* The transmitter on the oboe chip can work in one of two modes */ -/* for each ring->tx[] the transmitter can either */ -/* a) transmit the packet, leave the trasmitter enabled and proceed to */ -/* the next ring */ -/* OR */ -/* b) transmit the packet, switch off the transmitter and issue TxDone */ - -/* All packets are entered into the ring in mode b), if the ring was */ -/* empty the transmitter is started. */ - -/* If OPTIMIZE_TX is defined then in TxDone if the ring contains */ -/* more than one packet, all but the last are set to mode a) [HOWEVER */ -/* the hardware may not notice this, this is why we start in mode b) ] */ -/* then restart the transmitter */ - -/* If OPTIMIZE_TX is not defined then we just restart the transmitter */ -/* if the ring isn't empty */ - -/* Speed changes are delayed until the TxRing is empty */ -/* mtt is handled by generating packets with bad CRCs, before the data */ - -/* TODO: */ -/* check the mtt works ok */ -/* finish the watchdog */ - -/* No user servicable parts below here */ - -#include <linux/module.h> - -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/skbuff.h> -#include <linux/netdevice.h> -#include <linux/ioport.h> -#include <linux/delay.h> -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/pci.h> -#include <linux/rtnetlink.h> - -#include <asm/io.h> - -#include <net/irda/wrapper.h> -#include <net/irda/irda.h> -//#include <net/irda/irmod.h> -//#include <net/irda/irlap_frame.h> -#include <net/irda/irda_device.h> -#include <net/irda/crc.h> - -#include "donauboe.h" - -#define INB(port) inb_p(port) -#define OUTB(val,port) outb_p(val,port) -#define OUTBP(val,port) outb_p(val,port) - -#define PROMPT OUTB(OBOE_PROMPT_BIT,OBOE_PROMPT); - -#if PROBE_VERBOSE -#define PROBE_DEBUG(args...) (printk (args)) -#else -#define PROBE_DEBUG(args...) ; -#endif - -/* Set the DMA to be byte at a time */ -#define CONFIG0H_DMA_OFF OBOE_CONFIG0H_RCVANY -#define CONFIG0H_DMA_ON_NORX CONFIG0H_DMA_OFF| OBOE_CONFIG0H_ENDMAC -#define CONFIG0H_DMA_ON CONFIG0H_DMA_ON_NORX | OBOE_CONFIG0H_ENRX - -static const struct pci_device_id toshoboe_pci_tbl[] = { - { PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_FIR701, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_FIRD01, PCI_ANY_ID, PCI_ANY_ID, }, - { } /* Terminating entry */ -}; -MODULE_DEVICE_TABLE(pci, toshoboe_pci_tbl); - -#define DRIVER_NAME "toshoboe" -static char *driver_name = DRIVER_NAME; - -static int max_baud = 4000000; -#ifdef USE_PROBE -static bool do_probe = false; -#endif - - -/**********************************************************************/ -static int -toshoboe_checkfcs (unsigned char *buf, int len) -{ - int i; - union - { - __u16 value; - __u8 bytes[2]; - } - fcs; - - fcs.value = INIT_FCS; - - for (i = 0; i < len; ++i) - fcs.value = irda_fcs (fcs.value, *(buf++)); - - return fcs.value == GOOD_FCS; -} - -/***********************************************************************/ -/* Generic chip handling code */ -#ifdef DUMP_PACKETS -static unsigned char dump[50]; -static void -_dumpbufs (unsigned char *data, int len, char tete) -{ -int i,j; -char head=tete; -for (i=0;i<len;i+=16) { - for (j=0;j<16 && i+j<len;j++) { sprintf(&dump[3*j],"%02x.",data[i+j]); } - dump [3*j]=0; - pr_debug("%c%s\n", head, dump); - head='+'; - } -} -#endif - -#ifdef USE_PROBE -/* Dump the registers */ -static void -toshoboe_dumpregs (struct toshoboe_cb *self) -{ - __u32 ringbase; - - ringbase = INB (OBOE_RING_BASE0) << 10; - ringbase |= INB (OBOE_RING_BASE1) << 18; - ringbase |= INB (OBOE_RING_BASE2) << 26; - - printk (KERN_ERR DRIVER_NAME ": Register dump:\n"); - printk (KERN_ERR "Interrupts: Tx:%d Rx:%d TxUnder:%d RxOver:%d Sip:%d\n", - self->int_tx, self->int_rx, self->int_txunder, self->int_rxover, - self->int_sip); - printk (KERN_ERR "RX %02x TX %02x RingBase %08x\n", - INB (OBOE_RXSLOT), INB (OBOE_TXSLOT), ringbase); - printk (KERN_ERR "RING_SIZE %02x IER %02x ISR %02x\n", - INB (OBOE_RING_SIZE), INB (OBOE_IER), INB (OBOE_ISR)); - printk (KERN_ERR "CONFIG1 %02x STATUS %02x\n", - INB (OBOE_CONFIG1), INB (OBOE_STATUS)); - printk (KERN_ERR "CONFIG0 %02x%02x ENABLE %02x%02x\n", - INB (OBOE_CONFIG0H), INB (OBOE_CONFIG0L), - INB (OBOE_ENABLEH), INB (OBOE_ENABLEL)); - printk (KERN_ERR "NEW_PCONFIG %02x%02x CURR_PCONFIG %02x%02x\n", - INB (OBOE_NEW_PCONFIGH), INB (OBOE_NEW_PCONFIGL), - INB (OBOE_CURR_PCONFIGH), INB (OBOE_CURR_PCONFIGL)); - printk (KERN_ERR "MAXLEN %02x%02x RXCOUNT %02x%02x\n", - INB (OBOE_MAXLENH), INB (OBOE_MAXLENL), - INB (OBOE_RXCOUNTL), INB (OBOE_RXCOUNTH)); - - if (self->ring) - { - int i; - ringbase = virt_to_bus (self->ring); - printk (KERN_ERR "Ring at %08x:\n", ringbase); - printk (KERN_ERR "RX:"); - for (i = 0; i < RX_SLOTS; ++i) - printk (" (%d,%02x)",self->ring->rx[i].len,self->ring->rx[i].control); - printk ("\n"); - printk (KERN_ERR "TX:"); - for (i = 0; i < RX_SLOTS; ++i) - printk (" (%d,%02x)",self->ring->tx[i].len,self->ring->tx[i].control); - printk ("\n"); - } -} -#endif - -/*Don't let the chip look at memory */ -static void -toshoboe_disablebm (struct toshoboe_cb *self) -{ - __u8 command; - pci_read_config_byte (self->pdev, PCI_COMMAND, &command); - command &= ~PCI_COMMAND_MASTER; - pci_write_config_byte (self->pdev, PCI_COMMAND, command); - -} - -/* Shutdown the chip and point the taskfile reg somewhere else */ -static void -toshoboe_stopchip (struct toshoboe_cb *self) -{ - /*Disable interrupts */ - OUTB (0x0, OBOE_IER); - /*Disable DMA, Disable Rx, Disable Tx */ - OUTB (CONFIG0H_DMA_OFF, OBOE_CONFIG0H); - /*Disable SIR MIR FIR, Tx and Rx */ - OUTB (0x00, OBOE_ENABLEH); - /*Point the ring somewhere safe */ - OUTB (0x3f, OBOE_RING_BASE2); - OUTB (0xff, OBOE_RING_BASE1); - OUTB (0xff, OBOE_RING_BASE0); - - OUTB (RX_LEN >> 8, OBOE_MAXLENH); - OUTB (RX_LEN & 0xff, OBOE_MAXLENL); - - /*Acknoledge any pending interrupts */ - OUTB (0xff, OBOE_ISR); - - /*Why */ - OUTB (OBOE_ENABLEH_PHYANDCLOCK, OBOE_ENABLEH); - - /*switch it off */ - OUTB (OBOE_CONFIG1_OFF, OBOE_CONFIG1); - - toshoboe_disablebm (self); -} - -/* Transmitter initialization */ -static void -toshoboe_start_DMA (struct toshoboe_cb *self, int opts) -{ - OUTB (0x0, OBOE_ENABLEH); - OUTB (CONFIG0H_DMA_ON | opts, OBOE_CONFIG0H); - OUTB (OBOE_ENABLEH_PHYANDCLOCK, OBOE_ENABLEH); - PROMPT; -} - -/*Set the baud rate */ -static void -toshoboe_setbaud (struct toshoboe_cb *self) -{ - __u16 pconfig = 0; - __u8 config0l = 0; - - pr_debug("%s(%d/%d)\n", __func__, self->speed, self->io.speed); - - switch (self->speed) - { - case 2400: - case 4800: - case 9600: - case 19200: - case 38400: - case 57600: - case 115200: -#ifdef USE_MIR - case 1152000: -#endif - case 4000000: - break; - default: - - printk (KERN_ERR DRIVER_NAME ": switch to unsupported baudrate %d\n", - self->speed); - return; - } - - switch (self->speed) - { - /* For SIR the preamble is done by adding XBOFs */ - /* to the packet */ - /* set to filtered SIR mode, filter looks for BOF and EOF */ - case 2400: - pconfig |= 47 << OBOE_PCONFIG_BAUDSHIFT; - pconfig |= 25 << OBOE_PCONFIG_WIDTHSHIFT; - break; - case 4800: - pconfig |= 23 << OBOE_PCONFIG_BAUDSHIFT; - pconfig |= 25 << OBOE_PCONFIG_WIDTHSHIFT; - break; - case 9600: - pconfig |= 11 << OBOE_PCONFIG_BAUDSHIFT; - pconfig |= 25 << OBOE_PCONFIG_WIDTHSHIFT; - break; - case 19200: - pconfig |= 5 << OBOE_PCONFIG_BAUDSHIFT; - pconfig |= 25 << OBOE_PCONFIG_WIDTHSHIFT; - break; - case 38400: - pconfig |= 2 << OBOE_PCONFIG_BAUDSHIFT; - pconfig |= 25 << OBOE_PCONFIG_WIDTHSHIFT; - break; - case 57600: - pconfig |= 1 << OBOE_PCONFIG_BAUDSHIFT; - pconfig |= 25 << OBOE_PCONFIG_WIDTHSHIFT; - break; - case 115200: - pconfig |= 0 << OBOE_PCONFIG_BAUDSHIFT; - pconfig |= 25 << OBOE_PCONFIG_WIDTHSHIFT; - break; - default: - /*Set to packet based reception */ - OUTB (RX_LEN >> 8, OBOE_MAXLENH); - OUTB (RX_LEN & 0xff, OBOE_MAXLENL); - break; - } - - switch (self->speed) - { - case 2400: - case 4800: - case 9600: - case 19200: - case 38400: - case 57600: - case 115200: - config0l = OBOE_CONFIG0L_ENSIR; - if (self->async) - { - /*Set to character based reception */ - /*System will lock if MAXLEN=0 */ - /*so have to be careful */ - OUTB (0x01, OBOE_MAXLENH); - OUTB (0x01, OBOE_MAXLENL); - OUTB (0x00, OBOE_MAXLENH); - } - else - { - /*Set to packet based reception */ - config0l |= OBOE_CONFIG0L_ENSIRF; - OUTB (RX_LEN >> 8, OBOE_MAXLENH); - OUTB (RX_LEN & 0xff, OBOE_MAXLENL); - } - break; - -#ifdef USE_MIR - /* MIR mode */ - /* Set for 16 bit CRC and enable MIR */ - /* Preamble now handled by the chip */ - case 1152000: - pconfig |= 0 << OBOE_PCONFIG_BAUDSHIFT; - pconfig |= 8 << OBOE_PCONFIG_WIDTHSHIFT; - pconfig |= 1 << OBOE_PCONFIG_PREAMBLESHIFT; - config0l = OBOE_CONFIG0L_CRC16 | OBOE_CONFIG0L_ENMIR; - break; -#endif - /* FIR mode */ - /* Set for 32 bit CRC and enable FIR */ - /* Preamble handled by the chip */ - case 4000000: - pconfig |= 0 << OBOE_PCONFIG_BAUDSHIFT; - /* Documentation says 14, but toshiba use 15 in their drivers */ - pconfig |= 15 << OBOE_PCONFIG_PREAMBLESHIFT; - config0l = OBOE_CONFIG0L_ENFIR; - break; - } - - /* Copy into new PHY config buffer */ - OUTBP (pconfig >> 8, OBOE_NEW_PCONFIGH); - OUTB (pconfig & 0xff, OBOE_NEW_PCONFIGL); - OUTB (config0l, OBOE_CONFIG0L); - - /* Now make OBOE copy from new PHY to current PHY */ - OUTB (0x0, OBOE_ENABLEH); - OUTB (OBOE_ENABLEH_PHYANDCLOCK, OBOE_ENABLEH); - PROMPT; - - /* speed change executed */ - self->new_speed = 0; - self->io.speed = self->speed; -} - -/*Let the chip look at memory */ -static void -toshoboe_enablebm (struct toshoboe_cb *self) -{ - pci_set_master (self->pdev); -} - -/*setup the ring */ -static void -toshoboe_initring (struct toshoboe_cb *self) -{ - int i; - - for (i = 0; i < TX_SLOTS; ++i) - { - self->ring->tx[i].len = 0; - self->ring->tx[i].control = 0x00; - self->ring->tx[i].address = virt_to_bus (self->tx_bufs[i]); - } - - for (i = 0; i < RX_SLOTS; ++i) - { - self->ring->rx[i].len = RX_LEN; - self->ring->rx[i].len = 0; - self->ring->rx[i].address = virt_to_bus (self->rx_bufs[i]); - self->ring->rx[i].control = OBOE_CTL_RX_HW_OWNS; - } -} - -static void -toshoboe_resetptrs (struct toshoboe_cb *self) -{ - /* Can reset pointers by twidling DMA */ - OUTB (0x0, OBOE_ENABLEH); - OUTBP (CONFIG0H_DMA_OFF, OBOE_CONFIG0H); - OUTB (OBOE_ENABLEH_PHYANDCLOCK, OBOE_ENABLEH); - - self->rxs = inb_p (OBOE_RXSLOT) & OBOE_SLOT_MASK; - self->txs = inb_p (OBOE_TXSLOT) & OBOE_SLOT_MASK; -} - -/* Called in locked state */ -static void -toshoboe_initptrs (struct toshoboe_cb *self) -{ - - /* spin_lock_irqsave(self->spinlock, flags); */ - /* save_flags (flags); */ - - /* Can reset pointers by twidling DMA */ - toshoboe_resetptrs (self); - - OUTB (0x0, OBOE_ENABLEH); - OUTB (CONFIG0H_DMA_ON, OBOE_CONFIG0H); - OUTB (OBOE_ENABLEH_PHYANDCLOCK, OBOE_ENABLEH); - - self->txpending = 0; - - /* spin_unlock_irqrestore(self->spinlock, flags); */ - /* restore_flags (flags); */ -} - -/* Wake the chip up and get it looking at the rings */ -/* Called in locked state */ -static void -toshoboe_startchip (struct toshoboe_cb *self) -{ - __u32 physaddr; - - toshoboe_initring (self); - toshoboe_enablebm (self); - OUTBP (OBOE_CONFIG1_RESET, OBOE_CONFIG1); - OUTBP (OBOE_CONFIG1_ON, OBOE_CONFIG1); - - /* Stop the clocks */ - OUTB (0, OBOE_ENABLEH); - - /*Set size of rings */ - OUTB (RING_SIZE, OBOE_RING_SIZE); - - /*Acknoledge any pending interrupts */ - OUTB (0xff, OBOE_ISR); - - /*Enable ints */ - OUTB (OBOE_INT_TXDONE | OBOE_INT_RXDONE | - OBOE_INT_TXUNDER | OBOE_INT_RXOVER | OBOE_INT_SIP , OBOE_IER); - - /*Acknoledge any pending interrupts */ - OUTB (0xff, OBOE_ISR); - - /*Set the maximum packet length to 0xfff (4095) */ - OUTB (RX_LEN >> 8, OBOE_MAXLENH); - OUTB (RX_LEN & 0xff, OBOE_MAXLENL); - - /*Shutdown DMA */ - OUTB (CONFIG0H_DMA_OFF, OBOE_CONFIG0H); - - /*Find out where the rings live */ - physaddr = virt_to_bus (self->ring); - - IRDA_ASSERT ((physaddr & 0x3ff) == 0, - printk (KERN_ERR DRIVER_NAME "ring not correctly aligned\n"); - return;); - - OUTB ((physaddr >> 10) & 0xff, OBOE_RING_BASE0); - OUTB ((physaddr >> 18) & 0xff, OBOE_RING_BASE1); - OUTB ((physaddr >> 26) & 0x3f, OBOE_RING_BASE2); - - /*Enable DMA controller in byte mode and RX */ - OUTB (CONFIG0H_DMA_ON, OBOE_CONFIG0H); - - /* Start up the clocks */ - OUTB (OBOE_ENABLEH_PHYANDCLOCK, OBOE_ENABLEH); - - /*set to sensible speed */ - self->speed = 9600; - toshoboe_setbaud (self); - toshoboe_initptrs (self); -} - -static void -toshoboe_isntstuck (struct toshoboe_cb *self) -{ -} - -static void -toshoboe_checkstuck (struct toshoboe_cb *self) -{ - unsigned long flags; - - if (0) - { - spin_lock_irqsave(&self->spinlock, flags); - - /* This will reset the chip completely */ - printk (KERN_ERR DRIVER_NAME ": Resetting chip\n"); - - toshoboe_stopchip (self); - toshoboe_startchip (self); - spin_unlock_irqrestore(&self->spinlock, flags); - } -} - -/*Generate packet of about mtt us long */ -static int -toshoboe_makemttpacket (struct toshoboe_cb *self, void *buf, int mtt) -{ - int xbofs; - - xbofs = ((int) (mtt/100)) * (int) (self->speed); - xbofs=xbofs/80000; /*Eight bits per byte, and mtt is in us*/ - xbofs++; - - pr_debug(DRIVER_NAME ": generated mtt of %d bytes for %d us at %d baud\n", - xbofs, mtt, self->speed); - - if (xbofs > TX_LEN) - { - printk (KERN_ERR DRIVER_NAME ": wanted %d bytes MTT but TX_LEN is %d\n", - xbofs, TX_LEN); - xbofs = TX_LEN; - } - - /*xbofs will do for SIR, MIR and FIR,SIR mode doesn't generate a checksum anyway */ - memset (buf, XBOF, xbofs); - - return xbofs; -} - -#ifdef USE_PROBE -/***********************************************************************/ -/* Probe code */ - -static void -toshoboe_dumptx (struct toshoboe_cb *self) -{ - int i; - PROBE_DEBUG(KERN_WARNING "TX:"); - for (i = 0; i < RX_SLOTS; ++i) - PROBE_DEBUG(" (%d,%02x)",self->ring->tx[i].len,self->ring->tx[i].control); - PROBE_DEBUG(" [%d]\n",self->speed); -} - -static void -toshoboe_dumprx (struct toshoboe_cb *self, int score) -{ - int i; - PROBE_DEBUG(" %d\nRX:",score); - for (i = 0; i < RX_SLOTS; ++i) - PROBE_DEBUG(" (%d,%02x)",self->ring->rx[i].len,self->ring->rx[i].control); - PROBE_DEBUG("\n"); -} - -static inline int -stuff_byte (__u8 byte, __u8 * buf) -{ - switch (byte) - { - case BOF: /* FALLTHROUGH */ - case EOF: /* FALLTHROUGH */ - case CE: - /* Insert transparently coded */ - buf[0] = CE; /* Send link escape */ - buf[1] = byte ^ IRDA_TRANS; /* Complement bit 5 */ - return 2; - /* break; */ - default: - /* Non-special value, no transparency required */ - buf[0] = byte; - return 1; - /* break; */ - } -} - -static irqreturn_t -toshoboe_probeinterrupt (int irq, void *dev_id) -{ - struct toshoboe_cb *self = dev_id; - __u8 irqstat; - - irqstat = INB (OBOE_ISR); - -/* was it us */ - if (!(irqstat & OBOE_INT_MASK)) - return IRQ_NONE; - -/* Ack all the interrupts */ - OUTB (irqstat, OBOE_ISR); - - if (irqstat & OBOE_INT_TXDONE) - { - int txp; - - self->int_tx++; - PROBE_DEBUG("T"); - - txp = INB (OBOE_TXSLOT) & OBOE_SLOT_MASK; - if (self->ring->tx[txp].control & OBOE_CTL_TX_HW_OWNS) - { - self->int_tx+=100; - PROBE_DEBUG("S"); - toshoboe_start_DMA(self, OBOE_CONFIG0H_ENTX | OBOE_CONFIG0H_LOOP); - } - } - - if (irqstat & OBOE_INT_RXDONE) { - self->int_rx++; - PROBE_DEBUG("R"); } - if (irqstat & OBOE_INT_TXUNDER) { - self->int_txunder++; - PROBE_DEBUG("U"); } - if (irqstat & OBOE_INT_RXOVER) { - self->int_rxover++; - PROBE_DEBUG("O"); } - if (irqstat & OBOE_INT_SIP) { - self->int_sip++; - PROBE_DEBUG("I"); } - return IRQ_HANDLED; -} - -static int -toshoboe_maketestpacket (unsigned char *buf, int badcrc, int fir) -{ - int i; - int len = 0; - union - { - __u16 value; - __u8 bytes[2]; - } - fcs; - - if (fir) - { - memset (buf, 0, TT_LEN); - return TT_LEN; - } - - fcs.value = INIT_FCS; - - memset (buf, XBOF, 10); - len += 10; - buf[len++] = BOF; - - for (i = 0; i < TT_LEN; ++i) - { - len += stuff_byte (i, buf + len); - fcs.value = irda_fcs (fcs.value, i); - } - - len += stuff_byte (fcs.bytes[0] ^ badcrc, buf + len); - len += stuff_byte (fcs.bytes[1] ^ badcrc, buf + len); - buf[len++] = EOF; - len++; - return len; -} - -static int -toshoboe_probefail (struct toshoboe_cb *self, char *msg) -{ - printk (KERN_ERR DRIVER_NAME "probe(%d) failed %s\n",self-> speed, msg); - toshoboe_dumpregs (self); - toshoboe_stopchip (self); - free_irq (self->io.irq, (void *) self); - return 0; -} - -static int -toshoboe_numvalidrcvs (struct toshoboe_cb *self) -{ - int i, ret = 0; - for (i = 0; i < RX_SLOTS; ++i) - if ((self->ring->rx[i].control & 0xe0) == 0) - ret++; - - return ret; -} - -static int -toshoboe_numrcvs (struct toshoboe_cb *self) -{ - int i, ret = 0; - for (i = 0; i < RX_SLOTS; ++i) - if (!(self->ring->rx[i].control & OBOE_CTL_RX_HW_OWNS)) - ret++; - - return ret; -} - -static int -toshoboe_probe (struct toshoboe_cb *self) -{ - int i, j, n; -#ifdef USE_MIR - static const int bauds[] = { 9600, 115200, 4000000, 1152000 }; -#else - static const int bauds[] = { 9600, 115200, 4000000 }; -#endif - unsigned long flags; - - if (request_irq (self->io.irq, toshoboe_probeinterrupt, - self->io.irqflags, "toshoboe", (void *) self)) - { - printk (KERN_ERR DRIVER_NAME ": probe failed to allocate irq %d\n", - self->io.irq); - return 0; - } - - /* test 1: SIR filter and back to back */ - - for (j = 0; j < ARRAY_SIZE(bauds); ++j) - { - int fir = (j > 1); - toshoboe_stopchip (self); - - - spin_lock_irqsave(&self->spinlock, flags); - /*Address is already setup */ - toshoboe_startchip (self); - self->int_rx = self->int_tx = 0; - self->speed = bauds[j]; - toshoboe_setbaud (self); - toshoboe_initptrs (self); - spin_unlock_irqrestore(&self->spinlock, flags); - - self->ring->tx[self->txs].control = -/* (FIR only) OBOE_CTL_TX_SIP needed for switching to next slot */ -/* MIR: all received data is stored in one slot */ - (fir) ? OBOE_CTL_TX_HW_OWNS | OBOE_CTL_TX_RTCENTX - : OBOE_CTL_TX_HW_OWNS ; - self->ring->tx[self->txs].len = - toshoboe_maketestpacket (self->tx_bufs[self->txs], 0, fir); - self->txs++; - self->txs %= TX_SLOTS; - - self->ring->tx[self->txs].control = - (fir) ? OBOE_CTL_TX_HW_OWNS | OBOE_CTL_TX_SIP - : OBOE_CTL_TX_HW_OWNS | OBOE_CTL_TX_RTCENTX ; - self->ring->tx[self->txs].len = - toshoboe_maketestpacket (self->tx_bufs[self->txs], 0, fir); - self->txs++; - self->txs %= TX_SLOTS; - - self->ring->tx[self->txs].control = - (fir) ? OBOE_CTL_TX_HW_OWNS | OBOE_CTL_TX_RTCENTX - : OBOE_CTL_TX_HW_OWNS ; - self->ring->tx[self->txs].len = - toshoboe_maketestpacket (self->tx_bufs[self->txs], 0, fir); - self->txs++; - self->txs %= TX_SLOTS; - - self->ring->tx[self->txs].control = - (fir) ? OBOE_CTL_TX_HW_OWNS | OBOE_CTL_TX_RTCENTX - | OBOE_CTL_TX_SIP | OBOE_CTL_TX_BAD_CRC - : OBOE_CTL_TX_HW_OWNS | OBOE_CTL_TX_RTCENTX ; - self->ring->tx[self->txs].len = - toshoboe_maketestpacket (self->tx_bufs[self->txs], 0, fir); - self->txs++; - self->txs %= TX_SLOTS; - - toshoboe_dumptx (self); - /* Turn on TX and RX and loopback */ - toshoboe_start_DMA(self, OBOE_CONFIG0H_ENTX | OBOE_CONFIG0H_LOOP); - - i = 0; - n = fir ? 1 : 4; - while (toshoboe_numvalidrcvs (self) != n) - { - if (i > 4800) - return toshoboe_probefail (self, "filter test"); - udelay ((9600*(TT_LEN+16))/self->speed); - i++; - } - - n = fir ? 203 : 102; - while ((toshoboe_numrcvs(self) != self->int_rx) || (self->int_tx != n)) - { - if (i > 4800) - return toshoboe_probefail (self, "interrupt test"); - udelay ((9600*(TT_LEN+16))/self->speed); - i++; - } - toshoboe_dumprx (self,i); - - } - - /* test 2: SIR in char at a time */ - - toshoboe_stopchip (self); - self->int_rx = self->int_tx = 0; - - spin_lock_irqsave(&self->spinlock, flags); - toshoboe_startchip (self); - spin_unlock_irqrestore(&self->spinlock, flags); - - self->async = 1; - self->speed = 115200; - toshoboe_setbaud (self); - self->ring->tx[self->txs].control = - OBOE_CTL_TX_RTCENTX | OBOE_CTL_TX_HW_OWNS; - self->ring->tx[self->txs].len = 4; - - ((unsigned char *) self->tx_bufs[self->txs])[0] = 'f'; - ((unsigned char *) self->tx_bufs[self->txs])[1] = 'i'; - ((unsigned char *) self->tx_bufs[self->txs])[2] = 's'; - ((unsigned char *) self->tx_bufs[self->txs])[3] = 'h'; - toshoboe_dumptx (self); - toshoboe_start_DMA(self, OBOE_CONFIG0H_ENTX | OBOE_CONFIG0H_LOOP); - - i = 0; - while (toshoboe_numvalidrcvs (self) != 4) - { - if (i > 100) - return toshoboe_probefail (self, "Async test"); - udelay (100); - i++; - } - - while ((toshoboe_numrcvs (self) != self->int_rx) || (self->int_tx != 1)) - { - if (i > 100) - return toshoboe_probefail (self, "Async interrupt test"); - udelay (100); - i++; - } - toshoboe_dumprx (self,i); - - self->async = 0; - self->speed = 9600; - toshoboe_setbaud (self); - toshoboe_stopchip (self); - - free_irq (self->io.irq, (void *) self); - - printk (KERN_WARNING DRIVER_NAME ": Self test passed ok\n"); - - return 1; -} -#endif - -/******************************************************************/ -/* Netdev style code */ - -/* Transmit something */ -static netdev_tx_t -toshoboe_hard_xmit (struct sk_buff *skb, struct net_device *dev) -{ - struct toshoboe_cb *self; - __s32 speed; - int mtt, len, ctl; - unsigned long flags; - struct irda_skb_cb *cb = (struct irda_skb_cb *) skb->cb; - - self = netdev_priv(dev); - - IRDA_ASSERT (self != NULL, return NETDEV_TX_OK; ); - - pr_debug("%s.tx:%x(%x)%x\n", - __func__, skb->len, self->txpending, INB(OBOE_ENABLEH)); - if (!cb->magic) { - pr_debug("%s.Not IrLAP:%x\n", __func__, cb->magic); -#ifdef DUMP_PACKETS - _dumpbufs(skb->data,skb->len,'>'); -#endif - } - - /* change speed pending, wait for its execution */ - if (self->new_speed) - return NETDEV_TX_BUSY; - - /* device stopped (apm) wait for restart */ - if (self->stopped) - return NETDEV_TX_BUSY; - - toshoboe_checkstuck (self); - - /* Check if we need to change the speed */ - /* But not now. Wait after transmission if mtt not required */ - speed=irda_get_next_speed(skb); - if ((speed != self->io.speed) && (speed != -1)) - { - spin_lock_irqsave(&self->spinlock, flags); - - if (self->txpending || skb->len) - { - self->new_speed = speed; - pr_debug("%s: Queued TxDone scheduled speed change %d\n" , - __func__, speed); - /* if no data, that's all! */ - if (!skb->len) - { - spin_unlock_irqrestore(&self->spinlock, flags); - dev_kfree_skb (skb); - return NETDEV_TX_OK; - } - /* True packet, go on, but */ - /* do not accept anything before change speed execution */ - netif_stop_queue(dev); - /* ready to process TxDone interrupt */ - spin_unlock_irqrestore(&self->spinlock, flags); - } - else - { - /* idle and no data, change speed now */ - self->speed = speed; - toshoboe_setbaud (self); - spin_unlock_irqrestore(&self->spinlock, flags); - dev_kfree_skb (skb); - return NETDEV_TX_OK; - } - - } - - if ((mtt = irda_get_mtt(skb))) - { - /* This is fair since the queue should be empty anyway */ - spin_lock_irqsave(&self->spinlock, flags); - - if (self->txpending) - { - spin_unlock_irqrestore(&self->spinlock, flags); - return NETDEV_TX_BUSY; - } - - /* If in SIR mode we need to generate a string of XBOFs */ - /* In MIR and FIR we need to generate a string of data */ - /* which we will add a wrong checksum to */ - - mtt = toshoboe_makemttpacket (self, self->tx_bufs[self->txs], mtt); - pr_debug("%s.mtt:%x(%x)%d\n", __func__, skb->len, mtt, self->txpending); - if (mtt) - { - self->ring->tx[self->txs].len = mtt & 0xfff; - - ctl = OBOE_CTL_TX_HW_OWNS | OBOE_CTL_TX_RTCENTX; - if (INB (OBOE_ENABLEH) & OBOE_ENABLEH_FIRON) - { - ctl |= OBOE_CTL_TX_BAD_CRC | OBOE_CTL_TX_SIP ; - } -#ifdef USE_MIR - else if (INB (OBOE_ENABLEH) & OBOE_ENABLEH_MIRON) - { - ctl |= OBOE_CTL_TX_BAD_CRC; - } -#endif - self->ring->tx[self->txs].control = ctl; - - OUTB (0x0, OBOE_ENABLEH); - /* It is only a timer. Do not send mtt packet outside! */ - toshoboe_start_DMA(self, OBOE_CONFIG0H_ENTX | OBOE_CONFIG0H_LOOP); - - self->txpending++; - - self->txs++; - self->txs %= TX_SLOTS; - - } - else - { - printk(KERN_ERR DRIVER_NAME ": problem with mtt packet - ignored\n"); - } - spin_unlock_irqrestore(&self->spinlock, flags); - } - -#ifdef DUMP_PACKETS -dumpbufs(skb->data,skb->len,'>'); -#endif - - spin_lock_irqsave(&self->spinlock, flags); - - if (self->ring->tx[self->txs].control & OBOE_CTL_TX_HW_OWNS) - { - pr_debug("%s.ful:%x(%x)%x\n", - __func__, skb->len, self->ring->tx[self->txs].control, - self->txpending); - toshoboe_start_DMA(self, OBOE_CONFIG0H_ENTX); - spin_unlock_irqrestore(&self->spinlock, flags); - return NETDEV_TX_BUSY; - } - - if (INB (OBOE_ENABLEH) & OBOE_ENABLEH_SIRON) - { - len = async_wrap_skb (skb, self->tx_bufs[self->txs], TX_BUF_SZ); - } - else - { - len = skb->len; - skb_copy_from_linear_data(skb, self->tx_bufs[self->txs], len); - } - self->ring->tx[self->txs].len = len & 0x0fff; - - /*Sometimes the HW doesn't see us assert RTCENTX in the interrupt code */ - /*later this plays safe, we garuntee the last packet to be transmitted */ - /*has RTCENTX set */ - - ctl = OBOE_CTL_TX_HW_OWNS | OBOE_CTL_TX_RTCENTX; - if (INB (OBOE_ENABLEH) & OBOE_ENABLEH_FIRON) - { - ctl |= OBOE_CTL_TX_SIP ; - } - self->ring->tx[self->txs].control = ctl; - - /* If transmitter is idle start in one-shot mode */ - - if (!self->txpending) - toshoboe_start_DMA(self, OBOE_CONFIG0H_ENTX); - - self->txpending++; - - self->txs++; - self->txs %= TX_SLOTS; - - spin_unlock_irqrestore(&self->spinlock, flags); - dev_kfree_skb (skb); - - return NETDEV_TX_OK; -} - -/*interrupt handler */ -static irqreturn_t -toshoboe_interrupt (int irq, void *dev_id) -{ - struct toshoboe_cb *self = dev_id; - __u8 irqstat; - struct sk_buff *skb = NULL; - - irqstat = INB (OBOE_ISR); - -/* was it us */ - if (!(irqstat & OBOE_INT_MASK)) - return IRQ_NONE; - -/* Ack all the interrupts */ - OUTB (irqstat, OBOE_ISR); - - toshoboe_isntstuck (self); - -/* Txdone */ - if (irqstat & OBOE_INT_TXDONE) - { - int txp, txpc; - int i; - - txp = self->txpending; - self->txpending = 0; - - for (i = 0; i < TX_SLOTS; ++i) - { - if (self->ring->tx[i].control & OBOE_CTL_TX_HW_OWNS) - self->txpending++; - } - pr_debug("%s.txd(%x)%x/%x\n", __func__, irqstat, txp, self->txpending); - - txp = INB (OBOE_TXSLOT) & OBOE_SLOT_MASK; - - /* Got anything queued ? start it together */ - if (self->ring->tx[txp].control & OBOE_CTL_TX_HW_OWNS) - { - txpc = txp; -#ifdef OPTIMIZE_TX - while (self->ring->tx[txpc].control & OBOE_CTL_TX_HW_OWNS) - { - txp = txpc; - txpc++; - txpc %= TX_SLOTS; - self->netdev->stats.tx_packets++; - if (self->ring->tx[txpc].control & OBOE_CTL_TX_HW_OWNS) - self->ring->tx[txp].control &= ~OBOE_CTL_TX_RTCENTX; - } - self->netdev->stats.tx_packets--; -#else - self->netdev->stats.tx_packets++; -#endif - toshoboe_start_DMA(self, OBOE_CONFIG0H_ENTX); - } - - if ((!self->txpending) && (self->new_speed)) - { - self->speed = self->new_speed; - pr_debug("%s: Executed TxDone scheduled speed change %d\n", - __func__, self->speed); - toshoboe_setbaud (self); - } - - /* Tell network layer that we want more frames */ - if (!self->new_speed) - netif_wake_queue(self->netdev); - } - - if (irqstat & OBOE_INT_RXDONE) - { - while (!(self->ring->rx[self->rxs].control & OBOE_CTL_RX_HW_OWNS)) - { - int len = self->ring->rx[self->rxs].len; - skb = NULL; - pr_debug("%s.rcv:%x(%x)\n", __func__ - , len, self->ring->rx[self->rxs].control); - -#ifdef DUMP_PACKETS -dumpbufs(self->rx_bufs[self->rxs],len,'<'); -#endif - - if (self->ring->rx[self->rxs].control == 0) - { - __u8 enable = INB (OBOE_ENABLEH); - - /* In SIR mode we need to check the CRC as this */ - /* hasn't been done by the hardware */ - if (enable & OBOE_ENABLEH_SIRON) - { - if (!toshoboe_checkfcs (self->rx_bufs[self->rxs], len)) - len = 0; - /*Trim off the CRC */ - if (len > 1) - len -= 2; - else - len = 0; - pr_debug("%s.SIR:%x(%x)\n", __func__, len, enable); - } - -#ifdef USE_MIR - else if (enable & OBOE_ENABLEH_MIRON) - { - if (len > 1) - len -= 2; - else - len = 0; - pr_debug("%s.MIR:%x(%x)\n", __func__, len, enable); - } -#endif - else if (enable & OBOE_ENABLEH_FIRON) - { - if (len > 3) - len -= 4; /*FIXME: check this */ - else - len = 0; - pr_debug("%s.FIR:%x(%x)\n", __func__, len, enable); - } - else - pr_debug("%s.?IR:%x(%x)\n", __func__, len, enable); - - if (len) - { - skb = dev_alloc_skb (len + 1); - if (skb) - { - skb_reserve (skb, 1); - - skb_put (skb, len); - skb_copy_to_linear_data(skb, self->rx_bufs[self->rxs], - len); - self->netdev->stats.rx_packets++; - skb->dev = self->netdev; - skb_reset_mac_header(skb); - skb->protocol = htons (ETH_P_IRDA); - } - else - { - printk (KERN_INFO - "%s(), memory squeeze, dropping frame.\n", - __func__); - } - } - } - else - { - /* TODO: =========================================== */ - /* if OBOE_CTL_RX_LENGTH, our buffers are too small */ - /* (MIR or FIR) data is lost. */ - /* (SIR) data is splitted in several slots. */ - /* we have to join all the received buffers received */ - /*in a large buffer before checking CRC. */ - pr_debug("%s.err:%x(%x)\n", __func__ - , len, self->ring->rx[self->rxs].control); - } - - self->ring->rx[self->rxs].len = 0x0; - self->ring->rx[self->rxs].control = OBOE_CTL_RX_HW_OWNS; - - self->rxs++; - self->rxs %= RX_SLOTS; - - if (skb) - netif_rx (skb); - - } - } - - if (irqstat & OBOE_INT_TXUNDER) - { - printk (KERN_WARNING DRIVER_NAME ": tx fifo underflow\n"); - } - if (irqstat & OBOE_INT_RXOVER) - { - printk (KERN_WARNING DRIVER_NAME ": rx fifo overflow\n"); - } -/* This must be useful for something... */ - if (irqstat & OBOE_INT_SIP) - { - self->int_sip++; - pr_debug("%s.sip:%x(%x)%x\n", - __func__, self->int_sip, irqstat, self->txpending); - } - return IRQ_HANDLED; -} - - -static int -toshoboe_net_open (struct net_device *dev) -{ - struct toshoboe_cb *self; - unsigned long flags; - int rc; - - self = netdev_priv(dev); - - if (self->async) - return -EBUSY; - - if (self->stopped) - return 0; - - rc = request_irq (self->io.irq, toshoboe_interrupt, - IRQF_SHARED, dev->name, self); - if (rc) - return rc; - - spin_lock_irqsave(&self->spinlock, flags); - toshoboe_startchip (self); - spin_unlock_irqrestore(&self->spinlock, flags); - - /* Ready to play! */ - netif_start_queue(dev); - - /* - * Open new IrLAP layer instance, now that everything should be - * initialized properly - */ - self->irlap = irlap_open (dev, &self->qos, driver_name); - - self->irdad = 1; - - return 0; -} - -static int -toshoboe_net_close (struct net_device *dev) -{ - struct toshoboe_cb *self; - - IRDA_ASSERT (dev != NULL, return -1; ); - self = netdev_priv(dev); - - /* Stop device */ - netif_stop_queue(dev); - - /* Stop and remove instance of IrLAP */ - if (self->irlap) - irlap_close (self->irlap); - self->irlap = NULL; - - self->irdad = 0; - - free_irq (self->io.irq, (void *) self); - - if (!self->stopped) - { - toshoboe_stopchip (self); - } - - return 0; -} - -/* - * Function toshoboe_net_ioctl (dev, rq, cmd) - * - * Process IOCTL commands for this device - * - */ -static int -toshoboe_net_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct if_irda_req *irq = (struct if_irda_req *) rq; - struct toshoboe_cb *self; - unsigned long flags; - int ret = 0; - - IRDA_ASSERT (dev != NULL, return -1; ); - - self = netdev_priv(dev); - - IRDA_ASSERT (self != NULL, return -1; ); - - pr_debug("%s(), %s, (cmd=0x%X)\n", __func__, dev->name, cmd); - - /* Disable interrupts & save flags */ - spin_lock_irqsave(&self->spinlock, flags); - - switch (cmd) - { - case SIOCSBANDWIDTH: /* Set bandwidth */ - /* This function will also be used by IrLAP to change the - * speed, so we still must allow for speed change within - * interrupt context. - */ - pr_debug("%s(BANDWIDTH), %s, (%X/%ld\n", - __func__, dev->name, INB(OBOE_STATUS), irq->ifr_baudrate); - if (!in_interrupt () && !capable (CAP_NET_ADMIN)) { - ret = -EPERM; - goto out; - } - - /* self->speed=irq->ifr_baudrate; */ - /* toshoboe_setbaud(self); */ - /* Just change speed once - inserted by Paul Bristow */ - self->new_speed = irq->ifr_baudrate; - break; - case SIOCSMEDIABUSY: /* Set media busy */ - pr_debug("%s(MEDIABUSY), %s, (%X/%x)\n", - __func__, dev->name, - INB(OBOE_STATUS), capable(CAP_NET_ADMIN)); - if (!capable (CAP_NET_ADMIN)) { - ret = -EPERM; - goto out; - } - irda_device_set_media_busy (self->netdev, TRUE); - break; - case SIOCGRECEIVING: /* Check if we are receiving right now */ - irq->ifr_receiving = (INB (OBOE_STATUS) & OBOE_STATUS_RXBUSY) ? 1 : 0; - pr_debug("%s(RECEIVING), %s, (%X/%x)\n", - __func__, dev->name, INB(OBOE_STATUS), irq->ifr_receiving); - break; - default: - pr_debug("%s(?), %s, (cmd=0x%X)\n", __func__, dev->name, cmd); - ret = -EOPNOTSUPP; - } -out: - spin_unlock_irqrestore(&self->spinlock, flags); - return ret; - -} - -MODULE_DESCRIPTION("Toshiba OBOE IrDA Device Driver"); -MODULE_AUTHOR("James McKenzie <james@fishsoup.dhs.org>"); -MODULE_LICENSE("GPL"); - -module_param (max_baud, int, 0); -MODULE_PARM_DESC(max_baud, "Maximum baud rate"); - -#ifdef USE_PROBE -module_param (do_probe, bool, 0); -MODULE_PARM_DESC(do_probe, "Enable/disable chip probing and self-test"); -#endif - -static void -toshoboe_close (struct pci_dev *pci_dev) -{ - int i; - struct toshoboe_cb *self = pci_get_drvdata(pci_dev); - - IRDA_ASSERT (self != NULL, return; ); - - if (!self->stopped) - { - toshoboe_stopchip (self); - } - - release_region (self->io.fir_base, self->io.fir_ext); - - for (i = 0; i < TX_SLOTS; ++i) - { - kfree (self->tx_bufs[i]); - self->tx_bufs[i] = NULL; - } - - for (i = 0; i < RX_SLOTS; ++i) - { - kfree (self->rx_bufs[i]); - self->rx_bufs[i] = NULL; - } - - unregister_netdev(self->netdev); - - kfree (self->ringbuf); - self->ringbuf = NULL; - self->ring = NULL; - - free_netdev(self->netdev); -} - -static const struct net_device_ops toshoboe_netdev_ops = { - .ndo_open = toshoboe_net_open, - .ndo_stop = toshoboe_net_close, - .ndo_start_xmit = toshoboe_hard_xmit, - .ndo_do_ioctl = toshoboe_net_ioctl, -}; - -static int -toshoboe_open (struct pci_dev *pci_dev, const struct pci_device_id *pdid) -{ - struct toshoboe_cb *self; - struct net_device *dev; - int i = 0; - int ok = 0; - int err; - - if ((err=pci_enable_device(pci_dev))) - return err; - - dev = alloc_irdadev(sizeof (struct toshoboe_cb)); - if (dev == NULL) - { - printk (KERN_ERR DRIVER_NAME ": can't allocate memory for " - "IrDA control block\n"); - return -ENOMEM; - } - - self = netdev_priv(dev); - self->netdev = dev; - self->pdev = pci_dev; - self->base = pci_resource_start(pci_dev,0); - - self->io.fir_base = self->base; - self->io.fir_ext = OBOE_IO_EXTENT; - self->io.irq = pci_dev->irq; - self->io.irqflags = IRQF_SHARED; - - self->speed = self->io.speed = 9600; - self->async = 0; - - /* Lock the port that we need */ - if (NULL==request_region (self->io.fir_base, self->io.fir_ext, driver_name)) - { - printk (KERN_ERR DRIVER_NAME ": can't get iobase of 0x%03x\n" - ,self->io.fir_base); - err = -EBUSY; - goto freeself; - } - - spin_lock_init(&self->spinlock); - - irda_init_max_qos_capabilies (&self->qos); - self->qos.baud_rate.bits = 0; - - if (max_baud >= 2400) - self->qos.baud_rate.bits |= IR_2400; - /*if (max_baud>=4800) idev->qos.baud_rate.bits|=IR_4800; */ - if (max_baud >= 9600) - self->qos.baud_rate.bits |= IR_9600; - if (max_baud >= 19200) - self->qos.baud_rate.bits |= IR_19200; - if (max_baud >= 115200) - self->qos.baud_rate.bits |= IR_115200; -#ifdef USE_MIR - if (max_baud >= 1152000) - { - self->qos.baud_rate.bits |= IR_1152000; - } -#endif - if (max_baud >= 4000000) - { - self->qos.baud_rate.bits |= (IR_4000000 << 8); - } - - /*FIXME: work this out... */ - self->qos.min_turn_time.bits = 0xff; - - irda_qos_bits_to_value (&self->qos); - - /* Allocate twice the size to guarantee alignment */ - self->ringbuf = kmalloc(OBOE_RING_LEN << 1, GFP_KERNEL); - if (!self->ringbuf) - { - err = -ENOMEM; - goto freeregion; - } - -#if (BITS_PER_LONG == 64) -#error broken on 64-bit: casts pointer to 32-bit, and then back to pointer. -#endif - - /*We need to align the taskfile on a taskfile size boundary */ - { - unsigned long addr; - - addr = (__u32) self->ringbuf; - addr &= ~(OBOE_RING_LEN - 1); - addr += OBOE_RING_LEN; - self->ring = (struct OboeRing *) addr; - } - - memset (self->ring, 0, OBOE_RING_LEN); - self->io.mem_base = (__u32) self->ring; - - ok = 1; - for (i = 0; i < TX_SLOTS; ++i) - { - self->tx_bufs[i] = kmalloc (TX_BUF_SZ, GFP_KERNEL); - if (!self->tx_bufs[i]) - ok = 0; - } - - for (i = 0; i < RX_SLOTS; ++i) - { - self->rx_bufs[i] = kmalloc (RX_BUF_SZ, GFP_KERNEL); - if (!self->rx_bufs[i]) - ok = 0; - } - - if (!ok) - { - err = -ENOMEM; - goto freebufs; - } - - -#ifdef USE_PROBE - if (do_probe) - if (!toshoboe_probe (self)) - { - err = -ENODEV; - goto freebufs; - } -#endif - - SET_NETDEV_DEV(dev, &pci_dev->dev); - dev->netdev_ops = &toshoboe_netdev_ops; - - err = register_netdev(dev); - if (err) - { - printk (KERN_ERR DRIVER_NAME ": register_netdev() failed\n"); - err = -ENOMEM; - goto freebufs; - } - printk (KERN_INFO "IrDA: Registered device %s\n", dev->name); - - pci_set_drvdata(pci_dev,self); - - printk (KERN_INFO DRIVER_NAME ": Using multiple tasks\n"); - - return 0; - -freebufs: - for (i = 0; i < TX_SLOTS; ++i) - kfree (self->tx_bufs[i]); - for (i = 0; i < RX_SLOTS; ++i) - kfree (self->rx_bufs[i]); - kfree(self->ringbuf); - -freeregion: - release_region (self->io.fir_base, self->io.fir_ext); - -freeself: - free_netdev(dev); - - return err; -} - -static int -toshoboe_gotosleep (struct pci_dev *pci_dev, pm_message_t crap) -{ - struct toshoboe_cb *self = pci_get_drvdata(pci_dev); - unsigned long flags; - int i = 10; - - if (!self || self->stopped) - return 0; - - if ((!self->irdad) && (!self->async)) - return 0; - -/* Flush all packets */ - while ((i--) && (self->txpending)) - msleep(10); - - spin_lock_irqsave(&self->spinlock, flags); - - toshoboe_stopchip (self); - self->stopped = 1; - self->txpending = 0; - - spin_unlock_irqrestore(&self->spinlock, flags); - return 0; -} - -static int -toshoboe_wakeup (struct pci_dev *pci_dev) -{ - struct toshoboe_cb *self = pci_get_drvdata(pci_dev); - unsigned long flags; - - if (!self || !self->stopped) - return 0; - - if ((!self->irdad) && (!self->async)) - return 0; - - spin_lock_irqsave(&self->spinlock, flags); - - toshoboe_startchip (self); - self->stopped = 0; - - netif_wake_queue(self->netdev); - spin_unlock_irqrestore(&self->spinlock, flags); - return 0; -} - -static struct pci_driver donauboe_pci_driver = { - .name = "donauboe", - .id_table = toshoboe_pci_tbl, - .probe = toshoboe_open, - .remove = toshoboe_close, - .suspend = toshoboe_gotosleep, - .resume = toshoboe_wakeup -}; - -module_pci_driver(donauboe_pci_driver); diff --git a/drivers/net/irda/donauboe.h b/drivers/net/irda/donauboe.h deleted file mode 100644 index d92d54e839b9..000000000000 --- a/drivers/net/irda/donauboe.h +++ /dev/null @@ -1,362 +0,0 @@ -/********************************************************************* - * - * 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 controller 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 resemblance */ -/* to the IrDA controller in the Toshiba RISC TMPR3922 chip */ -/* the documentation for this is freely available at */ -/* http://www.madingley.org/james/resources/toshoboe/TMPR3922.pdf */ -/* 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 writing 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 */ -} -__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 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 diff --git a/drivers/net/irda/esi-sir.c b/drivers/net/irda/esi-sir.c deleted file mode 100644 index 019a3e848bcb..000000000000 --- a/drivers/net/irda/esi-sir.c +++ /dev/null @@ -1,157 +0,0 @@ -/********************************************************************* - * - * 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, see <http://www.gnu.org/licenses/>. - * - ********************************************************************/ - -#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); - diff --git a/drivers/net/irda/girbil-sir.c b/drivers/net/irda/girbil-sir.c deleted file mode 100644 index 7e0a5b8c6d53..000000000000 --- a/drivers/net/irda/girbil-sir.c +++ /dev/null @@ -1,252 +0,0 @@ -/********************************************************************* - * - * 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ø 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 emitted 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; - - /* 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) -{ - /* 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; - - /* 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: - net_err_ratelimited("%s - undefined state %d\n", - __func__, 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; - - 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: - net_err_ratelimited("%s(), undefined state %d\n", - __func__, 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); diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c deleted file mode 100644 index 723e49bc4baa..000000000000 --- a/drivers/net/irda/irda-usb.c +++ /dev/null @@ -1,1914 +0,0 @@ -/***************************************************************************** - * - * Filename: irda-usb.c - * Version: 0.10 - * Description: IrDA-USB Driver - * Status: Experimental - * Author: Dag Brattli <dag@brattli.net> - * - * Copyright (C) 2000, Roman Weissgaerber <weissg@vienna.at> - * Copyright (C) 2001, Dag Brattli <dag@brattli.net> - * Copyright (C) 2001, Jean Tourrilhes <jt@hpl.hp.com> - * Copyright (C) 2004, SigmaTel, Inc. <irquality@sigmatel.com> - * Copyright (C) 2005, Milan Beno <beno@pobox.sk> - * Copyright (C) 2006, Nick Fedchik <nick@fedchik.org.ua> - * - * 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. - * - *****************************************************************************/ - -/* - * IMPORTANT NOTE - * -------------- - * - * As of kernel 2.5.20, this is the state of compliance and testing of - * this driver (irda-usb) with regards to the USB low level drivers... - * - * This driver has been tested SUCCESSFULLY with the following drivers : - * o usb-uhci-hcd (For Intel/Via USB controllers) - * o uhci-hcd (Alternate/JE driver for Intel/Via USB controllers) - * o ohci-hcd (For other USB controllers) - * - * This driver has NOT been tested with the following drivers : - * o ehci-hcd (USB 2.0 controllers) - * - * Note that all HCD drivers do URB_ZERO_PACKET and timeout properly, - * so we don't have to worry about that anymore. - * One common problem is the failure to set the address on the dongle, - * but this happens before the driver gets loaded... - * - * Jean II - */ - -/*------------------------------------------------------------------*/ - -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/skbuff.h> -#include <linux/netdevice.h> -#include <linux/slab.h> -#include <linux/rtnetlink.h> -#include <linux/usb.h> -#include <linux/firmware.h> - -#include "irda-usb.h" - -/*------------------------------------------------------------------*/ - -static int qos_mtt_bits = 0; - -/* These are the currently known IrDA USB dongles. Add new dongles here */ -static const struct usb_device_id dongles[] = { - /* ACTiSYS Corp., ACT-IR2000U FIR-USB Adapter */ - { USB_DEVICE(0x9c4, 0x011), .driver_info = IUC_SPEED_BUG | IUC_NO_WINDOW }, - /* Look like ACTiSYS, Report : IBM Corp., IBM UltraPort IrDA */ - { USB_DEVICE(0x4428, 0x012), .driver_info = IUC_SPEED_BUG | IUC_NO_WINDOW }, - /* KC Technology Inc., KC-180 USB IrDA Device */ - { USB_DEVICE(0x50f, 0x180), .driver_info = IUC_SPEED_BUG | IUC_NO_WINDOW }, - /* Extended Systems, Inc., XTNDAccess IrDA USB (ESI-9685) */ - { USB_DEVICE(0x8e9, 0x100), .driver_info = IUC_SPEED_BUG | IUC_NO_WINDOW }, - /* SigmaTel STIR4210/4220/4116 USB IrDA (VFIR) Bridge */ - { USB_DEVICE(0x66f, 0x4210), .driver_info = IUC_STIR421X | IUC_SPEED_BUG }, - { USB_DEVICE(0x66f, 0x4220), .driver_info = IUC_STIR421X | IUC_SPEED_BUG }, - { USB_DEVICE(0x66f, 0x4116), .driver_info = IUC_STIR421X | IUC_SPEED_BUG }, - { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS | - USB_DEVICE_ID_MATCH_INT_SUBCLASS, - .bInterfaceClass = USB_CLASS_APP_SPEC, - .bInterfaceSubClass = USB_CLASS_IRDA, - .driver_info = IUC_DEFAULT, }, - { }, /* The end */ -}; - -/* - * Important note : - * Devices based on the SigmaTel chipset (0x66f, 0x4200) are not designed - * using the "USB-IrDA specification" (yes, there exist such a thing), and - * therefore not supported by this driver (don't add them above). - * There is a Linux driver, stir4200, that support those USB devices. - * Jean II - */ - -MODULE_DEVICE_TABLE(usb, dongles); - -/*------------------------------------------------------------------*/ - -static void irda_usb_init_qos(struct irda_usb_cb *self) ; -static struct irda_class_desc *irda_usb_find_class_desc(struct usb_interface *intf); -static void irda_usb_disconnect(struct usb_interface *intf); -static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self); -static netdev_tx_t irda_usb_hard_xmit(struct sk_buff *skb, - struct net_device *dev); -static int irda_usb_open(struct irda_usb_cb *self); -static void irda_usb_close(struct irda_usb_cb *self); -static void speed_bulk_callback(struct urb *urb); -static void write_bulk_callback(struct urb *urb); -static void irda_usb_receive(struct urb *urb); -static void irda_usb_rx_defer_expired(unsigned long data); -static int irda_usb_net_open(struct net_device *dev); -static int irda_usb_net_close(struct net_device *dev); -static int irda_usb_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); -static void irda_usb_net_timeout(struct net_device *dev); - -/************************ TRANSMIT ROUTINES ************************/ -/* - * Receive packets from the IrDA stack and send them on the USB pipe. - * Handle speed change, timeout and lot's of ugliness... - */ - -/*------------------------------------------------------------------*/ -/* - * Function irda_usb_build_header(self, skb, header) - * - * Builds USB-IrDA outbound header - * - * When we send an IrDA frame over an USB pipe, we add to it a 1 byte - * header. This function create this header with the proper values. - * - * Important note : the USB-IrDA spec 1.0 say very clearly in chapter 5.4.2.2 - * that the setting of the link speed and xbof number in this outbound header - * should be applied *AFTER* the frame has been sent. - * Unfortunately, some devices are not compliant with that... It seems that - * reading the spec is far too difficult... - * Jean II - */ -static void irda_usb_build_header(struct irda_usb_cb *self, - __u8 *header, - int force) -{ - /* Here we check if we have an STIR421x chip, - * and if either speed or xbofs (or both) needs - * to be changed. - */ - if (self->capability & IUC_STIR421X && - ((self->new_speed != -1) || (self->new_xbofs != -1))) { - - /* With STIR421x, speed and xBOFs must be set at the same - * time, even if only one of them changes. - */ - if (self->new_speed == -1) - self->new_speed = self->speed ; - - if (self->new_xbofs == -1) - self->new_xbofs = self->xbofs ; - } - - /* Set the link speed */ - if (self->new_speed != -1) { - /* Hum... Ugly hack :-( - * Some device are not compliant with the spec and change - * parameters *before* sending the frame. - Jean II - */ - if ((self->capability & IUC_SPEED_BUG) && - (!force) && (self->speed != -1)) { - /* No speed and xbofs change here - * (we'll do it later in the write callback) */ - pr_debug("%s(), not changing speed yet\n", __func__); - *header = 0; - return; - } - - pr_debug("%s(), changing speed to %d\n", - __func__, self->new_speed); - self->speed = self->new_speed; - /* We will do ` self->new_speed = -1; ' in the completion - * handler just in case the current URB fail - Jean II */ - - switch (self->speed) { - case 2400: - *header = SPEED_2400; - break; - default: - case 9600: - *header = SPEED_9600; - break; - case 19200: - *header = SPEED_19200; - break; - case 38400: - *header = SPEED_38400; - break; - case 57600: - *header = SPEED_57600; - break; - case 115200: - *header = SPEED_115200; - break; - case 576000: - *header = SPEED_576000; - break; - case 1152000: - *header = SPEED_1152000; - break; - case 4000000: - *header = SPEED_4000000; - self->new_xbofs = 0; - break; - case 16000000: - *header = SPEED_16000000; - self->new_xbofs = 0; - break; - } - } else - /* No change */ - *header = 0; - - /* Set the negotiated additional XBOFS */ - if (self->new_xbofs != -1) { - pr_debug("%s(), changing xbofs to %d\n", - __func__, self->new_xbofs); - self->xbofs = self->new_xbofs; - /* We will do ` self->new_xbofs = -1; ' in the completion - * handler just in case the current URB fail - Jean II */ - - switch (self->xbofs) { - case 48: - *header |= 0x10; - break; - case 28: - case 24: /* USB spec 1.0 says 24 */ - *header |= 0x20; - break; - default: - case 12: - *header |= 0x30; - break; - case 5: /* Bug in IrLAP spec? (should be 6) */ - case 6: - *header |= 0x40; - break; - case 3: - *header |= 0x50; - break; - case 2: - *header |= 0x60; - break; - case 1: - *header |= 0x70; - break; - case 0: - *header |= 0x80; - break; - } - } -} - -/* -* calculate turnaround time for SigmaTel header -*/ -static __u8 get_turnaround_time(struct sk_buff *skb) -{ - int turnaround_time = irda_get_mtt(skb); - - if ( turnaround_time == 0 ) - return 0; - else if ( turnaround_time <= 10 ) - return 1; - else if ( turnaround_time <= 50 ) - return 2; - else if ( turnaround_time <= 100 ) - return 3; - else if ( turnaround_time <= 500 ) - return 4; - else if ( turnaround_time <= 1000 ) - return 5; - else if ( turnaround_time <= 5000 ) - return 6; - else - return 7; -} - - -/*------------------------------------------------------------------*/ -/* - * Send a command to change the speed of the dongle - * Need to be called with spinlock on. - */ -static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self) -{ - __u8 *frame; - struct urb *urb; - int ret; - - pr_debug("%s(), speed=%d, xbofs=%d\n", __func__, - self->new_speed, self->new_xbofs); - - /* Grab the speed URB */ - urb = self->speed_urb; - if (urb->status != 0) { - net_warn_ratelimited("%s(), URB still in use!\n", __func__); - return; - } - - /* Allocate the fake frame */ - frame = self->speed_buff; - - /* Set the new speed and xbofs in this fake frame */ - irda_usb_build_header(self, frame, 1); - - if (self->capability & IUC_STIR421X) { - if (frame[0] == 0) return ; // do nothing if no change - frame[1] = 0; // other parameters don't change here - frame[2] = 0; - } - - /* Submit the 0 length IrDA frame to trigger new speed settings */ - usb_fill_bulk_urb(urb, self->usbdev, - usb_sndbulkpipe(self->usbdev, self->bulk_out_ep), - frame, IRDA_USB_SPEED_MTU, - speed_bulk_callback, self); - urb->transfer_buffer_length = self->header_length; - urb->transfer_flags = 0; - - /* Irq disabled -> GFP_ATOMIC */ - if ((ret = usb_submit_urb(urb, GFP_ATOMIC))) { - net_warn_ratelimited("%s(), failed Speed URB\n", __func__); - } -} - -/*------------------------------------------------------------------*/ -/* - * Speed URB callback - * Now, we can only get called for the speed URB. - */ -static void speed_bulk_callback(struct urb *urb) -{ - struct irda_usb_cb *self = urb->context; - - /* We should always have a context */ - IRDA_ASSERT(self != NULL, return;); - /* We should always be called for the speed URB */ - IRDA_ASSERT(urb == self->speed_urb, return;); - - /* Check for timeout and other USB nasties */ - if (urb->status != 0) { - /* I get a lot of -ECONNABORTED = -103 here - Jean II */ - pr_debug("%s(), URB complete status %d, transfer_flags 0x%04X\n", - __func__, urb->status, urb->transfer_flags); - - /* Don't do anything here, that might confuse the USB layer. - * Instead, we will wait for irda_usb_net_timeout(), the - * network layer watchdog, to fix the situation. - * Jean II */ - /* A reset of the dongle might be welcomed here - Jean II */ - return; - } - - /* urb is now available */ - //urb->status = 0; -> tested above - - /* New speed and xbof is now committed in hardware */ - self->new_speed = -1; - self->new_xbofs = -1; - - /* Allow the stack to send more packets */ - netif_wake_queue(self->netdev); -} - -/*------------------------------------------------------------------*/ -/* - * Send an IrDA frame to the USB dongle (for transmission) - */ -static netdev_tx_t irda_usb_hard_xmit(struct sk_buff *skb, - struct net_device *netdev) -{ - struct irda_usb_cb *self = netdev_priv(netdev); - struct urb *urb = self->tx_urb; - unsigned long flags; - s32 speed; - s16 xbofs; - int res, mtt; - - pr_debug("%s() on %s\n", __func__, netdev->name); - - netif_stop_queue(netdev); - - /* Protect us from USB callbacks, net watchdog and else. */ - spin_lock_irqsave(&self->lock, flags); - - /* Check if the device is still there. - * We need to check self->present under the spinlock because - * of irda_usb_disconnect() is synchronous - Jean II */ - if (!self->present) { - pr_debug("%s(), Device is gone...\n", __func__); - goto drop; - } - - /* Check if we need to change the number of xbofs */ - xbofs = irda_get_next_xbofs(skb); - if ((xbofs != self->xbofs) && (xbofs != -1)) { - self->new_xbofs = xbofs; - } - - /* Check if we need to change the speed */ - speed = irda_get_next_speed(skb); - if ((speed != self->speed) && (speed != -1)) { - /* Set the desired speed */ - self->new_speed = speed; - - /* Check for empty frame */ - if (!skb->len) { - /* IrLAP send us an empty frame to make us change the - * speed. Changing speed with the USB adapter is in - * fact sending an empty frame to the adapter, so we - * could just let the present function do its job. - * However, we would wait for min turn time, - * do an extra memcpy and increment packet counters... - * Jean II */ - irda_usb_change_speed_xbofs(self); - netif_trans_update(netdev); - /* Will netif_wake_queue() in callback */ - goto drop; - } - } - - if (urb->status != 0) { - net_warn_ratelimited("%s(), URB still in use!\n", __func__); - goto drop; - } - - skb_copy_from_linear_data(skb, self->tx_buff + self->header_length, skb->len); - - /* Change setting for next frame */ - if (self->capability & IUC_STIR421X) { - __u8 turnaround_time; - __u8* frame = self->tx_buff; - turnaround_time = get_turnaround_time( skb ); - irda_usb_build_header(self, frame, 0); - frame[2] = turnaround_time; - if ((skb->len != 0) && - ((skb->len % 128) == 0) && - ((skb->len % 512) != 0)) { - /* add extra byte for special SigmaTel feature */ - frame[1] = 1; - skb_put(skb, 1); - } else { - frame[1] = 0; - } - } else { - irda_usb_build_header(self, self->tx_buff, 0); - } - - /* FIXME: Make macro out of this one */ - ((struct irda_skb_cb *)skb->cb)->context = self; - - usb_fill_bulk_urb(urb, self->usbdev, - usb_sndbulkpipe(self->usbdev, self->bulk_out_ep), - self->tx_buff, skb->len + self->header_length, - write_bulk_callback, skb); - - /* This flag (URB_ZERO_PACKET) indicates that what we send is not - * a continuous stream of data but separate packets. - * In this case, the USB layer will insert an empty USB frame (TD) - * after each of our packets that is exact multiple of the frame size. - * This is how the dongle will detect the end of packet - Jean II */ - urb->transfer_flags = URB_ZERO_PACKET; - - /* Generate min turn time. FIXME: can we do better than this? */ - /* Trying to a turnaround time at this level is trying to measure - * processor clock cycle with a wrist-watch, approximate at best... - * - * What we know is the last time we received a frame over USB. - * Due to latency over USB that depend on the USB load, we don't - * know when this frame was received over IrDA (a few ms before ?) - * Then, same story for our outgoing frame... - * - * In theory, the USB dongle is supposed to handle the turnaround - * by itself (spec 1.0, chater 4, page 6). Who knows ??? That's - * why this code is enabled only for dongles that doesn't meet - * the spec. - * Jean II */ - if (self->capability & IUC_NO_TURN) { - mtt = irda_get_mtt(skb); - if (mtt) { - int diff; - diff = ktime_us_delta(ktime_get(), self->stamp); -#ifdef IU_USB_MIN_RTT - /* Factor in USB delays -> Get rid of udelay() that - * would be lost in the noise - Jean II */ - diff += IU_USB_MIN_RTT; -#endif /* IU_USB_MIN_RTT */ - - /* Check if the mtt is larger than the time we have - * already used by all the protocol processing - */ - if (mtt > diff) { - mtt -= diff; - if (mtt > 1000) - mdelay(mtt/1000); - else - udelay(mtt); - } - } - } - - /* Ask USB to send the packet - Irq disabled -> GFP_ATOMIC */ - if ((res = usb_submit_urb(urb, GFP_ATOMIC))) { - net_warn_ratelimited("%s(), failed Tx URB\n", __func__); - netdev->stats.tx_errors++; - /* Let USB recover : We will catch that in the watchdog */ - /*netif_start_queue(netdev);*/ - } else { - /* Increment packet stats */ - netdev->stats.tx_packets++; - netdev->stats.tx_bytes += skb->len; - - netif_trans_update(netdev); - } - spin_unlock_irqrestore(&self->lock, flags); - - return NETDEV_TX_OK; - -drop: - /* Drop silently the skb and exit */ - dev_kfree_skb(skb); - spin_unlock_irqrestore(&self->lock, flags); - return NETDEV_TX_OK; -} - -/*------------------------------------------------------------------*/ -/* - * Note : this function will be called only for tx_urb... - */ -static void write_bulk_callback(struct urb *urb) -{ - unsigned long flags; - struct sk_buff *skb = urb->context; - struct irda_usb_cb *self = ((struct irda_skb_cb *) skb->cb)->context; - - /* We should always have a context */ - IRDA_ASSERT(self != NULL, return;); - /* We should always be called for the speed URB */ - IRDA_ASSERT(urb == self->tx_urb, return;); - - /* Free up the skb */ - dev_kfree_skb_any(skb); - urb->context = NULL; - - /* Check for timeout and other USB nasties */ - if (urb->status != 0) { - /* I get a lot of -ECONNABORTED = -103 here - Jean II */ - pr_debug("%s(), URB complete status %d, transfer_flags 0x%04X\n", - __func__, urb->status, urb->transfer_flags); - - /* Don't do anything here, that might confuse the USB layer, - * and we could go in recursion and blow the kernel stack... - * Instead, we will wait for irda_usb_net_timeout(), the - * network layer watchdog, to fix the situation. - * Jean II */ - /* A reset of the dongle might be welcomed here - Jean II */ - return; - } - - /* urb is now available */ - //urb->status = 0; -> tested above - - /* Make sure we read self->present properly */ - spin_lock_irqsave(&self->lock, flags); - - /* If the network is closed, stop everything */ - if ((!self->netopen) || (!self->present)) { - pr_debug("%s(), Network is gone...\n", __func__); - spin_unlock_irqrestore(&self->lock, flags); - return; - } - - /* If changes to speed or xbofs is pending... */ - if ((self->new_speed != -1) || (self->new_xbofs != -1)) { - if ((self->new_speed != self->speed) || - (self->new_xbofs != self->xbofs)) { - /* We haven't changed speed yet (because of - * IUC_SPEED_BUG), so do it now - Jean II */ - pr_debug("%s(), Changing speed now...\n", __func__); - irda_usb_change_speed_xbofs(self); - } else { - /* New speed and xbof is now committed in hardware */ - self->new_speed = -1; - self->new_xbofs = -1; - /* Done, waiting for next packet */ - netif_wake_queue(self->netdev); - } - } else { - /* Otherwise, allow the stack to send more packets */ - netif_wake_queue(self->netdev); - } - spin_unlock_irqrestore(&self->lock, flags); -} - -/*------------------------------------------------------------------*/ -/* - * Watchdog timer from the network layer. - * After a predetermined timeout, if we don't give confirmation that - * the packet has been sent (i.e. no call to netif_wake_queue()), - * the network layer will call this function. - * Note that URB that we submit have also a timeout. When the URB timeout - * expire, the normal URB callback is called (write_bulk_callback()). - */ -static void irda_usb_net_timeout(struct net_device *netdev) -{ - unsigned long flags; - struct irda_usb_cb *self = netdev_priv(netdev); - struct urb *urb; - int done = 0; /* If we have made any progress */ - - pr_debug("%s(), Network layer thinks we timed out!\n", __func__); - IRDA_ASSERT(self != NULL, return;); - - /* Protect us from USB callbacks, net Tx and else. */ - spin_lock_irqsave(&self->lock, flags); - - /* self->present *MUST* be read under spinlock */ - if (!self->present) { - net_warn_ratelimited("%s(), device not present!\n", __func__); - netif_stop_queue(netdev); - spin_unlock_irqrestore(&self->lock, flags); - return; - } - - /* Check speed URB */ - urb = self->speed_urb; - if (urb->status != 0) { - pr_debug("%s: Speed change timed out, urb->status=%d, urb->transfer_flags=0x%04X\n", - netdev->name, urb->status, urb->transfer_flags); - - switch (urb->status) { - case -EINPROGRESS: - usb_unlink_urb(urb); - /* Note : above will *NOT* call netif_wake_queue() - * in completion handler, we will come back here. - * Jean II */ - done = 1; - break; - case -ECONNRESET: - case -ENOENT: /* urb unlinked by us */ - default: /* ??? - Play safe */ - urb->status = 0; - netif_wake_queue(self->netdev); - done = 1; - break; - } - } - - /* Check Tx URB */ - urb = self->tx_urb; - if (urb->status != 0) { - struct sk_buff *skb = urb->context; - - pr_debug("%s: Tx timed out, urb->status=%d, urb->transfer_flags=0x%04X\n", - netdev->name, urb->status, urb->transfer_flags); - - /* Increase error count */ - netdev->stats.tx_errors++; - -#ifdef IU_BUG_KICK_TIMEOUT - /* Can't be a bad idea to reset the speed ;-) - Jean II */ - if(self->new_speed == -1) - self->new_speed = self->speed; - if(self->new_xbofs == -1) - self->new_xbofs = self->xbofs; - irda_usb_change_speed_xbofs(self); -#endif /* IU_BUG_KICK_TIMEOUT */ - - switch (urb->status) { - case -EINPROGRESS: - usb_unlink_urb(urb); - /* Note : above will *NOT* call netif_wake_queue() - * in completion handler, because urb->status will - * be -ENOENT. We will fix that at the next watchdog, - * leaving more time to USB to recover... - * Jean II */ - done = 1; - break; - case -ECONNRESET: - case -ENOENT: /* urb unlinked by us */ - default: /* ??? - Play safe */ - if(skb != NULL) { - dev_kfree_skb_any(skb); - urb->context = NULL; - } - urb->status = 0; - netif_wake_queue(self->netdev); - done = 1; - break; - } - } - spin_unlock_irqrestore(&self->lock, flags); - - /* Maybe we need a reset */ - /* Note : Some drivers seem to use a usb_set_interface() when they - * need to reset the hardware. Hum... - */ - - /* if(done == 0) */ -} - -/************************* RECEIVE ROUTINES *************************/ -/* - * Receive packets from the USB layer stack and pass them to the IrDA stack. - * Try to work around USB failures... - */ - -/* - * Note : - * Some of you may have noticed that most dongle have an interrupt in pipe - * that we don't use. Here is the little secret... - * When we hang a Rx URB on the bulk in pipe, it generates some USB traffic - * in every USB frame. This is unnecessary overhead. - * The interrupt in pipe will generate an event every time a packet is - * received. Reading an interrupt pipe adds minimal overhead, but has some - * latency (~1ms). - * If we are connected (speed != 9600), we want to minimise latency, so - * we just always hang the Rx URB and ignore the interrupt. - * If we are not connected (speed == 9600), there is usually no Rx traffic, - * and we want to minimise the USB overhead. In this case we should wait - * on the interrupt pipe and hang the Rx URB only when an interrupt is - * received. - * Jean II - * - * Note : don't read the above as what we are currently doing, but as - * something we could do with KC dongle. Also don't forget that the - * interrupt pipe is not part of the original standard, so this would - * need to be optional... - * Jean II - */ - -/*------------------------------------------------------------------*/ -/* - * Submit a Rx URB to the USB layer to handle reception of a frame - * Mostly called by the completion callback of the previous URB. - * - * Jean II - */ -static void irda_usb_submit(struct irda_usb_cb *self, struct sk_buff *skb, struct urb *urb) -{ - struct irda_skb_cb *cb; - int ret; - - /* This should never happen */ - IRDA_ASSERT(skb != NULL, return;); - IRDA_ASSERT(urb != NULL, return;); - - /* Save ourselves in the skb */ - cb = (struct irda_skb_cb *) skb->cb; - cb->context = self; - - /* Reinitialize URB */ - usb_fill_bulk_urb(urb, self->usbdev, - usb_rcvbulkpipe(self->usbdev, self->bulk_in_ep), - skb->data, IRDA_SKB_MAX_MTU, - irda_usb_receive, skb); - urb->status = 0; - - /* Can be called from irda_usb_receive (irq handler) -> GFP_ATOMIC */ - ret = usb_submit_urb(urb, GFP_ATOMIC); - if (ret) { - /* If this ever happen, we are in deep s***. - * Basically, the Rx path will stop... */ - net_warn_ratelimited("%s(), Failed to submit Rx URB %d\n", - __func__, ret); - } -} - -/*------------------------------------------------------------------*/ -/* - * Function irda_usb_receive(urb) - * - * Called by the USB subsystem when a frame has been received - * - */ -static void irda_usb_receive(struct urb *urb) -{ - struct sk_buff *skb = (struct sk_buff *) urb->context; - struct irda_usb_cb *self; - struct irda_skb_cb *cb; - struct sk_buff *newskb; - struct sk_buff *dataskb; - struct urb *next_urb; - unsigned int len, docopy; - - pr_debug("%s(), len=%d\n", __func__, urb->actual_length); - - /* Find ourselves */ - cb = (struct irda_skb_cb *) skb->cb; - IRDA_ASSERT(cb != NULL, return;); - self = (struct irda_usb_cb *) cb->context; - IRDA_ASSERT(self != NULL, return;); - - /* If the network is closed or the device gone, stop everything */ - if ((!self->netopen) || (!self->present)) { - pr_debug("%s(), Network is gone!\n", __func__); - /* Don't re-submit the URB : will stall the Rx path */ - return; - } - - /* Check the status */ - if (urb->status != 0) { - switch (urb->status) { - case -EILSEQ: - self->netdev->stats.rx_crc_errors++; - /* Also precursor to a hot-unplug on UHCI. */ - /* Fallthrough... */ - case -ECONNRESET: - /* Random error, if I remember correctly */ - /* uhci_cleanup_unlink() is going to kill the Rx - * URB just after we return. No problem, at this - * point the URB will be idle ;-) - Jean II */ - case -ESHUTDOWN: - /* That's usually a hot-unplug. Submit will fail... */ - case -ETIME: - /* Usually precursor to a hot-unplug on OHCI. */ - default: - self->netdev->stats.rx_errors++; - pr_debug("%s(), RX status %d, transfer_flags 0x%04X\n", - __func__, urb->status, urb->transfer_flags); - break; - } - /* If we received an error, we don't want to resubmit the - * Rx URB straight away but to give the USB layer a little - * bit of breathing room. - * We are in the USB thread context, therefore there is a - * danger of recursion (new URB we submit fails, we come - * back here). - * With recent USB stack (2.6.15+), I'm seeing that on - * hot unplug of the dongle... - * Lowest effective timer is 10ms... - * Jean II */ - self->rx_defer_timer.function = irda_usb_rx_defer_expired; - self->rx_defer_timer.data = (unsigned long) urb; - mod_timer(&self->rx_defer_timer, - jiffies + msecs_to_jiffies(10)); - - return; - } - - /* Check for empty frames */ - if (urb->actual_length <= self->header_length) { - net_warn_ratelimited("%s(), empty frame!\n", __func__); - goto done; - } - - /* - * Remember the time we received this frame, so we can - * reduce the min turn time a bit since we will know - * how much time we have used for protocol processing - */ - self->stamp = ktime_get(); - - /* Check if we need to copy the data to a new skb or not. - * For most frames, we use ZeroCopy and pass the already - * allocated skb up the stack. - * If the frame is small, it is more efficient to copy it - * to save memory (copy will be fast anyway - that's - * called Rx-copy-break). Jean II */ - docopy = (urb->actual_length < IRDA_RX_COPY_THRESHOLD); - - /* Allocate a new skb */ - if (self->capability & IUC_STIR421X) - newskb = dev_alloc_skb(docopy ? urb->actual_length : - IRDA_SKB_MAX_MTU + - USB_IRDA_STIR421X_HEADER); - else - newskb = dev_alloc_skb(docopy ? urb->actual_length : - IRDA_SKB_MAX_MTU); - - if (!newskb) { - self->netdev->stats.rx_dropped++; - /* We could deliver the current skb, but this would stall - * the Rx path. Better drop the packet... Jean II */ - goto done; - } - - /* Make sure IP header get aligned (IrDA header is 5 bytes) */ - /* But IrDA-USB header is 1 byte. Jean II */ - //skb_reserve(newskb, USB_IRDA_HEADER - 1); - - if(docopy) { - /* Copy packet, so we can recycle the original */ - skb_copy_from_linear_data(skb, newskb->data, urb->actual_length); - /* Deliver this new skb */ - dataskb = newskb; - /* And hook the old skb to the URB - * Note : we don't need to "clean up" the old skb, - * as we never touched it. Jean II */ - } else { - /* We are using ZeroCopy. Deliver old skb */ - dataskb = skb; - /* And hook the new skb to the URB */ - skb = newskb; - } - - /* Set proper length on skb & remove USB-IrDA header */ - skb_put(dataskb, urb->actual_length); - skb_pull(dataskb, self->header_length); - - /* Ask the networking layer to queue the packet for the IrDA stack */ - dataskb->dev = self->netdev; - skb_reset_mac_header(dataskb); - dataskb->protocol = htons(ETH_P_IRDA); - len = dataskb->len; - netif_rx(dataskb); - - /* Keep stats up to date */ - self->netdev->stats.rx_bytes += len; - self->netdev->stats.rx_packets++; - -done: - /* Note : at this point, the URB we've just received (urb) - * is still referenced by the USB layer. For example, if we - * have received a -ECONNRESET, uhci_cleanup_unlink() will - * continue to process it (in fact, cleaning it up). - * If we were to submit this URB, disaster would ensue. - * Therefore, we submit our idle URB, and put this URB in our - * idle slot.... - * Jean II */ - /* Note : with this scheme, we could submit the idle URB before - * processing the Rx URB. I don't think it would buy us anything as - * we are running in the USB thread context. Jean II */ - next_urb = self->idle_rx_urb; - - /* Recycle Rx URB : Now, the idle URB is the present one */ - urb->context = NULL; - self->idle_rx_urb = urb; - - /* Submit the idle URB to replace the URB we've just received. - * Do it last to avoid race conditions... Jean II */ - irda_usb_submit(self, skb, next_urb); -} - -/*------------------------------------------------------------------*/ -/* - * In case of errors, we want the USB layer to have time to recover. - * Now, it is time to resubmit ouur Rx URB... - */ -static void irda_usb_rx_defer_expired(unsigned long data) -{ - struct urb *urb = (struct urb *) data; - struct sk_buff *skb = (struct sk_buff *) urb->context; - struct irda_usb_cb *self; - struct irda_skb_cb *cb; - struct urb *next_urb; - - /* Find ourselves */ - cb = (struct irda_skb_cb *) skb->cb; - IRDA_ASSERT(cb != NULL, return;); - self = (struct irda_usb_cb *) cb->context; - IRDA_ASSERT(self != NULL, return;); - - /* Same stuff as when Rx is done, see above... */ - next_urb = self->idle_rx_urb; - urb->context = NULL; - self->idle_rx_urb = urb; - irda_usb_submit(self, skb, next_urb); -} - -/*------------------------------------------------------------------*/ -/* - * Callbak from IrDA layer. IrDA wants to know if we have - * started receiving anything. - */ -static int irda_usb_is_receiving(struct irda_usb_cb *self) -{ - /* Note : because of the way UHCI works, it's almost impossible - * to get this info. The Controller DMA directly to memory and - * signal only when the whole frame is finished. To know if the - * first TD of the URB has been filled or not seems hard work... - * - * The other solution would be to use the "receiving" command - * on the default decriptor with a usb_control_msg(), but that - * would add USB traffic and would return result only in the - * next USB frame (~1ms). - * - * I've been told that current dongles send status info on their - * interrupt endpoint, and that's what the Windows driver uses - * to know this info. Unfortunately, this is not yet in the spec... - * - * Jean II - */ - - return 0; /* For now */ -} - -#define STIR421X_PATCH_PRODUCT_VER "Product Version: " -#define STIR421X_PATCH_STMP_TAG "STMP" -#define STIR421X_PATCH_CODE_OFFSET 512 /* patch image starts before here */ -/* marks end of patch file header (PC DOS text file EOF character) */ -#define STIR421X_PATCH_END_OF_HDR_TAG 0x1A -#define STIR421X_PATCH_BLOCK_SIZE 1023 - -/* - * Function stir421x_fwupload (struct irda_usb_cb *self, - * unsigned char *patch, - * const unsigned int patch_len) - * - * Upload firmware code to SigmaTel 421X IRDA-USB dongle - */ -static int stir421x_fw_upload(struct irda_usb_cb *self, - const unsigned char *patch, - const unsigned int patch_len) -{ - int ret = -ENOMEM; - int actual_len = 0; - unsigned int i; - unsigned int block_size = 0; - unsigned char *patch_block; - - patch_block = kzalloc(STIR421X_PATCH_BLOCK_SIZE, GFP_KERNEL); - if (patch_block == NULL) - return -ENOMEM; - - /* break up patch into 1023-byte sections */ - for (i = 0; i < patch_len; i += block_size) { - block_size = patch_len - i; - - if (block_size > STIR421X_PATCH_BLOCK_SIZE) - block_size = STIR421X_PATCH_BLOCK_SIZE; - - /* upload the patch section */ - memcpy(patch_block, patch + i, block_size); - - ret = usb_bulk_msg(self->usbdev, - usb_sndbulkpipe(self->usbdev, - self->bulk_out_ep), - patch_block, block_size, - &actual_len, msecs_to_jiffies(500)); - pr_debug("%s(): Bulk send %u bytes, ret=%d\n", - __func__, actual_len, ret); - - if (ret < 0) - break; - - mdelay(10); - } - - kfree(patch_block); - - return ret; - } - -/* - * Function stir421x_patch_device(struct irda_usb_cb *self) - * - * Get a firmware code from userspase using hotplug request_firmware() call - */ -static int stir421x_patch_device(struct irda_usb_cb *self) -{ - unsigned int i; - int ret; - char stir421x_fw_name[12]; - const struct firmware *fw; - const unsigned char *fw_version_ptr; /* pointer to version string */ - unsigned long fw_version = 0; - - /* - * Known firmware patch file names for STIR421x dongles - * are "42101001.sb" or "42101002.sb" - */ - sprintf(stir421x_fw_name, "4210%4X.sb", - le16_to_cpu(self->usbdev->descriptor.bcdDevice)); - ret = request_firmware(&fw, stir421x_fw_name, &self->usbdev->dev); - if (ret < 0) - return ret; - - /* We get a patch from userspace */ - net_info_ratelimited("%s(): Received firmware %s (%zu bytes)\n", - __func__, stir421x_fw_name, fw->size); - - ret = -EINVAL; - - /* Get the bcd product version */ - if (!memcmp(fw->data, STIR421X_PATCH_PRODUCT_VER, - sizeof(STIR421X_PATCH_PRODUCT_VER) - 1)) { - fw_version_ptr = fw->data + - sizeof(STIR421X_PATCH_PRODUCT_VER) - 1; - - /* Let's check if the product version is dotted */ - if (fw_version_ptr[3] == '.' && - fw_version_ptr[7] == '.') { - unsigned long major, minor, build; - major = simple_strtoul(fw_version_ptr, NULL, 10); - minor = simple_strtoul(fw_version_ptr + 4, NULL, 10); - build = simple_strtoul(fw_version_ptr + 8, NULL, 10); - - fw_version = (major << 12) - + (minor << 8) - + ((build / 10) << 4) - + (build % 10); - - pr_debug("%s(): Firmware Product version %ld\n", - __func__, fw_version); - } - } - - if (self->usbdev->descriptor.bcdDevice == cpu_to_le16(fw_version)) { - /* - * If we're here, we've found a correct patch - * The actual image starts after the "STMP" keyword - * so forward to the firmware header tag - */ - for (i = 0; i < fw->size && fw->data[i] != - STIR421X_PATCH_END_OF_HDR_TAG; i++) ; - /* here we check for the out of buffer case */ - if (i < STIR421X_PATCH_CODE_OFFSET && i < fw->size && - STIR421X_PATCH_END_OF_HDR_TAG == fw->data[i]) { - if (!memcmp(fw->data + i + 1, STIR421X_PATCH_STMP_TAG, - sizeof(STIR421X_PATCH_STMP_TAG) - 1)) { - - /* We can upload the patch to the target */ - i += sizeof(STIR421X_PATCH_STMP_TAG); - ret = stir421x_fw_upload(self, &fw->data[i], - fw->size - i); - } - } - } - - release_firmware(fw); - - return ret; -} - - -/********************** IRDA DEVICE CALLBACKS **********************/ -/* - * Main calls from the IrDA/Network subsystem. - * Mostly registering a new irda-usb device and removing it.... - * We only deal with the IrDA side of the business, the USB side will - * be dealt with below... - */ - - -/*------------------------------------------------------------------*/ -/* - * Function irda_usb_net_open (dev) - * - * Network device is taken up. Usually this is done by "ifconfig irda0 up" - * - * Note : don't mess with self->netopen - Jean II - */ -static int irda_usb_net_open(struct net_device *netdev) -{ - struct irda_usb_cb *self; - unsigned long flags; - char hwname[16]; - int i; - - IRDA_ASSERT(netdev != NULL, return -1;); - self = netdev_priv(netdev); - IRDA_ASSERT(self != NULL, return -1;); - - spin_lock_irqsave(&self->lock, flags); - /* Can only open the device if it's there */ - if(!self->present) { - spin_unlock_irqrestore(&self->lock, flags); - net_warn_ratelimited("%s(), device not present!\n", __func__); - return -1; - } - - if(self->needspatch) { - spin_unlock_irqrestore(&self->lock, flags); - net_warn_ratelimited("%s(), device needs patch\n", __func__); - return -EIO ; - } - - /* Initialise default speed and xbofs value - * (IrLAP will change that soon) */ - self->speed = -1; - self->xbofs = -1; - self->new_speed = -1; - self->new_xbofs = -1; - - /* To do *before* submitting Rx urbs and starting net Tx queue - * Jean II */ - self->netopen = 1; - spin_unlock_irqrestore(&self->lock, flags); - - /* - * Now that everything should be initialized properly, - * Open new IrLAP layer instance to take care of us... - * Note : will send immediately a speed change... - */ - sprintf(hwname, "usb#%d", self->usbdev->devnum); - self->irlap = irlap_open(netdev, &self->qos, hwname); - IRDA_ASSERT(self->irlap != NULL, return -1;); - - /* Allow IrLAP to send data to us */ - netif_start_queue(netdev); - - /* We submit all the Rx URB except for one that we keep idle. - * Need to be initialised before submitting other USBs, because - * in some cases as soon as we submit the URBs the USB layer - * will trigger a dummy receive - Jean II */ - self->idle_rx_urb = self->rx_urb[IU_MAX_ACTIVE_RX_URBS]; - self->idle_rx_urb->context = NULL; - - /* Now that we can pass data to IrLAP, allow the USB layer - * to send us some data... */ - for (i = 0; i < IU_MAX_ACTIVE_RX_URBS; i++) { - struct sk_buff *skb = dev_alloc_skb(IRDA_SKB_MAX_MTU); - if (!skb) { - /* If this ever happen, we are in deep s***. - * Basically, we can't start the Rx path... */ - return -1; - } - //skb_reserve(newskb, USB_IRDA_HEADER - 1); - irda_usb_submit(self, skb, self->rx_urb[i]); - } - - /* Ready to play !!! */ - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * Function irda_usb_net_close (self) - * - * Network device is taken down. Usually this is done by - * "ifconfig irda0 down" - */ -static int irda_usb_net_close(struct net_device *netdev) -{ - struct irda_usb_cb *self; - int i; - - IRDA_ASSERT(netdev != NULL, return -1;); - self = netdev_priv(netdev); - IRDA_ASSERT(self != NULL, return -1;); - - /* Clear this flag *before* unlinking the urbs and *before* - * stopping the network Tx queue - Jean II */ - self->netopen = 0; - - /* Stop network Tx queue */ - netif_stop_queue(netdev); - - /* Kill defered Rx URB */ - del_timer(&self->rx_defer_timer); - - /* Deallocate all the Rx path buffers (URBs and skb) */ - for (i = 0; i < self->max_rx_urb; i++) { - struct urb *urb = self->rx_urb[i]; - struct sk_buff *skb = (struct sk_buff *) urb->context; - /* Cancel the receive command */ - usb_kill_urb(urb); - /* The skb is ours, free it */ - if(skb) { - dev_kfree_skb(skb); - urb->context = NULL; - } - } - /* Cancel Tx and speed URB - need to be synchronous to avoid races */ - usb_kill_urb(self->tx_urb); - usb_kill_urb(self->speed_urb); - - /* Stop and remove instance of IrLAP */ - if (self->irlap) - irlap_close(self->irlap); - self->irlap = NULL; - - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * IOCTLs : Extra out-of-band network commands... - */ -static int irda_usb_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - unsigned long flags; - struct if_irda_req *irq = (struct if_irda_req *) rq; - struct irda_usb_cb *self; - int ret = 0; - - IRDA_ASSERT(dev != NULL, return -1;); - self = netdev_priv(dev); - IRDA_ASSERT(self != NULL, return -1;); - - pr_debug("%s(), %s, (cmd=0x%X)\n", __func__, dev->name, cmd); - - switch (cmd) { - case SIOCSBANDWIDTH: /* Set bandwidth */ - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - /* Protect us from USB callbacks, net watchdog and else. */ - spin_lock_irqsave(&self->lock, flags); - /* Check if the device is still there */ - if(self->present) { - /* Set the desired speed */ - self->new_speed = irq->ifr_baudrate; - irda_usb_change_speed_xbofs(self); - } - spin_unlock_irqrestore(&self->lock, flags); - break; - case SIOCSMEDIABUSY: /* Set media busy */ - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - /* Check if the IrDA stack is still there */ - if(self->netopen) - irda_device_set_media_busy(self->netdev, TRUE); - break; - case SIOCGRECEIVING: /* Check if we are receiving right now */ - irq->ifr_receiving = irda_usb_is_receiving(self); - break; - default: - ret = -EOPNOTSUPP; - } - - return ret; -} - -/*------------------------------------------------------------------*/ - -/********************* IRDA CONFIG SUBROUTINES *********************/ -/* - * Various subroutines dealing with IrDA and network stuff we use to - * configure and initialise each irda-usb instance. - * These functions are used below in the main calls of the driver... - */ - -/*------------------------------------------------------------------*/ -/* - * Set proper values in the IrDA QOS structure - */ -static inline void irda_usb_init_qos(struct irda_usb_cb *self) -{ - struct irda_class_desc *desc; - - - desc = self->irda_desc; - - /* Initialize QoS for this device */ - irda_init_max_qos_capabilies(&self->qos); - - /* See spec section 7.2 for meaning. - * Values are little endian (as most USB stuff), the IrDA stack - * use it in native order (see parameters.c). - Jean II */ - self->qos.baud_rate.bits = le16_to_cpu(desc->wBaudRate); - self->qos.min_turn_time.bits = desc->bmMinTurnaroundTime; - self->qos.additional_bofs.bits = desc->bmAdditionalBOFs; - self->qos.window_size.bits = desc->bmWindowSize; - self->qos.data_size.bits = desc->bmDataSize; - - pr_debug("%s(), dongle says speed=0x%X, size=0x%X, window=0x%X, bofs=0x%X, turn=0x%X\n", - __func__, self->qos.baud_rate.bits, self->qos.data_size.bits, - self->qos.window_size.bits, self->qos.additional_bofs.bits, - self->qos.min_turn_time.bits); - - /* Don't always trust what the dongle tell us */ - if(self->capability & IUC_SIR_ONLY) - self->qos.baud_rate.bits &= 0x00ff; - if(self->capability & IUC_SMALL_PKT) - self->qos.data_size.bits = 0x07; - if(self->capability & IUC_NO_WINDOW) - self->qos.window_size.bits = 0x01; - if(self->capability & IUC_MAX_WINDOW) - self->qos.window_size.bits = 0x7f; - if(self->capability & IUC_MAX_XBOFS) - self->qos.additional_bofs.bits = 0x01; - -#if 1 - /* Module parameter can override the rx window size */ - if (qos_mtt_bits) - self->qos.min_turn_time.bits = qos_mtt_bits; -#endif - /* - * Note : most of those values apply only for the receive path, - * the transmit path will be set differently - Jean II - */ - irda_qos_bits_to_value(&self->qos); -} - -/*------------------------------------------------------------------*/ -static const struct net_device_ops irda_usb_netdev_ops = { - .ndo_open = irda_usb_net_open, - .ndo_stop = irda_usb_net_close, - .ndo_do_ioctl = irda_usb_net_ioctl, - .ndo_start_xmit = irda_usb_hard_xmit, - .ndo_tx_timeout = irda_usb_net_timeout, -}; - -/* - * Initialise the network side of the irda-usb instance - * Called when a new USB instance is registered in irda_usb_probe() - */ -static inline int irda_usb_open(struct irda_usb_cb *self) -{ - struct net_device *netdev = self->netdev; - - netdev->netdev_ops = &irda_usb_netdev_ops; - - irda_usb_init_qos(self); - - return register_netdev(netdev); -} - -/*------------------------------------------------------------------*/ -/* - * Cleanup the network side of the irda-usb instance - * Called when a USB instance is removed in irda_usb_disconnect() - */ -static inline void irda_usb_close(struct irda_usb_cb *self) -{ - /* Remove netdevice */ - unregister_netdev(self->netdev); - - /* Remove the speed buffer */ - kfree(self->speed_buff); - self->speed_buff = NULL; - - kfree(self->tx_buff); - self->tx_buff = NULL; -} - -/********************** USB CONFIG SUBROUTINES **********************/ -/* - * Various subroutines dealing with USB stuff we use to configure and - * initialise each irda-usb instance. - * These functions are used below in the main calls of the driver... - */ - -/*------------------------------------------------------------------*/ -/* - * Function irda_usb_parse_endpoints(dev, ifnum) - * - * Parse the various endpoints and find the one we need. - * - * The endpoint are the pipes used to communicate with the USB device. - * The spec defines 2 endpoints of type bulk transfer, one in, and one out. - * These are used to pass frames back and forth with the dongle. - * Most dongle have also an interrupt endpoint, that will be probably - * documented in the next spec... - */ -static inline int irda_usb_parse_endpoints(struct irda_usb_cb *self, struct usb_host_endpoint *endpoint, int ennum) -{ - int i; /* Endpoint index in table */ - - /* Init : no endpoints */ - self->bulk_in_ep = 0; - self->bulk_out_ep = 0; - self->bulk_int_ep = 0; - - /* Let's look at all those endpoints */ - for(i = 0; i < ennum; i++) { - /* All those variables will get optimised by the compiler, - * so let's aim for clarity... - Jean II */ - __u8 ep; /* Endpoint address */ - __u8 dir; /* Endpoint direction */ - __u8 attr; /* Endpoint attribute */ - __u16 psize; /* Endpoint max packet size in bytes */ - - /* Get endpoint address, direction and attribute */ - ep = endpoint[i].desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; - dir = endpoint[i].desc.bEndpointAddress & USB_ENDPOINT_DIR_MASK; - attr = endpoint[i].desc.bmAttributes; - psize = le16_to_cpu(endpoint[i].desc.wMaxPacketSize); - - /* Is it a bulk endpoint ??? */ - if(attr == USB_ENDPOINT_XFER_BULK) { - /* We need to find an IN and an OUT */ - if(dir == USB_DIR_IN) { - /* This is our Rx endpoint */ - self->bulk_in_ep = ep; - } else { - /* This is our Tx endpoint */ - self->bulk_out_ep = ep; - self->bulk_out_mtu = psize; - } - } else { - if((attr == USB_ENDPOINT_XFER_INT) && - (dir == USB_DIR_IN)) { - /* This is our interrupt endpoint */ - self->bulk_int_ep = ep; - } else { - net_err_ratelimited("%s(), Unrecognised endpoint %02X\n", - __func__, ep); - } - } - } - - pr_debug("%s(), And our endpoints are : in=%02X, out=%02X (%d), int=%02X\n", - __func__, self->bulk_in_ep, self->bulk_out_ep, - self->bulk_out_mtu, self->bulk_int_ep); - - return (self->bulk_in_ep != 0) && (self->bulk_out_ep != 0); -} - -#ifdef IU_DUMP_CLASS_DESC -/*------------------------------------------------------------------*/ -/* - * Function usb_irda_dump_class_desc(desc) - * - * Prints out the contents of the IrDA class descriptor - * - */ -static inline void irda_usb_dump_class_desc(struct irda_class_desc *desc) -{ - /* Values are little endian */ - printk("bLength=%x\n", desc->bLength); - printk("bDescriptorType=%x\n", desc->bDescriptorType); - printk("bcdSpecRevision=%x\n", le16_to_cpu(desc->bcdSpecRevision)); - printk("bmDataSize=%x\n", desc->bmDataSize); - printk("bmWindowSize=%x\n", desc->bmWindowSize); - printk("bmMinTurnaroundTime=%d\n", desc->bmMinTurnaroundTime); - printk("wBaudRate=%x\n", le16_to_cpu(desc->wBaudRate)); - printk("bmAdditionalBOFs=%x\n", desc->bmAdditionalBOFs); - printk("bIrdaRateSniff=%x\n", desc->bIrdaRateSniff); - printk("bMaxUnicastList=%x\n", desc->bMaxUnicastList); -} -#endif /* IU_DUMP_CLASS_DESC */ - -/*------------------------------------------------------------------*/ -/* - * Function irda_usb_find_class_desc(intf) - * - * Returns instance of IrDA class descriptor, or NULL if not found - * - * The class descriptor is some extra info that IrDA USB devices will - * offer to us, describing their IrDA characteristics. We will use that in - * irda_usb_init_qos() - */ -static inline struct irda_class_desc *irda_usb_find_class_desc(struct usb_interface *intf) -{ - struct usb_device *dev = interface_to_usbdev (intf); - struct irda_class_desc *desc; - int ret; - - desc = kzalloc(sizeof(*desc), GFP_KERNEL); - if (!desc) - return NULL; - - /* USB-IrDA class spec 1.0: - * 6.1.3: Standard "Get Descriptor" Device Request is not - * appropriate to retrieve class-specific descriptor - * 6.2.5: Class Specific "Get Class Descriptor" Interface Request - * is mandatory and returns the USB-IrDA class descriptor - */ - - ret = usb_control_msg(dev, usb_rcvctrlpipe(dev,0), - IU_REQ_GET_CLASS_DESC, - USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, - 0, intf->altsetting->desc.bInterfaceNumber, desc, - sizeof(*desc), 500); - - pr_debug("%s(), ret=%d\n", __func__, ret); - if (ret < sizeof(*desc)) { - net_warn_ratelimited("usb-irda: class_descriptor read %s (%d)\n", - ret < 0 ? "failed" : "too short", ret); - } - else if (desc->bDescriptorType != USB_DT_IRDA) { - net_warn_ratelimited("usb-irda: bad class_descriptor type\n"); - } - else { -#ifdef IU_DUMP_CLASS_DESC - irda_usb_dump_class_desc(desc); -#endif /* IU_DUMP_CLASS_DESC */ - - return desc; - } - kfree(desc); - return NULL; -} - -/*********************** USB DEVICE CALLBACKS ***********************/ -/* - * Main calls from the USB subsystem. - * Mostly registering a new irda-usb device and removing it.... - */ - -/*------------------------------------------------------------------*/ -/* - * This routine is called by the USB subsystem for each new device - * in the system. We need to check if the device is ours, and in - * this case start handling it. - * The USB layer protect us from reentrancy (via BKL), so we don't need - * to spinlock in there... Jean II - */ -static int irda_usb_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct net_device *net; - struct usb_device *dev = interface_to_usbdev(intf); - struct irda_usb_cb *self; - struct usb_host_interface *interface; - struct irda_class_desc *irda_desc; - int ret = -ENOMEM; - int i; /* Driver instance index / Rx URB index */ - - /* Note : the probe make sure to call us only for devices that - * matches the list of dongle (top of the file). So, we - * don't need to check if the dongle is really ours. - * Jean II */ - - net_info_ratelimited("IRDA-USB found at address %d, Vendor: %x, Product: %x\n", - dev->devnum, le16_to_cpu(dev->descriptor.idVendor), - le16_to_cpu(dev->descriptor.idProduct)); - - net = alloc_irdadev(sizeof(*self)); - if (!net) - goto err_out; - - SET_NETDEV_DEV(net, &intf->dev); - self = netdev_priv(net); - self->netdev = net; - spin_lock_init(&self->lock); - init_timer(&self->rx_defer_timer); - - self->capability = id->driver_info; - self->needspatch = ((self->capability & IUC_STIR421X) != 0); - - /* Create all of the needed urbs */ - if (self->capability & IUC_STIR421X) { - self->max_rx_urb = IU_SIGMATEL_MAX_RX_URBS; - self->header_length = USB_IRDA_STIR421X_HEADER; - } else { - self->max_rx_urb = IU_MAX_RX_URBS; - self->header_length = USB_IRDA_HEADER; - } - - self->rx_urb = kcalloc(self->max_rx_urb, sizeof(struct urb *), - GFP_KERNEL); - if (!self->rx_urb) - goto err_free_net; - - for (i = 0; i < self->max_rx_urb; i++) { - self->rx_urb[i] = usb_alloc_urb(0, GFP_KERNEL); - if (!self->rx_urb[i]) { - goto err_out_1; - } - } - self->tx_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!self->tx_urb) { - goto err_out_1; - } - self->speed_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!self->speed_urb) { - goto err_out_2; - } - - /* Is this really necessary? (no, except maybe for broken devices) */ - if (usb_reset_configuration (dev) < 0) { - dev_err(&intf->dev, "reset_configuration failed\n"); - ret = -EIO; - goto err_out_3; - } - - /* Is this really necessary? */ - /* Note : some driver do hardcode the interface number, some others - * specify an alternate, but very few driver do like this. - * Jean II */ - ret = usb_set_interface(dev, intf->altsetting->desc.bInterfaceNumber, 0); - pr_debug("usb-irda: set interface %d result %d\n", - intf->altsetting->desc.bInterfaceNumber, ret); - switch (ret) { - case 0: - break; - case -EPIPE: /* -EPIPE = -32 */ - /* Martin Diehl says if we get a -EPIPE we should - * be fine and we don't need to do a usb_clear_halt(). - * - Jean II */ - pr_debug("%s(), Received -EPIPE, ignoring...\n", - __func__); - break; - default: - pr_debug("%s(), Unknown error %d\n", __func__, ret); - ret = -EIO; - goto err_out_3; - } - - /* Find our endpoints */ - interface = intf->cur_altsetting; - if(!irda_usb_parse_endpoints(self, interface->endpoint, - interface->desc.bNumEndpoints)) { - net_err_ratelimited("%s(), Bogus endpoints...\n", __func__); - ret = -EIO; - goto err_out_3; - } - - self->usbdev = dev; - - /* Find IrDA class descriptor */ - irda_desc = irda_usb_find_class_desc(intf); - ret = -ENODEV; - if (!irda_desc) - goto err_out_3; - - if (self->needspatch) { - ret = usb_control_msg (self->usbdev, usb_sndctrlpipe (self->usbdev, 0), - 0x02, 0x40, 0, 0, NULL, 0, 500); - if (ret < 0) { - pr_debug("usb_control_msg failed %d\n", ret); - goto err_out_3; - } else { - mdelay(10); - } - } - - self->irda_desc = irda_desc; - self->present = 1; - self->netopen = 0; - self->usbintf = intf; - - /* Allocate the buffer for speed changes */ - /* Don't change this buffer size and allocation without doing - * some heavy and complete testing. Don't ask why :-( - * Jean II */ - ret = -ENOMEM; - self->speed_buff = kzalloc(IRDA_USB_SPEED_MTU, GFP_KERNEL); - if (!self->speed_buff) - goto err_out_3; - - self->tx_buff = kzalloc(IRDA_SKB_MAX_MTU + self->header_length, - GFP_KERNEL); - if (!self->tx_buff) - goto err_out_4; - - ret = irda_usb_open(self); - if (ret) - goto err_out_5; - - net_info_ratelimited("IrDA: Registered device %s\n", net->name); - usb_set_intfdata(intf, self); - - if (self->needspatch) { - /* Now we fetch and upload the firmware patch */ - ret = stir421x_patch_device(self); - self->needspatch = (ret < 0); - if (self->needspatch) { - net_err_ratelimited("STIR421X: Couldn't upload patch\n"); - goto err_out_6; - } - - /* replace IrDA class descriptor with what patched device is now reporting */ - irda_desc = irda_usb_find_class_desc (self->usbintf); - if (!irda_desc) { - ret = -ENODEV; - goto err_out_6; - } - kfree(self->irda_desc); - self->irda_desc = irda_desc; - irda_usb_init_qos(self); - } - - return 0; -err_out_6: - unregister_netdev(self->netdev); -err_out_5: - kfree(self->tx_buff); -err_out_4: - kfree(self->speed_buff); -err_out_3: - /* Free all urbs that we may have created */ - usb_free_urb(self->speed_urb); -err_out_2: - usb_free_urb(self->tx_urb); -err_out_1: - for (i = 0; i < self->max_rx_urb; i++) - usb_free_urb(self->rx_urb[i]); - kfree(self->rx_urb); -err_free_net: - free_netdev(net); -err_out: - return ret; -} - -/*------------------------------------------------------------------*/ -/* - * The current irda-usb device is removed, the USB layer tell us - * to shut it down... - * One of the constraints is that when we exit this function, - * we cannot use the usb_device no more. Gone. Destroyed. kfree(). - * Most other subsystem allow you to destroy the instance at a time - * when it's convenient to you, to postpone it to a later date, but - * not the USB subsystem. - * So, we must make bloody sure that everything gets deactivated. - * Jean II - */ -static void irda_usb_disconnect(struct usb_interface *intf) -{ - unsigned long flags; - struct irda_usb_cb *self = usb_get_intfdata(intf); - int i; - - usb_set_intfdata(intf, NULL); - if (!self) - return; - - /* Make sure that the Tx path is not executing. - Jean II */ - spin_lock_irqsave(&self->lock, flags); - - /* Oups ! We are not there any more. - * This will stop/desactivate the Tx path. - Jean II */ - self->present = 0; - - /* Kill defered Rx URB */ - del_timer(&self->rx_defer_timer); - - /* We need to have irq enabled to unlink the URBs. That's OK, - * at this point the Tx path is gone - Jean II */ - spin_unlock_irqrestore(&self->lock, flags); - - /* Hum... Check if networking is still active (avoid races) */ - if((self->netopen) || (self->irlap)) { - /* Accept no more transmissions */ - /*netif_device_detach(self->netdev);*/ - netif_stop_queue(self->netdev); - /* Stop all the receive URBs. Must be synchronous. */ - for (i = 0; i < self->max_rx_urb; i++) - usb_kill_urb(self->rx_urb[i]); - /* Cancel Tx and speed URB. - * Make sure it's synchronous to avoid races. */ - usb_kill_urb(self->tx_urb); - usb_kill_urb(self->speed_urb); - } - - /* Cleanup the device stuff */ - irda_usb_close(self); - /* No longer attached to USB bus */ - self->usbdev = NULL; - self->usbintf = NULL; - - /* Clean up our urbs */ - for (i = 0; i < self->max_rx_urb; i++) - usb_free_urb(self->rx_urb[i]); - kfree(self->rx_urb); - /* Clean up Tx and speed URB */ - usb_free_urb(self->tx_urb); - usb_free_urb(self->speed_urb); - - /* Free self and network device */ - free_netdev(self->netdev); - pr_debug("%s(), USB IrDA Disconnected\n", __func__); -} - -#ifdef CONFIG_PM -/* USB suspend, so power off the transmitter/receiver */ -static int irda_usb_suspend(struct usb_interface *intf, pm_message_t message) -{ - struct irda_usb_cb *self = usb_get_intfdata(intf); - int i; - - netif_device_detach(self->netdev); - - if (self->tx_urb != NULL) - usb_kill_urb(self->tx_urb); - if (self->speed_urb != NULL) - usb_kill_urb(self->speed_urb); - for (i = 0; i < self->max_rx_urb; i++) { - if (self->rx_urb[i] != NULL) - usb_kill_urb(self->rx_urb[i]); - } - return 0; -} - -/* Coming out of suspend, so reset hardware */ -static int irda_usb_resume(struct usb_interface *intf) -{ - struct irda_usb_cb *self = usb_get_intfdata(intf); - int i; - - for (i = 0; i < self->max_rx_urb; i++) { - if (self->rx_urb[i] != NULL) - usb_submit_urb(self->rx_urb[i], GFP_KERNEL); - } - - netif_device_attach(self->netdev); - return 0; -} -#endif - -/*------------------------------------------------------------------*/ -/* - * USB device callbacks - */ -static struct usb_driver irda_driver = { - .name = "irda-usb", - .probe = irda_usb_probe, - .disconnect = irda_usb_disconnect, - .id_table = dongles, -#ifdef CONFIG_PM - .suspend = irda_usb_suspend, - .resume = irda_usb_resume, -#endif -}; - -module_usb_driver(irda_driver); - -/* - * Module parameters - */ -module_param(qos_mtt_bits, int, 0); -MODULE_PARM_DESC(qos_mtt_bits, "Minimum Turn Time"); -MODULE_AUTHOR("Roman Weissgaerber <weissg@vienna.at>, Dag Brattli <dag@brattli.net>, Jean Tourrilhes <jt@hpl.hp.com> and Nick Fedchik <nick@fedchik.org.ua>"); -MODULE_DESCRIPTION("IrDA-USB Dongle Driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/net/irda/irda-usb.h b/drivers/net/irda/irda-usb.h deleted file mode 100644 index 8ac389fa9348..000000000000 --- a/drivers/net/irda/irda-usb.h +++ /dev/null @@ -1,174 +0,0 @@ -/***************************************************************************** - * - * Filename: irda-usb.h - * Version: 0.10 - * 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> - * Copyright (C) 2004, SigmaTel, Inc. <irquality@sigmatel.com> - * Copyright (C) 2005, Milan Beno <beno@pobox.sk> - * Copyright (C) 2006, Nick FEdchik <nick@fedchik.org.ua> - * - * 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/ktime.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 -#define SPEED_16000000 0x0a - -/* 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 */ -#define IUC_STIR421X 0x80 /* SigmaTel 4210/4220/4116 VFIR */ - -/* USB class definitions */ -#define USB_IRDA_HEADER 0x01 -#define USB_CLASS_IRDA 0x02 /* USB_CLASS_APP_SPEC subclass */ -#define USB_DT_IRDA 0x21 -#define USB_IRDA_STIR421X_HEADER 0x03 -#define IU_SIGMATEL_MAX_RX_URBS (IU_MAX_ACTIVE_RX_URBS + \ - USB_IRDA_STIR421X_HEADER) - -struct irda_class_desc { - __u8 bLength; - __u8 bDescriptorType; - __le16 bcdSpecRevision; - __u8 bmDataSize; - __u8 bmWindowSize; - __u8 bmMinTurnaroundTime; - __le16 wBaudRate; - __u8 bmAdditionalBOFs; - __u8 bIrdaRateSniff; - __u8 bMaxUnicastList; -} __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 -#define STIR421X_MAX_PATCH_DOWNLOAD_SIZE 1023 - -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 */ - - __u8 max_rx_urb; - struct urb **rx_urb; /* 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 irlap_cb *irlap; /* The link layer we are binded to */ - struct qos_info qos; - char *speed_buff; /* Buffer for speed changes */ - char *tx_buff; - - ktime_t stamp; - - spinlock_t lock; /* For serializing Tx 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 */ - - __u8 header_length; /* USB-IrDA frame header size */ - int needspatch; /* device needs firmware patch */ - - struct timer_list rx_defer_timer; /* Wait for Rx error to clear */ -}; - diff --git a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c deleted file mode 100644 index 7a20a9a4663a..000000000000 --- a/drivers/net/irda/irtty-sir.c +++ /dev/null @@ -1,570 +0,0 @@ -/********************************************************************* - * - * 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ø 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/slab.h> -#include <linux/tty.h> -#include <linux/init.h> -#include <linux/uaccess.h> -#include <linux/delay.h> -#include <linux/mutex.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 tty_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->ops->wait_until_sent) { - tty->ops->wait_until_sent(tty, msecs_to_jiffies(100)); - } - 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 ktermios old_termios; - int cflag; - - IRDA_ASSERT(priv != NULL, return -1;); - IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return -1;); - - tty = priv->tty; - - down_write(&tty->termios_rwsem); - old_termios = tty->termios; - cflag = tty->termios.c_cflag; - tty_encode_baud_rate(tty, speed, speed); - if (tty->ops->set_termios) - tty->ops->set_termios(tty, &old_termios); - priv->io.speed = speed; - up_write(&tty->termios_rwsem); - - 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->ops->tiocmset != NULL, return -1;); - priv->tty->ops->tiocmset(priv->tty, 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->ops->write) - return 0; - set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); - writelen = tty_write_room(tty); - if (writelen > len) - writelen = len; - return tty->ops->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->port->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) { - net_warn_ratelimited("%s(), not ready yet!\n", __func__); - return; - } - - for (i = 0; i < count; i++) { - /* - * Characters received with a parity error, etc? - */ - if (fp && *fp++) { - pr_debug("Framing or parity error!\n"); - sirdev_receive(dev, NULL, 0); /* notify sir_dev (updating stats) */ - return; - } - } - - sirdev_receive(dev, cp, count); -} - -/* - * 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;); - - clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); - 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 ktermios old_termios; - int cflag; - - down_write(&tty->termios_rwsem); - old_termios = tty->termios; - cflag = tty->termios.c_cflag; - - if (stop) - cflag &= ~CREAD; - else - cflag |= CREAD; - - tty->termios.c_cflag = cflag; - if (tty->ops->set_termios) - tty->ops->set_termios(tty, &old_termios); - up_write(&tty->termios_rwsem); -} - -/*****************************************************************/ - -/* serialize ldisc open/close with sir_dev */ -static DEFINE_MUTEX(irtty_mutex); - -/* 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 */ - mutex_lock(&irtty_mutex); - - priv = dev->priv; - if (unlikely(!priv || priv->magic!=IRTTY_MAGIC)) { - mutex_unlock(&irtty_mutex); - return -ESTALE; - } - - tty = priv->tty; - - if (tty->ops->start) - tty->ops->start(tty); - /* Make sure we can receive more data */ - irtty_stop_receiver(tty, FALSE); - - mutex_unlock(&irtty_mutex); - 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 */ - mutex_lock(&irtty_mutex); - - priv = dev->priv; - if (unlikely(!priv || priv->magic!=IRTTY_MAGIC)) { - mutex_unlock(&irtty_mutex); - return -ESTALE; - } - - tty = priv->tty; - - /* Make sure we don't receive more data */ - irtty_stop_receiver(tty, TRUE); - if (tty->ops->stop) - tty->ops->stop(tty); - - mutex_unlock(&irtty_mutex); - - 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;); - - pr_debug("%s(cmd=0x%X)\n", __func__, cmd); - - dev = priv->dev; - IRDA_ASSERT(dev != NULL, return -1;); - - switch (cmd) { - 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 = tty_mode_ioctl(tty, file, cmd, arg); - 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 */ - - /* stop the underlying driver */ - irtty_stop_receiver(tty, TRUE); - if (tty->ops->stop) - tty->ops->stop(tty); - - 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 = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) { - ret = -ENOMEM; - goto out_put; - } - - priv->magic = IRTTY_MAGIC; - priv->tty = tty; - priv->dev = dev; - - /* serialize with start_dev - in case we were racing with ifup */ - mutex_lock(&irtty_mutex); - - dev->priv = priv; - tty->disc_data = priv; - tty->receive_room = 65536; - - mutex_unlock(&irtty_mutex); - - pr_debug("%s - %s: irda line discipline opened\n", __func__, 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 */ - clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); - if (tty->ops->stop) - tty->ops->stop(tty); - - kfree(priv); - - pr_debug("%s - %s: irda line discipline closed\n", __func__, tty->name); -} - -/* ------------------------------------------------------- */ - -static struct tty_ldisc_ops 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, - .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) - net_err_ratelimited("IrDA: can't register line discipline (err = %d)\n", - err); - return err; -} - -static void __exit irtty_sir_cleanup(void) -{ - int err; - - if ((err = tty_unregister_ldisc(N_IRDA))) { - net_err_ratelimited("%s(), can't unregister line discipline (err = %d)\n", - __func__, 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"); - diff --git a/drivers/net/irda/irtty-sir.h b/drivers/net/irda/irtty-sir.h deleted file mode 100644 index b132d8f6eb13..000000000000 --- a/drivers/net/irda/irtty-sir.h +++ /dev/null @@ -1,34 +0,0 @@ -/********************************************************************* - * - * 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 diff --git a/drivers/net/irda/kingsun-sir.c b/drivers/net/irda/kingsun-sir.c deleted file mode 100644 index 4fd4ac2fe09f..000000000000 --- a/drivers/net/irda/kingsun-sir.c +++ /dev/null @@ -1,634 +0,0 @@ -/***************************************************************************** -* -* Filename: kingsun-sir.c -* Version: 0.1.1 -* Description: Irda KingSun/DonShine USB Dongle -* Status: Experimental -* Author: Alex VillacÃs Lasso <a_villacis@palosanto.com> -* -* Based on stir4200 and mcs7780 drivers, with (strange?) differences -* -* 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. -* -* 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. -* -*****************************************************************************/ - -/* - * This is my current (2007-04-25) understanding of how this dongle is supposed - * to work. This is based on reverse-engineering and examination of the packet - * data sent and received by the WinXP driver using USBSnoopy. Feel free to - * update here as more of this dongle is known: - * - * General: Unlike the other USB IrDA dongles, this particular dongle exposes, - * not two bulk (in and out) endpoints, but two *interrupt* ones. This dongle, - * like the bulk based ones (stir4200.c and mcs7780.c), requires polling in - * order to receive data. - * Transmission: Just like stir4200, this dongle uses a raw stream of data, - * which needs to be wrapped and escaped in a similar way as in stir4200.c. - * Reception: Poll-based, as in stir4200. Each read returns the contents of a - * 8-byte buffer, of which the first byte (LSB) indicates the number of bytes - * (1-7) of valid data contained within the remaining 7 bytes. For example, if - * the buffer had the following contents: - * 06 ff ff ff c0 01 04 aa - * This means that (06) there are 6 bytes of valid data. The byte 0xaa at the - * end is garbage (left over from a previous reception) and is discarded. - * If a read returns an "impossible" value as the length of valid data (such as - * 0x36) in the first byte, then the buffer is uninitialized (as is the case of - * first plug-in) and its contents should be discarded. There is currently no - * evidence that the top 5 bits of the 1st byte of the buffer can have values - * other than 0 once reception begins. - * Once valid bytes are collected, the assembled stream is a sequence of - * wrapped IrDA frames that is unwrapped and unescaped as in stir4200.c. - * BIG FAT WARNING: the dongle does *not* reset the RX buffer in any way after - * a successful read from the host, which means that in absence of further - * reception, repeated reads from the dongle will return the exact same - * contents repeatedly. Attempts to be smart and cache a previous read seem - * to result in corrupted packets, so this driver depends on the unwrap logic - * to sort out any repeated reads. - * Speed change: no commands observed so far to change speed, assumed fixed - * 9600bps (SIR). - */ - -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/slab.h> -#include <linux/usb.h> -#include <linux/device.h> -#include <linux/crc32.h> - -#include <asm/unaligned.h> -#include <asm/byteorder.h> -#include <linux/uaccess.h> - -#include <net/irda/irda.h> -#include <net/irda/wrapper.h> -#include <net/irda/crc.h> - -/* - * According to lsusb, 0x07c0 is assigned to - * "Code Mercenaries Hard- und Software GmbH" - */ -#define KING_VENDOR_ID 0x07c0 -#define KING_PRODUCT_ID 0x4200 - -/* These are the currently known USB ids */ -static const struct usb_device_id dongles[] = { - /* KingSun Co,Ltd IrDA/USB Bridge */ - { USB_DEVICE(KING_VENDOR_ID, KING_PRODUCT_ID) }, - { } -}; - -MODULE_DEVICE_TABLE(usb, dongles); - -#define KINGSUN_MTT 0x07 - -#define KINGSUN_FIFO_SIZE 4096 -#define KINGSUN_EP_IN 0 -#define KINGSUN_EP_OUT 1 - -struct kingsun_cb { - struct usb_device *usbdev; /* init: probe_irda */ - struct net_device *netdev; /* network layer */ - struct irlap_cb *irlap; /* The link layer we are binded to */ - - struct qos_info qos; - - __u8 *in_buf; /* receive buffer */ - __u8 *out_buf; /* transmit buffer */ - __u8 max_rx; /* max. atomic read from dongle - (usually 8), also size of in_buf */ - __u8 max_tx; /* max. atomic write to dongle - (usually 8) */ - - iobuff_t rx_buff; /* receive unwrap state machine */ - spinlock_t lock; - int receiving; - - __u8 ep_in; - __u8 ep_out; - - struct urb *tx_urb; - struct urb *rx_urb; -}; - -/* Callback transmission routine */ -static void kingsun_send_irq(struct urb *urb) -{ - struct kingsun_cb *kingsun = urb->context; - struct net_device *netdev = kingsun->netdev; - - /* in process of stopping, just drop data */ - if (!netif_running(kingsun->netdev)) { - dev_err(&kingsun->usbdev->dev, - "kingsun_send_irq: Network not running!\n"); - return; - } - - /* unlink, shutdown, unplug, other nasties */ - if (urb->status != 0) { - dev_err(&kingsun->usbdev->dev, - "kingsun_send_irq: urb asynchronously failed - %d\n", - urb->status); - } - netif_wake_queue(netdev); -} - -/* - * Called from net/core when new frame is available. - */ -static netdev_tx_t kingsun_hard_xmit(struct sk_buff *skb, - struct net_device *netdev) -{ - struct kingsun_cb *kingsun; - int wraplen; - int ret = 0; - - netif_stop_queue(netdev); - - /* the IRDA wrapping routines don't deal with non linear skb */ - SKB_LINEAR_ASSERT(skb); - - kingsun = netdev_priv(netdev); - - spin_lock(&kingsun->lock); - - /* Append data to the end of whatever data remains to be transmitted */ - wraplen = async_wrap_skb(skb, - kingsun->out_buf, - KINGSUN_FIFO_SIZE); - - /* Calculate how much data can be transmitted in this urb */ - usb_fill_int_urb(kingsun->tx_urb, kingsun->usbdev, - usb_sndintpipe(kingsun->usbdev, kingsun->ep_out), - kingsun->out_buf, wraplen, kingsun_send_irq, - kingsun, 1); - - if ((ret = usb_submit_urb(kingsun->tx_urb, GFP_ATOMIC))) { - dev_err(&kingsun->usbdev->dev, - "kingsun_hard_xmit: failed tx_urb submit: %d\n", ret); - switch (ret) { - case -ENODEV: - case -EPIPE: - break; - default: - netdev->stats.tx_errors++; - netif_start_queue(netdev); - } - } else { - netdev->stats.tx_packets++; - netdev->stats.tx_bytes += skb->len; - } - - dev_kfree_skb(skb); - spin_unlock(&kingsun->lock); - - return NETDEV_TX_OK; -} - -/* Receive callback function */ -static void kingsun_rcv_irq(struct urb *urb) -{ - struct kingsun_cb *kingsun = urb->context; - int ret; - - /* in process of stopping, just drop data */ - if (!netif_running(kingsun->netdev)) { - kingsun->receiving = 0; - return; - } - - /* unlink, shutdown, unplug, other nasties */ - if (urb->status != 0) { - dev_err(&kingsun->usbdev->dev, - "kingsun_rcv_irq: urb asynchronously failed - %d\n", - urb->status); - kingsun->receiving = 0; - return; - } - - if (urb->actual_length == kingsun->max_rx) { - __u8 *bytes = urb->transfer_buffer; - int i; - - /* The very first byte in the buffer indicates the length of - valid data in the read. This byte must be in the range - 1..kingsun->max_rx -1 . Values outside this range indicate - an uninitialized Rx buffer when the dongle has just been - plugged in. */ - if (bytes[0] >= 1 && bytes[0] < kingsun->max_rx) { - for (i = 1; i <= bytes[0]; i++) { - async_unwrap_char(kingsun->netdev, - &kingsun->netdev->stats, - &kingsun->rx_buff, bytes[i]); - } - kingsun->receiving = - (kingsun->rx_buff.state != OUTSIDE_FRAME) - ? 1 : 0; - } - } else if (urb->actual_length > 0) { - dev_err(&kingsun->usbdev->dev, - "%s(): Unexpected response length, expected %d got %d\n", - __func__, kingsun->max_rx, urb->actual_length); - } - /* This urb has already been filled in kingsun_net_open */ - ret = usb_submit_urb(urb, GFP_ATOMIC); -} - -/* - * Function kingsun_net_open (dev) - * - * Network device is taken up. Usually this is done by "ifconfig irda0 up" - */ -static int kingsun_net_open(struct net_device *netdev) -{ - struct kingsun_cb *kingsun = netdev_priv(netdev); - int err = -ENOMEM; - char hwname[16]; - - /* At this point, urbs are NULL, and skb is NULL (see kingsun_probe) */ - kingsun->receiving = 0; - - /* Initialize for SIR to copy data directly into skb. */ - kingsun->rx_buff.in_frame = FALSE; - kingsun->rx_buff.state = OUTSIDE_FRAME; - kingsun->rx_buff.truesize = IRDA_SKB_MAX_MTU; - kingsun->rx_buff.skb = dev_alloc_skb(IRDA_SKB_MAX_MTU); - if (!kingsun->rx_buff.skb) - goto free_mem; - - skb_reserve(kingsun->rx_buff.skb, 1); - kingsun->rx_buff.head = kingsun->rx_buff.skb->data; - - kingsun->rx_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!kingsun->rx_urb) - goto free_mem; - - kingsun->tx_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!kingsun->tx_urb) - goto free_mem; - - /* - * Now that everything should be initialized properly, - * Open new IrLAP layer instance to take care of us... - */ - sprintf(hwname, "usb#%d", kingsun->usbdev->devnum); - kingsun->irlap = irlap_open(netdev, &kingsun->qos, hwname); - if (!kingsun->irlap) { - dev_err(&kingsun->usbdev->dev, "irlap_open failed\n"); - goto free_mem; - } - - /* Start first reception */ - usb_fill_int_urb(kingsun->rx_urb, kingsun->usbdev, - usb_rcvintpipe(kingsun->usbdev, kingsun->ep_in), - kingsun->in_buf, kingsun->max_rx, - kingsun_rcv_irq, kingsun, 1); - kingsun->rx_urb->status = 0; - err = usb_submit_urb(kingsun->rx_urb, GFP_KERNEL); - if (err) { - dev_err(&kingsun->usbdev->dev, - "first urb-submit failed: %d\n", err); - goto close_irlap; - } - - netif_start_queue(netdev); - - /* Situation at this point: - - all work buffers allocated - - urbs allocated and ready to fill - - max rx packet known (in max_rx) - - unwrap state machine initialized, in state outside of any frame - - receive request in progress - - IrLAP layer started, about to hand over packets to send - */ - - return 0; - - close_irlap: - irlap_close(kingsun->irlap); - free_mem: - if (kingsun->tx_urb) { - usb_free_urb(kingsun->tx_urb); - kingsun->tx_urb = NULL; - } - if (kingsun->rx_urb) { - usb_free_urb(kingsun->rx_urb); - kingsun->rx_urb = NULL; - } - if (kingsun->rx_buff.skb) { - kfree_skb(kingsun->rx_buff.skb); - kingsun->rx_buff.skb = NULL; - kingsun->rx_buff.head = NULL; - } - return err; -} - -/* - * Function kingsun_net_close (kingsun) - * - * Network device is taken down. Usually this is done by - * "ifconfig irda0 down" - */ -static int kingsun_net_close(struct net_device *netdev) -{ - struct kingsun_cb *kingsun = netdev_priv(netdev); - - /* Stop transmit processing */ - netif_stop_queue(netdev); - - /* Mop up receive && transmit urb's */ - usb_kill_urb(kingsun->tx_urb); - usb_kill_urb(kingsun->rx_urb); - - usb_free_urb(kingsun->tx_urb); - usb_free_urb(kingsun->rx_urb); - - kingsun->tx_urb = NULL; - kingsun->rx_urb = NULL; - - kfree_skb(kingsun->rx_buff.skb); - kingsun->rx_buff.skb = NULL; - kingsun->rx_buff.head = NULL; - kingsun->rx_buff.in_frame = FALSE; - kingsun->rx_buff.state = OUTSIDE_FRAME; - kingsun->receiving = 0; - - /* Stop and remove instance of IrLAP */ - if (kingsun->irlap) - irlap_close(kingsun->irlap); - - kingsun->irlap = NULL; - - return 0; -} - -/* - * IOCTLs : Extra out-of-band network commands... - */ -static int kingsun_net_ioctl(struct net_device *netdev, struct ifreq *rq, - int cmd) -{ - struct if_irda_req *irq = (struct if_irda_req *) rq; - struct kingsun_cb *kingsun = netdev_priv(netdev); - int ret = 0; - - switch (cmd) { - case SIOCSBANDWIDTH: /* Set bandwidth */ - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - /* Check if the device is still there */ - if (netif_device_present(kingsun->netdev)) - /* No observed commands for speed change */ - ret = -EOPNOTSUPP; - break; - - case SIOCSMEDIABUSY: /* Set media busy */ - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - /* Check if the IrDA stack is still there */ - if (netif_running(kingsun->netdev)) - irda_device_set_media_busy(kingsun->netdev, TRUE); - break; - - case SIOCGRECEIVING: - /* Only approximately true */ - irq->ifr_receiving = kingsun->receiving; - break; - - default: - ret = -EOPNOTSUPP; - } - - return ret; -} - -static const struct net_device_ops kingsun_ops = { - .ndo_start_xmit = kingsun_hard_xmit, - .ndo_open = kingsun_net_open, - .ndo_stop = kingsun_net_close, - .ndo_do_ioctl = kingsun_net_ioctl, -}; - -/* - * This routine is called by the USB subsystem for each new device - * in the system. We need to check if the device is ours, and in - * this case start handling it. - */ -static int kingsun_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct usb_host_interface *interface; - struct usb_endpoint_descriptor *endpoint; - - struct usb_device *dev = interface_to_usbdev(intf); - struct kingsun_cb *kingsun = NULL; - struct net_device *net = NULL; - int ret = -ENOMEM; - int pipe, maxp_in, maxp_out; - __u8 ep_in; - __u8 ep_out; - - /* Check that there really are two interrupt endpoints. - Check based on the one in drivers/usb/input/usbmouse.c - */ - interface = intf->cur_altsetting; - if (interface->desc.bNumEndpoints != 2) { - dev_err(&intf->dev, - "kingsun-sir: expected 2 endpoints, found %d\n", - interface->desc.bNumEndpoints); - return -ENODEV; - } - endpoint = &interface->endpoint[KINGSUN_EP_IN].desc; - if (!usb_endpoint_is_int_in(endpoint)) { - dev_err(&intf->dev, - "kingsun-sir: endpoint 0 is not interrupt IN\n"); - return -ENODEV; - } - - ep_in = endpoint->bEndpointAddress; - pipe = usb_rcvintpipe(dev, ep_in); - maxp_in = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); - if (maxp_in > 255 || maxp_in <= 1) { - dev_err(&intf->dev, - "endpoint 0 has max packet size %d not in range\n", - maxp_in); - return -ENODEV; - } - - endpoint = &interface->endpoint[KINGSUN_EP_OUT].desc; - if (!usb_endpoint_is_int_out(endpoint)) { - dev_err(&intf->dev, - "kingsun-sir: endpoint 1 is not interrupt OUT\n"); - return -ENODEV; - } - - ep_out = endpoint->bEndpointAddress; - pipe = usb_sndintpipe(dev, ep_out); - maxp_out = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); - - /* Allocate network device container. */ - net = alloc_irdadev(sizeof(*kingsun)); - if(!net) - goto err_out1; - - SET_NETDEV_DEV(net, &intf->dev); - kingsun = netdev_priv(net); - kingsun->irlap = NULL; - kingsun->tx_urb = NULL; - kingsun->rx_urb = NULL; - kingsun->ep_in = ep_in; - kingsun->ep_out = ep_out; - kingsun->in_buf = NULL; - kingsun->out_buf = NULL; - kingsun->max_rx = (__u8)maxp_in; - kingsun->max_tx = (__u8)maxp_out; - kingsun->netdev = net; - kingsun->usbdev = dev; - kingsun->rx_buff.in_frame = FALSE; - kingsun->rx_buff.state = OUTSIDE_FRAME; - kingsun->rx_buff.skb = NULL; - kingsun->receiving = 0; - spin_lock_init(&kingsun->lock); - - /* Allocate input buffer */ - kingsun->in_buf = kmalloc(kingsun->max_rx, GFP_KERNEL); - if (!kingsun->in_buf) - goto free_mem; - - /* Allocate output buffer */ - kingsun->out_buf = kmalloc(KINGSUN_FIFO_SIZE, GFP_KERNEL); - if (!kingsun->out_buf) - goto free_mem; - - printk(KERN_INFO "KingSun/DonShine IRDA/USB found at address %d, " - "Vendor: %x, Product: %x\n", - dev->devnum, le16_to_cpu(dev->descriptor.idVendor), - le16_to_cpu(dev->descriptor.idProduct)); - - /* Initialize QoS for this device */ - irda_init_max_qos_capabilies(&kingsun->qos); - - /* That's the Rx capability. */ - kingsun->qos.baud_rate.bits &= IR_9600; - kingsun->qos.min_turn_time.bits &= KINGSUN_MTT; - irda_qos_bits_to_value(&kingsun->qos); - - /* Override the network functions we need to use */ - net->netdev_ops = &kingsun_ops; - - ret = register_netdev(net); - if (ret != 0) - goto free_mem; - - dev_info(&net->dev, "IrDA: Registered KingSun/DonShine device %s\n", - net->name); - - usb_set_intfdata(intf, kingsun); - - /* Situation at this point: - - all work buffers allocated - - urbs not allocated, set to NULL - - max rx packet known (in max_rx) - - unwrap state machine (partially) initialized, but skb == NULL - */ - - return 0; - -free_mem: - kfree(kingsun->out_buf); - kfree(kingsun->in_buf); - free_netdev(net); -err_out1: - return ret; -} - -/* - * The current device is removed, the USB layer tell us to shut it down... - */ -static void kingsun_disconnect(struct usb_interface *intf) -{ - struct kingsun_cb *kingsun = usb_get_intfdata(intf); - - if (!kingsun) - return; - - unregister_netdev(kingsun->netdev); - - /* Mop up receive && transmit urb's */ - if (kingsun->tx_urb != NULL) { - usb_kill_urb(kingsun->tx_urb); - usb_free_urb(kingsun->tx_urb); - kingsun->tx_urb = NULL; - } - if (kingsun->rx_urb != NULL) { - usb_kill_urb(kingsun->rx_urb); - usb_free_urb(kingsun->rx_urb); - kingsun->rx_urb = NULL; - } - - kfree(kingsun->out_buf); - kfree(kingsun->in_buf); - free_netdev(kingsun->netdev); - - usb_set_intfdata(intf, NULL); -} - -#ifdef CONFIG_PM -/* USB suspend, so power off the transmitter/receiver */ -static int kingsun_suspend(struct usb_interface *intf, pm_message_t message) -{ - struct kingsun_cb *kingsun = usb_get_intfdata(intf); - - netif_device_detach(kingsun->netdev); - if (kingsun->tx_urb != NULL) usb_kill_urb(kingsun->tx_urb); - if (kingsun->rx_urb != NULL) usb_kill_urb(kingsun->rx_urb); - return 0; -} - -/* Coming out of suspend, so reset hardware */ -static int kingsun_resume(struct usb_interface *intf) -{ - struct kingsun_cb *kingsun = usb_get_intfdata(intf); - - if (kingsun->rx_urb != NULL) - usb_submit_urb(kingsun->rx_urb, GFP_KERNEL); - netif_device_attach(kingsun->netdev); - - return 0; -} -#endif - -/* - * USB device callbacks - */ -static struct usb_driver irda_driver = { - .name = "kingsun-sir", - .probe = kingsun_probe, - .disconnect = kingsun_disconnect, - .id_table = dongles, -#ifdef CONFIG_PM - .suspend = kingsun_suspend, - .resume = kingsun_resume, -#endif -}; - -module_usb_driver(irda_driver); - -MODULE_AUTHOR("Alex VillacÃs Lasso <a_villacis@palosanto.com>"); -MODULE_DESCRIPTION("IrDA-USB Dongle Driver for KingSun/DonShine"); -MODULE_LICENSE("GPL"); diff --git a/drivers/net/irda/ks959-sir.c b/drivers/net/irda/ks959-sir.c deleted file mode 100644 index 8025741e7586..000000000000 --- a/drivers/net/irda/ks959-sir.c +++ /dev/null @@ -1,912 +0,0 @@ -/***************************************************************************** -* -* Filename: ks959-sir.c -* Version: 0.1.2 -* Description: Irda KingSun KS-959 USB Dongle -* Status: Experimental -* Author: Alex VillacÃs Lasso <a_villacis@palosanto.com> -* with help from Domen Puncer <domen@coderock.org> -* -* Based on stir4200, mcs7780, kingsun-sir drivers. -* -* 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. -* -* 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. -* -*****************************************************************************/ - -/* - * Following is my most current (2007-07-17) understanding of how the Kingsun - * KS-959 dongle is supposed to work. This information was deduced by - * reverse-engineering and examining the USB traffic captured with USBSnoopy - * from the WinXP driver. Feel free to update here as more of the dongle is - * known. - * - * My most sincere thanks must go to Domen Puncer <domen@coderock.org> for - * invaluable help in cracking the obfuscation and padding required for this - * dongle. - * - * General: This dongle exposes one interface with one interrupt IN endpoint. - * However, the interrupt endpoint is NOT used at all for this dongle. Instead, - * this dongle uses control transfers for everything, including sending and - * receiving the IrDA frame data. Apparently the interrupt endpoint is just a - * dummy to ensure the dongle has a valid interface to present to the PC.And I - * thought the DonShine dongle was weird... In addition, this dongle uses - * obfuscation (?!?!), applied at the USB level, to hide the traffic, both sent - * and received, from the dongle. I call it obfuscation because the XOR keying - * and padding required to produce an USB traffic acceptable for the dongle can - * not be explained by any other technical requirement. - * - * Transmission: To transmit an IrDA frame, the driver must prepare a control - * URB with the following as a setup packet: - * bRequestType USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE - * bRequest 0x09 - * wValue <length of valid data before padding, little endian> - * wIndex 0x0000 - * wLength <length of padded data> - * The payload packet must be manually wrapped and escaped (as in stir4200.c), - * then padded and obfuscated before being sent. Both padding and obfuscation - * are implemented in the procedure obfuscate_tx_buffer(). Suffice to say, the - * designer/programmer of the dongle used his name as a source for the - * obfuscation. WTF?! - * Apparently the dongle cannot handle payloads larger than 256 bytes. The - * driver has to perform fragmentation in order to send anything larger than - * this limit. - * - * Reception: To receive data, the driver must poll the dongle regularly (like - * kingsun-sir.c) with control URBs and the following as a setup packet: - * bRequestType USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE - * bRequest 0x01 - * wValue 0x0200 - * wIndex 0x0000 - * wLength 0x0800 (size of available buffer) - * If there is data to be read, it will be returned as the response payload. - * This data is (apparently) not padded, but it is obfuscated. To de-obfuscate - * it, the driver must XOR every byte, in sequence, with a value that starts at - * 1 and is incremented with each byte processed, and then with 0x55. The value - * incremented with each byte processed overflows as an unsigned char. The - * resulting bytes form a wrapped SIR frame that is unwrapped and unescaped - * as in stir4200.c The incremented value is NOT reset with each frame, but is - * kept across the entire session with the dongle. Also, the dongle inserts an - * extra garbage byte with value 0x95 (after decoding) every 0xff bytes, which - * must be skipped. - * - * Speed change: To change the speed of the dongle, the driver prepares a - * control URB with the following as a setup packet: - * bRequestType USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE - * bRequest 0x09 - * wValue 0x0200 - * wIndex 0x0001 - * wLength 0x0008 (length of the payload) - * The payload is a 8-byte record, apparently identical to the one used in - * drivers/usb/serial/cypress_m8.c to change speed: - * __u32 baudSpeed; - * unsigned int dataBits : 2; // 0 - 5 bits 3 - 8 bits - * unsigned int : 1; - * unsigned int stopBits : 1; - * unsigned int parityEnable : 1; - * unsigned int parityType : 1; - * unsigned int : 1; - * unsigned int reset : 1; - * unsigned char reserved[3]; // set to 0 - * - * For now only SIR speeds have been observed with this dongle. Therefore, - * nothing is known on what changes (if any) must be done to frame wrapping / - * unwrapping for higher than SIR speeds. This driver assumes no change is - * necessary and announces support for all the way to 57600 bps. Although the - * package announces support for up to 4MBps, tests with a Sony Ericcson K300 - * phone show corruption when receiving large frames at 115200 bps, the highest - * speed announced by the phone. However, transmission at 115200 bps is OK. Go - * figure. Since I don't know whether the phone or the dongle is at fault, max - * announced speed is 57600 bps until someone produces a device that can run - * at higher speeds with this dongle. - */ - -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/slab.h> -#include <linux/usb.h> -#include <linux/device.h> -#include <linux/crc32.h> - -#include <asm/unaligned.h> -#include <asm/byteorder.h> -#include <linux/uaccess.h> - -#include <net/irda/irda.h> -#include <net/irda/wrapper.h> -#include <net/irda/crc.h> - -#define KS959_VENDOR_ID 0x07d0 -#define KS959_PRODUCT_ID 0x4959 - -/* These are the currently known USB ids */ -static const struct usb_device_id dongles[] = { - /* KingSun Co,Ltd IrDA/USB Bridge */ - {USB_DEVICE(KS959_VENDOR_ID, KS959_PRODUCT_ID)}, - {} -}; - -MODULE_DEVICE_TABLE(usb, dongles); - -#define KINGSUN_MTT 0x07 -#define KINGSUN_REQ_RECV 0x01 -#define KINGSUN_REQ_SEND 0x09 - -#define KINGSUN_RCV_FIFO_SIZE 2048 /* Max length we can receive */ -#define KINGSUN_SND_FIFO_SIZE 2048 /* Max packet we can send */ -#define KINGSUN_SND_PACKET_SIZE 256 /* Max packet dongle can handle */ - -struct ks959_speedparams { - __le32 baudrate; /* baud rate, little endian */ - __u8 flags; - __u8 reserved[3]; -} __packed; - -#define KS_DATA_5_BITS 0x00 -#define KS_DATA_6_BITS 0x01 -#define KS_DATA_7_BITS 0x02 -#define KS_DATA_8_BITS 0x03 - -#define KS_STOP_BITS_1 0x00 -#define KS_STOP_BITS_2 0x08 - -#define KS_PAR_DISABLE 0x00 -#define KS_PAR_EVEN 0x10 -#define KS_PAR_ODD 0x30 -#define KS_RESET 0x80 - -struct ks959_cb { - struct usb_device *usbdev; /* init: probe_irda */ - struct net_device *netdev; /* network layer */ - struct irlap_cb *irlap; /* The link layer we are binded to */ - - struct qos_info qos; - - struct usb_ctrlrequest *tx_setuprequest; - struct urb *tx_urb; - __u8 *tx_buf_clear; - unsigned int tx_buf_clear_used; - unsigned int tx_buf_clear_sent; - __u8 *tx_buf_xored; - - struct usb_ctrlrequest *rx_setuprequest; - struct urb *rx_urb; - __u8 *rx_buf; - __u8 rx_variable_xormask; - iobuff_t rx_unwrap_buff; - - struct usb_ctrlrequest *speed_setuprequest; - struct urb *speed_urb; - struct ks959_speedparams speedparams; - unsigned int new_speed; - - spinlock_t lock; - int receiving; -}; - -/* Procedure to perform the obfuscation/padding expected by the dongle - * - * buf_cleartext (IN) Cleartext version of the IrDA frame to transmit - * len_cleartext (IN) Length of the cleartext version of IrDA frame - * buf_xoredtext (OUT) Obfuscated version of frame built by proc - * len_maxbuf (OUT) Maximum space available at buf_xoredtext - * - * (return) length of obfuscated frame with padding - * - * If not enough space (as indicated by len_maxbuf vs. required padding), - * zero is returned - * - * The value of lookup_string is actually a required portion of the algorithm. - * Seems the designer of the dongle wanted to state who exactly is responsible - * for implementing obfuscation. Send your best (or other) wishes to him ]:-) - */ -static unsigned int obfuscate_tx_buffer(const __u8 * buf_cleartext, - unsigned int len_cleartext, - __u8 * buf_xoredtext, - unsigned int len_maxbuf) -{ - unsigned int len_xoredtext; - - /* Calculate required length with padding, check for necessary space */ - len_xoredtext = ((len_cleartext + 7) & ~0x7) + 0x10; - if (len_xoredtext <= len_maxbuf) { - static const __u8 lookup_string[] = "wangshuofei19710"; - __u8 xor_mask; - - /* Unlike the WinXP driver, we *do* clear out the padding */ - memset(buf_xoredtext, 0, len_xoredtext); - - xor_mask = lookup_string[(len_cleartext & 0x0f) ^ 0x06] ^ 0x55; - - while (len_cleartext-- > 0) { - *buf_xoredtext++ = *buf_cleartext++ ^ xor_mask; - } - } else { - len_xoredtext = 0; - } - return len_xoredtext; -} - -/* Callback transmission routine */ -static void ks959_speed_irq(struct urb *urb) -{ - /* unlink, shutdown, unplug, other nasties */ - if (urb->status != 0) { - dev_err(&urb->dev->dev, - "ks959_speed_irq: urb asynchronously failed - %d\n", - urb->status); - } -} - -/* Send a control request to change speed of the dongle */ -static int ks959_change_speed(struct ks959_cb *kingsun, unsigned speed) -{ - static unsigned int supported_speeds[] = { 2400, 9600, 19200, 38400, - 57600, 115200, 576000, 1152000, 4000000, 0 - }; - int err; - unsigned int i; - - if (kingsun->speed_setuprequest == NULL || kingsun->speed_urb == NULL) - return -ENOMEM; - - /* Check that requested speed is among the supported ones */ - for (i = 0; supported_speeds[i] && supported_speeds[i] != speed; i++) ; - if (supported_speeds[i] == 0) - return -EOPNOTSUPP; - - memset(&(kingsun->speedparams), 0, sizeof(struct ks959_speedparams)); - kingsun->speedparams.baudrate = cpu_to_le32(speed); - kingsun->speedparams.flags = KS_DATA_8_BITS; - - /* speed_setuprequest pre-filled in ks959_probe */ - usb_fill_control_urb(kingsun->speed_urb, kingsun->usbdev, - usb_sndctrlpipe(kingsun->usbdev, 0), - (unsigned char *)kingsun->speed_setuprequest, - &(kingsun->speedparams), - sizeof(struct ks959_speedparams), ks959_speed_irq, - kingsun); - kingsun->speed_urb->status = 0; - err = usb_submit_urb(kingsun->speed_urb, GFP_ATOMIC); - - return err; -} - -/* Submit one fragment of an IrDA frame to the dongle */ -static void ks959_send_irq(struct urb *urb); -static int ks959_submit_tx_fragment(struct ks959_cb *kingsun) -{ - unsigned int padlen; - unsigned int wraplen; - int ret; - - /* Check whether current plaintext can produce a padded buffer that fits - within the range handled by the dongle */ - wraplen = (KINGSUN_SND_PACKET_SIZE & ~0x7) - 0x10; - if (wraplen > kingsun->tx_buf_clear_used) - wraplen = kingsun->tx_buf_clear_used; - - /* Perform dongle obfuscation. Also remove the portion of the frame that - was just obfuscated and will now be sent to the dongle. */ - padlen = obfuscate_tx_buffer(kingsun->tx_buf_clear, wraplen, - kingsun->tx_buf_xored, - KINGSUN_SND_PACKET_SIZE); - - /* Calculate how much data can be transmitted in this urb */ - kingsun->tx_setuprequest->wValue = cpu_to_le16(wraplen); - kingsun->tx_setuprequest->wLength = cpu_to_le16(padlen); - /* Rest of the fields were filled in ks959_probe */ - usb_fill_control_urb(kingsun->tx_urb, kingsun->usbdev, - usb_sndctrlpipe(kingsun->usbdev, 0), - (unsigned char *)kingsun->tx_setuprequest, - kingsun->tx_buf_xored, padlen, - ks959_send_irq, kingsun); - kingsun->tx_urb->status = 0; - ret = usb_submit_urb(kingsun->tx_urb, GFP_ATOMIC); - - /* Remember how much data was sent, in order to update at callback */ - kingsun->tx_buf_clear_sent = (ret == 0) ? wraplen : 0; - return ret; -} - -/* Callback transmission routine */ -static void ks959_send_irq(struct urb *urb) -{ - struct ks959_cb *kingsun = urb->context; - struct net_device *netdev = kingsun->netdev; - int ret = 0; - - /* in process of stopping, just drop data */ - if (!netif_running(kingsun->netdev)) { - dev_err(&kingsun->usbdev->dev, - "ks959_send_irq: Network not running!\n"); - return; - } - - /* unlink, shutdown, unplug, other nasties */ - if (urb->status != 0) { - dev_err(&kingsun->usbdev->dev, - "ks959_send_irq: urb asynchronously failed - %d\n", - urb->status); - return; - } - - if (kingsun->tx_buf_clear_used > 0) { - /* Update data remaining to be sent */ - if (kingsun->tx_buf_clear_sent < kingsun->tx_buf_clear_used) { - memmove(kingsun->tx_buf_clear, - kingsun->tx_buf_clear + - kingsun->tx_buf_clear_sent, - kingsun->tx_buf_clear_used - - kingsun->tx_buf_clear_sent); - } - kingsun->tx_buf_clear_used -= kingsun->tx_buf_clear_sent; - kingsun->tx_buf_clear_sent = 0; - - if (kingsun->tx_buf_clear_used > 0) { - /* There is more data to be sent */ - if ((ret = ks959_submit_tx_fragment(kingsun)) != 0) { - dev_err(&kingsun->usbdev->dev, - "ks959_send_irq: failed tx_urb submit: %d\n", - ret); - switch (ret) { - case -ENODEV: - case -EPIPE: - break; - default: - netdev->stats.tx_errors++; - netif_start_queue(netdev); - } - } - } else { - /* All data sent, send next speed && wake network queue */ - if (kingsun->new_speed != -1 && - cpu_to_le32(kingsun->new_speed) != - kingsun->speedparams.baudrate) - ks959_change_speed(kingsun, kingsun->new_speed); - - netif_wake_queue(netdev); - } - } -} - -/* - * Called from net/core when new frame is available. - */ -static netdev_tx_t ks959_hard_xmit(struct sk_buff *skb, - struct net_device *netdev) -{ - struct ks959_cb *kingsun; - unsigned int wraplen; - int ret = 0; - - netif_stop_queue(netdev); - - /* the IRDA wrapping routines don't deal with non linear skb */ - SKB_LINEAR_ASSERT(skb); - - kingsun = netdev_priv(netdev); - - spin_lock(&kingsun->lock); - kingsun->new_speed = irda_get_next_speed(skb); - - /* Append data to the end of whatever data remains to be transmitted */ - wraplen = - async_wrap_skb(skb, kingsun->tx_buf_clear, KINGSUN_SND_FIFO_SIZE); - kingsun->tx_buf_clear_used = wraplen; - - if ((ret = ks959_submit_tx_fragment(kingsun)) != 0) { - dev_err(&kingsun->usbdev->dev, - "ks959_hard_xmit: failed tx_urb submit: %d\n", ret); - switch (ret) { - case -ENODEV: - case -EPIPE: - break; - default: - netdev->stats.tx_errors++; - netif_start_queue(netdev); - } - } else { - netdev->stats.tx_packets++; - netdev->stats.tx_bytes += skb->len; - - } - - dev_kfree_skb(skb); - spin_unlock(&kingsun->lock); - - return NETDEV_TX_OK; -} - -/* Receive callback function */ -static void ks959_rcv_irq(struct urb *urb) -{ - struct ks959_cb *kingsun = urb->context; - int ret; - - /* in process of stopping, just drop data */ - if (!netif_running(kingsun->netdev)) { - kingsun->receiving = 0; - return; - } - - /* unlink, shutdown, unplug, other nasties */ - if (urb->status != 0) { - dev_err(&kingsun->usbdev->dev, - "kingsun_rcv_irq: urb asynchronously failed - %d\n", - urb->status); - kingsun->receiving = 0; - return; - } - - if (urb->actual_length > 0) { - __u8 *bytes = urb->transfer_buffer; - unsigned int i; - - for (i = 0; i < urb->actual_length; i++) { - /* De-obfuscation implemented here: variable portion of - xormask is incremented, and then used with the encoded - byte for the XOR. The result of the operation is used - to unwrap the SIR frame. */ - kingsun->rx_variable_xormask++; - bytes[i] = - bytes[i] ^ kingsun->rx_variable_xormask ^ 0x55u; - - /* rx_variable_xormask doubles as an index counter so we - can skip the byte at 0xff (wrapped around to 0). - */ - if (kingsun->rx_variable_xormask != 0) { - async_unwrap_char(kingsun->netdev, - &kingsun->netdev->stats, - &kingsun->rx_unwrap_buff, - bytes[i]); - } - } - kingsun->receiving = - (kingsun->rx_unwrap_buff.state != OUTSIDE_FRAME) ? 1 : 0; - } - - /* This urb has already been filled in kingsun_net_open. Setup - packet must be re-filled, but it is assumed that urb keeps the - pointer to the initial setup packet, as well as the payload buffer. - Setup packet is already pre-filled at ks959_probe. - */ - urb->status = 0; - ret = usb_submit_urb(urb, GFP_ATOMIC); -} - -/* - * Function kingsun_net_open (dev) - * - * Network device is taken up. Usually this is done by "ifconfig irda0 up" - */ -static int ks959_net_open(struct net_device *netdev) -{ - struct ks959_cb *kingsun = netdev_priv(netdev); - int err = -ENOMEM; - char hwname[16]; - - /* At this point, urbs are NULL, and skb is NULL (see kingsun_probe) */ - kingsun->receiving = 0; - - /* Initialize for SIR to copy data directly into skb. */ - kingsun->rx_unwrap_buff.in_frame = FALSE; - kingsun->rx_unwrap_buff.state = OUTSIDE_FRAME; - kingsun->rx_unwrap_buff.truesize = IRDA_SKB_MAX_MTU; - kingsun->rx_unwrap_buff.skb = dev_alloc_skb(IRDA_SKB_MAX_MTU); - if (!kingsun->rx_unwrap_buff.skb) - goto free_mem; - - skb_reserve(kingsun->rx_unwrap_buff.skb, 1); - kingsun->rx_unwrap_buff.head = kingsun->rx_unwrap_buff.skb->data; - - kingsun->rx_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!kingsun->rx_urb) - goto free_mem; - - kingsun->tx_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!kingsun->tx_urb) - goto free_mem; - - kingsun->speed_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!kingsun->speed_urb) - goto free_mem; - - /* Initialize speed for dongle */ - kingsun->new_speed = 9600; - err = ks959_change_speed(kingsun, 9600); - if (err < 0) - goto free_mem; - - /* - * Now that everything should be initialized properly, - * Open new IrLAP layer instance to take care of us... - */ - sprintf(hwname, "usb#%d", kingsun->usbdev->devnum); - kingsun->irlap = irlap_open(netdev, &kingsun->qos, hwname); - if (!kingsun->irlap) { - err = -ENOMEM; - dev_err(&kingsun->usbdev->dev, "irlap_open failed\n"); - goto free_mem; - } - - /* Start reception. Setup request already pre-filled in ks959_probe */ - usb_fill_control_urb(kingsun->rx_urb, kingsun->usbdev, - usb_rcvctrlpipe(kingsun->usbdev, 0), - (unsigned char *)kingsun->rx_setuprequest, - kingsun->rx_buf, KINGSUN_RCV_FIFO_SIZE, - ks959_rcv_irq, kingsun); - kingsun->rx_urb->status = 0; - err = usb_submit_urb(kingsun->rx_urb, GFP_KERNEL); - if (err) { - dev_err(&kingsun->usbdev->dev, - "first urb-submit failed: %d\n", err); - goto close_irlap; - } - - netif_start_queue(netdev); - - /* Situation at this point: - - all work buffers allocated - - urbs allocated and ready to fill - - max rx packet known (in max_rx) - - unwrap state machine initialized, in state outside of any frame - - receive request in progress - - IrLAP layer started, about to hand over packets to send - */ - - return 0; - - close_irlap: - irlap_close(kingsun->irlap); - free_mem: - usb_free_urb(kingsun->speed_urb); - kingsun->speed_urb = NULL; - usb_free_urb(kingsun->tx_urb); - kingsun->tx_urb = NULL; - usb_free_urb(kingsun->rx_urb); - kingsun->rx_urb = NULL; - if (kingsun->rx_unwrap_buff.skb) { - kfree_skb(kingsun->rx_unwrap_buff.skb); - kingsun->rx_unwrap_buff.skb = NULL; - kingsun->rx_unwrap_buff.head = NULL; - } - return err; -} - -/* - * Function kingsun_net_close (kingsun) - * - * Network device is taken down. Usually this is done by - * "ifconfig irda0 down" - */ -static int ks959_net_close(struct net_device *netdev) -{ - struct ks959_cb *kingsun = netdev_priv(netdev); - - /* Stop transmit processing */ - netif_stop_queue(netdev); - - /* Mop up receive && transmit urb's */ - usb_kill_urb(kingsun->tx_urb); - usb_free_urb(kingsun->tx_urb); - kingsun->tx_urb = NULL; - - usb_kill_urb(kingsun->speed_urb); - usb_free_urb(kingsun->speed_urb); - kingsun->speed_urb = NULL; - - usb_kill_urb(kingsun->rx_urb); - usb_free_urb(kingsun->rx_urb); - kingsun->rx_urb = NULL; - - kfree_skb(kingsun->rx_unwrap_buff.skb); - kingsun->rx_unwrap_buff.skb = NULL; - kingsun->rx_unwrap_buff.head = NULL; - kingsun->rx_unwrap_buff.in_frame = FALSE; - kingsun->rx_unwrap_buff.state = OUTSIDE_FRAME; - kingsun->receiving = 0; - - /* Stop and remove instance of IrLAP */ - if (kingsun->irlap) - irlap_close(kingsun->irlap); - - kingsun->irlap = NULL; - - return 0; -} - -/* - * IOCTLs : Extra out-of-band network commands... - */ -static int ks959_net_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) -{ - struct if_irda_req *irq = (struct if_irda_req *)rq; - struct ks959_cb *kingsun = netdev_priv(netdev); - int ret = 0; - - switch (cmd) { - case SIOCSBANDWIDTH: /* Set bandwidth */ - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - /* Check if the device is still there */ - if (netif_device_present(kingsun->netdev)) - return ks959_change_speed(kingsun, irq->ifr_baudrate); - break; - - case SIOCSMEDIABUSY: /* Set media busy */ - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - /* Check if the IrDA stack is still there */ - if (netif_running(kingsun->netdev)) - irda_device_set_media_busy(kingsun->netdev, TRUE); - break; - - case SIOCGRECEIVING: - /* Only approximately true */ - irq->ifr_receiving = kingsun->receiving; - break; - - default: - ret = -EOPNOTSUPP; - } - - return ret; -} - -static const struct net_device_ops ks959_ops = { - .ndo_start_xmit = ks959_hard_xmit, - .ndo_open = ks959_net_open, - .ndo_stop = ks959_net_close, - .ndo_do_ioctl = ks959_net_ioctl, -}; -/* - * This routine is called by the USB subsystem for each new device - * in the system. We need to check if the device is ours, and in - * this case start handling it. - */ -static int ks959_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct usb_device *dev = interface_to_usbdev(intf); - struct ks959_cb *kingsun = NULL; - struct net_device *net = NULL; - int ret = -ENOMEM; - - /* Allocate network device container. */ - net = alloc_irdadev(sizeof(*kingsun)); - if (!net) - goto err_out1; - - SET_NETDEV_DEV(net, &intf->dev); - kingsun = netdev_priv(net); - kingsun->netdev = net; - kingsun->usbdev = dev; - kingsun->irlap = NULL; - kingsun->tx_setuprequest = NULL; - kingsun->tx_urb = NULL; - kingsun->tx_buf_clear = NULL; - kingsun->tx_buf_xored = NULL; - kingsun->tx_buf_clear_used = 0; - kingsun->tx_buf_clear_sent = 0; - - kingsun->rx_setuprequest = NULL; - kingsun->rx_urb = NULL; - kingsun->rx_buf = NULL; - kingsun->rx_variable_xormask = 0; - kingsun->rx_unwrap_buff.in_frame = FALSE; - kingsun->rx_unwrap_buff.state = OUTSIDE_FRAME; - kingsun->rx_unwrap_buff.skb = NULL; - kingsun->receiving = 0; - spin_lock_init(&kingsun->lock); - - kingsun->speed_setuprequest = NULL; - kingsun->speed_urb = NULL; - kingsun->speedparams.baudrate = 0; - - /* Allocate input buffer */ - kingsun->rx_buf = kmalloc(KINGSUN_RCV_FIFO_SIZE, GFP_KERNEL); - if (!kingsun->rx_buf) - goto free_mem; - - /* Allocate input setup packet */ - kingsun->rx_setuprequest = - kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL); - if (!kingsun->rx_setuprequest) - goto free_mem; - kingsun->rx_setuprequest->bRequestType = - USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE; - kingsun->rx_setuprequest->bRequest = KINGSUN_REQ_RECV; - kingsun->rx_setuprequest->wValue = cpu_to_le16(0x0200); - kingsun->rx_setuprequest->wIndex = 0; - kingsun->rx_setuprequest->wLength = cpu_to_le16(KINGSUN_RCV_FIFO_SIZE); - - /* Allocate output buffer */ - kingsun->tx_buf_clear = kmalloc(KINGSUN_SND_FIFO_SIZE, GFP_KERNEL); - if (!kingsun->tx_buf_clear) - goto free_mem; - kingsun->tx_buf_xored = kmalloc(KINGSUN_SND_PACKET_SIZE, GFP_KERNEL); - if (!kingsun->tx_buf_xored) - goto free_mem; - - /* Allocate and initialize output setup packet */ - kingsun->tx_setuprequest = - kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL); - if (!kingsun->tx_setuprequest) - goto free_mem; - kingsun->tx_setuprequest->bRequestType = - USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE; - kingsun->tx_setuprequest->bRequest = KINGSUN_REQ_SEND; - kingsun->tx_setuprequest->wValue = 0; - kingsun->tx_setuprequest->wIndex = 0; - kingsun->tx_setuprequest->wLength = 0; - - /* Allocate and initialize speed setup packet */ - kingsun->speed_setuprequest = - kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL); - if (!kingsun->speed_setuprequest) - goto free_mem; - kingsun->speed_setuprequest->bRequestType = - USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE; - kingsun->speed_setuprequest->bRequest = KINGSUN_REQ_SEND; - kingsun->speed_setuprequest->wValue = cpu_to_le16(0x0200); - kingsun->speed_setuprequest->wIndex = cpu_to_le16(0x0001); - kingsun->speed_setuprequest->wLength = - cpu_to_le16(sizeof(struct ks959_speedparams)); - - printk(KERN_INFO "KingSun KS-959 IRDA/USB found at address %d, " - "Vendor: %x, Product: %x\n", - dev->devnum, le16_to_cpu(dev->descriptor.idVendor), - le16_to_cpu(dev->descriptor.idProduct)); - - /* Initialize QoS for this device */ - irda_init_max_qos_capabilies(&kingsun->qos); - - /* Baud rates known to be supported. Please uncomment if devices (other - than a SonyEriccson K300 phone) can be shown to support higher speed - with this dongle. - */ - kingsun->qos.baud_rate.bits = - IR_2400 | IR_9600 | IR_19200 | IR_38400 | IR_57600; - kingsun->qos.min_turn_time.bits &= KINGSUN_MTT; - irda_qos_bits_to_value(&kingsun->qos); - - /* Override the network functions we need to use */ - net->netdev_ops = &ks959_ops; - - ret = register_netdev(net); - if (ret != 0) - goto free_mem; - - dev_info(&net->dev, "IrDA: Registered KingSun KS-959 device %s\n", - net->name); - - usb_set_intfdata(intf, kingsun); - - /* Situation at this point: - - all work buffers allocated - - setup requests pre-filled - - urbs not allocated, set to NULL - - max rx packet known (is KINGSUN_FIFO_SIZE) - - unwrap state machine (partially) initialized, but skb == NULL - */ - - return 0; - - free_mem: - kfree(kingsun->speed_setuprequest); - kfree(kingsun->tx_setuprequest); - kfree(kingsun->tx_buf_xored); - kfree(kingsun->tx_buf_clear); - kfree(kingsun->rx_setuprequest); - kfree(kingsun->rx_buf); - free_netdev(net); - err_out1: - return ret; -} - -/* - * The current device is removed, the USB layer tell us to shut it down... - */ -static void ks959_disconnect(struct usb_interface *intf) -{ - struct ks959_cb *kingsun = usb_get_intfdata(intf); - - if (!kingsun) - return; - - unregister_netdev(kingsun->netdev); - - /* Mop up receive && transmit urb's */ - if (kingsun->speed_urb != NULL) { - usb_kill_urb(kingsun->speed_urb); - usb_free_urb(kingsun->speed_urb); - kingsun->speed_urb = NULL; - } - if (kingsun->tx_urb != NULL) { - usb_kill_urb(kingsun->tx_urb); - usb_free_urb(kingsun->tx_urb); - kingsun->tx_urb = NULL; - } - if (kingsun->rx_urb != NULL) { - usb_kill_urb(kingsun->rx_urb); - usb_free_urb(kingsun->rx_urb); - kingsun->rx_urb = NULL; - } - - kfree(kingsun->speed_setuprequest); - kfree(kingsun->tx_setuprequest); - kfree(kingsun->tx_buf_xored); - kfree(kingsun->tx_buf_clear); - kfree(kingsun->rx_setuprequest); - kfree(kingsun->rx_buf); - free_netdev(kingsun->netdev); - - usb_set_intfdata(intf, NULL); -} - -#ifdef CONFIG_PM -/* USB suspend, so power off the transmitter/receiver */ -static int ks959_suspend(struct usb_interface *intf, pm_message_t message) -{ - struct ks959_cb *kingsun = usb_get_intfdata(intf); - - netif_device_detach(kingsun->netdev); - if (kingsun->speed_urb != NULL) - usb_kill_urb(kingsun->speed_urb); - if (kingsun->tx_urb != NULL) - usb_kill_urb(kingsun->tx_urb); - if (kingsun->rx_urb != NULL) - usb_kill_urb(kingsun->rx_urb); - return 0; -} - -/* Coming out of suspend, so reset hardware */ -static int ks959_resume(struct usb_interface *intf) -{ - struct ks959_cb *kingsun = usb_get_intfdata(intf); - - if (kingsun->rx_urb != NULL) { - /* Setup request already filled in ks959_probe */ - usb_submit_urb(kingsun->rx_urb, GFP_KERNEL); - } - netif_device_attach(kingsun->netdev); - - return 0; -} -#endif - -/* - * USB device callbacks - */ -static struct usb_driver irda_driver = { - .name = "ks959-sir", - .probe = ks959_probe, - .disconnect = ks959_disconnect, - .id_table = dongles, -#ifdef CONFIG_PM - .suspend = ks959_suspend, - .resume = ks959_resume, -#endif -}; - -module_usb_driver(irda_driver); - -MODULE_AUTHOR("Alex VillacÃs Lasso <a_villacis@palosanto.com>"); -MODULE_DESCRIPTION("IrDA-USB Dongle Driver for KingSun KS-959"); -MODULE_LICENSE("GPL"); diff --git a/drivers/net/irda/ksdazzle-sir.c b/drivers/net/irda/ksdazzle-sir.c deleted file mode 100644 index d2a0755df596..000000000000 --- a/drivers/net/irda/ksdazzle-sir.c +++ /dev/null @@ -1,813 +0,0 @@ -/***************************************************************************** -* -* Filename: ksdazzle.c -* Version: 0.1.2 -* Description: Irda KingSun Dazzle USB Dongle -* Status: Experimental -* Author: Alex VillacÃs Lasso <a_villacis@palosanto.com> -* -* Based on stir4200, mcs7780, kingsun-sir drivers. -* -* 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. -* -* 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. -* -*****************************************************************************/ - -/* - * Following is my most current (2007-07-26) understanding of how the Kingsun - * 07D0:4100 dongle (sometimes known as the MA-660) is supposed to work. This - * information was deduced by examining the USB traffic captured with USBSnoopy - * from the WinXP driver. Feel free to update here as more of the dongle is - * known. - * - * General: This dongle exposes one interface with two interrupt endpoints, one - * IN and one OUT. In this regard, it is similar to what the Kingsun/Donshine - * dongle (07c0:4200) exposes. Traffic is raw and needs to be wrapped and - * unwrapped manually as in stir4200, kingsun-sir, and ks959-sir. - * - * Transmission: To transmit an IrDA frame, it is necessary to wrap it, then - * split it into multiple segments of up to 7 bytes each, and transmit each in - * sequence. It seems that sending a single big block (like kingsun-sir does) - * won't work with this dongle. Each segment needs to be prefixed with a value - * equal to (unsigned char)0xF8 + <number of bytes in segment>, inside a payload - * of exactly 8 bytes. For example, a segment of 1 byte gets prefixed by 0xF9, - * and one of 7 bytes gets prefixed by 0xFF. The bytes at the end of the - * payload, not considered by the prefix, are ignored (set to 0 by this - * implementation). - * - * Reception: To receive data, the driver must poll the dongle regularly (like - * kingsun-sir.c) with interrupt URBs. If data is available, it will be returned - * in payloads from 0 to 8 bytes long. When concatenated, these payloads form - * a raw IrDA stream that needs to be unwrapped as in stir4200 and kingsun-sir - * - * Speed change: To change the speed of the dongle, the driver prepares a - * control URB with the following as a setup packet: - * bRequestType USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE - * bRequest 0x09 - * wValue 0x0200 - * wIndex 0x0001 - * wLength 0x0008 (length of the payload) - * The payload is a 8-byte record, apparently identical to the one used in - * drivers/usb/serial/cypress_m8.c to change speed: - * __u32 baudSpeed; - * unsigned int dataBits : 2; // 0 - 5 bits 3 - 8 bits - * unsigned int : 1; - * unsigned int stopBits : 1; - * unsigned int parityEnable : 1; - * unsigned int parityType : 1; - * unsigned int : 1; - * unsigned int reset : 1; - * unsigned char reserved[3]; // set to 0 - * - * For now only SIR speeds have been observed with this dongle. Therefore, - * nothing is known on what changes (if any) must be done to frame wrapping / - * unwrapping for higher than SIR speeds. This driver assumes no change is - * necessary and announces support for all the way to 115200 bps. - */ - -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/slab.h> -#include <linux/usb.h> -#include <linux/device.h> -#include <linux/crc32.h> - -#include <asm/unaligned.h> -#include <asm/byteorder.h> -#include <linux/uaccess.h> - -#include <net/irda/irda.h> -#include <net/irda/wrapper.h> -#include <net/irda/crc.h> - -#define KSDAZZLE_VENDOR_ID 0x07d0 -#define KSDAZZLE_PRODUCT_ID 0x4100 - -/* These are the currently known USB ids */ -static const struct usb_device_id dongles[] = { - /* KingSun Co,Ltd IrDA/USB Bridge */ - {USB_DEVICE(KSDAZZLE_VENDOR_ID, KSDAZZLE_PRODUCT_ID)}, - {} -}; - -MODULE_DEVICE_TABLE(usb, dongles); - -#define KINGSUN_MTT 0x07 -#define KINGSUN_REQ_RECV 0x01 -#define KINGSUN_REQ_SEND 0x09 - -#define KINGSUN_SND_FIFO_SIZE 2048 /* Max packet we can send */ -#define KINGSUN_RCV_MAX 2048 /* Max transfer we can receive */ - -struct ksdazzle_speedparams { - __le32 baudrate; /* baud rate, little endian */ - __u8 flags; - __u8 reserved[3]; -} __packed; - -#define KS_DATA_5_BITS 0x00 -#define KS_DATA_6_BITS 0x01 -#define KS_DATA_7_BITS 0x02 -#define KS_DATA_8_BITS 0x03 - -#define KS_STOP_BITS_1 0x00 -#define KS_STOP_BITS_2 0x08 - -#define KS_PAR_DISABLE 0x00 -#define KS_PAR_EVEN 0x10 -#define KS_PAR_ODD 0x30 -#define KS_RESET 0x80 - -#define KINGSUN_EP_IN 0 -#define KINGSUN_EP_OUT 1 - -struct ksdazzle_cb { - struct usb_device *usbdev; /* init: probe_irda */ - struct net_device *netdev; /* network layer */ - struct irlap_cb *irlap; /* The link layer we are binded to */ - - struct qos_info qos; - - struct urb *tx_urb; - __u8 *tx_buf_clear; - unsigned int tx_buf_clear_used; - unsigned int tx_buf_clear_sent; - __u8 tx_payload[8]; - - struct urb *rx_urb; - __u8 *rx_buf; - iobuff_t rx_unwrap_buff; - - struct usb_ctrlrequest *speed_setuprequest; - struct urb *speed_urb; - struct ksdazzle_speedparams speedparams; - unsigned int new_speed; - - __u8 ep_in; - __u8 ep_out; - - spinlock_t lock; - int receiving; -}; - -/* Callback transmission routine */ -static void ksdazzle_speed_irq(struct urb *urb) -{ - /* unlink, shutdown, unplug, other nasties */ - if (urb->status != 0) - dev_err(&urb->dev->dev, - "ksdazzle_speed_irq: urb asynchronously failed - %d\n", - urb->status); -} - -/* Send a control request to change speed of the dongle */ -static int ksdazzle_change_speed(struct ksdazzle_cb *kingsun, unsigned speed) -{ - static unsigned int supported_speeds[] = { 2400, 9600, 19200, 38400, - 57600, 115200, 576000, 1152000, 4000000, 0 - }; - int err; - unsigned int i; - - if (kingsun->speed_setuprequest == NULL || kingsun->speed_urb == NULL) - return -ENOMEM; - - /* Check that requested speed is among the supported ones */ - for (i = 0; supported_speeds[i] && supported_speeds[i] != speed; i++) ; - if (supported_speeds[i] == 0) - return -EOPNOTSUPP; - - memset(&(kingsun->speedparams), 0, sizeof(struct ksdazzle_speedparams)); - kingsun->speedparams.baudrate = cpu_to_le32(speed); - kingsun->speedparams.flags = KS_DATA_8_BITS; - - /* speed_setuprequest pre-filled in ksdazzle_probe */ - usb_fill_control_urb(kingsun->speed_urb, kingsun->usbdev, - usb_sndctrlpipe(kingsun->usbdev, 0), - (unsigned char *)kingsun->speed_setuprequest, - &(kingsun->speedparams), - sizeof(struct ksdazzle_speedparams), - ksdazzle_speed_irq, kingsun); - kingsun->speed_urb->status = 0; - err = usb_submit_urb(kingsun->speed_urb, GFP_ATOMIC); - - return err; -} - -/* Submit one fragment of an IrDA frame to the dongle */ -static void ksdazzle_send_irq(struct urb *urb); -static int ksdazzle_submit_tx_fragment(struct ksdazzle_cb *kingsun) -{ - unsigned int wraplen; - int ret; - - /* We can send at most 7 bytes of payload at a time */ - wraplen = 7; - if (wraplen > kingsun->tx_buf_clear_used) - wraplen = kingsun->tx_buf_clear_used; - - /* Prepare payload prefix with used length */ - memset(kingsun->tx_payload, 0, 8); - kingsun->tx_payload[0] = (unsigned char)0xf8 + wraplen; - memcpy(kingsun->tx_payload + 1, kingsun->tx_buf_clear, wraplen); - - usb_fill_int_urb(kingsun->tx_urb, kingsun->usbdev, - usb_sndintpipe(kingsun->usbdev, kingsun->ep_out), - kingsun->tx_payload, 8, ksdazzle_send_irq, kingsun, 1); - kingsun->tx_urb->status = 0; - ret = usb_submit_urb(kingsun->tx_urb, GFP_ATOMIC); - - /* Remember how much data was sent, in order to update at callback */ - kingsun->tx_buf_clear_sent = (ret == 0) ? wraplen : 0; - return ret; -} - -/* Callback transmission routine */ -static void ksdazzle_send_irq(struct urb *urb) -{ - struct ksdazzle_cb *kingsun = urb->context; - struct net_device *netdev = kingsun->netdev; - int ret = 0; - - /* in process of stopping, just drop data */ - if (!netif_running(kingsun->netdev)) { - dev_err(&kingsun->usbdev->dev, - "ksdazzle_send_irq: Network not running!\n"); - return; - } - - /* unlink, shutdown, unplug, other nasties */ - if (urb->status != 0) { - dev_err(&kingsun->usbdev->dev, - "ksdazzle_send_irq: urb asynchronously failed - %d\n", - urb->status); - return; - } - - if (kingsun->tx_buf_clear_used > 0) { - /* Update data remaining to be sent */ - if (kingsun->tx_buf_clear_sent < kingsun->tx_buf_clear_used) { - memmove(kingsun->tx_buf_clear, - kingsun->tx_buf_clear + - kingsun->tx_buf_clear_sent, - kingsun->tx_buf_clear_used - - kingsun->tx_buf_clear_sent); - } - kingsun->tx_buf_clear_used -= kingsun->tx_buf_clear_sent; - kingsun->tx_buf_clear_sent = 0; - - if (kingsun->tx_buf_clear_used > 0) { - /* There is more data to be sent */ - if ((ret = ksdazzle_submit_tx_fragment(kingsun)) != 0) { - dev_err(&kingsun->usbdev->dev, - "ksdazzle_send_irq: failed tx_urb submit: %d\n", - ret); - switch (ret) { - case -ENODEV: - case -EPIPE: - break; - default: - netdev->stats.tx_errors++; - netif_start_queue(netdev); - } - } - } else { - /* All data sent, send next speed && wake network queue */ - if (kingsun->new_speed != -1 && - cpu_to_le32(kingsun->new_speed) != - kingsun->speedparams.baudrate) - ksdazzle_change_speed(kingsun, - kingsun->new_speed); - - netif_wake_queue(netdev); - } - } -} - -/* - * Called from net/core when new frame is available. - */ -static netdev_tx_t ksdazzle_hard_xmit(struct sk_buff *skb, - struct net_device *netdev) -{ - struct ksdazzle_cb *kingsun; - unsigned int wraplen; - int ret = 0; - - netif_stop_queue(netdev); - - /* the IRDA wrapping routines don't deal with non linear skb */ - SKB_LINEAR_ASSERT(skb); - - kingsun = netdev_priv(netdev); - - spin_lock(&kingsun->lock); - kingsun->new_speed = irda_get_next_speed(skb); - - /* Append data to the end of whatever data remains to be transmitted */ - wraplen = - async_wrap_skb(skb, kingsun->tx_buf_clear, KINGSUN_SND_FIFO_SIZE); - kingsun->tx_buf_clear_used = wraplen; - - if ((ret = ksdazzle_submit_tx_fragment(kingsun)) != 0) { - dev_err(&kingsun->usbdev->dev, - "ksdazzle_hard_xmit: failed tx_urb submit: %d\n", ret); - switch (ret) { - case -ENODEV: - case -EPIPE: - break; - default: - netdev->stats.tx_errors++; - netif_start_queue(netdev); - } - } else { - netdev->stats.tx_packets++; - netdev->stats.tx_bytes += skb->len; - - } - - dev_kfree_skb(skb); - spin_unlock(&kingsun->lock); - - return NETDEV_TX_OK; -} - -/* Receive callback function */ -static void ksdazzle_rcv_irq(struct urb *urb) -{ - struct ksdazzle_cb *kingsun = urb->context; - struct net_device *netdev = kingsun->netdev; - - /* in process of stopping, just drop data */ - if (!netif_running(netdev)) { - kingsun->receiving = 0; - return; - } - - /* unlink, shutdown, unplug, other nasties */ - if (urb->status != 0) { - dev_err(&kingsun->usbdev->dev, - "ksdazzle_rcv_irq: urb asynchronously failed - %d\n", - urb->status); - kingsun->receiving = 0; - return; - } - - if (urb->actual_length > 0) { - __u8 *bytes = urb->transfer_buffer; - unsigned int i; - - for (i = 0; i < urb->actual_length; i++) { - async_unwrap_char(netdev, &netdev->stats, - &kingsun->rx_unwrap_buff, bytes[i]); - } - kingsun->receiving = - (kingsun->rx_unwrap_buff.state != OUTSIDE_FRAME) ? 1 : 0; - } - - /* This urb has already been filled in ksdazzle_net_open. It is assumed that - urb keeps the pointer to the payload buffer. - */ - urb->status = 0; - usb_submit_urb(urb, GFP_ATOMIC); -} - -/* - * Function ksdazzle_net_open (dev) - * - * Network device is taken up. Usually this is done by "ifconfig irda0 up" - */ -static int ksdazzle_net_open(struct net_device *netdev) -{ - struct ksdazzle_cb *kingsun = netdev_priv(netdev); - int err = -ENOMEM; - char hwname[16]; - - /* At this point, urbs are NULL, and skb is NULL (see ksdazzle_probe) */ - kingsun->receiving = 0; - - /* Initialize for SIR to copy data directly into skb. */ - kingsun->rx_unwrap_buff.in_frame = FALSE; - kingsun->rx_unwrap_buff.state = OUTSIDE_FRAME; - kingsun->rx_unwrap_buff.truesize = IRDA_SKB_MAX_MTU; - kingsun->rx_unwrap_buff.skb = dev_alloc_skb(IRDA_SKB_MAX_MTU); - if (!kingsun->rx_unwrap_buff.skb) - goto free_mem; - - skb_reserve(kingsun->rx_unwrap_buff.skb, 1); - kingsun->rx_unwrap_buff.head = kingsun->rx_unwrap_buff.skb->data; - - kingsun->rx_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!kingsun->rx_urb) - goto free_mem; - - kingsun->tx_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!kingsun->tx_urb) - goto free_mem; - - kingsun->speed_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!kingsun->speed_urb) - goto free_mem; - - /* Initialize speed for dongle */ - kingsun->new_speed = 9600; - err = ksdazzle_change_speed(kingsun, 9600); - if (err < 0) - goto free_mem; - - /* - * Now that everything should be initialized properly, - * Open new IrLAP layer instance to take care of us... - */ - sprintf(hwname, "usb#%d", kingsun->usbdev->devnum); - kingsun->irlap = irlap_open(netdev, &kingsun->qos, hwname); - if (!kingsun->irlap) { - err = -ENOMEM; - dev_err(&kingsun->usbdev->dev, "irlap_open failed\n"); - goto free_mem; - } - - /* Start reception. */ - usb_fill_int_urb(kingsun->rx_urb, kingsun->usbdev, - usb_rcvintpipe(kingsun->usbdev, kingsun->ep_in), - kingsun->rx_buf, KINGSUN_RCV_MAX, ksdazzle_rcv_irq, - kingsun, 1); - kingsun->rx_urb->status = 0; - err = usb_submit_urb(kingsun->rx_urb, GFP_KERNEL); - if (err) { - dev_err(&kingsun->usbdev->dev, "first urb-submit failed: %d\n", err); - goto close_irlap; - } - - netif_start_queue(netdev); - - /* Situation at this point: - - all work buffers allocated - - urbs allocated and ready to fill - - max rx packet known (in max_rx) - - unwrap state machine initialized, in state outside of any frame - - receive request in progress - - IrLAP layer started, about to hand over packets to send - */ - - return 0; - - close_irlap: - irlap_close(kingsun->irlap); - free_mem: - usb_free_urb(kingsun->speed_urb); - kingsun->speed_urb = NULL; - usb_free_urb(kingsun->tx_urb); - kingsun->tx_urb = NULL; - usb_free_urb(kingsun->rx_urb); - kingsun->rx_urb = NULL; - if (kingsun->rx_unwrap_buff.skb) { - kfree_skb(kingsun->rx_unwrap_buff.skb); - kingsun->rx_unwrap_buff.skb = NULL; - kingsun->rx_unwrap_buff.head = NULL; - } - return err; -} - -/* - * Function ksdazzle_net_close (dev) - * - * Network device is taken down. Usually this is done by - * "ifconfig irda0 down" - */ -static int ksdazzle_net_close(struct net_device *netdev) -{ - struct ksdazzle_cb *kingsun = netdev_priv(netdev); - - /* Stop transmit processing */ - netif_stop_queue(netdev); - - /* Mop up receive && transmit urb's */ - usb_kill_urb(kingsun->tx_urb); - usb_free_urb(kingsun->tx_urb); - kingsun->tx_urb = NULL; - - usb_kill_urb(kingsun->speed_urb); - usb_free_urb(kingsun->speed_urb); - kingsun->speed_urb = NULL; - - usb_kill_urb(kingsun->rx_urb); - usb_free_urb(kingsun->rx_urb); - kingsun->rx_urb = NULL; - - kfree_skb(kingsun->rx_unwrap_buff.skb); - kingsun->rx_unwrap_buff.skb = NULL; - kingsun->rx_unwrap_buff.head = NULL; - kingsun->rx_unwrap_buff.in_frame = FALSE; - kingsun->rx_unwrap_buff.state = OUTSIDE_FRAME; - kingsun->receiving = 0; - - /* Stop and remove instance of IrLAP */ - irlap_close(kingsun->irlap); - - kingsun->irlap = NULL; - - return 0; -} - -/* - * IOCTLs : Extra out-of-band network commands... - */ -static int ksdazzle_net_ioctl(struct net_device *netdev, struct ifreq *rq, - int cmd) -{ - struct if_irda_req *irq = (struct if_irda_req *)rq; - struct ksdazzle_cb *kingsun = netdev_priv(netdev); - int ret = 0; - - switch (cmd) { - case SIOCSBANDWIDTH: /* Set bandwidth */ - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - /* Check if the device is still there */ - if (netif_device_present(kingsun->netdev)) - return ksdazzle_change_speed(kingsun, - irq->ifr_baudrate); - break; - - case SIOCSMEDIABUSY: /* Set media busy */ - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - /* Check if the IrDA stack is still there */ - if (netif_running(kingsun->netdev)) - irda_device_set_media_busy(kingsun->netdev, TRUE); - break; - - case SIOCGRECEIVING: - /* Only approximately true */ - irq->ifr_receiving = kingsun->receiving; - break; - - default: - ret = -EOPNOTSUPP; - } - - return ret; -} - -static const struct net_device_ops ksdazzle_ops = { - .ndo_start_xmit = ksdazzle_hard_xmit, - .ndo_open = ksdazzle_net_open, - .ndo_stop = ksdazzle_net_close, - .ndo_do_ioctl = ksdazzle_net_ioctl, -}; - -/* - * This routine is called by the USB subsystem for each new device - * in the system. We need to check if the device is ours, and in - * this case start handling it. - */ -static int ksdazzle_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct usb_host_interface *interface; - struct usb_endpoint_descriptor *endpoint; - - struct usb_device *dev = interface_to_usbdev(intf); - struct ksdazzle_cb *kingsun = NULL; - struct net_device *net = NULL; - int ret = -ENOMEM; - int pipe, maxp_in, maxp_out; - __u8 ep_in; - __u8 ep_out; - - /* Check that there really are two interrupt endpoints. Check based on the - one in drivers/usb/input/usbmouse.c - */ - interface = intf->cur_altsetting; - if (interface->desc.bNumEndpoints != 2) { - dev_err(&intf->dev, "ksdazzle: expected 2 endpoints, found %d\n", - interface->desc.bNumEndpoints); - return -ENODEV; - } - endpoint = &interface->endpoint[KINGSUN_EP_IN].desc; - if (!usb_endpoint_is_int_in(endpoint)) { - dev_err(&intf->dev, - "ksdazzle: endpoint 0 is not interrupt IN\n"); - return -ENODEV; - } - - ep_in = endpoint->bEndpointAddress; - pipe = usb_rcvintpipe(dev, ep_in); - maxp_in = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); - if (maxp_in > 255 || maxp_in <= 1) { - dev_err(&intf->dev, - "ksdazzle: endpoint 0 has max packet size %d not in range [2..255]\n", - maxp_in); - return -ENODEV; - } - - endpoint = &interface->endpoint[KINGSUN_EP_OUT].desc; - if (!usb_endpoint_is_int_out(endpoint)) { - dev_err(&intf->dev, - "ksdazzle: endpoint 1 is not interrupt OUT\n"); - return -ENODEV; - } - - ep_out = endpoint->bEndpointAddress; - pipe = usb_sndintpipe(dev, ep_out); - maxp_out = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); - - /* Allocate network device container. */ - net = alloc_irdadev(sizeof(*kingsun)); - if (!net) - goto err_out1; - - SET_NETDEV_DEV(net, &intf->dev); - kingsun = netdev_priv(net); - kingsun->netdev = net; - kingsun->usbdev = dev; - kingsun->ep_in = ep_in; - kingsun->ep_out = ep_out; - kingsun->irlap = NULL; - kingsun->tx_urb = NULL; - kingsun->tx_buf_clear = NULL; - kingsun->tx_buf_clear_used = 0; - kingsun->tx_buf_clear_sent = 0; - - kingsun->rx_urb = NULL; - kingsun->rx_buf = NULL; - kingsun->rx_unwrap_buff.in_frame = FALSE; - kingsun->rx_unwrap_buff.state = OUTSIDE_FRAME; - kingsun->rx_unwrap_buff.skb = NULL; - kingsun->receiving = 0; - spin_lock_init(&kingsun->lock); - - kingsun->speed_setuprequest = NULL; - kingsun->speed_urb = NULL; - kingsun->speedparams.baudrate = 0; - - /* Allocate input buffer */ - kingsun->rx_buf = kmalloc(KINGSUN_RCV_MAX, GFP_KERNEL); - if (!kingsun->rx_buf) - goto free_mem; - - /* Allocate output buffer */ - kingsun->tx_buf_clear = kmalloc(KINGSUN_SND_FIFO_SIZE, GFP_KERNEL); - if (!kingsun->tx_buf_clear) - goto free_mem; - - /* Allocate and initialize speed setup packet */ - kingsun->speed_setuprequest = - kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL); - if (!kingsun->speed_setuprequest) - goto free_mem; - kingsun->speed_setuprequest->bRequestType = - USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE; - kingsun->speed_setuprequest->bRequest = KINGSUN_REQ_SEND; - kingsun->speed_setuprequest->wValue = cpu_to_le16(0x0200); - kingsun->speed_setuprequest->wIndex = cpu_to_le16(0x0001); - kingsun->speed_setuprequest->wLength = - cpu_to_le16(sizeof(struct ksdazzle_speedparams)); - - printk(KERN_INFO "KingSun/Dazzle IRDA/USB found at address %d, " - "Vendor: %x, Product: %x\n", - dev->devnum, le16_to_cpu(dev->descriptor.idVendor), - le16_to_cpu(dev->descriptor.idProduct)); - - /* Initialize QoS for this device */ - irda_init_max_qos_capabilies(&kingsun->qos); - - /* Baud rates known to be supported. Please uncomment if devices (other - than a SonyEriccson K300 phone) can be shown to support higher speeds - with this dongle. - */ - kingsun->qos.baud_rate.bits = - IR_2400 | IR_9600 | IR_19200 | IR_38400 | IR_57600 | IR_115200; - kingsun->qos.min_turn_time.bits &= KINGSUN_MTT; - irda_qos_bits_to_value(&kingsun->qos); - - /* Override the network functions we need to use */ - net->netdev_ops = &ksdazzle_ops; - - ret = register_netdev(net); - if (ret != 0) - goto free_mem; - - dev_info(&net->dev, "IrDA: Registered KingSun/Dazzle device %s\n", - net->name); - - usb_set_intfdata(intf, kingsun); - - /* Situation at this point: - - all work buffers allocated - - setup requests pre-filled - - urbs not allocated, set to NULL - - max rx packet known (is KINGSUN_FIFO_SIZE) - - unwrap state machine (partially) initialized, but skb == NULL - */ - - return 0; - - free_mem: - kfree(kingsun->speed_setuprequest); - kfree(kingsun->tx_buf_clear); - kfree(kingsun->rx_buf); - free_netdev(net); - err_out1: - return ret; -} - -/* - * The current device is removed, the USB layer tell us to shut it down... - */ -static void ksdazzle_disconnect(struct usb_interface *intf) -{ - struct ksdazzle_cb *kingsun = usb_get_intfdata(intf); - - if (!kingsun) - return; - - unregister_netdev(kingsun->netdev); - - /* Mop up receive && transmit urb's */ - usb_kill_urb(kingsun->speed_urb); - usb_free_urb(kingsun->speed_urb); - kingsun->speed_urb = NULL; - - usb_kill_urb(kingsun->tx_urb); - usb_free_urb(kingsun->tx_urb); - kingsun->tx_urb = NULL; - - usb_kill_urb(kingsun->rx_urb); - usb_free_urb(kingsun->rx_urb); - kingsun->rx_urb = NULL; - - kfree(kingsun->speed_setuprequest); - kfree(kingsun->tx_buf_clear); - kfree(kingsun->rx_buf); - free_netdev(kingsun->netdev); - - usb_set_intfdata(intf, NULL); -} - -#ifdef CONFIG_PM -/* USB suspend, so power off the transmitter/receiver */ -static int ksdazzle_suspend(struct usb_interface *intf, pm_message_t message) -{ - struct ksdazzle_cb *kingsun = usb_get_intfdata(intf); - - netif_device_detach(kingsun->netdev); - if (kingsun->speed_urb != NULL) - usb_kill_urb(kingsun->speed_urb); - if (kingsun->tx_urb != NULL) - usb_kill_urb(kingsun->tx_urb); - if (kingsun->rx_urb != NULL) - usb_kill_urb(kingsun->rx_urb); - return 0; -} - -/* Coming out of suspend, so reset hardware */ -static int ksdazzle_resume(struct usb_interface *intf) -{ - struct ksdazzle_cb *kingsun = usb_get_intfdata(intf); - - if (kingsun->rx_urb != NULL) { - /* Setup request already filled in ksdazzle_probe */ - usb_submit_urb(kingsun->rx_urb, GFP_KERNEL); - } - netif_device_attach(kingsun->netdev); - - return 0; -} -#endif - -/* - * USB device callbacks - */ -static struct usb_driver irda_driver = { - .name = "ksdazzle-sir", - .probe = ksdazzle_probe, - .disconnect = ksdazzle_disconnect, - .id_table = dongles, -#ifdef CONFIG_PM - .suspend = ksdazzle_suspend, - .resume = ksdazzle_resume, -#endif -}; - -module_usb_driver(irda_driver); - -MODULE_AUTHOR("Alex VillacÃs Lasso <a_villacis@palosanto.com>"); -MODULE_DESCRIPTION("IrDA-USB Dongle Driver for KingSun Dazzle"); -MODULE_LICENSE("GPL"); diff --git a/drivers/net/irda/litelink-sir.c b/drivers/net/irda/litelink-sir.c deleted file mode 100644 index 8eefcb44bac3..000000000000 --- a/drivers/net/irda/litelink-sir.c +++ /dev/null @@ -1,199 +0,0 @@ -/********************************************************************* - * - * 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, see <http://www.gnu.org/licenses/>. - * - ********************************************************************/ - -/* - * 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; - - /* 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) -{ - /* 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; - - /* 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) -{ - /* 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); diff --git a/drivers/net/irda/ma600-sir.c b/drivers/net/irda/ma600-sir.c deleted file mode 100644 index a764817b47f1..000000000000 --- a/drivers/net/irda/ma600-sir.c +++ /dev/null @@ -1,253 +0,0 @@ -/********************************************************************* - * - * 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, see <http://www.gnu.org/licenses/>. - * - ********************************************************************/ - -#include <linux/module.h> -#include <linux/delay.h> -#include <linux/init.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) -{ - return irda_register_dongle(&ma600); -} - -static void __exit ma600_sir_cleanup(void) -{ - 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; - - 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) -{ - /* 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; - - pr_debug("%s(), speed=%d (was %d)\n", __func__, - 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)) { - net_warn_ratelimited("%s(): bad control byte read-back %02x != %02x\n", - __func__, (unsigned)byte, - (unsigned)get_control_byte(speed)); - return -1; - } - else - pr_debug("%s() control byte write read OK\n", __func__); -#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 - */ - -static int ma600_reset(struct sir_dev *dev) -{ - /* 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); - diff --git a/drivers/net/irda/mcp2120-sir.c b/drivers/net/irda/mcp2120-sir.c deleted file mode 100644 index 2e33f91bfe8f..000000000000 --- a/drivers/net/irda/mcp2120-sir.c +++ /dev/null @@ -1,224 +0,0 @@ -/********************************************************************* - * - * - * 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; - - /* 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) -{ - /* 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; - - 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: - net_err_ratelimited("%s(), undefine state %d\n", - __func__, 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; - - 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: - net_err_ratelimited("%s(), undefined state %d\n", - __func__, 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); diff --git a/drivers/net/irda/mcs7780.c b/drivers/net/irda/mcs7780.c deleted file mode 100644 index c3f0b254b344..000000000000 --- a/drivers/net/irda/mcs7780.c +++ /dev/null @@ -1,987 +0,0 @@ -/***************************************************************************** -* -* Filename: mcs7780.c -* Version: 0.4-alpha -* Description: Irda MosChip USB Dongle Driver -* Authors: Lukasz Stelmach <stlman@poczta.fm> -* Brian Pugh <bpugh@cs.pdx.edu> -* Judy Fischbach <jfisch@cs.pdx.edu> -* -* Based on stir4200 driver, but some things done differently. -* Based on earlier driver by Paul Stewart <stewart@parc.com> -* -* Copyright (C) 2000, Roman Weissgaerber <weissg@vienna.at> -* Copyright (C) 2001, Dag Brattli <dag@brattli.net> -* Copyright (C) 2001, Jean Tourrilhes <jt@hpl.hp.com> -* Copyright (C) 2004, Stephen Hemminger <shemminger@osdl.org> -* Copyright (C) 2005, Lukasz Stelmach <stlman@poczta.fm> -* Copyright (C) 2005, Brian Pugh <bpugh@cs.pdx.edu> -* Copyright (C) 2005, Judy Fischbach <jfisch@cs.pdx.edu> -* -* 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. -* -*****************************************************************************/ - -/* - * MCS7780 is a simple USB to IrDA bridge by MosChip. It is neither - * compatibile with irda-usb nor with stir4200. Although it is quite - * similar to the later as far as general idea of operation is concerned. - * That is it requires the software to do all the framing job at SIR speeds. - * The hardware does take care of the framing at MIR and FIR speeds. - * It supports all speeds from 2400 through 4Mbps - */ - -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/slab.h> -#include <linux/usb.h> -#include <linux/device.h> -#include <linux/crc32.h> - -#include <asm/unaligned.h> -#include <asm/byteorder.h> -#include <linux/uaccess.h> - -#include <net/irda/irda.h> -#include <net/irda/wrapper.h> -#include <net/irda/crc.h> - -#include "mcs7780.h" - -#define MCS_VENDOR_ID 0x9710 -#define MCS_PRODUCT_ID 0x7780 - -static const struct usb_device_id mcs_table[] = { - /* MosChip Corp., MCS7780 FIR-USB Adapter */ - {USB_DEVICE(MCS_VENDOR_ID, MCS_PRODUCT_ID)}, - {}, -}; - -MODULE_AUTHOR("Brian Pugh <bpugh@cs.pdx.edu>"); -MODULE_DESCRIPTION("IrDA-USB Dongle Driver for MosChip MCS7780"); -MODULE_VERSION("0.3alpha"); -MODULE_LICENSE("GPL"); - -MODULE_DEVICE_TABLE(usb, mcs_table); - -static int qos_mtt_bits = 0x07 /* > 1ms */ ; -module_param(qos_mtt_bits, int, 0); -MODULE_PARM_DESC(qos_mtt_bits, "Minimum Turn Time"); - -static int receive_mode = 0x1; -module_param(receive_mode, int, 0); -MODULE_PARM_DESC(receive_mode, - "Receive mode of the device (1:fast, 0:slow, default:1)"); - -static int sir_tweak = 1; -module_param(sir_tweak, int, 0444); -MODULE_PARM_DESC(sir_tweak, - "Default pulse width (1:1.6us, 0:3/16 bit, default:1)."); - -static int transceiver_type = MCS_TSC_VISHAY; -module_param(transceiver_type, int, 0444); -MODULE_PARM_DESC(transceiver_type, "IR transceiver type, see mcs7780.h."); - -static struct usb_driver mcs_driver = { - .name = "mcs7780", - .probe = mcs_probe, - .disconnect = mcs_disconnect, - .id_table = mcs_table, -}; - -/* speed flag selection by direct addressing. -addr = (speed >> 8) & 0x0f - -0x1 57600 0x2 115200 0x4 1152000 0x5 9600 -0x6 38400 0x9 2400 0xa 576000 0xb 19200 - -4Mbps (or 2400) must be checked separately. Since it also has -to be programmed in a different manner that is not a big problem. -*/ -static __u16 mcs_speed_set[16] = { 0, - MCS_SPEED_57600, - MCS_SPEED_115200, - 0, - MCS_SPEED_1152000, - MCS_SPEED_9600, - MCS_SPEED_38400, - 0, 0, - MCS_SPEED_2400, - MCS_SPEED_576000, - MCS_SPEED_19200, - 0, 0, 0, -}; - -/* Set given 16 bit register with a 16 bit value. Send control message - * to set dongle register. */ -static int mcs_set_reg(struct mcs_cb *mcs, __u16 reg, __u16 val) -{ - struct usb_device *dev = mcs->usbdev; - return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), MCS_WRREQ, - MCS_WR_RTYPE, val, reg, NULL, 0, - msecs_to_jiffies(MCS_CTRL_TIMEOUT)); -} - -/* Get 16 bit register value. Send contol message to read dongle register. */ -static int mcs_get_reg(struct mcs_cb *mcs, __u16 reg, __u16 * val) -{ - struct usb_device *dev = mcs->usbdev; - void *dmabuf; - int ret; - - dmabuf = kmalloc(sizeof(__u16), GFP_KERNEL); - if (!dmabuf) - return -ENOMEM; - - ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), MCS_RDREQ, - MCS_RD_RTYPE, 0, reg, dmabuf, 2, - msecs_to_jiffies(MCS_CTRL_TIMEOUT)); - - memcpy(val, dmabuf, sizeof(__u16)); - kfree(dmabuf); - - return ret; -} - -/* Setup a communication between mcs7780 and TFDU chips. It is described - * in more detail in the data sheet. The setup sequence puts the the - * vishay tranceiver into high speed mode. It will also receive SIR speed - * packets but at reduced sensitivity. - */ - -/* 0: OK 1:ERROR */ -static inline int mcs_setup_transceiver_vishay(struct mcs_cb *mcs) -{ - int ret = 0; - __u16 rval; - - /* mcs_get_reg should read exactly two bytes from the dongle */ - ret = mcs_get_reg(mcs, MCS_XCVR_REG, &rval); - if (unlikely(ret != 2)) { - ret = -EIO; - goto error; - } - - /* The MCS_XCVR_CONF bit puts the transceiver into configuration - * mode. The MCS_MODE0 bit must start out high (1) and then - * transition to low and the MCS_STFIR and MCS_MODE1 bits must - * be low. - */ - rval |= (MCS_MODE0 | MCS_XCVR_CONF); - rval &= ~MCS_STFIR; - rval &= ~MCS_MODE1; - ret = mcs_set_reg(mcs, MCS_XCVR_REG, rval); - if (unlikely(ret)) - goto error; - - rval &= ~MCS_MODE0; - ret = mcs_set_reg(mcs, MCS_XCVR_REG, rval); - if (unlikely(ret)) - goto error; - - rval &= ~MCS_XCVR_CONF; - ret = mcs_set_reg(mcs, MCS_XCVR_REG, rval); - if (unlikely(ret)) - goto error; - - ret = 0; -error: - return ret; -} - -/* Setup a communication between mcs7780 and agilent chip. */ -static inline int mcs_setup_transceiver_agilent(struct mcs_cb *mcs) -{ - net_warn_ratelimited("This transceiver type is not supported yet\n"); - return 1; -} - -/* Setup a communication between mcs7780 and sharp chip. */ -static inline int mcs_setup_transceiver_sharp(struct mcs_cb *mcs) -{ - net_warn_ratelimited("This transceiver type is not supported yet\n"); - return 1; -} - -/* Common setup for all transceivers */ -static inline int mcs_setup_transceiver(struct mcs_cb *mcs) -{ - int ret = 0; - __u16 rval; - const char *msg; - - msg = "Basic transceiver setup error"; - - /* read value of MODE Register, set the DRIVER and RESET bits - * and write value back out to MODE Register - */ - ret = mcs_get_reg(mcs, MCS_MODE_REG, &rval); - if(unlikely(ret != 2)) - goto error; - rval |= MCS_DRIVER; /* put the mcs7780 into configuration mode. */ - ret = mcs_set_reg(mcs, MCS_MODE_REG, rval); - if(unlikely(ret)) - goto error; - - rval = 0; /* set min pulse width to 0 initially. */ - ret = mcs_set_reg(mcs, MCS_MINRXPW_REG, rval); - if(unlikely(ret)) - goto error; - - ret = mcs_get_reg(mcs, MCS_MODE_REG, &rval); - if(unlikely(ret != 2)) - goto error; - - rval &= ~MCS_FIR; /* turn off fir mode. */ - if(mcs->sir_tweak) - rval |= MCS_SIR16US; /* 1.6us pulse width */ - else - rval &= ~MCS_SIR16US; /* 3/16 bit time pulse width */ - - /* make sure ask mode and back to back packets are off. */ - rval &= ~(MCS_BBTG | MCS_ASK); - - rval &= ~MCS_SPEED_MASK; - rval |= MCS_SPEED_9600; /* make sure initial speed is 9600. */ - mcs->speed = 9600; - mcs->new_speed = 0; /* new_speed is set to 0 */ - rval &= ~MCS_PLLPWDN; /* disable power down. */ - - /* make sure device determines direction and that the auto send sip - * pulse are on. - */ - rval |= MCS_DTD | MCS_SIPEN; - - ret = mcs_set_reg(mcs, MCS_MODE_REG, rval); - if(unlikely(ret)) - goto error; - - msg = "transceiver model specific setup error"; - switch (mcs->transceiver_type) { - case MCS_TSC_VISHAY: - ret = mcs_setup_transceiver_vishay(mcs); - break; - - case MCS_TSC_SHARP: - ret = mcs_setup_transceiver_sharp(mcs); - break; - - case MCS_TSC_AGILENT: - ret = mcs_setup_transceiver_agilent(mcs); - break; - - default: - net_warn_ratelimited("Unknown transceiver type: %d\n", - mcs->transceiver_type); - ret = 1; - } - if (unlikely(ret)) - goto error; - - /* If transceiver is not SHARP, then if receive mode set - * on the RXFAST bit in the XCVR Register otherwise unset it - */ - if (mcs->transceiver_type != MCS_TSC_SHARP) { - - ret = mcs_get_reg(mcs, MCS_XCVR_REG, &rval); - if (unlikely(ret != 2)) - goto error; - if (mcs->receive_mode) - rval |= MCS_RXFAST; - else - rval &= ~MCS_RXFAST; - ret = mcs_set_reg(mcs, MCS_XCVR_REG, rval); - if (unlikely(ret)) - goto error; - } - - msg = "transceiver reset"; - - ret = mcs_get_reg(mcs, MCS_MODE_REG, &rval); - if (unlikely(ret != 2)) - goto error; - - /* reset the mcs7780 so all changes take effect. */ - rval &= ~MCS_RESET; - ret = mcs_set_reg(mcs, MCS_MODE_REG, rval); - if (unlikely(ret)) - goto error; - else - return ret; - -error: - net_err_ratelimited("%s\n", msg); - return ret; -} - -/* Wraps the data in format for SIR */ -static inline int mcs_wrap_sir_skb(struct sk_buff *skb, __u8 * buf) -{ - int wraplen; - - /* 2: full frame length, including "the length" */ - wraplen = async_wrap_skb(skb, buf + 2, 4094); - - wraplen += 2; - buf[0] = wraplen & 0xff; - buf[1] = (wraplen >> 8) & 0xff; - - return wraplen; -} - -/* Wraps the data in format for FIR */ -static unsigned mcs_wrap_fir_skb(const struct sk_buff *skb, __u8 *buf) -{ - unsigned int len = 0; - __u32 fcs = ~(crc32_le(~0, skb->data, skb->len)); - - /* add 2 bytes for length value and 4 bytes for fcs. */ - len = skb->len + 6; - - /* The mcs7780 requires that the first two bytes are the packet - * length in little endian order. Note: the length value includes - * the two bytes for the length value itself. - */ - buf[0] = len & 0xff; - buf[1] = (len >> 8) & 0xff; - /* copy the data into the tx buffer. */ - skb_copy_from_linear_data(skb, buf + 2, skb->len); - /* put the fcs in the last four bytes in little endian order. */ - buf[len - 4] = fcs & 0xff; - buf[len - 3] = (fcs >> 8) & 0xff; - buf[len - 2] = (fcs >> 16) & 0xff; - buf[len - 1] = (fcs >> 24) & 0xff; - - return len; -} - -/* Wraps the data in format for MIR */ -static unsigned mcs_wrap_mir_skb(const struct sk_buff *skb, __u8 *buf) -{ - __u16 fcs = 0; - int len = skb->len + 4; - - fcs = ~(irda_calc_crc16(~fcs, skb->data, skb->len)); - /* put the total packet length in first. Note: packet length - * value includes the two bytes that hold the packet length - * itself. - */ - buf[0] = len & 0xff; - buf[1] = (len >> 8) & 0xff; - /* copy the data */ - skb_copy_from_linear_data(skb, buf + 2, skb->len); - /* put the fcs in last two bytes in little endian order. */ - buf[len - 2] = fcs & 0xff; - buf[len - 1] = (fcs >> 8) & 0xff; - - return len; -} - -/* Unwrap received packets at MIR speed. A 16 bit crc_ccitt checksum is - * used for the fcs. When performed over the entire packet the result - * should be GOOD_FCS = 0xf0b8. Hands the unwrapped data off to the IrDA - * layer via a sk_buff. - */ -static void mcs_unwrap_mir(struct mcs_cb *mcs, __u8 *buf, int len) -{ - __u16 fcs; - int new_len; - struct sk_buff *skb; - - /* Assume that the frames are going to fill a single packet - * rather than span multiple packets. - */ - - new_len = len - 2; - if(unlikely(new_len <= 0)) { - net_err_ratelimited("%s short frame length %d\n", - mcs->netdev->name, new_len); - ++mcs->netdev->stats.rx_errors; - ++mcs->netdev->stats.rx_length_errors; - return; - } - fcs = 0; - fcs = irda_calc_crc16(~fcs, buf, len); - - if(fcs != GOOD_FCS) { - net_err_ratelimited("crc error calc 0x%x len %d\n", - fcs, new_len); - mcs->netdev->stats.rx_errors++; - mcs->netdev->stats.rx_crc_errors++; - return; - } - - skb = dev_alloc_skb(new_len + 1); - if(unlikely(!skb)) { - ++mcs->netdev->stats.rx_dropped; - return; - } - - skb_reserve(skb, 1); - skb_copy_to_linear_data(skb, buf, new_len); - skb_put(skb, new_len); - skb_reset_mac_header(skb); - skb->protocol = htons(ETH_P_IRDA); - skb->dev = mcs->netdev; - - netif_rx(skb); - - mcs->netdev->stats.rx_packets++; - mcs->netdev->stats.rx_bytes += new_len; -} - -/* Unwrap received packets at FIR speed. A 32 bit crc_ccitt checksum is - * used for the fcs. Hands the unwrapped data off to the IrDA - * layer via a sk_buff. - */ -static void mcs_unwrap_fir(struct mcs_cb *mcs, __u8 *buf, int len) -{ - __u32 fcs; - int new_len; - struct sk_buff *skb; - - /* Assume that the frames are going to fill a single packet - * rather than span multiple packets. This is most likely a false - * assumption. - */ - - new_len = len - 4; - if(unlikely(new_len <= 0)) { - net_err_ratelimited("%s short frame length %d\n", - mcs->netdev->name, new_len); - ++mcs->netdev->stats.rx_errors; - ++mcs->netdev->stats.rx_length_errors; - return; - } - - fcs = ~(crc32_le(~0, buf, new_len)); - if(fcs != get_unaligned_le32(buf + new_len)) { - net_err_ratelimited("crc error calc 0x%x len %d\n", - fcs, new_len); - mcs->netdev->stats.rx_errors++; - mcs->netdev->stats.rx_crc_errors++; - return; - } - - skb = dev_alloc_skb(new_len + 1); - if(unlikely(!skb)) { - ++mcs->netdev->stats.rx_dropped; - return; - } - - skb_reserve(skb, 1); - skb_copy_to_linear_data(skb, buf, new_len); - skb_put(skb, new_len); - skb_reset_mac_header(skb); - skb->protocol = htons(ETH_P_IRDA); - skb->dev = mcs->netdev; - - netif_rx(skb); - - mcs->netdev->stats.rx_packets++; - mcs->netdev->stats.rx_bytes += new_len; -} - - -/* Allocates urbs for both receive and transmit. - * If alloc fails return error code 0 (fail) otherwise - * return error code 1 (success). - */ -static inline int mcs_setup_urbs(struct mcs_cb *mcs) -{ - mcs->rx_urb = NULL; - - mcs->tx_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!mcs->tx_urb) - return 0; - - mcs->rx_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!mcs->rx_urb) { - usb_free_urb(mcs->tx_urb); - mcs->tx_urb = NULL; - return 0; - } - - return 1; -} - -/* Sets up state to be initially outside frame, gets receive urb, - * sets status to successful and then submits the urb to start - * receiving the data. - */ -static inline int mcs_receive_start(struct mcs_cb *mcs) -{ - mcs->rx_buff.in_frame = FALSE; - mcs->rx_buff.state = OUTSIDE_FRAME; - - usb_fill_bulk_urb(mcs->rx_urb, mcs->usbdev, - usb_rcvbulkpipe(mcs->usbdev, mcs->ep_in), - mcs->in_buf, 4096, mcs_receive_irq, mcs); - - mcs->rx_urb->status = 0; - return usb_submit_urb(mcs->rx_urb, GFP_KERNEL); -} - -/* Finds the in and out endpoints for the mcs control block */ -static inline int mcs_find_endpoints(struct mcs_cb *mcs, - struct usb_host_endpoint *ep, int epnum) -{ - int i; - int ret = 0; - - /* If no place to store the endpoints just return */ - if (!ep) - return ret; - - /* cycle through all endpoints, find the first two that are DIR_IN */ - for (i = 0; i < epnum; i++) { - if (ep[i].desc.bEndpointAddress & USB_DIR_IN) - mcs->ep_in = ep[i].desc.bEndpointAddress; - else - mcs->ep_out = ep[i].desc.bEndpointAddress; - - /* MosChip says that the chip has only two bulk - * endpoints. Find one for each direction and move on. - */ - if ((mcs->ep_in != 0) && (mcs->ep_out != 0)) { - ret = 1; - break; - } - } - - return ret; -} - -static void mcs_speed_work(struct work_struct *work) -{ - struct mcs_cb *mcs = container_of(work, struct mcs_cb, work); - struct net_device *netdev = mcs->netdev; - - mcs_speed_change(mcs); - netif_wake_queue(netdev); -} - -/* Function to change the speed of the mcs7780. Fully supports SIR, - * MIR, and FIR speeds. - */ -static int mcs_speed_change(struct mcs_cb *mcs) -{ - int ret = 0; - int rst = 0; - int cnt = 0; - __u16 nspeed; - __u16 rval; - - nspeed = mcs_speed_set[(mcs->new_speed >> 8) & 0x0f]; - - do { - mcs_get_reg(mcs, MCS_RESV_REG, &rval); - } while(cnt++ < 100 && (rval & MCS_IRINTX)); - - if (cnt > 100) { - net_err_ratelimited("unable to change speed\n"); - ret = -EIO; - goto error; - } - - mcs_get_reg(mcs, MCS_MODE_REG, &rval); - - /* MINRXPW values recommended by MosChip */ - if (mcs->new_speed <= 115200) { - rval &= ~MCS_FIR; - - if ((rst = (mcs->speed > 115200))) - mcs_set_reg(mcs, MCS_MINRXPW_REG, 0); - - } else if (mcs->new_speed <= 1152000) { - rval &= ~MCS_FIR; - - if ((rst = !(mcs->speed == 576000 || mcs->speed == 1152000))) - mcs_set_reg(mcs, MCS_MINRXPW_REG, 5); - - } else { - rval |= MCS_FIR; - - if ((rst = (mcs->speed != 4000000))) - mcs_set_reg(mcs, MCS_MINRXPW_REG, 5); - - } - - rval &= ~MCS_SPEED_MASK; - rval |= nspeed; - - ret = mcs_set_reg(mcs, MCS_MODE_REG, rval); - if (unlikely(ret)) - goto error; - - if (rst) - switch (mcs->transceiver_type) { - case MCS_TSC_VISHAY: - ret = mcs_setup_transceiver_vishay(mcs); - break; - - case MCS_TSC_SHARP: - ret = mcs_setup_transceiver_sharp(mcs); - break; - - case MCS_TSC_AGILENT: - ret = mcs_setup_transceiver_agilent(mcs); - break; - - default: - ret = 1; - net_warn_ratelimited("Unknown transceiver type: %d\n", - mcs->transceiver_type); - } - if (unlikely(ret)) - goto error; - - mcs_get_reg(mcs, MCS_MODE_REG, &rval); - rval &= ~MCS_RESET; - ret = mcs_set_reg(mcs, MCS_MODE_REG, rval); - - mcs->speed = mcs->new_speed; -error: - mcs->new_speed = 0; - return ret; -} - -/* Ioctl calls not supported at this time. Can be an area of future work. */ -static int mcs_net_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) -{ - /* struct if_irda_req *irq = (struct if_irda_req *)rq; */ - /* struct mcs_cb *mcs = netdev_priv(netdev); */ - int ret = 0; - - switch (cmd) { - default: - ret = -EOPNOTSUPP; - } - - return ret; -} - -/* Network device is taken down, done by "ifconfig irda0 down" */ -static int mcs_net_close(struct net_device *netdev) -{ - int ret = 0; - struct mcs_cb *mcs = netdev_priv(netdev); - - /* Stop transmit processing */ - netif_stop_queue(netdev); - - kfree_skb(mcs->rx_buff.skb); - - /* kill and free the receive and transmit URBs */ - usb_kill_urb(mcs->rx_urb); - usb_free_urb(mcs->rx_urb); - usb_kill_urb(mcs->tx_urb); - usb_free_urb(mcs->tx_urb); - - /* Stop and remove instance of IrLAP */ - if (mcs->irlap) - irlap_close(mcs->irlap); - - mcs->irlap = NULL; - return ret; -} - -/* Network device is taken up, done by "ifconfig irda0 up" */ -static int mcs_net_open(struct net_device *netdev) -{ - struct mcs_cb *mcs = netdev_priv(netdev); - char hwname[16]; - int ret = 0; - - ret = usb_clear_halt(mcs->usbdev, - usb_sndbulkpipe(mcs->usbdev, mcs->ep_in)); - if (ret) - goto error1; - ret = usb_clear_halt(mcs->usbdev, - usb_rcvbulkpipe(mcs->usbdev, mcs->ep_out)); - if (ret) - goto error1; - - ret = mcs_setup_transceiver(mcs); - if (ret) - goto error1; - - ret = -ENOMEM; - - /* Initialize for SIR/FIR to copy data directly into skb. */ - mcs->receiving = 0; - mcs->rx_buff.truesize = IRDA_SKB_MAX_MTU; - mcs->rx_buff.skb = dev_alloc_skb(IRDA_SKB_MAX_MTU); - if (!mcs->rx_buff.skb) - goto error1; - - skb_reserve(mcs->rx_buff.skb, 1); - mcs->rx_buff.head = mcs->rx_buff.skb->data; - - /* - * Now that everything should be initialized properly, - * Open new IrLAP layer instance to take care of us... - * Note : will send immediately a speed change... - */ - sprintf(hwname, "usb#%d", mcs->usbdev->devnum); - mcs->irlap = irlap_open(netdev, &mcs->qos, hwname); - if (!mcs->irlap) { - net_err_ratelimited("mcs7780: irlap_open failed\n"); - goto error2; - } - - if (!mcs_setup_urbs(mcs)) - goto error3; - - ret = mcs_receive_start(mcs); - if (ret) - goto error4; - - netif_start_queue(netdev); - return 0; - -error4: - usb_free_urb(mcs->rx_urb); - usb_free_urb(mcs->tx_urb); -error3: - irlap_close(mcs->irlap); -error2: - kfree_skb(mcs->rx_buff.skb); -error1: - return ret; -} - -/* Receive callback function. */ -static void mcs_receive_irq(struct urb *urb) -{ - __u8 *bytes; - struct mcs_cb *mcs = urb->context; - int i; - int ret; - - if (!netif_running(mcs->netdev)) - return; - - if (urb->status) - return; - - if (urb->actual_length > 0) { - bytes = urb->transfer_buffer; - - /* MCS returns frames without BOF and EOF - * I assume it returns whole frames. - */ - /* SIR speed */ - if(mcs->speed < 576000) { - async_unwrap_char(mcs->netdev, &mcs->netdev->stats, - &mcs->rx_buff, 0xc0); - - for (i = 0; i < urb->actual_length; i++) - async_unwrap_char(mcs->netdev, &mcs->netdev->stats, - &mcs->rx_buff, bytes[i]); - - async_unwrap_char(mcs->netdev, &mcs->netdev->stats, - &mcs->rx_buff, 0xc1); - } - /* MIR speed */ - else if(mcs->speed == 576000 || mcs->speed == 1152000) { - mcs_unwrap_mir(mcs, urb->transfer_buffer, - urb->actual_length); - } - /* FIR speed */ - else { - mcs_unwrap_fir(mcs, urb->transfer_buffer, - urb->actual_length); - } - } - - ret = usb_submit_urb(urb, GFP_ATOMIC); -} - -/* Transmit callback function. */ -static void mcs_send_irq(struct urb *urb) -{ - struct mcs_cb *mcs = urb->context; - struct net_device *ndev = mcs->netdev; - - if (unlikely(mcs->new_speed)) - schedule_work(&mcs->work); - else - netif_wake_queue(ndev); -} - -/* Transmit callback function. */ -static netdev_tx_t mcs_hard_xmit(struct sk_buff *skb, - struct net_device *ndev) -{ - unsigned long flags; - struct mcs_cb *mcs; - int wraplen; - int ret = 0; - - netif_stop_queue(ndev); - mcs = netdev_priv(ndev); - - spin_lock_irqsave(&mcs->lock, flags); - - mcs->new_speed = irda_get_next_speed(skb); - if (likely(mcs->new_speed == mcs->speed)) - mcs->new_speed = 0; - - /* SIR speed */ - if(mcs->speed < 576000) { - wraplen = mcs_wrap_sir_skb(skb, mcs->out_buf); - } - /* MIR speed */ - else if(mcs->speed == 576000 || mcs->speed == 1152000) { - wraplen = mcs_wrap_mir_skb(skb, mcs->out_buf); - } - /* FIR speed */ - else { - wraplen = mcs_wrap_fir_skb(skb, mcs->out_buf); - } - usb_fill_bulk_urb(mcs->tx_urb, mcs->usbdev, - usb_sndbulkpipe(mcs->usbdev, mcs->ep_out), - mcs->out_buf, wraplen, mcs_send_irq, mcs); - - if ((ret = usb_submit_urb(mcs->tx_urb, GFP_ATOMIC))) { - net_err_ratelimited("failed tx_urb: %d\n", ret); - switch (ret) { - case -ENODEV: - case -EPIPE: - break; - default: - mcs->netdev->stats.tx_errors++; - netif_start_queue(ndev); - } - } else { - mcs->netdev->stats.tx_packets++; - mcs->netdev->stats.tx_bytes += skb->len; - } - - dev_kfree_skb(skb); - spin_unlock_irqrestore(&mcs->lock, flags); - return NETDEV_TX_OK; -} - -static const struct net_device_ops mcs_netdev_ops = { - .ndo_open = mcs_net_open, - .ndo_stop = mcs_net_close, - .ndo_start_xmit = mcs_hard_xmit, - .ndo_do_ioctl = mcs_net_ioctl, -}; - -/* - * This function is called by the USB subsystem for each new device in the - * system. Need to verify the device and if it is, then start handling it. - */ -static int mcs_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct usb_device *udev = interface_to_usbdev(intf); - struct net_device *ndev = NULL; - struct mcs_cb *mcs; - int ret = -ENOMEM; - - ndev = alloc_irdadev(sizeof(*mcs)); - if (!ndev) - goto error1; - - pr_debug("MCS7780 USB-IrDA bridge found at %d.\n", udev->devnum); - - SET_NETDEV_DEV(ndev, &intf->dev); - - ret = usb_reset_configuration(udev); - if (ret != 0) { - net_err_ratelimited("mcs7780: usb reset configuration failed\n"); - goto error2; - } - - mcs = netdev_priv(ndev); - mcs->usbdev = udev; - mcs->netdev = ndev; - spin_lock_init(&mcs->lock); - - /* Initialize QoS for this device */ - irda_init_max_qos_capabilies(&mcs->qos); - - /* That's the Rx capability. */ - mcs->qos.baud_rate.bits &= - IR_2400 | IR_9600 | IR_19200 | IR_38400 | IR_57600 | IR_115200 - | IR_576000 | IR_1152000 | (IR_4000000 << 8); - - - mcs->qos.min_turn_time.bits &= qos_mtt_bits; - irda_qos_bits_to_value(&mcs->qos); - - /* Speed change work initialisation*/ - INIT_WORK(&mcs->work, mcs_speed_work); - - ndev->netdev_ops = &mcs_netdev_ops; - - if (!intf->cur_altsetting) { - ret = -ENOMEM; - goto error2; - } - - ret = mcs_find_endpoints(mcs, intf->cur_altsetting->endpoint, - intf->cur_altsetting->desc.bNumEndpoints); - if (!ret) { - ret = -ENODEV; - goto error2; - } - - ret = register_netdev(ndev); - if (ret != 0) - goto error2; - - pr_debug("IrDA: Registered MosChip MCS7780 device as %s\n", - ndev->name); - - mcs->transceiver_type = transceiver_type; - mcs->sir_tweak = sir_tweak; - mcs->receive_mode = receive_mode; - - usb_set_intfdata(intf, mcs); - return 0; - -error2: - free_netdev(ndev); - -error1: - return ret; -} - -/* The current device is removed, the USB layer tells us to shut down. */ -static void mcs_disconnect(struct usb_interface *intf) -{ - struct mcs_cb *mcs = usb_get_intfdata(intf); - - if (!mcs) - return; - - cancel_work_sync(&mcs->work); - - unregister_netdev(mcs->netdev); - free_netdev(mcs->netdev); - - usb_set_intfdata(intf, NULL); - pr_debug("MCS7780 now disconnected.\n"); -} - -module_usb_driver(mcs_driver); diff --git a/drivers/net/irda/mcs7780.h b/drivers/net/irda/mcs7780.h deleted file mode 100644 index a6e8f7dbafc9..000000000000 --- a/drivers/net/irda/mcs7780.h +++ /dev/null @@ -1,165 +0,0 @@ -/***************************************************************************** -* -* Filename: mcs7780.h -* Version: 0.2-alpha -* Description: Irda MosChip USB Dongle -* Status: Experimental -* Authors: Lukasz Stelmach <stlman@poczta.fm> -* Brian Pugh <bpugh@cs.pdx.edu> -* -* Copyright (C) 2005, Lukasz Stelmach <stlman@poczta.fm> -* Copyright (C) 2005, Brian Pugh <bpugh@cs.pdx.edu> -* -* 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. -* -*****************************************************************************/ -#ifndef _MCS7780_H -#define _MCS7780_H - -#define MCS_MODE_SIR 0 -#define MCS_MODE_MIR 1 -#define MCS_MODE_FIR 2 - -#define MCS_CTRL_TIMEOUT 500 -#define MCS_XMIT_TIMEOUT 500 -/* Possible transceiver types */ -#define MCS_TSC_VISHAY 0 /* Vishay TFD, default choice */ -#define MCS_TSC_AGILENT 1 /* Agilent 3602/3600 */ -#define MCS_TSC_SHARP 2 /* Sharp GP2W1000YP */ - -/* Requests */ -#define MCS_RD_RTYPE 0xC0 -#define MCS_WR_RTYPE 0x40 -#define MCS_RDREQ 0x0F -#define MCS_WRREQ 0x0E - -/* Register 0x00 */ -#define MCS_MODE_REG 0 -#define MCS_FIR ((__u16)0x0001) -#define MCS_SIR16US ((__u16)0x0002) -#define MCS_BBTG ((__u16)0x0004) -#define MCS_ASK ((__u16)0x0008) -#define MCS_PARITY ((__u16)0x0010) - -/* SIR/MIR speed constants */ -#define MCS_SPEED_SHIFT 5 -#define MCS_SPEED_MASK ((__u16)0x00E0) -#define MCS_SPEED(x) ((x & MCS_SPEED_MASK) >> MCS_SPEED_SHIFT) -#define MCS_SPEED_2400 ((0 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK) -#define MCS_SPEED_9600 ((1 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK) -#define MCS_SPEED_19200 ((2 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK) -#define MCS_SPEED_38400 ((3 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK) -#define MCS_SPEED_57600 ((4 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK) -#define MCS_SPEED_115200 ((5 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK) -#define MCS_SPEED_576000 ((6 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK) -#define MCS_SPEED_1152000 ((7 << MCS_SPEED_SHIFT) & MCS_SPEED_MASK) - -#define MCS_PLLPWDN ((__u16)0x0100) -#define MCS_DRIVER ((__u16)0x0200) -#define MCS_DTD ((__u16)0x0400) -#define MCS_DIR ((__u16)0x0800) -#define MCS_SIPEN ((__u16)0x1000) -#define MCS_SENDSIP ((__u16)0x2000) -#define MCS_CHGDIR ((__u16)0x4000) -#define MCS_RESET ((__u16)0x8000) - -/* Register 0x02 */ -#define MCS_XCVR_REG 2 -#define MCS_MODE0 ((__u16)0x0001) -#define MCS_STFIR ((__u16)0x0002) -#define MCS_XCVR_CONF ((__u16)0x0004) -#define MCS_RXFAST ((__u16)0x0008) -/* TXCUR [6:4] */ -#define MCS_TXCUR_SHIFT 4 -#define MCS_TXCUR_MASK ((__u16)0x0070) -#define MCS_TXCUR(x) ((x & MCS_TXCUR_MASK) >> MCS_TXCUR_SHIFT) -#define MCS_SETTXCUR(x,y) \ - ((x & ~MCS_TXCUR_MASK) | (y << MCS_TXCUR_SHIFT) & MCS_TXCUR_MASK) - -#define MCS_MODE1 ((__u16)0x0080) -#define MCS_SMODE0 ((__u16)0x0100) -#define MCS_SMODE1 ((__u16)0x0200) -#define MCS_INVTX ((__u16)0x0400) -#define MCS_INVRX ((__u16)0x0800) - -#define MCS_MINRXPW_REG 4 - -#define MCS_RESV_REG 7 -#define MCS_IRINTX ((__u16)0x0001) -#define MCS_IRINRX ((__u16)0x0002) - -struct mcs_cb { - struct usb_device *usbdev; /* init: probe_irda */ - struct net_device *netdev; /* network layer */ - struct irlap_cb *irlap; /* The link layer we are binded to */ - struct qos_info qos; - unsigned int speed; /* Current speed */ - unsigned int new_speed; /* new speed */ - - struct work_struct work; /* Change speed work */ - - struct sk_buff *tx_pending; - char in_buf[4096]; /* transmit/receive buffer */ - char out_buf[4096]; /* transmit/receive buffer */ - __u8 *fifo_status; - - iobuff_t rx_buff; /* receive unwrap state machine */ - spinlock_t lock; - int receiving; - - __u8 ep_in; - __u8 ep_out; - - struct urb *rx_urb; - struct urb *tx_urb; - - int transceiver_type; - int sir_tweak; - int receive_mode; -}; - -static int mcs_set_reg(struct mcs_cb *mcs, __u16 reg, __u16 val); -static int mcs_get_reg(struct mcs_cb *mcs, __u16 reg, __u16 * val); - -static inline int mcs_setup_transceiver_vishay(struct mcs_cb *mcs); -static inline int mcs_setup_transceiver_agilent(struct mcs_cb *mcs); -static inline int mcs_setup_transceiver_sharp(struct mcs_cb *mcs); -static inline int mcs_setup_transceiver(struct mcs_cb *mcs); -static inline int mcs_wrap_sir_skb(struct sk_buff *skb, __u8 * buf); -static unsigned mcs_wrap_fir_skb(const struct sk_buff *skb, __u8 *buf); -static unsigned mcs_wrap_mir_skb(const struct sk_buff *skb, __u8 *buf); -static void mcs_unwrap_mir(struct mcs_cb *mcs, __u8 *buf, int len); -static void mcs_unwrap_fir(struct mcs_cb *mcs, __u8 *buf, int len); -static inline int mcs_setup_urbs(struct mcs_cb *mcs); -static inline int mcs_receive_start(struct mcs_cb *mcs); -static inline int mcs_find_endpoints(struct mcs_cb *mcs, - struct usb_host_endpoint *ep, int epnum); - -static int mcs_speed_change(struct mcs_cb *mcs); - -static int mcs_net_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd); -static int mcs_net_close(struct net_device *netdev); -static int mcs_net_open(struct net_device *netdev); - -static void mcs_receive_irq(struct urb *urb); -static void mcs_send_irq(struct urb *urb); -static netdev_tx_t mcs_hard_xmit(struct sk_buff *skb, - struct net_device *netdev); - -static int mcs_probe(struct usb_interface *intf, - const struct usb_device_id *id); -static void mcs_disconnect(struct usb_interface *intf); - -#endif /* _MCS7780_H */ diff --git a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c deleted file mode 100644 index 7beae147be11..000000000000 --- a/drivers/net/irda/nsc-ircc.c +++ /dev/null @@ -1,2410 +0,0 @@ -/********************************************************************* - * - * Filename: nsc-ircc.c - * Version: 1.0 - * Description: Driver for the NSC PC'108 and PC'338 IrDA chipsets - * Status: Stable. - * Author: Dag Brattli <dagb@cs.uit.no> - * Created at: Sat Nov 7 21:43:15 1998 - * Modified at: Wed Mar 1 11:29:34 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 - * Copyright (c) 2000-2004 Jean Tourrilhes <jt@hpl.hp.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ø admit liability nor - * provide warranty for any of this software. This material is - * provided "AS-IS" and at no charge. - * - * Notice that all functions that needs to access the chip in _any_ - * way, must save BSR register on entry, and restore it on exit. - * It is _very_ important to follow this policy! - * - * __u8 bank; - * - * bank = inb(iobase+BSR); - * - * do_your_stuff_here(); - * - * outb(bank, iobase+BSR); - * - * If you find bugs in this file, its very likely that the same bug - * will also be in w83977af_ir.c since the implementations are quite - * similar. - * - ********************************************************************/ - -#include <linux/module.h> -#include <linux/gfp.h> - -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/skbuff.h> -#include <linux/netdevice.h> -#include <linux/ioport.h> -#include <linux/delay.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/rtnetlink.h> -#include <linux/dma-mapping.h> -#include <linux/pnp.h> -#include <linux/platform_device.h> - -#include <asm/io.h> -#include <asm/dma.h> -#include <asm/byteorder.h> - -#include <net/irda/wrapper.h> -#include <net/irda/irda.h> -#include <net/irda/irda_device.h> - -#include "nsc-ircc.h" - -#define CHIP_IO_EXTENT 8 -#define BROKEN_DONGLE_ID - -static char *driver_name = "nsc-ircc"; - -/* Power Management */ -#define NSC_IRCC_DRIVER_NAME "nsc-ircc" -static int nsc_ircc_suspend(struct platform_device *dev, pm_message_t state); -static int nsc_ircc_resume(struct platform_device *dev); - -static struct platform_driver nsc_ircc_driver = { - .suspend = nsc_ircc_suspend, - .resume = nsc_ircc_resume, - .driver = { - .name = NSC_IRCC_DRIVER_NAME, - }, -}; - -/* Module parameters */ -static int qos_mtt_bits = 0x07; /* 1 ms or more */ -static int dongle_id; - -/* Use BIOS settions by default, but user may supply module parameters */ -static unsigned int io[] = { ~0, ~0, ~0, ~0, ~0 }; -static unsigned int irq[] = { 0, 0, 0, 0, 0 }; -static unsigned int dma[] = { 0, 0, 0, 0, 0 }; - -static int nsc_ircc_probe_108(nsc_chip_t *chip, chipio_t *info); -static int nsc_ircc_probe_338(nsc_chip_t *chip, chipio_t *info); -static int nsc_ircc_probe_39x(nsc_chip_t *chip, chipio_t *info); -static int nsc_ircc_init_108(nsc_chip_t *chip, chipio_t *info); -static int nsc_ircc_init_338(nsc_chip_t *chip, chipio_t *info); -static int nsc_ircc_init_39x(nsc_chip_t *chip, chipio_t *info); -#ifdef CONFIG_PNP -static int nsc_ircc_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *id); -#endif - -/* These are the known NSC chips */ -static nsc_chip_t chips[] = { -/* Name, {cfg registers}, chip id index reg, chip id expected value, revision mask */ - { "PC87108", { 0x150, 0x398, 0xea }, 0x05, 0x10, 0xf0, - nsc_ircc_probe_108, nsc_ircc_init_108 }, - { "PC87338", { 0x398, 0x15c, 0x2e }, 0x08, 0xb0, 0xf8, - nsc_ircc_probe_338, nsc_ircc_init_338 }, - /* Contributed by Steffen Pingel - IBM X40 */ - { "PC8738x", { 0x164e, 0x4e, 0x2e }, 0x20, 0xf4, 0xff, - nsc_ircc_probe_39x, nsc_ircc_init_39x }, - /* Contributed by Jan Frey - IBM A30/A31 */ - { "PC8739x", { 0x2e, 0x4e, 0x0 }, 0x20, 0xea, 0xff, - nsc_ircc_probe_39x, nsc_ircc_init_39x }, - /* IBM ThinkPads using PC8738x (T60/X60/Z60) */ - { "IBM-PC8738x", { 0x2e, 0x4e, 0x0 }, 0x20, 0xf4, 0xff, - nsc_ircc_probe_39x, nsc_ircc_init_39x }, - /* IBM ThinkPads using PC8394T (T43/R52/?) */ - { "IBM-PC8394T", { 0x2e, 0x4e, 0x0 }, 0x20, 0xf9, 0xff, - nsc_ircc_probe_39x, nsc_ircc_init_39x }, - { NULL } -}; - -static struct nsc_ircc_cb *dev_self[] = { NULL, NULL, NULL, NULL, NULL }; - -static char *dongle_types[] = { - "Differential serial interface", - "Differential serial interface", - "Reserved", - "Reserved", - "Sharp RY5HD01", - "Reserved", - "Single-ended serial interface", - "Consumer-IR only", - "HP HSDL-2300, HP HSDL-3600/HSDL-3610", - "IBM31T1100 or Temic TFDS6000/TFDS6500", - "Reserved", - "Reserved", - "HP HSDL-1100/HSDL-2100", - "HP HSDL-1100/HSDL-2100", - "Supports SIR Mode only", - "No dongle connected", -}; - -/* PNP probing */ -static chipio_t pnp_info; -static const struct pnp_device_id nsc_ircc_pnp_table[] = { - { .id = "NSC6001", .driver_data = 0 }, - { .id = "HWPC224", .driver_data = 0 }, - { .id = "IBM0071", .driver_data = NSC_FORCE_DONGLE_TYPE9 }, - { } -}; - -MODULE_DEVICE_TABLE(pnp, nsc_ircc_pnp_table); - -static struct pnp_driver nsc_ircc_pnp_driver = { -#ifdef CONFIG_PNP - .name = "nsc-ircc", - .id_table = nsc_ircc_pnp_table, - .probe = nsc_ircc_pnp_probe, -#endif -}; - -/* Some prototypes */ -static int nsc_ircc_open(chipio_t *info); -static int nsc_ircc_close(struct nsc_ircc_cb *self); -static int nsc_ircc_setup(chipio_t *info); -static void nsc_ircc_pio_receive(struct nsc_ircc_cb *self); -static int nsc_ircc_dma_receive(struct nsc_ircc_cb *self); -static int nsc_ircc_dma_receive_complete(struct nsc_ircc_cb *self, int iobase); -static netdev_tx_t nsc_ircc_hard_xmit_sir(struct sk_buff *skb, - struct net_device *dev); -static netdev_tx_t nsc_ircc_hard_xmit_fir(struct sk_buff *skb, - struct net_device *dev); -static int nsc_ircc_pio_write(int iobase, __u8 *buf, int len, int fifo_size); -static void nsc_ircc_dma_xmit(struct nsc_ircc_cb *self, int iobase); -static __u8 nsc_ircc_change_speed(struct nsc_ircc_cb *self, __u32 baud); -static int nsc_ircc_is_receiving(struct nsc_ircc_cb *self); -static int nsc_ircc_read_dongle_id (int iobase); -static void nsc_ircc_init_dongle_interface (int iobase, int dongle_id); - -static int nsc_ircc_net_open(struct net_device *dev); -static int nsc_ircc_net_close(struct net_device *dev); -static int nsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); - -/* Globals */ -static int pnp_registered; -static int pnp_succeeded; - -/* - * Function nsc_ircc_init () - * - * Initialize chip. Just try to find out how many chips we are dealing with - * and where they are - */ -static int __init nsc_ircc_init(void) -{ - chipio_t info; - nsc_chip_t *chip; - int ret; - int cfg_base; - int cfg, id; - int reg; - int i = 0; - - ret = platform_driver_register(&nsc_ircc_driver); - if (ret) { - net_err_ratelimited("%s, Can't register driver!\n", - driver_name); - return ret; - } - - /* Register with PnP subsystem to detect disable ports */ - ret = pnp_register_driver(&nsc_ircc_pnp_driver); - - if (!ret) - pnp_registered = 1; - - ret = -ENODEV; - - /* Probe for all the NSC chipsets we know about */ - for (chip = chips; chip->name ; chip++) { - pr_debug("%s(), Probing for %s ...\n", __func__, - chip->name); - - /* Try all config registers for this chip */ - for (cfg = 0; cfg < ARRAY_SIZE(chip->cfg); cfg++) { - cfg_base = chip->cfg[cfg]; - if (!cfg_base) - continue; - - /* Read index register */ - reg = inb(cfg_base); - if (reg == 0xff) { - pr_debug("%s() no chip at 0x%03x\n", - __func__, cfg_base); - continue; - } - - /* Read chip identification register */ - outb(chip->cid_index, cfg_base); - id = inb(cfg_base+1); - if ((id & chip->cid_mask) == chip->cid_value) { - pr_debug("%s() Found %s chip, revision=%d\n", - __func__, chip->name, - id & ~chip->cid_mask); - - /* - * If we found a correct PnP setting, - * we first try it. - */ - if (pnp_succeeded) { - memset(&info, 0, sizeof(chipio_t)); - info.cfg_base = cfg_base; - info.fir_base = pnp_info.fir_base; - info.dma = pnp_info.dma; - info.irq = pnp_info.irq; - - if (info.fir_base < 0x2000) { - net_info_ratelimited("%s, chip->init\n", - driver_name); - chip->init(chip, &info); - } else - chip->probe(chip, &info); - - if (nsc_ircc_open(&info) >= 0) - ret = 0; - } - - /* - * Opening based on PnP values failed. - * Let's fallback to user values, or probe - * the chip. - */ - if (ret) { - pr_debug("%s, PnP init failed\n", - driver_name); - memset(&info, 0, sizeof(chipio_t)); - info.cfg_base = cfg_base; - info.fir_base = io[i]; - info.dma = dma[i]; - info.irq = irq[i]; - - /* - * If the user supplies the base address, then - * we init the chip, if not we probe the values - * set by the BIOS - */ - if (io[i] < 0x2000) { - chip->init(chip, &info); - } else - chip->probe(chip, &info); - - if (nsc_ircc_open(&info) >= 0) - ret = 0; - } - i++; - } else { - pr_debug("%s(), Wrong chip id=0x%02x\n", - __func__, id); - } - } - } - - if (ret) { - platform_driver_unregister(&nsc_ircc_driver); - pnp_unregister_driver(&nsc_ircc_pnp_driver); - pnp_registered = 0; - } - - return ret; -} - -/* - * Function nsc_ircc_cleanup () - * - * Close all configured chips - * - */ -static void __exit nsc_ircc_cleanup(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(dev_self); i++) { - if (dev_self[i]) - nsc_ircc_close(dev_self[i]); - } - - platform_driver_unregister(&nsc_ircc_driver); - - if (pnp_registered) - pnp_unregister_driver(&nsc_ircc_pnp_driver); - - pnp_registered = 0; -} - -static const struct net_device_ops nsc_ircc_sir_ops = { - .ndo_open = nsc_ircc_net_open, - .ndo_stop = nsc_ircc_net_close, - .ndo_start_xmit = nsc_ircc_hard_xmit_sir, - .ndo_do_ioctl = nsc_ircc_net_ioctl, -}; - -static const struct net_device_ops nsc_ircc_fir_ops = { - .ndo_open = nsc_ircc_net_open, - .ndo_stop = nsc_ircc_net_close, - .ndo_start_xmit = nsc_ircc_hard_xmit_fir, - .ndo_do_ioctl = nsc_ircc_net_ioctl, -}; - -/* - * Function nsc_ircc_open (iobase, irq) - * - * Open driver instance - * - */ -static int __init nsc_ircc_open(chipio_t *info) -{ - struct net_device *dev; - struct nsc_ircc_cb *self; - void *ret; - int err, chip_index; - - for (chip_index = 0; chip_index < ARRAY_SIZE(dev_self); chip_index++) { - if (!dev_self[chip_index]) - break; - } - - if (chip_index == ARRAY_SIZE(dev_self)) { - net_err_ratelimited("%s(), maximum number of supported chips reached!\n", - __func__); - return -ENOMEM; - } - - net_info_ratelimited("%s, Found chip at base=0x%03x\n", - driver_name, info->cfg_base); - - if ((nsc_ircc_setup(info)) == -1) - return -1; - - net_info_ratelimited("%s, driver loaded (Dag Brattli)\n", driver_name); - - dev = alloc_irdadev(sizeof(struct nsc_ircc_cb)); - if (dev == NULL) { - net_err_ratelimited("%s(), can't allocate memory for control block!\n", - __func__); - return -ENOMEM; - } - - self = netdev_priv(dev); - self->netdev = dev; - spin_lock_init(&self->lock); - - /* Need to store self somewhere */ - dev_self[chip_index] = self; - self->index = chip_index; - - /* Initialize IO */ - self->io.cfg_base = info->cfg_base; - self->io.fir_base = info->fir_base; - self->io.irq = info->irq; - self->io.fir_ext = CHIP_IO_EXTENT; - self->io.dma = info->dma; - self->io.fifo_size = 32; - - /* Reserve the ioports that we need */ - ret = request_region(self->io.fir_base, self->io.fir_ext, driver_name); - if (!ret) { - net_warn_ratelimited("%s(), can't get iobase of 0x%03x\n", - __func__, self->io.fir_base); - err = -ENODEV; - goto out1; - } - - /* Initialize QoS for this device */ - irda_init_max_qos_capabilies(&self->qos); - - /* The only value we must override it the baudrate */ - self->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600| - IR_115200|IR_576000|IR_1152000 |(IR_4000000 << 8); - - self->qos.min_turn_time.bits = qos_mtt_bits; - irda_qos_bits_to_value(&self->qos); - - /* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */ - self->rx_buff.truesize = 14384; - self->tx_buff.truesize = 14384; - - /* Allocate memory if needed */ - self->rx_buff.head = - dma_zalloc_coherent(NULL, self->rx_buff.truesize, - &self->rx_buff_dma, GFP_KERNEL); - if (self->rx_buff.head == NULL) { - err = -ENOMEM; - goto out2; - - } - - self->tx_buff.head = - dma_zalloc_coherent(NULL, self->tx_buff.truesize, - &self->tx_buff_dma, GFP_KERNEL); - if (self->tx_buff.head == NULL) { - err = -ENOMEM; - goto out3; - } - - self->rx_buff.in_frame = FALSE; - self->rx_buff.state = OUTSIDE_FRAME; - self->tx_buff.data = self->tx_buff.head; - self->rx_buff.data = self->rx_buff.head; - - /* Reset Tx queue info */ - self->tx_fifo.len = self->tx_fifo.ptr = self->tx_fifo.free = 0; - self->tx_fifo.tail = self->tx_buff.head; - - /* Override the network functions we need to use */ - dev->netdev_ops = &nsc_ircc_sir_ops; - - err = register_netdev(dev); - if (err) { - net_err_ratelimited("%s(), register_netdev() failed!\n", - __func__); - goto out4; - } - net_info_ratelimited("IrDA: Registered device %s\n", dev->name); - - /* Check if user has supplied a valid dongle id or not */ - if ((dongle_id <= 0) || - (dongle_id >= ARRAY_SIZE(dongle_types))) { - dongle_id = nsc_ircc_read_dongle_id(self->io.fir_base); - - net_info_ratelimited("%s, Found dongle: %s\n", - driver_name, dongle_types[dongle_id]); - } else { - net_info_ratelimited("%s, Using dongle: %s\n", - driver_name, dongle_types[dongle_id]); - } - - self->io.dongle_id = dongle_id; - nsc_ircc_init_dongle_interface(self->io.fir_base, dongle_id); - - self->pldev = platform_device_register_simple(NSC_IRCC_DRIVER_NAME, - self->index, NULL, 0); - if (IS_ERR(self->pldev)) { - err = PTR_ERR(self->pldev); - goto out5; - } - platform_set_drvdata(self->pldev, self); - - return chip_index; - - out5: - unregister_netdev(dev); - out4: - dma_free_coherent(NULL, self->tx_buff.truesize, - self->tx_buff.head, self->tx_buff_dma); - out3: - dma_free_coherent(NULL, self->rx_buff.truesize, - self->rx_buff.head, self->rx_buff_dma); - out2: - release_region(self->io.fir_base, self->io.fir_ext); - out1: - free_netdev(dev); - dev_self[chip_index] = NULL; - return err; -} - -/* - * Function nsc_ircc_close (self) - * - * Close driver instance - * - */ -static int __exit nsc_ircc_close(struct nsc_ircc_cb *self) -{ - int iobase; - - IRDA_ASSERT(self != NULL, return -1;); - - iobase = self->io.fir_base; - - platform_device_unregister(self->pldev); - - /* Remove netdevice */ - unregister_netdev(self->netdev); - - /* Release the PORT that this driver is using */ - pr_debug("%s(), Releasing Region %03x\n", - __func__, self->io.fir_base); - release_region(self->io.fir_base, self->io.fir_ext); - - if (self->tx_buff.head) - dma_free_coherent(NULL, self->tx_buff.truesize, - self->tx_buff.head, self->tx_buff_dma); - - if (self->rx_buff.head) - dma_free_coherent(NULL, self->rx_buff.truesize, - self->rx_buff.head, self->rx_buff_dma); - - dev_self[self->index] = NULL; - free_netdev(self->netdev); - - return 0; -} - -/* - * Function nsc_ircc_init_108 (iobase, cfg_base, irq, dma) - * - * Initialize the NSC '108 chip - * - */ -static int nsc_ircc_init_108(nsc_chip_t *chip, chipio_t *info) -{ - int cfg_base = info->cfg_base; - __u8 temp=0; - - outb(2, cfg_base); /* Mode Control Register (MCTL) */ - outb(0x00, cfg_base+1); /* Disable device */ - - /* Base Address and Interrupt Control Register (BAIC) */ - outb(CFG_108_BAIC, cfg_base); - switch (info->fir_base) { - case 0x3e8: outb(0x14, cfg_base+1); break; - case 0x2e8: outb(0x15, cfg_base+1); break; - case 0x3f8: outb(0x16, cfg_base+1); break; - case 0x2f8: outb(0x17, cfg_base+1); break; - default: net_err_ratelimited("%s(), invalid base_address\n", __func__); - } - - /* Control Signal Routing Register (CSRT) */ - switch (info->irq) { - case 3: temp = 0x01; break; - case 4: temp = 0x02; break; - case 5: temp = 0x03; break; - case 7: temp = 0x04; break; - case 9: temp = 0x05; break; - case 11: temp = 0x06; break; - case 15: temp = 0x07; break; - default: net_err_ratelimited("%s(), invalid irq\n", __func__); - } - outb(CFG_108_CSRT, cfg_base); - - switch (info->dma) { - case 0: outb(0x08+temp, cfg_base+1); break; - case 1: outb(0x10+temp, cfg_base+1); break; - case 3: outb(0x18+temp, cfg_base+1); break; - default: net_err_ratelimited("%s(), invalid dma\n", __func__); - } - - outb(CFG_108_MCTL, cfg_base); /* Mode Control Register (MCTL) */ - outb(0x03, cfg_base+1); /* Enable device */ - - return 0; -} - -/* - * Function nsc_ircc_probe_108 (chip, info) - * - * - * - */ -static int nsc_ircc_probe_108(nsc_chip_t *chip, chipio_t *info) -{ - int cfg_base = info->cfg_base; - int reg; - - /* Read address and interrupt control register (BAIC) */ - outb(CFG_108_BAIC, cfg_base); - reg = inb(cfg_base+1); - - switch (reg & 0x03) { - case 0: - info->fir_base = 0x3e8; - break; - case 1: - info->fir_base = 0x2e8; - break; - case 2: - info->fir_base = 0x3f8; - break; - case 3: - info->fir_base = 0x2f8; - break; - } - info->sir_base = info->fir_base; - pr_debug("%s(), probing fir_base=0x%03x\n", __func__, - info->fir_base); - - /* Read control signals routing register (CSRT) */ - outb(CFG_108_CSRT, cfg_base); - reg = inb(cfg_base+1); - - switch (reg & 0x07) { - case 0: - info->irq = -1; - break; - case 1: - info->irq = 3; - break; - case 2: - info->irq = 4; - break; - case 3: - info->irq = 5; - break; - case 4: - info->irq = 7; - break; - case 5: - info->irq = 9; - break; - case 6: - info->irq = 11; - break; - case 7: - info->irq = 15; - break; - } - pr_debug("%s(), probing irq=%d\n", __func__, info->irq); - - /* Currently we only read Rx DMA but it will also be used for Tx */ - switch ((reg >> 3) & 0x03) { - case 0: - info->dma = -1; - break; - case 1: - info->dma = 0; - break; - case 2: - info->dma = 1; - break; - case 3: - info->dma = 3; - break; - } - pr_debug("%s(), probing dma=%d\n", __func__, info->dma); - - /* Read mode control register (MCTL) */ - outb(CFG_108_MCTL, cfg_base); - reg = inb(cfg_base+1); - - info->enabled = reg & 0x01; - info->suspended = !((reg >> 1) & 0x01); - - return 0; -} - -/* - * Function nsc_ircc_init_338 (chip, info) - * - * Initialize the NSC '338 chip. Remember that the 87338 needs two - * consecutive writes to the data registers while CPU interrupts are - * disabled. The 97338 does not require this, but shouldn't be any - * harm if we do it anyway. - */ -static int nsc_ircc_init_338(nsc_chip_t *chip, chipio_t *info) -{ - /* No init yet */ - - return 0; -} - -/* - * Function nsc_ircc_probe_338 (chip, info) - * - * - * - */ -static int nsc_ircc_probe_338(nsc_chip_t *chip, chipio_t *info) -{ - int cfg_base = info->cfg_base; - int reg, com = 0; - int pnp; - - /* Read function enable register (FER) */ - outb(CFG_338_FER, cfg_base); - reg = inb(cfg_base+1); - - info->enabled = (reg >> 2) & 0x01; - - /* Check if we are in Legacy or PnP mode */ - outb(CFG_338_PNP0, cfg_base); - reg = inb(cfg_base+1); - - pnp = (reg >> 3) & 0x01; - if (pnp) { - pr_debug("(), Chip is in PnP mode\n"); - outb(0x46, cfg_base); - reg = (inb(cfg_base+1) & 0xfe) << 2; - - outb(0x47, cfg_base); - reg |= ((inb(cfg_base+1) & 0xfc) << 8); - - info->fir_base = reg; - } else { - /* Read function address register (FAR) */ - outb(CFG_338_FAR, cfg_base); - reg = inb(cfg_base+1); - - switch ((reg >> 4) & 0x03) { - case 0: - info->fir_base = 0x3f8; - break; - case 1: - info->fir_base = 0x2f8; - break; - case 2: - com = 3; - break; - case 3: - com = 4; - break; - } - - if (com) { - switch ((reg >> 6) & 0x03) { - case 0: - if (com == 3) - info->fir_base = 0x3e8; - else - info->fir_base = 0x2e8; - break; - case 1: - if (com == 3) - info->fir_base = 0x338; - else - info->fir_base = 0x238; - break; - case 2: - if (com == 3) - info->fir_base = 0x2e8; - else - info->fir_base = 0x2e0; - break; - case 3: - if (com == 3) - info->fir_base = 0x220; - else - info->fir_base = 0x228; - break; - } - } - } - info->sir_base = info->fir_base; - - /* Read PnP register 1 (PNP1) */ - outb(CFG_338_PNP1, cfg_base); - reg = inb(cfg_base+1); - - info->irq = reg >> 4; - - /* Read PnP register 3 (PNP3) */ - outb(CFG_338_PNP3, cfg_base); - reg = inb(cfg_base+1); - - info->dma = (reg & 0x07) - 1; - - /* Read power and test register (PTR) */ - outb(CFG_338_PTR, cfg_base); - reg = inb(cfg_base+1); - - info->suspended = reg & 0x01; - - return 0; -} - - -/* - * Function nsc_ircc_init_39x (chip, info) - * - * Now that we know it's a '39x (see probe below), we need to - * configure it so we can use it. - * - * The NSC '338 chip is a Super I/O chip with a "bank" architecture, - * the configuration of the different functionality (serial, parallel, - * floppy...) are each in a different bank (Logical Device Number). - * The base address, irq and dma configuration registers are common - * to all functionalities (index 0x30 to 0x7F). - * There is only one configuration register specific to the - * serial port, CFG_39X_SPC. - * JeanII - * - * Note : this code was written by Jan Frey <janfrey@web.de> - */ -static int nsc_ircc_init_39x(nsc_chip_t *chip, chipio_t *info) -{ - int cfg_base = info->cfg_base; - int enabled; - - /* User is sure about his config... accept it. */ - pr_debug("%s(): nsc_ircc_init_39x (user settings): io=0x%04x, irq=%d, dma=%d\n", - __func__, info->fir_base, info->irq, info->dma); - - /* Access bank for SP2 */ - outb(CFG_39X_LDN, cfg_base); - outb(0x02, cfg_base+1); - - /* Configure SP2 */ - - /* We want to enable the device if not enabled */ - outb(CFG_39X_ACT, cfg_base); - enabled = inb(cfg_base+1) & 0x01; - - if (!enabled) { - /* Enable the device */ - outb(CFG_39X_SIOCF1, cfg_base); - outb(0x01, cfg_base+1); - /* May want to update info->enabled. Jean II */ - } - - /* Enable UART bank switching (bit 7) ; Sets the chip to normal - * power mode (wake up from sleep mode) (bit 1) */ - outb(CFG_39X_SPC, cfg_base); - outb(0x82, cfg_base+1); - - return 0; -} - -/* - * Function nsc_ircc_probe_39x (chip, info) - * - * Test if we really have a '39x chip at the given address - * - * Note : this code was written by Jan Frey <janfrey@web.de> - */ -static int nsc_ircc_probe_39x(nsc_chip_t *chip, chipio_t *info) -{ - int cfg_base = info->cfg_base; - int reg1, reg2, irq, irqt, dma1, dma2; - int enabled, susp; - - pr_debug("%s(), nsc_ircc_probe_39x, base=%d\n", - __func__, cfg_base); - - /* This function should be executed with irq off to avoid - * another driver messing with the Super I/O bank - Jean II */ - - /* Access bank for SP2 */ - outb(CFG_39X_LDN, cfg_base); - outb(0x02, cfg_base+1); - - /* Read infos about SP2 ; store in info struct */ - outb(CFG_39X_BASEH, cfg_base); - reg1 = inb(cfg_base+1); - outb(CFG_39X_BASEL, cfg_base); - reg2 = inb(cfg_base+1); - info->fir_base = (reg1 << 8) | reg2; - - outb(CFG_39X_IRQNUM, cfg_base); - irq = inb(cfg_base+1); - outb(CFG_39X_IRQSEL, cfg_base); - irqt = inb(cfg_base+1); - info->irq = irq; - - outb(CFG_39X_DMA0, cfg_base); - dma1 = inb(cfg_base+1); - outb(CFG_39X_DMA1, cfg_base); - dma2 = inb(cfg_base+1); - info->dma = dma1 -1; - - outb(CFG_39X_ACT, cfg_base); - info->enabled = enabled = inb(cfg_base+1) & 0x01; - - outb(CFG_39X_SPC, cfg_base); - susp = 1 - ((inb(cfg_base+1) & 0x02) >> 1); - - pr_debug("%s(): io=0x%02x%02x, irq=%d (type %d), rxdma=%d, txdma=%d, enabled=%d (suspended=%d)\n", - __func__, reg1, reg2, irq, irqt, dma1, dma2, enabled, susp); - - /* Configure SP2 */ - - /* We want to enable the device if not enabled */ - outb(CFG_39X_ACT, cfg_base); - enabled = inb(cfg_base+1) & 0x01; - - if (!enabled) { - /* Enable the device */ - outb(CFG_39X_SIOCF1, cfg_base); - outb(0x01, cfg_base+1); - /* May want to update info->enabled. Jean II */ - } - - /* Enable UART bank switching (bit 7) ; Sets the chip to normal - * power mode (wake up from sleep mode) (bit 1) */ - outb(CFG_39X_SPC, cfg_base); - outb(0x82, cfg_base+1); - - return 0; -} - -#ifdef CONFIG_PNP -/* PNP probing */ -static int nsc_ircc_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *id) -{ - memset(&pnp_info, 0, sizeof(chipio_t)); - pnp_info.irq = -1; - pnp_info.dma = -1; - pnp_succeeded = 1; - - if (id->driver_data & NSC_FORCE_DONGLE_TYPE9) - dongle_id = 0x9; - - /* There doesn't seem to be any way of getting the cfg_base. - * On my box, cfg_base is in the PnP descriptor of the - * motherboard. Oh well... Jean II */ - - if (pnp_port_valid(dev, 0) && - !(pnp_port_flags(dev, 0) & IORESOURCE_DISABLED)) - pnp_info.fir_base = pnp_port_start(dev, 0); - - if (pnp_irq_valid(dev, 0) && - !(pnp_irq_flags(dev, 0) & IORESOURCE_DISABLED)) - pnp_info.irq = pnp_irq(dev, 0); - - if (pnp_dma_valid(dev, 0) && - !(pnp_dma_flags(dev, 0) & IORESOURCE_DISABLED)) - pnp_info.dma = pnp_dma(dev, 0); - - pr_debug("%s() : From PnP, found firbase 0x%03X ; irq %d ; dma %d.\n", - __func__, pnp_info.fir_base, pnp_info.irq, pnp_info.dma); - - if((pnp_info.fir_base == 0) || - (pnp_info.irq == -1) || (pnp_info.dma == -1)) { - /* Returning an error will disable the device. Yuck ! */ - //return -EINVAL; - pnp_succeeded = 0; - } - - return 0; -} -#endif - -/* - * Function nsc_ircc_setup (info) - * - * Returns non-negative on success. - * - */ -static int nsc_ircc_setup(chipio_t *info) -{ - int version; - int iobase = info->fir_base; - - /* Read the Module ID */ - switch_bank(iobase, BANK3); - version = inb(iobase+MID); - - pr_debug("%s() Driver %s Found chip version %02x\n", - __func__, driver_name, version); - - /* Should be 0x2? */ - if (0x20 != (version & 0xf0)) { - net_err_ratelimited("%s, Wrong chip version %02x\n", - driver_name, version); - return -1; - } - - /* Switch to advanced mode */ - switch_bank(iobase, BANK2); - outb(ECR1_EXT_SL, iobase+ECR1); - switch_bank(iobase, BANK0); - - /* Set FIFO threshold to TX17, RX16, reset and enable FIFO's */ - switch_bank(iobase, BANK0); - outb(FCR_RXTH|FCR_TXTH|FCR_TXSR|FCR_RXSR|FCR_FIFO_EN, iobase+FCR); - - outb(0x03, iobase+LCR); /* 8 bit word length */ - outb(MCR_SIR, iobase+MCR); /* Start at SIR-mode, also clears LSR*/ - - /* Set FIFO size to 32 */ - switch_bank(iobase, BANK2); - outb(EXCR2_RFSIZ|EXCR2_TFSIZ, iobase+EXCR2); - - /* IRCR2: FEND_MD is not set */ - switch_bank(iobase, BANK5); - outb(0x02, iobase+4); - - /* Make sure that some defaults are OK */ - switch_bank(iobase, BANK6); - outb(0x20, iobase+0); /* Set 32 bits FIR CRC */ - outb(0x0a, iobase+1); /* Set MIR pulse width */ - outb(0x0d, iobase+2); /* Set SIR pulse width to 1.6us */ - outb(0x2a, iobase+4); /* Set beginning frag, and preamble length */ - - /* Enable receive interrupts */ - switch_bank(iobase, BANK0); - outb(IER_RXHDL_IE, iobase+IER); - - return 0; -} - -/* - * Function nsc_ircc_read_dongle_id (void) - * - * Try to read dongle identification. This procedure needs to be executed - * once after power-on/reset. It also needs to be used whenever you suspect - * that the user may have plugged/unplugged the IrDA Dongle. - */ -static int nsc_ircc_read_dongle_id (int iobase) -{ - int dongle_id; - __u8 bank; - - bank = inb(iobase+BSR); - - /* Select Bank 7 */ - switch_bank(iobase, BANK7); - - /* IRCFG4: IRSL0_DS and IRSL21_DS are cleared */ - outb(0x00, iobase+7); - - /* ID0, 1, and 2 are pulled up/down very slowly */ - udelay(50); - - /* IRCFG1: read the ID bits */ - dongle_id = inb(iobase+4) & 0x0f; - -#ifdef BROKEN_DONGLE_ID - if (dongle_id == 0x0a) - dongle_id = 0x09; -#endif - /* Go back to bank 0 before returning */ - switch_bank(iobase, BANK0); - - outb(bank, iobase+BSR); - - return dongle_id; -} - -/* - * Function nsc_ircc_init_dongle_interface (iobase, dongle_id) - * - * This function initializes the dongle for the transceiver that is - * used. This procedure needs to be executed once after - * power-on/reset. It also needs to be used whenever you suspect that - * the dongle is changed. - */ -static void nsc_ircc_init_dongle_interface (int iobase, int dongle_id) -{ - int bank; - - /* Save current bank */ - bank = inb(iobase+BSR); - - /* Select Bank 7 */ - switch_bank(iobase, BANK7); - - /* IRCFG4: set according to dongle_id */ - switch (dongle_id) { - case 0x00: /* same as */ - case 0x01: /* Differential serial interface */ - pr_debug("%s(), %s not defined by irda yet\n", - __func__, dongle_types[dongle_id]); - break; - case 0x02: /* same as */ - case 0x03: /* Reserved */ - pr_debug("%s(), %s not defined by irda yet\n", - __func__, dongle_types[dongle_id]); - break; - case 0x04: /* Sharp RY5HD01 */ - break; - case 0x05: /* Reserved, but this is what the Thinkpad reports */ - pr_debug("%s(), %s not defined by irda yet\n", - __func__, dongle_types[dongle_id]); - break; - case 0x06: /* Single-ended serial interface */ - pr_debug("%s(), %s not defined by irda yet\n", - __func__, dongle_types[dongle_id]); - break; - case 0x07: /* Consumer-IR only */ - pr_debug("%s(), %s is not for IrDA mode\n", - __func__, dongle_types[dongle_id]); - break; - case 0x08: /* HP HSDL-2300, HP HSDL-3600/HSDL-3610 */ - pr_debug("%s(), %s\n", - __func__, dongle_types[dongle_id]); - break; - case 0x09: /* IBM31T1100 or Temic TFDS6000/TFDS6500 */ - outb(0x28, iobase+7); /* Set irsl[0-2] as output */ - break; - case 0x0A: /* same as */ - case 0x0B: /* Reserved */ - pr_debug("%s(), %s not defined by irda yet\n", - __func__, dongle_types[dongle_id]); - break; - case 0x0C: /* same as */ - case 0x0D: /* HP HSDL-1100/HSDL-2100 */ - /* - * Set irsl0 as input, irsl[1-2] as output, and separate - * inputs are used for SIR and MIR/FIR - */ - outb(0x48, iobase+7); - break; - case 0x0E: /* Supports SIR Mode only */ - outb(0x28, iobase+7); /* Set irsl[0-2] as output */ - break; - case 0x0F: /* No dongle connected */ - pr_debug("%s(), %s\n", - __func__, dongle_types[dongle_id]); - - switch_bank(iobase, BANK0); - outb(0x62, iobase+MCR); - break; - default: - pr_debug("%s(), invalid dongle_id %#x", - __func__, dongle_id); - } - - /* IRCFG1: IRSL1 and 2 are set to IrDA mode */ - outb(0x00, iobase+4); - - /* Restore bank register */ - outb(bank, iobase+BSR); - -} /* set_up_dongle_interface */ - -/* - * Function nsc_ircc_change_dongle_speed (iobase, speed, dongle_id) - * - * Change speed of the attach dongle - * - */ -static void nsc_ircc_change_dongle_speed(int iobase, int speed, int dongle_id) -{ - __u8 bank; - - /* Save current bank */ - bank = inb(iobase+BSR); - - /* Select Bank 7 */ - switch_bank(iobase, BANK7); - - /* IRCFG1: set according to dongle_id */ - switch (dongle_id) { - case 0x00: /* same as */ - case 0x01: /* Differential serial interface */ - pr_debug("%s(), %s not defined by irda yet\n", - __func__, dongle_types[dongle_id]); - break; - case 0x02: /* same as */ - case 0x03: /* Reserved */ - pr_debug("%s(), %s not defined by irda yet\n", - __func__, dongle_types[dongle_id]); - break; - case 0x04: /* Sharp RY5HD01 */ - break; - case 0x05: /* Reserved */ - pr_debug("%s(), %s not defined by irda yet\n", - __func__, dongle_types[dongle_id]); - break; - case 0x06: /* Single-ended serial interface */ - pr_debug("%s(), %s not defined by irda yet\n", - __func__, dongle_types[dongle_id]); - break; - case 0x07: /* Consumer-IR only */ - pr_debug("%s(), %s is not for IrDA mode\n", - __func__, dongle_types[dongle_id]); - break; - case 0x08: /* HP HSDL-2300, HP HSDL-3600/HSDL-3610 */ - pr_debug("%s(), %s\n", - __func__, dongle_types[dongle_id]); - outb(0x00, iobase+4); - if (speed > 115200) - outb(0x01, iobase+4); - break; - case 0x09: /* IBM31T1100 or Temic TFDS6000/TFDS6500 */ - outb(0x01, iobase+4); - - if (speed == 4000000) { - /* There was a cli() there, but we now are already - * under spin_lock_irqsave() - JeanII */ - outb(0x81, iobase+4); - outb(0x80, iobase+4); - } else - outb(0x00, iobase+4); - break; - case 0x0A: /* same as */ - case 0x0B: /* Reserved */ - pr_debug("%s(), %s not defined by irda yet\n", - __func__, dongle_types[dongle_id]); - break; - case 0x0C: /* same as */ - case 0x0D: /* HP HSDL-1100/HSDL-2100 */ - break; - case 0x0E: /* Supports SIR Mode only */ - break; - case 0x0F: /* No dongle connected */ - pr_debug("%s(), %s is not for IrDA mode\n", - __func__, dongle_types[dongle_id]); - - switch_bank(iobase, BANK0); - outb(0x62, iobase+MCR); - break; - default: - pr_debug("%s(), invalid data_rate\n", __func__); - } - /* Restore bank register */ - outb(bank, iobase+BSR); -} - -/* - * Function nsc_ircc_change_speed (self, baud) - * - * Change the speed of the device - * - * This function *must* be called with irq off and spin-lock. - */ -static __u8 nsc_ircc_change_speed(struct nsc_ircc_cb *self, __u32 speed) -{ - struct net_device *dev; - __u8 mcr = MCR_SIR; - int iobase; - __u8 bank; - __u8 ier; /* Interrupt enable register */ - - pr_debug("%s(), speed=%d\n", __func__, speed); - - IRDA_ASSERT(self != NULL, return 0;); - - dev = self->netdev; - iobase = self->io.fir_base; - - /* Update accounting for new speed */ - self->io.speed = speed; - - /* Save current bank */ - bank = inb(iobase+BSR); - - /* Disable interrupts */ - switch_bank(iobase, BANK0); - outb(0, iobase+IER); - - /* Select Bank 2 */ - switch_bank(iobase, BANK2); - - outb(0x00, iobase+BGDH); - switch (speed) { - case 9600: outb(0x0c, iobase+BGDL); break; - case 19200: outb(0x06, iobase+BGDL); break; - case 38400: outb(0x03, iobase+BGDL); break; - case 57600: outb(0x02, iobase+BGDL); break; - case 115200: outb(0x01, iobase+BGDL); break; - case 576000: - switch_bank(iobase, BANK5); - - /* IRCR2: MDRS is set */ - outb(inb(iobase+4) | 0x04, iobase+4); - - mcr = MCR_MIR; - pr_debug("%s(), handling baud of 576000\n", __func__); - break; - case 1152000: - mcr = MCR_MIR; - pr_debug("%s(), handling baud of 1152000\n", __func__); - break; - case 4000000: - mcr = MCR_FIR; - pr_debug("%s(), handling baud of 4000000\n", __func__); - break; - default: - mcr = MCR_FIR; - pr_debug("%s(), unknown baud rate of %d\n", - __func__, speed); - break; - } - - /* Set appropriate speed mode */ - switch_bank(iobase, BANK0); - outb(mcr | MCR_TX_DFR, iobase+MCR); - - /* Give some hits to the transceiver */ - nsc_ircc_change_dongle_speed(iobase, speed, self->io.dongle_id); - - /* Set FIFO threshold to TX17, RX16 */ - switch_bank(iobase, BANK0); - outb(0x00, iobase+FCR); - outb(FCR_FIFO_EN, iobase+FCR); - outb(FCR_RXTH| /* Set Rx FIFO threshold */ - FCR_TXTH| /* Set Tx FIFO threshold */ - FCR_TXSR| /* Reset Tx FIFO */ - FCR_RXSR| /* Reset Rx FIFO */ - FCR_FIFO_EN, /* Enable FIFOs */ - iobase+FCR); - - /* Set FIFO size to 32 */ - switch_bank(iobase, BANK2); - outb(EXCR2_RFSIZ|EXCR2_TFSIZ, iobase+EXCR2); - - /* Enable some interrupts so we can receive frames */ - switch_bank(iobase, BANK0); - if (speed > 115200) { - /* Install FIR xmit handler */ - dev->netdev_ops = &nsc_ircc_fir_ops; - ier = IER_SFIF_IE; - nsc_ircc_dma_receive(self); - } else { - /* Install SIR xmit handler */ - dev->netdev_ops = &nsc_ircc_sir_ops; - ier = IER_RXHDL_IE; - } - /* Set our current interrupt mask */ - outb(ier, iobase+IER); - - /* Restore BSR */ - outb(bank, iobase+BSR); - - /* Make sure interrupt handlers keep the proper interrupt mask */ - return ier; -} - -/* - * Function nsc_ircc_hard_xmit (skb, dev) - * - * Transmit the frame! - * - */ -static netdev_tx_t nsc_ircc_hard_xmit_sir(struct sk_buff *skb, - struct net_device *dev) -{ - struct nsc_ircc_cb *self; - unsigned long flags; - int iobase; - __s32 speed; - __u8 bank; - - self = netdev_priv(dev); - - IRDA_ASSERT(self != NULL, return NETDEV_TX_OK;); - - iobase = self->io.fir_base; - - netif_stop_queue(dev); - - /* Make sure tests *& speed change are atomic */ - spin_lock_irqsave(&self->lock, flags); - - /* Check if we need to change the speed */ - speed = irda_get_next_speed(skb); - if ((speed != self->io.speed) && (speed != -1)) { - /* Check for empty frame. */ - if (!skb->len) { - /* If we just sent a frame, we get called before - * the last bytes get out (because of the SIR FIFO). - * If this is the case, let interrupt handler change - * the speed itself... Jean II */ - if (self->io.direction == IO_RECV) { - nsc_ircc_change_speed(self, speed); - /* TODO : For SIR->SIR, the next packet - * may get corrupted - Jean II */ - netif_wake_queue(dev); - } else { - self->new_speed = speed; - /* Queue will be restarted after speed change - * to make sure packets gets through the - * proper xmit handler - Jean II */ - } - netif_trans_update(dev); - spin_unlock_irqrestore(&self->lock, flags); - dev_kfree_skb(skb); - return NETDEV_TX_OK; - } else - self->new_speed = speed; - } - - /* Save current bank */ - bank = inb(iobase+BSR); - - self->tx_buff.data = self->tx_buff.head; - - self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data, - self->tx_buff.truesize); - - dev->stats.tx_bytes += self->tx_buff.len; - - /* Add interrupt on tx low level (will fire immediately) */ - switch_bank(iobase, BANK0); - outb(IER_TXLDL_IE, iobase+IER); - - /* Restore bank register */ - outb(bank, iobase+BSR); - - netif_trans_update(dev); - spin_unlock_irqrestore(&self->lock, flags); - - dev_kfree_skb(skb); - - return NETDEV_TX_OK; -} - -static netdev_tx_t nsc_ircc_hard_xmit_fir(struct sk_buff *skb, - struct net_device *dev) -{ - struct nsc_ircc_cb *self; - unsigned long flags; - int iobase; - __s32 speed; - __u8 bank; - int mtt, diff; - - self = netdev_priv(dev); - iobase = self->io.fir_base; - - netif_stop_queue(dev); - - /* Make sure tests *& speed change are atomic */ - spin_lock_irqsave(&self->lock, flags); - - /* Check if we need to change the speed */ - speed = irda_get_next_speed(skb); - if ((speed != self->io.speed) && (speed != -1)) { - /* Check for empty frame. */ - if (!skb->len) { - /* If we are currently transmitting, defer to - * interrupt handler. - Jean II */ - if(self->tx_fifo.len == 0) { - nsc_ircc_change_speed(self, speed); - netif_wake_queue(dev); - } else { - self->new_speed = speed; - /* Keep queue stopped : - * the speed change operation may change the - * xmit handler, and we want to make sure - * the next packet get through the proper - * Tx path, so block the Tx queue until - * the speed change has been done. - * Jean II */ - } - netif_trans_update(dev); - spin_unlock_irqrestore(&self->lock, flags); - dev_kfree_skb(skb); - return NETDEV_TX_OK; - } else { - /* Change speed after current frame */ - self->new_speed = speed; - } - } - - /* Save current bank */ - bank = inb(iobase+BSR); - - /* Register and copy this frame to DMA memory */ - self->tx_fifo.queue[self->tx_fifo.free].start = self->tx_fifo.tail; - self->tx_fifo.queue[self->tx_fifo.free].len = skb->len; - self->tx_fifo.tail += skb->len; - - dev->stats.tx_bytes += skb->len; - - skb_copy_from_linear_data(skb, self->tx_fifo.queue[self->tx_fifo.free].start, - skb->len); - self->tx_fifo.len++; - self->tx_fifo.free++; - - /* Start transmit only if there is currently no transmit going on */ - if (self->tx_fifo.len == 1) { - /* Check if we must wait the min turn time or not */ - mtt = irda_get_mtt(skb); - if (mtt) { - /* Check how much time we have used already */ - diff = ktime_us_delta(ktime_get(), self->stamp); - - /* Check if the mtt is larger than the time we have - * already used by all the protocol processing - */ - if (mtt > diff) { - mtt -= diff; - - /* - * Use timer if delay larger than 125 us, and - * use udelay for smaller values which should - * be acceptable - */ - if (mtt > 125) { - /* Adjust for timer resolution */ - mtt = mtt / 125; - - /* Setup timer */ - switch_bank(iobase, BANK4); - outb(mtt & 0xff, iobase+TMRL); - outb((mtt >> 8) & 0x0f, iobase+TMRH); - - /* Start timer */ - outb(IRCR1_TMR_EN, iobase+IRCR1); - self->io.direction = IO_XMIT; - - /* Enable timer interrupt */ - switch_bank(iobase, BANK0); - outb(IER_TMR_IE, iobase+IER); - - /* Timer will take care of the rest */ - goto out; - } else - udelay(mtt); - } - } - /* Enable DMA interrupt */ - switch_bank(iobase, BANK0); - outb(IER_DMA_IE, iobase+IER); - - /* Transmit frame */ - nsc_ircc_dma_xmit(self, iobase); - } - out: - /* Not busy transmitting anymore if window is not full, - * and if we don't need to change speed */ - if ((self->tx_fifo.free < MAX_TX_WINDOW) && (self->new_speed == 0)) - netif_wake_queue(self->netdev); - - /* Restore bank register */ - outb(bank, iobase+BSR); - - netif_trans_update(dev); - spin_unlock_irqrestore(&self->lock, flags); - dev_kfree_skb(skb); - - return NETDEV_TX_OK; -} - -/* - * Function nsc_ircc_dma_xmit (self, iobase) - * - * Transmit data using DMA - * - */ -static void nsc_ircc_dma_xmit(struct nsc_ircc_cb *self, int iobase) -{ - int bsr; - - /* Save current bank */ - bsr = inb(iobase+BSR); - - /* Disable DMA */ - switch_bank(iobase, BANK0); - outb(inb(iobase+MCR) & ~MCR_DMA_EN, iobase+MCR); - - self->io.direction = IO_XMIT; - - /* Choose transmit DMA channel */ - switch_bank(iobase, BANK2); - outb(ECR1_DMASWP|ECR1_DMANF|ECR1_EXT_SL, iobase+ECR1); - - irda_setup_dma(self->io.dma, - ((u8 *)self->tx_fifo.queue[self->tx_fifo.ptr].start - - self->tx_buff.head) + self->tx_buff_dma, - self->tx_fifo.queue[self->tx_fifo.ptr].len, - DMA_TX_MODE); - - /* Enable DMA and SIR interaction pulse */ - switch_bank(iobase, BANK0); - outb(inb(iobase+MCR)|MCR_TX_DFR|MCR_DMA_EN|MCR_IR_PLS, iobase+MCR); - - /* Restore bank register */ - outb(bsr, iobase+BSR); -} - -/* - * Function nsc_ircc_pio_xmit (self, iobase) - * - * Transmit data using PIO. Returns the number of bytes that actually - * got transferred - * - */ -static int nsc_ircc_pio_write(int iobase, __u8 *buf, int len, int fifo_size) -{ - int actual = 0; - __u8 bank; - - /* Save current bank */ - bank = inb(iobase+BSR); - - switch_bank(iobase, BANK0); - if (!(inb_p(iobase+LSR) & LSR_TXEMP)) { - pr_debug("%s(), warning, FIFO not empty yet!\n", - __func__); - - /* FIFO may still be filled to the Tx interrupt threshold */ - fifo_size -= 17; - } - - /* Fill FIFO with current frame */ - while ((fifo_size-- > 0) && (actual < len)) { - /* Transmit next byte */ - outb(buf[actual++], iobase+TXD); - } - - pr_debug("%s(), fifo_size %d ; %d sent of %d\n", - __func__, fifo_size, actual, len); - - /* Restore bank */ - outb(bank, iobase+BSR); - - return actual; -} - -/* - * Function nsc_ircc_dma_xmit_complete (self) - * - * The transfer of a frame in finished. This function will only be called - * by the interrupt handler - * - */ -static int nsc_ircc_dma_xmit_complete(struct nsc_ircc_cb *self) -{ - int iobase; - __u8 bank; - int ret = TRUE; - - iobase = self->io.fir_base; - - /* Save current bank */ - bank = inb(iobase+BSR); - - /* Disable DMA */ - switch_bank(iobase, BANK0); - outb(inb(iobase+MCR) & ~MCR_DMA_EN, iobase+MCR); - - /* Check for underrun! */ - if (inb(iobase+ASCR) & ASCR_TXUR) { - self->netdev->stats.tx_errors++; - self->netdev->stats.tx_fifo_errors++; - - /* Clear bit, by writing 1 into it */ - outb(ASCR_TXUR, iobase+ASCR); - } else { - self->netdev->stats.tx_packets++; - } - - /* Finished with this frame, so prepare for next */ - self->tx_fifo.ptr++; - self->tx_fifo.len--; - - /* Any frames to be sent back-to-back? */ - if (self->tx_fifo.len) { - nsc_ircc_dma_xmit(self, iobase); - - /* Not finished yet! */ - ret = FALSE; - } else { - /* Reset Tx FIFO info */ - self->tx_fifo.len = self->tx_fifo.ptr = self->tx_fifo.free = 0; - self->tx_fifo.tail = self->tx_buff.head; - } - - /* Make sure we have room for more frames and - * that we don't need to change speed */ - if ((self->tx_fifo.free < MAX_TX_WINDOW) && (self->new_speed == 0)) { - /* Not busy transmitting anymore */ - /* Tell the network layer, that we can accept more frames */ - netif_wake_queue(self->netdev); - } - - /* Restore bank */ - outb(bank, iobase+BSR); - - return ret; -} - -/* - * Function nsc_ircc_dma_receive (self) - * - * Get ready for receiving a frame. The device will initiate a DMA - * if it starts to receive a frame. - * - */ -static int nsc_ircc_dma_receive(struct nsc_ircc_cb *self) -{ - int iobase; - __u8 bsr; - - iobase = self->io.fir_base; - - /* Reset Tx FIFO info */ - self->tx_fifo.len = self->tx_fifo.ptr = self->tx_fifo.free = 0; - self->tx_fifo.tail = self->tx_buff.head; - - /* Save current bank */ - bsr = inb(iobase+BSR); - - /* Disable DMA */ - switch_bank(iobase, BANK0); - outb(inb(iobase+MCR) & ~MCR_DMA_EN, iobase+MCR); - - /* Choose DMA Rx, DMA Fairness, and Advanced mode */ - switch_bank(iobase, BANK2); - outb(ECR1_DMANF|ECR1_EXT_SL, iobase+ECR1); - - self->io.direction = IO_RECV; - self->rx_buff.data = self->rx_buff.head; - - /* Reset Rx FIFO. This will also flush the ST_FIFO */ - switch_bank(iobase, BANK0); - outb(FCR_RXSR|FCR_FIFO_EN, iobase+FCR); - - self->st_fifo.len = self->st_fifo.pending_bytes = 0; - self->st_fifo.tail = self->st_fifo.head = 0; - - irda_setup_dma(self->io.dma, self->rx_buff_dma, self->rx_buff.truesize, - DMA_RX_MODE); - - /* Enable DMA */ - switch_bank(iobase, BANK0); - outb(inb(iobase+MCR)|MCR_DMA_EN, iobase+MCR); - - /* Restore bank register */ - outb(bsr, iobase+BSR); - - return 0; -} - -/* - * Function nsc_ircc_dma_receive_complete (self) - * - * Finished with receiving frames - * - * - */ -static int nsc_ircc_dma_receive_complete(struct nsc_ircc_cb *self, int iobase) -{ - struct st_fifo *st_fifo; - struct sk_buff *skb; - __u8 status; - __u8 bank; - int len; - - st_fifo = &self->st_fifo; - - /* Save current bank */ - bank = inb(iobase+BSR); - - /* Read all entries in status FIFO */ - switch_bank(iobase, BANK5); - while ((status = inb(iobase+FRM_ST)) & FRM_ST_VLD) { - /* We must empty the status FIFO no matter what */ - len = inb(iobase+RFLFL) | ((inb(iobase+RFLFH) & 0x1f) << 8); - - if (st_fifo->tail >= MAX_RX_WINDOW) { - pr_debug("%s(), window is full!\n", __func__); - continue; - } - - st_fifo->entries[st_fifo->tail].status = status; - st_fifo->entries[st_fifo->tail].len = len; - st_fifo->pending_bytes += len; - st_fifo->tail++; - st_fifo->len++; - } - /* Try to process all entries in status FIFO */ - while (st_fifo->len > 0) { - /* Get first entry */ - status = st_fifo->entries[st_fifo->head].status; - len = st_fifo->entries[st_fifo->head].len; - st_fifo->pending_bytes -= len; - st_fifo->head++; - st_fifo->len--; - - /* Check for errors */ - if (status & FRM_ST_ERR_MSK) { - if (status & FRM_ST_LOST_FR) { - /* Add number of lost frames to stats */ - self->netdev->stats.rx_errors += len; - } else { - /* Skip frame */ - self->netdev->stats.rx_errors++; - - self->rx_buff.data += len; - - if (status & FRM_ST_MAX_LEN) - self->netdev->stats.rx_length_errors++; - - if (status & FRM_ST_PHY_ERR) - self->netdev->stats.rx_frame_errors++; - - if (status & FRM_ST_BAD_CRC) - self->netdev->stats.rx_crc_errors++; - } - /* The errors below can be reported in both cases */ - if (status & FRM_ST_OVR1) - self->netdev->stats.rx_fifo_errors++; - - if (status & FRM_ST_OVR2) - self->netdev->stats.rx_fifo_errors++; - } else { - /* - * First we must make sure that the frame we - * want to deliver is all in main memory. If we - * cannot tell, then we check if the Rx FIFO is - * empty. If not then we will have to take a nap - * and try again later. - */ - if (st_fifo->pending_bytes < self->io.fifo_size) { - switch_bank(iobase, BANK0); - if (inb(iobase+LSR) & LSR_RXDA) { - /* Put this entry back in fifo */ - st_fifo->head--; - st_fifo->len++; - st_fifo->pending_bytes += len; - st_fifo->entries[st_fifo->head].status = status; - st_fifo->entries[st_fifo->head].len = len; - /* - * DMA not finished yet, so try again - * later, set timer value, resolution - * 125 us - */ - switch_bank(iobase, BANK4); - outb(0x02, iobase+TMRL); /* x 125 us */ - outb(0x00, iobase+TMRH); - - /* Start timer */ - outb(IRCR1_TMR_EN, iobase+IRCR1); - - /* Restore bank register */ - outb(bank, iobase+BSR); - - return FALSE; /* I'll be back! */ - } - } - - /* - * Remember the time we received this frame, so we can - * reduce the min turn time a bit since we will know - * how much time we have used for protocol processing - */ - self->stamp = ktime_get(); - - skb = dev_alloc_skb(len+1); - if (skb == NULL) { - self->netdev->stats.rx_dropped++; - - /* Restore bank register */ - outb(bank, iobase+BSR); - - return FALSE; - } - - /* Make sure IP header gets aligned */ - skb_reserve(skb, 1); - - /* Copy frame without CRC */ - if (self->io.speed < 4000000) { - skb_put(skb, len-2); - skb_copy_to_linear_data(skb, - self->rx_buff.data, - len - 2); - } else { - skb_put(skb, len-4); - skb_copy_to_linear_data(skb, - self->rx_buff.data, - len - 4); - } - - /* Move to next frame */ - self->rx_buff.data += len; - self->netdev->stats.rx_bytes += len; - self->netdev->stats.rx_packets++; - - skb->dev = self->netdev; - skb_reset_mac_header(skb); - skb->protocol = htons(ETH_P_IRDA); - netif_rx(skb); - } - } - /* Restore bank register */ - outb(bank, iobase+BSR); - - return TRUE; -} - -/* - * Function nsc_ircc_pio_receive (self) - * - * Receive all data in receiver FIFO - * - */ -static void nsc_ircc_pio_receive(struct nsc_ircc_cb *self) -{ - __u8 byte; - int iobase; - - iobase = self->io.fir_base; - - /* Receive all characters in Rx FIFO */ - do { - byte = inb(iobase+RXD); - async_unwrap_char(self->netdev, &self->netdev->stats, - &self->rx_buff, byte); - } while (inb(iobase+LSR) & LSR_RXDA); /* Data available */ -} - -/* - * Function nsc_ircc_sir_interrupt (self, eir) - * - * Handle SIR interrupt - * - */ -static void nsc_ircc_sir_interrupt(struct nsc_ircc_cb *self, int eir) -{ - int actual; - - /* Check if transmit FIFO is low on data */ - if (eir & EIR_TXLDL_EV) { - /* Write data left in transmit buffer */ - actual = nsc_ircc_pio_write(self->io.fir_base, - self->tx_buff.data, - self->tx_buff.len, - self->io.fifo_size); - self->tx_buff.data += actual; - self->tx_buff.len -= actual; - - self->io.direction = IO_XMIT; - - /* Check if finished */ - if (self->tx_buff.len > 0) - self->ier = IER_TXLDL_IE; - else { - - self->netdev->stats.tx_packets++; - netif_wake_queue(self->netdev); - self->ier = IER_TXEMP_IE; - } - - } - /* Check if transmission has completed */ - if (eir & EIR_TXEMP_EV) { - /* Turn around and get ready to receive some data */ - self->io.direction = IO_RECV; - self->ier = IER_RXHDL_IE; - /* Check if we need to change the speed? - * Need to be after self->io.direction to avoid race with - * nsc_ircc_hard_xmit_sir() - Jean II */ - if (self->new_speed) { - pr_debug("%s(), Changing speed!\n", __func__); - self->ier = nsc_ircc_change_speed(self, - self->new_speed); - self->new_speed = 0; - netif_wake_queue(self->netdev); - - /* Check if we are going to FIR */ - if (self->io.speed > 115200) { - /* No need to do anymore SIR stuff */ - return; - } - } - } - - /* Rx FIFO threshold or timeout */ - if (eir & EIR_RXHDL_EV) { - nsc_ircc_pio_receive(self); - - /* Keep receiving */ - self->ier = IER_RXHDL_IE; - } -} - -/* - * Function nsc_ircc_fir_interrupt (self, eir) - * - * Handle MIR/FIR interrupt - * - */ -static void nsc_ircc_fir_interrupt(struct nsc_ircc_cb *self, int iobase, - int eir) -{ - __u8 bank; - - bank = inb(iobase+BSR); - - /* Status FIFO event*/ - if (eir & EIR_SFIF_EV) { - /* Check if DMA has finished */ - if (nsc_ircc_dma_receive_complete(self, iobase)) { - /* Wait for next status FIFO interrupt */ - self->ier = IER_SFIF_IE; - } else { - self->ier = IER_SFIF_IE | IER_TMR_IE; - } - } else if (eir & EIR_TMR_EV) { /* Timer finished */ - /* Disable timer */ - switch_bank(iobase, BANK4); - outb(0, iobase+IRCR1); - - /* Clear timer event */ - switch_bank(iobase, BANK0); - outb(ASCR_CTE, iobase+ASCR); - - /* Check if this is a Tx timer interrupt */ - if (self->io.direction == IO_XMIT) { - nsc_ircc_dma_xmit(self, iobase); - - /* Interrupt on DMA */ - self->ier = IER_DMA_IE; - } else { - /* Check (again) if DMA has finished */ - if (nsc_ircc_dma_receive_complete(self, iobase)) { - self->ier = IER_SFIF_IE; - } else { - self->ier = IER_SFIF_IE | IER_TMR_IE; - } - } - } else if (eir & EIR_DMA_EV) { - /* Finished with all transmissions? */ - if (nsc_ircc_dma_xmit_complete(self)) { - if(self->new_speed != 0) { - /* As we stop the Tx queue, the speed change - * need to be done when the Tx fifo is - * empty. Ask for a Tx done interrupt */ - self->ier = IER_TXEMP_IE; - } else { - /* Check if there are more frames to be - * transmitted */ - if (irda_device_txqueue_empty(self->netdev)) { - /* Prepare for receive */ - nsc_ircc_dma_receive(self); - self->ier = IER_SFIF_IE; - } else - net_warn_ratelimited("%s(), potential Tx queue lockup !\n", - __func__); - } - } else { - /* Not finished yet, so interrupt on DMA again */ - self->ier = IER_DMA_IE; - } - } else if (eir & EIR_TXEMP_EV) { - /* The Tx FIFO has totally drained out, so now we can change - * the speed... - Jean II */ - self->ier = nsc_ircc_change_speed(self, self->new_speed); - self->new_speed = 0; - netif_wake_queue(self->netdev); - /* Note : nsc_ircc_change_speed() restarted Rx fifo */ - } - - outb(bank, iobase+BSR); -} - -/* - * Function nsc_ircc_interrupt (irq, dev_id, regs) - * - * An interrupt from the chip has arrived. Time to do some work - * - */ -static irqreturn_t nsc_ircc_interrupt(int irq, void *dev_id) -{ - struct net_device *dev = dev_id; - struct nsc_ircc_cb *self; - __u8 bsr, eir; - int iobase; - - self = netdev_priv(dev); - - spin_lock(&self->lock); - - iobase = self->io.fir_base; - - bsr = inb(iobase+BSR); /* Save current bank */ - - switch_bank(iobase, BANK0); - self->ier = inb(iobase+IER); - eir = inb(iobase+EIR) & self->ier; /* Mask out the interesting ones */ - - outb(0, iobase+IER); /* Disable interrupts */ - - if (eir) { - /* Dispatch interrupt handler for the current speed */ - if (self->io.speed > 115200) - nsc_ircc_fir_interrupt(self, iobase, eir); - else - nsc_ircc_sir_interrupt(self, eir); - } - - outb(self->ier, iobase+IER); /* Restore interrupts */ - outb(bsr, iobase+BSR); /* Restore bank register */ - - spin_unlock(&self->lock); - return IRQ_RETVAL(eir); -} - -/* - * Function nsc_ircc_is_receiving (self) - * - * Return TRUE is we are currently receiving a frame - * - */ -static int nsc_ircc_is_receiving(struct nsc_ircc_cb *self) -{ - unsigned long flags; - int status = FALSE; - int iobase; - __u8 bank; - - IRDA_ASSERT(self != NULL, return FALSE;); - - spin_lock_irqsave(&self->lock, flags); - - if (self->io.speed > 115200) { - iobase = self->io.fir_base; - - /* Check if rx FIFO is not empty */ - bank = inb(iobase+BSR); - switch_bank(iobase, BANK2); - if ((inb(iobase+RXFLV) & 0x3f) != 0) { - /* We are receiving something */ - status = TRUE; - } - outb(bank, iobase+BSR); - } else - status = (self->rx_buff.state != OUTSIDE_FRAME); - - spin_unlock_irqrestore(&self->lock, flags); - - return status; -} - -/* - * Function nsc_ircc_net_open (dev) - * - * Start the device - * - */ -static int nsc_ircc_net_open(struct net_device *dev) -{ - struct nsc_ircc_cb *self; - int iobase; - char hwname[32]; - __u8 bank; - - - IRDA_ASSERT(dev != NULL, return -1;); - self = netdev_priv(dev); - - IRDA_ASSERT(self != NULL, return 0;); - - iobase = self->io.fir_base; - - if (request_irq(self->io.irq, nsc_ircc_interrupt, 0, dev->name, dev)) { - net_warn_ratelimited("%s, unable to allocate irq=%d\n", - driver_name, self->io.irq); - return -EAGAIN; - } - /* - * Always allocate the DMA channel after the IRQ, and clean up on - * failure. - */ - if (request_dma(self->io.dma, dev->name)) { - net_warn_ratelimited("%s, unable to allocate dma=%d\n", - driver_name, self->io.dma); - free_irq(self->io.irq, dev); - return -EAGAIN; - } - - /* Save current bank */ - bank = inb(iobase+BSR); - - /* turn on interrupts */ - switch_bank(iobase, BANK0); - outb(IER_LS_IE | IER_RXHDL_IE, iobase+IER); - - /* Restore bank register */ - outb(bank, iobase+BSR); - - /* Ready to play! */ - netif_start_queue(dev); - - /* Give self a hardware name */ - sprintf(hwname, "NSC-FIR @ 0x%03x", self->io.fir_base); - - /* - * Open new IrLAP layer instance, now that everything should be - * initialized properly - */ - self->irlap = irlap_open(dev, &self->qos, hwname); - - return 0; -} - -/* - * Function nsc_ircc_net_close (dev) - * - * Stop the device - * - */ -static int nsc_ircc_net_close(struct net_device *dev) -{ - struct nsc_ircc_cb *self; - int iobase; - __u8 bank; - - - IRDA_ASSERT(dev != NULL, return -1;); - - self = netdev_priv(dev); - IRDA_ASSERT(self != NULL, return 0;); - - /* Stop device */ - netif_stop_queue(dev); - - /* Stop and remove instance of IrLAP */ - if (self->irlap) - irlap_close(self->irlap); - self->irlap = NULL; - - iobase = self->io.fir_base; - - disable_dma(self->io.dma); - - /* Save current bank */ - bank = inb(iobase+BSR); - - /* Disable interrupts */ - switch_bank(iobase, BANK0); - outb(0, iobase+IER); - - free_irq(self->io.irq, dev); - free_dma(self->io.dma); - - /* Restore bank register */ - outb(bank, iobase+BSR); - - return 0; -} - -/* - * Function nsc_ircc_net_ioctl (dev, rq, cmd) - * - * Process IOCTL commands for this device - * - */ -static int nsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct if_irda_req *irq = (struct if_irda_req *) rq; - struct nsc_ircc_cb *self; - unsigned long flags; - int ret = 0; - - IRDA_ASSERT(dev != NULL, return -1;); - - self = netdev_priv(dev); - - IRDA_ASSERT(self != NULL, return -1;); - - pr_debug("%s(), %s, (cmd=0x%X)\n", __func__, dev->name, cmd); - - switch (cmd) { - case SIOCSBANDWIDTH: /* Set bandwidth */ - if (!capable(CAP_NET_ADMIN)) { - ret = -EPERM; - break; - } - spin_lock_irqsave(&self->lock, flags); - nsc_ircc_change_speed(self, irq->ifr_baudrate); - spin_unlock_irqrestore(&self->lock, flags); - break; - case SIOCSMEDIABUSY: /* Set media busy */ - if (!capable(CAP_NET_ADMIN)) { - ret = -EPERM; - break; - } - irda_device_set_media_busy(self->netdev, TRUE); - break; - case SIOCGRECEIVING: /* Check if we are receiving right now */ - /* This is already protected */ - irq->ifr_receiving = nsc_ircc_is_receiving(self); - break; - default: - ret = -EOPNOTSUPP; - } - return ret; -} - -static int nsc_ircc_suspend(struct platform_device *dev, pm_message_t state) -{ - struct nsc_ircc_cb *self = platform_get_drvdata(dev); - int bank; - unsigned long flags; - int iobase = self->io.fir_base; - - if (self->io.suspended) - return 0; - - pr_debug("%s, Suspending\n", driver_name); - - rtnl_lock(); - if (netif_running(self->netdev)) { - netif_device_detach(self->netdev); - spin_lock_irqsave(&self->lock, flags); - /* Save current bank */ - bank = inb(iobase+BSR); - - /* Disable interrupts */ - switch_bank(iobase, BANK0); - outb(0, iobase+IER); - - /* Restore bank register */ - outb(bank, iobase+BSR); - - spin_unlock_irqrestore(&self->lock, flags); - free_irq(self->io.irq, self->netdev); - disable_dma(self->io.dma); - } - self->io.suspended = 1; - rtnl_unlock(); - - return 0; -} - -static int nsc_ircc_resume(struct platform_device *dev) -{ - struct nsc_ircc_cb *self = platform_get_drvdata(dev); - unsigned long flags; - - if (!self->io.suspended) - return 0; - - pr_debug("%s, Waking up\n", driver_name); - - rtnl_lock(); - nsc_ircc_setup(&self->io); - nsc_ircc_init_dongle_interface(self->io.fir_base, self->io.dongle_id); - - if (netif_running(self->netdev)) { - if (request_irq(self->io.irq, nsc_ircc_interrupt, 0, - self->netdev->name, self->netdev)) { - net_warn_ratelimited("%s, unable to allocate irq=%d\n", - driver_name, self->io.irq); - - /* - * Don't fail resume process, just kill this - * network interface - */ - unregister_netdevice(self->netdev); - } else { - spin_lock_irqsave(&self->lock, flags); - nsc_ircc_change_speed(self, self->io.speed); - spin_unlock_irqrestore(&self->lock, flags); - netif_device_attach(self->netdev); - } - - } else { - spin_lock_irqsave(&self->lock, flags); - nsc_ircc_change_speed(self, 9600); - spin_unlock_irqrestore(&self->lock, flags); - } - self->io.suspended = 0; - rtnl_unlock(); - - return 0; -} - -MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>"); -MODULE_DESCRIPTION("NSC IrDA Device Driver"); -MODULE_LICENSE("GPL"); - - -module_param(qos_mtt_bits, int, 0); -MODULE_PARM_DESC(qos_mtt_bits, "Minimum Turn Time"); -module_param_hw_array(io, int, ioport, NULL, 0); -MODULE_PARM_DESC(io, "Base I/O addresses"); -module_param_hw_array(irq, int, irq, NULL, 0); -MODULE_PARM_DESC(irq, "IRQ lines"); -module_param_hw_array(dma, int, dma, NULL, 0); -MODULE_PARM_DESC(dma, "DMA channels"); -module_param(dongle_id, int, 0); -MODULE_PARM_DESC(dongle_id, "Type-id of used dongle"); - -module_init(nsc_ircc_init); -module_exit(nsc_ircc_cleanup); - diff --git a/drivers/net/irda/nsc-ircc.h b/drivers/net/irda/nsc-ircc.h deleted file mode 100644 index 7be5acb56532..000000000000 --- a/drivers/net/irda/nsc-ircc.h +++ /dev/null @@ -1,281 +0,0 @@ -/********************************************************************* - * - * 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ø 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/ktime.h> - -#include <linux/spinlock.h> -#include <linux/pm.h> -#include <linux/types.h> -#include <asm/io.h> - -/* Features for chips (set in driver_data) */ -#define NSC_FORCE_DONGLE_TYPE9 0x00000001 - -/* 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 /* Auxiliary 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; /* Length 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; /* Length 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 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 */ - - ktime_t stamp; - - spinlock_t lock; /* For serializing operations */ - - __u32 new_speed; - int index; /* Instance index */ - - struct platform_device *pldev; -}; - -static inline void switch_bank(int iobase, int bank) -{ - outb(bank, iobase+BSR); -} - -#endif /* NSC_IRCC_H */ diff --git a/drivers/net/irda/old_belkin-sir.c b/drivers/net/irda/old_belkin-sir.c deleted file mode 100644 index a7c2e990ae69..000000000000 --- a/drivers/net/irda/old_belkin-sir.c +++ /dev/null @@ -1,146 +0,0 @@ -/********************************************************************* - * - * 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, see <http://www.gnu.org/licenses/>. - * - ********************************************************************/ - -#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; - - /* 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) -{ - /* 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) -{ - 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) -{ - /* 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); diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c deleted file mode 100644 index 1dba16bc7f8d..000000000000 --- a/drivers/net/irda/pxaficp_ir.c +++ /dev/null @@ -1,1076 +0,0 @@ -/* - * linux/drivers/net/irda/pxaficp_ir.c - * - * Based on sa1100_ir.c by Russell King - * - * Changes copyright (C) 2003-2005 MontaVista Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Infra-red driver (SIR/FIR) for the PXA2xx embedded microprocessor - * - */ -#include <linux/dma-mapping.h> -#include <linux/interrupt.h> -#include <linux/module.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/platform_device.h> -#include <linux/clk.h> -#include <linux/dmaengine.h> -#include <linux/dma-mapping.h> -#include <linux/dma/pxa-dma.h> -#include <linux/gpio.h> -#include <linux/slab.h> -#include <linux/sched/clock.h> - -#include <net/irda/irda.h> -#include <net/irda/irmod.h> -#include <net/irda/wrapper.h> -#include <net/irda/irda_device.h> - -#include <linux/platform_data/irda-pxaficp.h> -#undef __REG -#define __REG(x) ((x) & 0xffff) -#include <mach/regs-uart.h> - -#define ICCR0 0x0000 /* ICP Control Register 0 */ -#define ICCR1 0x0004 /* ICP Control Register 1 */ -#define ICCR2 0x0008 /* ICP Control Register 2 */ -#define ICDR 0x000c /* ICP Data Register */ -#define ICSR0 0x0014 /* ICP Status Register 0 */ -#define ICSR1 0x0018 /* ICP Status Register 1 */ - -#define ICCR0_AME (1 << 7) /* Address match enable */ -#define ICCR0_TIE (1 << 6) /* Transmit FIFO interrupt enable */ -#define ICCR0_RIE (1 << 5) /* Receive FIFO interrupt enable */ -#define ICCR0_RXE (1 << 4) /* Receive enable */ -#define ICCR0_TXE (1 << 3) /* Transmit enable */ -#define ICCR0_TUS (1 << 2) /* Transmit FIFO underrun select */ -#define ICCR0_LBM (1 << 1) /* Loopback mode */ -#define ICCR0_ITR (1 << 0) /* IrDA transmission */ - -#define ICCR2_RXP (1 << 3) /* Receive Pin Polarity select */ -#define ICCR2_TXP (1 << 2) /* Transmit Pin Polarity select */ -#define ICCR2_TRIG (3 << 0) /* Receive FIFO Trigger threshold */ -#define ICCR2_TRIG_8 (0 << 0) /* >= 8 bytes */ -#define ICCR2_TRIG_16 (1 << 0) /* >= 16 bytes */ -#define ICCR2_TRIG_32 (2 << 0) /* >= 32 bytes */ - -#define ICSR0_EOC (1 << 6) /* DMA End of Descriptor Chain */ -#define ICSR0_FRE (1 << 5) /* Framing error */ -#define ICSR0_RFS (1 << 4) /* Receive FIFO service request */ -#define ICSR0_TFS (1 << 3) /* Transnit FIFO service request */ -#define ICSR0_RAB (1 << 2) /* Receiver abort */ -#define ICSR0_TUR (1 << 1) /* Trunsmit FIFO underun */ -#define ICSR0_EIF (1 << 0) /* End/Error in FIFO */ - -#define ICSR1_ROR (1 << 6) /* Receiver FIFO underrun */ -#define ICSR1_CRE (1 << 5) /* CRC error */ -#define ICSR1_EOF (1 << 4) /* End of frame */ -#define ICSR1_TNF (1 << 3) /* Transmit FIFO not full */ -#define ICSR1_RNE (1 << 2) /* Receive FIFO not empty */ -#define ICSR1_TBY (1 << 1) /* Tramsmiter busy flag */ -#define ICSR1_RSY (1 << 0) /* Recevier synchronized flag */ - -#define IrSR_RXPL_NEG_IS_ZERO (1<<4) -#define IrSR_RXPL_POS_IS_ZERO 0x0 -#define IrSR_TXPL_NEG_IS_ZERO (1<<3) -#define IrSR_TXPL_POS_IS_ZERO 0x0 -#define IrSR_XMODE_PULSE_1_6 (1<<2) -#define IrSR_XMODE_PULSE_3_16 0x0 -#define IrSR_RCVEIR_IR_MODE (1<<1) -#define IrSR_RCVEIR_UART_MODE 0x0 -#define IrSR_XMITIR_IR_MODE (1<<0) -#define IrSR_XMITIR_UART_MODE 0x0 - -#define IrSR_IR_RECEIVE_ON (\ - IrSR_RXPL_NEG_IS_ZERO | \ - IrSR_TXPL_POS_IS_ZERO | \ - IrSR_XMODE_PULSE_3_16 | \ - IrSR_RCVEIR_IR_MODE | \ - IrSR_XMITIR_UART_MODE) - -#define IrSR_IR_TRANSMIT_ON (\ - IrSR_RXPL_NEG_IS_ZERO | \ - IrSR_TXPL_POS_IS_ZERO | \ - IrSR_XMODE_PULSE_3_16 | \ - IrSR_RCVEIR_UART_MODE | \ - IrSR_XMITIR_IR_MODE) - -/* macros for registers read/write */ -#define ficp_writel(irda, val, off) \ - do { \ - dev_vdbg(irda->dev, \ - "%s():%d ficp_writel(0x%x, %s)\n", \ - __func__, __LINE__, (val), #off); \ - writel_relaxed((val), (irda)->irda_base + (off)); \ - } while (0) - -#define ficp_readl(irda, off) \ - ({ \ - unsigned int _v; \ - _v = readl_relaxed((irda)->irda_base + (off)); \ - dev_vdbg(irda->dev, \ - "%s():%d ficp_readl(%s): 0x%x\n", \ - __func__, __LINE__, #off, _v); \ - _v; \ - }) - -#define stuart_writel(irda, val, off) \ - do { \ - dev_vdbg(irda->dev, \ - "%s():%d stuart_writel(0x%x, %s)\n", \ - __func__, __LINE__, (val), #off); \ - writel_relaxed((val), (irda)->stuart_base + (off)); \ - } while (0) - -#define stuart_readl(irda, off) \ - ({ \ - unsigned int _v; \ - _v = readl_relaxed((irda)->stuart_base + (off)); \ - dev_vdbg(irda->dev, \ - "%s():%d stuart_readl(%s): 0x%x\n", \ - __func__, __LINE__, #off, _v); \ - _v; \ - }) - -struct pxa_irda { - int speed; - int newspeed; - unsigned long long last_clk; - - void __iomem *stuart_base; - void __iomem *irda_base; - unsigned char *dma_rx_buff; - unsigned char *dma_tx_buff; - dma_addr_t dma_rx_buff_phy; - dma_addr_t dma_tx_buff_phy; - unsigned int dma_tx_buff_len; - struct dma_chan *txdma; - struct dma_chan *rxdma; - dma_cookie_t rx_cookie; - dma_cookie_t tx_cookie; - int drcmr_rx; - int drcmr_tx; - - int uart_irq; - int icp_irq; - - struct irlap_cb *irlap; - struct qos_info qos; - - iobuff_t tx_buff; - iobuff_t rx_buff; - - struct device *dev; - struct pxaficp_platform_data *pdata; - struct clk *fir_clk; - struct clk *sir_clk; - struct clk *cur_clk; -}; - -static int pxa_irda_set_speed(struct pxa_irda *si, int speed); - -static inline void pxa_irda_disable_clk(struct pxa_irda *si) -{ - if (si->cur_clk) - clk_disable_unprepare(si->cur_clk); - si->cur_clk = NULL; -} - -static inline void pxa_irda_enable_firclk(struct pxa_irda *si) -{ - si->cur_clk = si->fir_clk; - clk_prepare_enable(si->fir_clk); -} - -static inline void pxa_irda_enable_sirclk(struct pxa_irda *si) -{ - si->cur_clk = si->sir_clk; - clk_prepare_enable(si->sir_clk); -} - - -#define IS_FIR(si) ((si)->speed >= 4000000) -#define IRDA_FRAME_SIZE_LIMIT 2047 - -static void pxa_irda_fir_dma_rx_irq(void *data); -static void pxa_irda_fir_dma_tx_irq(void *data); - -inline static void pxa_irda_fir_dma_rx_start(struct pxa_irda *si) -{ - struct dma_async_tx_descriptor *tx; - - tx = dmaengine_prep_slave_single(si->rxdma, si->dma_rx_buff_phy, - IRDA_FRAME_SIZE_LIMIT, DMA_FROM_DEVICE, - DMA_PREP_INTERRUPT); - if (!tx) { - dev_err(si->dev, "prep_slave_sg() failed\n"); - return; - } - tx->callback = pxa_irda_fir_dma_rx_irq; - tx->callback_param = si; - si->rx_cookie = dmaengine_submit(tx); - dma_async_issue_pending(si->rxdma); -} - -inline static void pxa_irda_fir_dma_tx_start(struct pxa_irda *si) -{ - struct dma_async_tx_descriptor *tx; - - tx = dmaengine_prep_slave_single(si->txdma, si->dma_tx_buff_phy, - si->dma_tx_buff_len, DMA_TO_DEVICE, - DMA_PREP_INTERRUPT); - if (!tx) { - dev_err(si->dev, "prep_slave_sg() failed\n"); - return; - } - tx->callback = pxa_irda_fir_dma_tx_irq; - tx->callback_param = si; - si->tx_cookie = dmaengine_submit(tx); - dma_async_issue_pending(si->rxdma); -} - -/* - * Set the IrDA communications mode. - */ -static void pxa_irda_set_mode(struct pxa_irda *si, int mode) -{ - if (si->pdata->transceiver_mode) - si->pdata->transceiver_mode(si->dev, mode); - else { - if (gpio_is_valid(si->pdata->gpio_pwdown)) - gpio_set_value(si->pdata->gpio_pwdown, - !(mode & IR_OFF) ^ - !si->pdata->gpio_pwdown_inverted); - pxa2xx_transceiver_mode(si->dev, mode); - } -} - -/* - * Set the IrDA communications speed. - */ -static int pxa_irda_set_speed(struct pxa_irda *si, int speed) -{ - unsigned long flags; - unsigned int divisor; - - switch (speed) { - case 9600: case 19200: case 38400: - case 57600: case 115200: - - /* refer to PXA250/210 Developer's Manual 10-7 */ - /* BaudRate = 14.7456 MHz / (16*Divisor) */ - divisor = 14745600 / (16 * speed); - - local_irq_save(flags); - - if (IS_FIR(si)) { - /* stop RX DMA */ - dmaengine_terminate_all(si->rxdma); - /* disable FICP */ - ficp_writel(si, 0, ICCR0); - pxa_irda_disable_clk(si); - - /* set board transceiver to SIR mode */ - pxa_irda_set_mode(si, IR_SIRMODE); - - /* enable the STUART clock */ - pxa_irda_enable_sirclk(si); - } - - /* disable STUART first */ - stuart_writel(si, 0, STIER); - - /* access DLL & DLH */ - stuart_writel(si, stuart_readl(si, STLCR) | LCR_DLAB, STLCR); - stuart_writel(si, divisor & 0xff, STDLL); - stuart_writel(si, divisor >> 8, STDLH); - stuart_writel(si, stuart_readl(si, STLCR) & ~LCR_DLAB, STLCR); - - si->speed = speed; - stuart_writel(si, IrSR_IR_RECEIVE_ON | IrSR_XMODE_PULSE_1_6, - STISR); - stuart_writel(si, IER_UUE | IER_RLSE | IER_RAVIE | IER_RTIOE, - STIER); - - local_irq_restore(flags); - break; - - case 4000000: - local_irq_save(flags); - - /* disable STUART */ - stuart_writel(si, 0, STIER); - stuart_writel(si, 0, STISR); - pxa_irda_disable_clk(si); - - /* disable FICP first */ - ficp_writel(si, 0, ICCR0); - - /* set board transceiver to FIR mode */ - pxa_irda_set_mode(si, IR_FIRMODE); - - /* enable the FICP clock */ - pxa_irda_enable_firclk(si); - - si->speed = speed; - pxa_irda_fir_dma_rx_start(si); - ficp_writel(si, ICCR0_ITR | ICCR0_RXE, ICCR0); - - local_irq_restore(flags); - break; - - default: - return -EINVAL; - } - - return 0; -} - -/* SIR interrupt service routine. */ -static irqreturn_t pxa_irda_sir_irq(int irq, void *dev_id) -{ - struct net_device *dev = dev_id; - struct pxa_irda *si = netdev_priv(dev); - int iir, lsr, data; - - iir = stuart_readl(si, STIIR); - - switch (iir & 0x0F) { - case 0x06: /* Receiver Line Status */ - lsr = stuart_readl(si, STLSR); - while (lsr & LSR_FIFOE) { - data = stuart_readl(si, STRBR); - if (lsr & (LSR_OE | LSR_PE | LSR_FE | LSR_BI)) { - printk(KERN_DEBUG "pxa_ir: sir receiving error\n"); - dev->stats.rx_errors++; - if (lsr & LSR_FE) - dev->stats.rx_frame_errors++; - if (lsr & LSR_OE) - dev->stats.rx_fifo_errors++; - } else { - dev->stats.rx_bytes++; - async_unwrap_char(dev, &dev->stats, - &si->rx_buff, data); - } - lsr = stuart_readl(si, STLSR); - } - si->last_clk = sched_clock(); - break; - - case 0x04: /* Received Data Available */ - /* forth through */ - - case 0x0C: /* Character Timeout Indication */ - do { - dev->stats.rx_bytes++; - async_unwrap_char(dev, &dev->stats, &si->rx_buff, - stuart_readl(si, STRBR)); - } while (stuart_readl(si, STLSR) & LSR_DR); - si->last_clk = sched_clock(); - break; - - case 0x02: /* Transmit FIFO Data Request */ - while ((si->tx_buff.len) && - (stuart_readl(si, STLSR) & LSR_TDRQ)) { - stuart_writel(si, *si->tx_buff.data++, STTHR); - si->tx_buff.len -= 1; - } - - if (si->tx_buff.len == 0) { - dev->stats.tx_packets++; - dev->stats.tx_bytes += si->tx_buff.data - si->tx_buff.head; - - /* We need to ensure that the transmitter has finished. */ - while ((stuart_readl(si, STLSR) & LSR_TEMT) == 0) - cpu_relax(); - si->last_clk = sched_clock(); - - /* - * Ok, we've finished transmitting. Now enable - * the receiver. Sometimes we get a receive IRQ - * immediately after a transmit... - */ - if (si->newspeed) { - pxa_irda_set_speed(si, si->newspeed); - si->newspeed = 0; - } else { - /* enable IR Receiver, disable IR Transmitter */ - stuart_writel(si, IrSR_IR_RECEIVE_ON | - IrSR_XMODE_PULSE_1_6, STISR); - /* enable STUART and receive interrupts */ - stuart_writel(si, IER_UUE | IER_RLSE | - IER_RAVIE | IER_RTIOE, STIER); - } - /* I'm hungry! */ - netif_wake_queue(dev); - } - break; - } - - return IRQ_HANDLED; -} - -/* FIR Receive DMA interrupt handler */ -static void pxa_irda_fir_dma_rx_irq(void *data) -{ - struct net_device *dev = data; - struct pxa_irda *si = netdev_priv(dev); - - dmaengine_terminate_all(si->rxdma); - netdev_dbg(dev, "pxa_ir: fir rx dma bus error\n"); -} - -/* FIR Transmit DMA interrupt handler */ -static void pxa_irda_fir_dma_tx_irq(void *data) -{ - struct net_device *dev = data; - struct pxa_irda *si = netdev_priv(dev); - - dmaengine_terminate_all(si->txdma); - if (dmaengine_tx_status(si->txdma, si->tx_cookie, NULL) == DMA_ERROR) { - dev->stats.tx_errors++; - } else { - dev->stats.tx_packets++; - dev->stats.tx_bytes += si->dma_tx_buff_len; - } - - while (ficp_readl(si, ICSR1) & ICSR1_TBY) - cpu_relax(); - si->last_clk = sched_clock(); - - /* - * HACK: It looks like the TBY bit is dropped too soon. - * Without this delay things break. - */ - udelay(120); - - if (si->newspeed) { - pxa_irda_set_speed(si, si->newspeed); - si->newspeed = 0; - } else { - int i = 64; - - ficp_writel(si, 0, ICCR0); - pxa_irda_fir_dma_rx_start(si); - while ((ficp_readl(si, ICSR1) & ICSR1_RNE) && i--) - ficp_readl(si, ICDR); - ficp_writel(si, ICCR0_ITR | ICCR0_RXE, ICCR0); - - if (i < 0) - printk(KERN_ERR "pxa_ir: cannot clear Rx FIFO!\n"); - } - netif_wake_queue(dev); -} - -/* EIF(Error in FIFO/End in Frame) handler for FIR */ -static void pxa_irda_fir_irq_eif(struct pxa_irda *si, struct net_device *dev, int icsr0) -{ - unsigned int len, stat, data; - struct dma_tx_state state; - - /* Get the current data position. */ - - dmaengine_tx_status(si->rxdma, si->rx_cookie, &state); - len = IRDA_FRAME_SIZE_LIMIT - state.residue; - - do { - /* Read Status, and then Data. */ - stat = ficp_readl(si, ICSR1); - rmb(); - data = ficp_readl(si, ICDR); - - if (stat & (ICSR1_CRE | ICSR1_ROR)) { - dev->stats.rx_errors++; - if (stat & ICSR1_CRE) { - printk(KERN_DEBUG "pxa_ir: fir receive CRC error\n"); - dev->stats.rx_crc_errors++; - } - if (stat & ICSR1_ROR) { - printk(KERN_DEBUG "pxa_ir: fir receive overrun\n"); - dev->stats.rx_over_errors++; - } - } else { - si->dma_rx_buff[len++] = data; - } - /* If we hit the end of frame, there's no point in continuing. */ - if (stat & ICSR1_EOF) - break; - } while (ficp_readl(si, ICSR0) & ICSR0_EIF); - - if (stat & ICSR1_EOF) { - /* end of frame. */ - struct sk_buff *skb; - - if (icsr0 & ICSR0_FRE) { - printk(KERN_ERR "pxa_ir: dropping erroneous frame\n"); - dev->stats.rx_dropped++; - return; - } - - skb = alloc_skb(len+1,GFP_ATOMIC); - if (!skb) { - printk(KERN_ERR "pxa_ir: fir out of memory for receive skb\n"); - dev->stats.rx_dropped++; - return; - } - - /* Align IP header to 20 bytes */ - skb_reserve(skb, 1); - skb_copy_to_linear_data(skb, si->dma_rx_buff, len); - skb_put(skb, len); - - /* Feed it to IrLAP */ - skb->dev = dev; - skb_reset_mac_header(skb); - skb->protocol = htons(ETH_P_IRDA); - netif_rx(skb); - - dev->stats.rx_packets++; - dev->stats.rx_bytes += len; - } -} - -/* FIR interrupt handler */ -static irqreturn_t pxa_irda_fir_irq(int irq, void *dev_id) -{ - struct net_device *dev = dev_id; - struct pxa_irda *si = netdev_priv(dev); - int icsr0, i = 64; - - /* stop RX DMA */ - dmaengine_terminate_all(si->rxdma); - si->last_clk = sched_clock(); - icsr0 = ficp_readl(si, ICSR0); - - if (icsr0 & (ICSR0_FRE | ICSR0_RAB)) { - if (icsr0 & ICSR0_FRE) { - printk(KERN_DEBUG "pxa_ir: fir receive frame error\n"); - dev->stats.rx_frame_errors++; - } else { - printk(KERN_DEBUG "pxa_ir: fir receive abort\n"); - dev->stats.rx_errors++; - } - ficp_writel(si, icsr0 & (ICSR0_FRE | ICSR0_RAB), ICSR0); - } - - if (icsr0 & ICSR0_EIF) { - /* An error in FIFO occurred, or there is a end of frame */ - pxa_irda_fir_irq_eif(si, dev, icsr0); - } - - ficp_writel(si, 0, ICCR0); - pxa_irda_fir_dma_rx_start(si); - while ((ficp_readl(si, ICSR1) & ICSR1_RNE) && i--) - ficp_readl(si, ICDR); - ficp_writel(si, ICCR0_ITR | ICCR0_RXE, ICCR0); - - if (i < 0) - printk(KERN_ERR "pxa_ir: cannot clear Rx FIFO!\n"); - - return IRQ_HANDLED; -} - -/* hard_xmit interface of irda device */ -static int pxa_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct pxa_irda *si = netdev_priv(dev); - int speed = irda_get_next_speed(skb); - - /* - * Does this packet contain a request to change the interface - * speed? If so, remember it until we complete the transmission - * of this frame. - */ - if (speed != si->speed && speed != -1) - si->newspeed = speed; - - /* - * If this is an empty frame, we can bypass a lot. - */ - if (skb->len == 0) { - if (si->newspeed) { - si->newspeed = 0; - pxa_irda_set_speed(si, speed); - } - dev_kfree_skb(skb); - return NETDEV_TX_OK; - } - - netif_stop_queue(dev); - - if (!IS_FIR(si)) { - si->tx_buff.data = si->tx_buff.head; - si->tx_buff.len = async_wrap_skb(skb, si->tx_buff.data, si->tx_buff.truesize); - - /* Disable STUART interrupts and switch to transmit mode. */ - stuart_writel(si, 0, STIER); - stuart_writel(si, IrSR_IR_TRANSMIT_ON | IrSR_XMODE_PULSE_1_6, - STISR); - - /* enable STUART and transmit interrupts */ - stuart_writel(si, IER_UUE | IER_TIE, STIER); - } else { - unsigned long mtt = irda_get_mtt(skb); - - si->dma_tx_buff_len = skb->len; - skb_copy_from_linear_data(skb, si->dma_tx_buff, skb->len); - - if (mtt) - while ((sched_clock() - si->last_clk) * 1000 < mtt) - cpu_relax(); - - /* stop RX DMA, disable FICP */ - dmaengine_terminate_all(si->rxdma); - ficp_writel(si, 0, ICCR0); - - pxa_irda_fir_dma_tx_start(si); - ficp_writel(si, ICCR0_ITR | ICCR0_TXE, ICCR0); - } - - dev_kfree_skb(skb); - return NETDEV_TX_OK; -} - -static int pxa_irda_ioctl(struct net_device *dev, struct ifreq *ifreq, int cmd) -{ - struct if_irda_req *rq = (struct if_irda_req *)ifreq; - struct pxa_irda *si = netdev_priv(dev); - int ret; - - switch (cmd) { - case SIOCSBANDWIDTH: - ret = -EPERM; - if (capable(CAP_NET_ADMIN)) { - /* - * We are unable to set the speed if the - * device is not running. - */ - if (netif_running(dev)) { - ret = pxa_irda_set_speed(si, - rq->ifr_baudrate); - } else { - printk(KERN_INFO "pxa_ir: SIOCSBANDWIDTH: !netif_running\n"); - ret = 0; - } - } - break; - - case SIOCSMEDIABUSY: - ret = -EPERM; - if (capable(CAP_NET_ADMIN)) { - irda_device_set_media_busy(dev, TRUE); - ret = 0; - } - break; - - case SIOCGRECEIVING: - ret = 0; - rq->ifr_receiving = IS_FIR(si) ? 0 - : si->rx_buff.state != OUTSIDE_FRAME; - break; - - default: - ret = -EOPNOTSUPP; - break; - } - - return ret; -} - -static void pxa_irda_startup(struct pxa_irda *si) -{ - /* Disable STUART interrupts */ - stuart_writel(si, 0, STIER); - /* enable STUART interrupt to the processor */ - stuart_writel(si, MCR_OUT2, STMCR); - /* configure SIR frame format: StartBit - Data 7 ... Data 0 - Stop Bit */ - stuart_writel(si, LCR_WLS0 | LCR_WLS1, STLCR); - /* enable FIFO, we use FIFO to improve performance */ - stuart_writel(si, FCR_TRFIFOE | FCR_ITL_32, STFCR); - - /* disable FICP */ - ficp_writel(si, 0, ICCR0); - /* configure FICP ICCR2 */ - ficp_writel(si, ICCR2_TXP | ICCR2_TRIG_32, ICCR2); - - /* force SIR reinitialization */ - si->speed = 4000000; - pxa_irda_set_speed(si, 9600); - - printk(KERN_DEBUG "pxa_ir: irda startup\n"); -} - -static void pxa_irda_shutdown(struct pxa_irda *si) -{ - unsigned long flags; - - local_irq_save(flags); - - /* disable STUART and interrupt */ - stuart_writel(si, 0, STIER); - /* disable STUART SIR mode */ - stuart_writel(si, 0, STISR); - - /* disable DMA */ - dmaengine_terminate_all(si->rxdma); - dmaengine_terminate_all(si->txdma); - /* disable FICP */ - ficp_writel(si, 0, ICCR0); - - /* disable the STUART or FICP clocks */ - pxa_irda_disable_clk(si); - - local_irq_restore(flags); - - /* power off board transceiver */ - pxa_irda_set_mode(si, IR_OFF); - - printk(KERN_DEBUG "pxa_ir: irda shutdown\n"); -} - -static int pxa_irda_start(struct net_device *dev) -{ - struct pxa_irda *si = netdev_priv(dev); - dma_cap_mask_t mask; - struct dma_slave_config config; - struct pxad_param param; - int err; - - si->speed = 9600; - - err = request_irq(si->uart_irq, pxa_irda_sir_irq, 0, dev->name, dev); - if (err) - goto err_irq1; - - err = request_irq(si->icp_irq, pxa_irda_fir_irq, 0, dev->name, dev); - if (err) - goto err_irq2; - - /* - * The interrupt must remain disabled for now. - */ - disable_irq(si->uart_irq); - disable_irq(si->icp_irq); - - err = -EBUSY; - dma_cap_zero(mask); - dma_cap_set(DMA_SLAVE, mask); - param.prio = PXAD_PRIO_LOWEST; - - memset(&config, 0, sizeof(config)); - config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; - config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; - config.src_addr = (dma_addr_t)si->irda_base + ICDR; - config.dst_addr = (dma_addr_t)si->irda_base + ICDR; - config.src_maxburst = 32; - config.dst_maxburst = 32; - - param.drcmr = si->drcmr_rx; - si->rxdma = dma_request_slave_channel_compat(mask, pxad_filter_fn, - ¶m, &dev->dev, "rx"); - if (!si->rxdma) - goto err_rx_dma; - - param.drcmr = si->drcmr_tx; - si->txdma = dma_request_slave_channel_compat(mask, pxad_filter_fn, - ¶m, &dev->dev, "tx"); - if (!si->txdma) - goto err_tx_dma; - - err = dmaengine_slave_config(si->rxdma, &config); - if (err) - goto err_dma_rx_buff; - err = dmaengine_slave_config(si->txdma, &config); - if (err) - goto err_dma_rx_buff; - - err = -ENOMEM; - si->dma_rx_buff = dma_alloc_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT, - &si->dma_rx_buff_phy, GFP_KERNEL); - if (!si->dma_rx_buff) - goto err_dma_rx_buff; - - si->dma_tx_buff = dma_alloc_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT, - &si->dma_tx_buff_phy, GFP_KERNEL); - if (!si->dma_tx_buff) - goto err_dma_tx_buff; - - /* Setup the serial port for the initial speed. */ - pxa_irda_startup(si); - - /* - * Open a new IrLAP layer instance. - */ - si->irlap = irlap_open(dev, &si->qos, "pxa"); - err = -ENOMEM; - if (!si->irlap) - goto err_irlap; - - /* - * Now enable the interrupt and start the queue - */ - enable_irq(si->uart_irq); - enable_irq(si->icp_irq); - netif_start_queue(dev); - - printk(KERN_DEBUG "pxa_ir: irda driver opened\n"); - - return 0; - -err_irlap: - pxa_irda_shutdown(si); - dma_free_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT, si->dma_tx_buff, si->dma_tx_buff_phy); -err_dma_tx_buff: - dma_free_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT, si->dma_rx_buff, si->dma_rx_buff_phy); -err_dma_rx_buff: - dma_release_channel(si->txdma); -err_tx_dma: - dma_release_channel(si->rxdma); -err_rx_dma: - free_irq(si->icp_irq, dev); -err_irq2: - free_irq(si->uart_irq, dev); -err_irq1: - - return err; -} - -static int pxa_irda_stop(struct net_device *dev) -{ - struct pxa_irda *si = netdev_priv(dev); - - netif_stop_queue(dev); - - pxa_irda_shutdown(si); - - /* Stop IrLAP */ - if (si->irlap) { - irlap_close(si->irlap); - si->irlap = NULL; - } - - free_irq(si->uart_irq, dev); - free_irq(si->icp_irq, dev); - - dmaengine_terminate_all(si->rxdma); - dmaengine_terminate_all(si->txdma); - dma_release_channel(si->rxdma); - dma_release_channel(si->txdma); - - if (si->dma_rx_buff) - dma_free_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT, si->dma_tx_buff, si->dma_tx_buff_phy); - if (si->dma_tx_buff) - dma_free_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT, si->dma_rx_buff, si->dma_rx_buff_phy); - - printk(KERN_DEBUG "pxa_ir: irda driver closed\n"); - return 0; -} - -static int pxa_irda_suspend(struct platform_device *_dev, pm_message_t state) -{ - struct net_device *dev = platform_get_drvdata(_dev); - struct pxa_irda *si; - - if (dev && netif_running(dev)) { - si = netdev_priv(dev); - netif_device_detach(dev); - pxa_irda_shutdown(si); - } - - return 0; -} - -static int pxa_irda_resume(struct platform_device *_dev) -{ - struct net_device *dev = platform_get_drvdata(_dev); - struct pxa_irda *si; - - if (dev && netif_running(dev)) { - si = netdev_priv(dev); - pxa_irda_startup(si); - netif_device_attach(dev); - netif_wake_queue(dev); - } - - return 0; -} - - -static int pxa_irda_init_iobuf(iobuff_t *io, int size) -{ - io->head = kmalloc(size, GFP_KERNEL | GFP_DMA); - 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 const struct net_device_ops pxa_irda_netdev_ops = { - .ndo_open = pxa_irda_start, - .ndo_stop = pxa_irda_stop, - .ndo_start_xmit = pxa_irda_hard_xmit, - .ndo_do_ioctl = pxa_irda_ioctl, -}; - -static int pxa_irda_probe(struct platform_device *pdev) -{ - struct net_device *dev; - struct resource *res; - struct pxa_irda *si; - void __iomem *ficp, *stuart; - unsigned int baudrate_mask; - int err; - - if (!pdev->dev.platform_data) - return -ENODEV; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - ficp = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(ficp)) { - dev_err(&pdev->dev, "resource ficp not defined\n"); - return PTR_ERR(ficp); - } - - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - stuart = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(stuart)) { - dev_err(&pdev->dev, "resource stuart not defined\n"); - return PTR_ERR(stuart); - } - - dev = alloc_irdadev(sizeof(struct pxa_irda)); - if (!dev) { - err = -ENOMEM; - goto err_mem_1; - } - - SET_NETDEV_DEV(dev, &pdev->dev); - si = netdev_priv(dev); - si->dev = &pdev->dev; - si->pdata = pdev->dev.platform_data; - - si->irda_base = ficp; - si->stuart_base = stuart; - si->uart_irq = platform_get_irq(pdev, 0); - si->icp_irq = platform_get_irq(pdev, 1); - - si->sir_clk = devm_clk_get(&pdev->dev, "UARTCLK"); - si->fir_clk = devm_clk_get(&pdev->dev, "FICPCLK"); - if (IS_ERR(si->sir_clk) || IS_ERR(si->fir_clk)) { - err = PTR_ERR(IS_ERR(si->sir_clk) ? si->sir_clk : si->fir_clk); - goto err_mem_4; - } - - res = platform_get_resource(pdev, IORESOURCE_DMA, 0); - if (res) - si->drcmr_rx = res->start; - res = platform_get_resource(pdev, IORESOURCE_DMA, 1); - if (res) - si->drcmr_tx = res->start; - - /* - * Initialise the SIR buffers - */ - err = pxa_irda_init_iobuf(&si->rx_buff, 14384); - if (err) - goto err_mem_4; - err = pxa_irda_init_iobuf(&si->tx_buff, 4000); - if (err) - goto err_mem_5; - - if (gpio_is_valid(si->pdata->gpio_pwdown)) { - err = gpio_request(si->pdata->gpio_pwdown, "IrDA switch"); - if (err) - goto err_startup; - err = gpio_direction_output(si->pdata->gpio_pwdown, - !si->pdata->gpio_pwdown_inverted); - if (err) { - gpio_free(si->pdata->gpio_pwdown); - goto err_startup; - } - } - - if (si->pdata->startup) { - err = si->pdata->startup(si->dev); - if (err) - goto err_startup; - } - - if (gpio_is_valid(si->pdata->gpio_pwdown) && si->pdata->startup) - dev_warn(si->dev, "gpio_pwdown and startup() both defined!\n"); - - dev->netdev_ops = &pxa_irda_netdev_ops; - - irda_init_max_qos_capabilies(&si->qos); - - baudrate_mask = 0; - if (si->pdata->transceiver_cap & IR_SIRMODE) - baudrate_mask |= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200; - if (si->pdata->transceiver_cap & IR_FIRMODE) - baudrate_mask |= IR_4000000 << 8; - - si->qos.baud_rate.bits &= baudrate_mask; - si->qos.min_turn_time.bits = 7; /* 1ms or more */ - - irda_qos_bits_to_value(&si->qos); - - err = register_netdev(dev); - - if (err == 0) - platform_set_drvdata(pdev, dev); - - if (err) { - if (si->pdata->shutdown) - si->pdata->shutdown(si->dev); -err_startup: - kfree(si->tx_buff.head); -err_mem_5: - kfree(si->rx_buff.head); -err_mem_4: - free_netdev(dev); - } -err_mem_1: - return err; -} - -static int pxa_irda_remove(struct platform_device *_dev) -{ - struct net_device *dev = platform_get_drvdata(_dev); - - if (dev) { - struct pxa_irda *si = netdev_priv(dev); - unregister_netdev(dev); - if (gpio_is_valid(si->pdata->gpio_pwdown)) - gpio_free(si->pdata->gpio_pwdown); - if (si->pdata->shutdown) - si->pdata->shutdown(si->dev); - kfree(si->tx_buff.head); - kfree(si->rx_buff.head); - free_netdev(dev); - } - - return 0; -} - -static struct platform_driver pxa_ir_driver = { - .driver = { - .name = "pxa2xx-ir", - }, - .probe = pxa_irda_probe, - .remove = pxa_irda_remove, - .suspend = pxa_irda_suspend, - .resume = pxa_irda_resume, -}; - -module_platform_driver(pxa_ir_driver); - -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:pxa2xx-ir"); diff --git a/drivers/net/irda/sa1100_ir.c b/drivers/net/irda/sa1100_ir.c deleted file mode 100644 index b6e44ff4e373..000000000000 --- a/drivers/net/irda/sa1100_ir.c +++ /dev/null @@ -1,1150 +0,0 @@ -/* - * linux/drivers/net/irda/sa1100_ir.c - * - * Copyright (C) 2000-2001 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Infra-red driver for the StrongARM SA1100 embedded microprocessor - * - * Note that we don't have to worry about the SA1111's DMA bugs in here, - * so we use the straight forward dma_map_* functions with a null pointer. - * - * This driver takes one kernel command line parameter, sa1100ir=, with - * the following options: - * max_rate:baudrate - set the maximum baud rate - * power_level:level - set the transmitter power level - * tx_lpm:0|1 - set transmit low power mode - */ -#include <linux/module.h> -#include <linux/moduleparam.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/delay.h> -#include <linux/platform_device.h> -#include <linux/dma-mapping.h> -#include <linux/dmaengine.h> -#include <linux/sa11x0-dma.h> - -#include <net/irda/irda.h> -#include <net/irda/wrapper.h> -#include <net/irda/irda_device.h> - -#include <mach/hardware.h> -#include <linux/platform_data/irda-sa11x0.h> - -static int power_level = 3; -static int tx_lpm; -static int max_rate = 4000000; - -struct sa1100_buf { - struct device *dev; - struct sk_buff *skb; - struct scatterlist sg; - struct dma_chan *chan; - dma_cookie_t cookie; -}; - -struct sa1100_irda { - unsigned char utcr4; - unsigned char power; - unsigned char open; - - int speed; - int newspeed; - - struct sa1100_buf dma_rx; - struct sa1100_buf dma_tx; - - struct device *dev; - struct irda_platform_data *pdata; - struct irlap_cb *irlap; - struct qos_info qos; - - iobuff_t tx_buff; - iobuff_t rx_buff; - - int (*tx_start)(struct sk_buff *, struct net_device *, struct sa1100_irda *); - irqreturn_t (*irq)(struct net_device *, struct sa1100_irda *); -}; - -static int sa1100_irda_set_speed(struct sa1100_irda *, int); - -#define IS_FIR(si) ((si)->speed >= 4000000) - -#define HPSIR_MAX_RXLEN 2047 - -static struct dma_slave_config sa1100_irda_sir_tx = { - .direction = DMA_TO_DEVICE, - .dst_addr = __PREG(Ser2UTDR), - .dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE, - .dst_maxburst = 4, -}; - -static struct dma_slave_config sa1100_irda_fir_rx = { - .direction = DMA_FROM_DEVICE, - .src_addr = __PREG(Ser2HSDR), - .src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE, - .src_maxburst = 8, -}; - -static struct dma_slave_config sa1100_irda_fir_tx = { - .direction = DMA_TO_DEVICE, - .dst_addr = __PREG(Ser2HSDR), - .dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE, - .dst_maxburst = 8, -}; - -static unsigned sa1100_irda_dma_xferred(struct sa1100_buf *buf) -{ - struct dma_chan *chan = buf->chan; - struct dma_tx_state state; - enum dma_status status; - - status = chan->device->device_tx_status(chan, buf->cookie, &state); - if (status != DMA_PAUSED) - return 0; - - return sg_dma_len(&buf->sg) - state.residue; -} - -static int sa1100_irda_dma_request(struct device *dev, struct sa1100_buf *buf, - const char *name, struct dma_slave_config *cfg) -{ - dma_cap_mask_t m; - int ret; - - dma_cap_zero(m); - dma_cap_set(DMA_SLAVE, m); - - buf->chan = dma_request_channel(m, sa11x0_dma_filter_fn, (void *)name); - if (!buf->chan) { - dev_err(dev, "unable to request DMA channel for %s\n", - name); - return -ENOENT; - } - - ret = dmaengine_slave_config(buf->chan, cfg); - if (ret) - dev_warn(dev, "DMA slave_config for %s returned %d\n", - name, ret); - - buf->dev = buf->chan->device->dev; - - return 0; -} - -static void sa1100_irda_dma_start(struct sa1100_buf *buf, - enum dma_transfer_direction dir, dma_async_tx_callback cb, void *cb_p) -{ - struct dma_async_tx_descriptor *desc; - struct dma_chan *chan = buf->chan; - - desc = dmaengine_prep_slave_sg(chan, &buf->sg, 1, dir, - DMA_PREP_INTERRUPT | DMA_CTRL_ACK); - if (desc) { - desc->callback = cb; - desc->callback_param = cb_p; - buf->cookie = dmaengine_submit(desc); - dma_async_issue_pending(chan); - } -} - -/* - * Allocate and map the receive buffer, unless it is already allocated. - */ -static int sa1100_irda_rx_alloc(struct sa1100_irda *si) -{ - if (si->dma_rx.skb) - return 0; - - si->dma_rx.skb = alloc_skb(HPSIR_MAX_RXLEN + 1, GFP_ATOMIC); - if (!si->dma_rx.skb) { - printk(KERN_ERR "sa1100_ir: out of memory for RX SKB\n"); - return -ENOMEM; - } - - /* - * Align any IP headers that may be contained - * within the frame. - */ - skb_reserve(si->dma_rx.skb, 1); - - sg_set_buf(&si->dma_rx.sg, si->dma_rx.skb->data, HPSIR_MAX_RXLEN); - if (dma_map_sg(si->dma_rx.dev, &si->dma_rx.sg, 1, DMA_FROM_DEVICE) == 0) { - dev_kfree_skb_any(si->dma_rx.skb); - return -ENOMEM; - } - - return 0; -} - -/* - * We want to get here as soon as possible, and get the receiver setup. - * We use the existing buffer. - */ -static void sa1100_irda_rx_dma_start(struct sa1100_irda *si) -{ - if (!si->dma_rx.skb) { - printk(KERN_ERR "sa1100_ir: rx buffer went missing\n"); - return; - } - - /* - * First empty receive FIFO - */ - Ser2HSCR0 = HSCR0_HSSP; - - /* - * Enable the DMA, receiver and receive interrupt. - */ - dmaengine_terminate_all(si->dma_rx.chan); - sa1100_irda_dma_start(&si->dma_rx, DMA_DEV_TO_MEM, NULL, NULL); - - Ser2HSCR0 = HSCR0_HSSP | HSCR0_RXE; -} - -static void sa1100_irda_check_speed(struct sa1100_irda *si) -{ - if (si->newspeed) { - sa1100_irda_set_speed(si, si->newspeed); - si->newspeed = 0; - } -} - -/* - * HP-SIR format support. - */ -static void sa1100_irda_sirtxdma_irq(void *id) -{ - struct net_device *dev = id; - struct sa1100_irda *si = netdev_priv(dev); - - dma_unmap_sg(si->dma_tx.dev, &si->dma_tx.sg, 1, DMA_TO_DEVICE); - dev_kfree_skb(si->dma_tx.skb); - si->dma_tx.skb = NULL; - - dev->stats.tx_packets++; - dev->stats.tx_bytes += sg_dma_len(&si->dma_tx.sg); - - /* We need to ensure that the transmitter has finished. */ - do - rmb(); - while (Ser2UTSR1 & UTSR1_TBY); - - /* - * Ok, we've finished transmitting. Now enable the receiver. - * Sometimes we get a receive IRQ immediately after a transmit... - */ - Ser2UTSR0 = UTSR0_REB | UTSR0_RBB | UTSR0_RID; - Ser2UTCR3 = UTCR3_RIE | UTCR3_RXE | UTCR3_TXE; - - sa1100_irda_check_speed(si); - - /* I'm hungry! */ - netif_wake_queue(dev); -} - -static int sa1100_irda_sir_tx_start(struct sk_buff *skb, struct net_device *dev, - struct sa1100_irda *si) -{ - si->tx_buff.data = si->tx_buff.head; - si->tx_buff.len = async_wrap_skb(skb, si->tx_buff.data, - si->tx_buff.truesize); - - si->dma_tx.skb = skb; - sg_set_buf(&si->dma_tx.sg, si->tx_buff.data, si->tx_buff.len); - if (dma_map_sg(si->dma_tx.dev, &si->dma_tx.sg, 1, DMA_TO_DEVICE) == 0) { - si->dma_tx.skb = NULL; - netif_wake_queue(dev); - dev->stats.tx_dropped++; - return NETDEV_TX_OK; - } - - sa1100_irda_dma_start(&si->dma_tx, DMA_MEM_TO_DEV, sa1100_irda_sirtxdma_irq, dev); - - /* - * The mean turn-around time is enforced by XBOF padding, - * so we don't have to do anything special here. - */ - Ser2UTCR3 = UTCR3_TXE; - - return NETDEV_TX_OK; -} - -static irqreturn_t sa1100_irda_sir_irq(struct net_device *dev, struct sa1100_irda *si) -{ - int status; - - status = Ser2UTSR0; - - /* - * Deal with any receive errors first. The bytes in error may be - * the only bytes in the receive FIFO, so we do this first. - */ - while (status & UTSR0_EIF) { - int stat, data; - - stat = Ser2UTSR1; - data = Ser2UTDR; - - if (stat & (UTSR1_FRE | UTSR1_ROR)) { - dev->stats.rx_errors++; - if (stat & UTSR1_FRE) - dev->stats.rx_frame_errors++; - if (stat & UTSR1_ROR) - dev->stats.rx_fifo_errors++; - } else - async_unwrap_char(dev, &dev->stats, &si->rx_buff, data); - - status = Ser2UTSR0; - } - - /* - * We must clear certain bits. - */ - Ser2UTSR0 = status & (UTSR0_RID | UTSR0_RBB | UTSR0_REB); - - if (status & UTSR0_RFS) { - /* - * There are at least 4 bytes in the FIFO. Read 3 bytes - * and leave the rest to the block below. - */ - async_unwrap_char(dev, &dev->stats, &si->rx_buff, Ser2UTDR); - async_unwrap_char(dev, &dev->stats, &si->rx_buff, Ser2UTDR); - async_unwrap_char(dev, &dev->stats, &si->rx_buff, Ser2UTDR); - } - - if (status & (UTSR0_RFS | UTSR0_RID)) { - /* - * Fifo contains more than 1 character. - */ - do { - async_unwrap_char(dev, &dev->stats, &si->rx_buff, - Ser2UTDR); - } while (Ser2UTSR1 & UTSR1_RNE); - - } - - return IRQ_HANDLED; -} - -/* - * FIR format support. - */ -static void sa1100_irda_firtxdma_irq(void *id) -{ - struct net_device *dev = id; - struct sa1100_irda *si = netdev_priv(dev); - struct sk_buff *skb; - - /* - * Wait for the transmission to complete. Unfortunately, - * the hardware doesn't give us an interrupt to indicate - * "end of frame". - */ - do - rmb(); - while (!(Ser2HSSR0 & HSSR0_TUR) || Ser2HSSR1 & HSSR1_TBY); - - /* - * Clear the transmit underrun bit. - */ - Ser2HSSR0 = HSSR0_TUR; - - /* - * Do we need to change speed? Note that we're lazy - * here - we don't free the old dma_rx.skb. We don't need - * to allocate a buffer either. - */ - sa1100_irda_check_speed(si); - - /* - * Start reception. This disables the transmitter for - * us. This will be using the existing RX buffer. - */ - sa1100_irda_rx_dma_start(si); - - /* Account and free the packet. */ - skb = si->dma_tx.skb; - if (skb) { - dma_unmap_sg(si->dma_tx.dev, &si->dma_tx.sg, 1, - DMA_TO_DEVICE); - dev->stats.tx_packets ++; - dev->stats.tx_bytes += skb->len; - dev_kfree_skb_irq(skb); - si->dma_tx.skb = NULL; - } - - /* - * Make sure that the TX queue is available for sending - * (for retries). TX has priority over RX at all times. - */ - netif_wake_queue(dev); -} - -static int sa1100_irda_fir_tx_start(struct sk_buff *skb, struct net_device *dev, - struct sa1100_irda *si) -{ - int mtt = irda_get_mtt(skb); - - si->dma_tx.skb = skb; - sg_set_buf(&si->dma_tx.sg, skb->data, skb->len); - if (dma_map_sg(si->dma_tx.dev, &si->dma_tx.sg, 1, DMA_TO_DEVICE) == 0) { - si->dma_tx.skb = NULL; - netif_wake_queue(dev); - dev->stats.tx_dropped++; - dev_kfree_skb(skb); - return NETDEV_TX_OK; - } - - sa1100_irda_dma_start(&si->dma_tx, DMA_MEM_TO_DEV, sa1100_irda_firtxdma_irq, dev); - - /* - * If we have a mean turn-around time, impose the specified - * specified delay. We could shorten this by timing from - * the point we received the packet. - */ - if (mtt) - udelay(mtt); - - Ser2HSCR0 = HSCR0_HSSP | HSCR0_TXE; - - return NETDEV_TX_OK; -} - -static void sa1100_irda_fir_error(struct sa1100_irda *si, struct net_device *dev) -{ - struct sk_buff *skb = si->dma_rx.skb; - unsigned int len, stat, data; - - if (!skb) { - printk(KERN_ERR "sa1100_ir: SKB is NULL!\n"); - return; - } - - /* - * Get the current data position. - */ - len = sa1100_irda_dma_xferred(&si->dma_rx); - if (len > HPSIR_MAX_RXLEN) - len = HPSIR_MAX_RXLEN; - dma_unmap_sg(si->dma_rx.dev, &si->dma_rx.sg, 1, DMA_FROM_DEVICE); - - do { - /* - * Read Status, and then Data. - */ - stat = Ser2HSSR1; - rmb(); - data = Ser2HSDR; - - if (stat & (HSSR1_CRE | HSSR1_ROR)) { - dev->stats.rx_errors++; - if (stat & HSSR1_CRE) - dev->stats.rx_crc_errors++; - if (stat & HSSR1_ROR) - dev->stats.rx_frame_errors++; - } else - skb->data[len++] = data; - - /* - * If we hit the end of frame, there's - * no point in continuing. - */ - if (stat & HSSR1_EOF) - break; - } while (Ser2HSSR0 & HSSR0_EIF); - - if (stat & HSSR1_EOF) { - si->dma_rx.skb = NULL; - - skb_put(skb, len); - skb->dev = dev; - skb_reset_mac_header(skb); - skb->protocol = htons(ETH_P_IRDA); - dev->stats.rx_packets++; - dev->stats.rx_bytes += len; - - /* - * Before we pass the buffer up, allocate a new one. - */ - sa1100_irda_rx_alloc(si); - - netif_rx(skb); - } else { - /* - * Remap the buffer - it was previously mapped, and we - * hope that this succeeds. - */ - dma_map_sg(si->dma_rx.dev, &si->dma_rx.sg, 1, DMA_FROM_DEVICE); - } -} - -/* - * We only have to handle RX events here; transmit events go via the TX - * DMA handler. We disable RX, process, and the restart RX. - */ -static irqreturn_t sa1100_irda_fir_irq(struct net_device *dev, struct sa1100_irda *si) -{ - /* - * Stop RX DMA - */ - dmaengine_pause(si->dma_rx.chan); - - /* - * Framing error - we throw away the packet completely. - * Clearing RXE flushes the error conditions and data - * from the fifo. - */ - if (Ser2HSSR0 & (HSSR0_FRE | HSSR0_RAB)) { - dev->stats.rx_errors++; - - if (Ser2HSSR0 & HSSR0_FRE) - dev->stats.rx_frame_errors++; - - /* - * Clear out the DMA... - */ - Ser2HSCR0 = HSCR0_HSSP; - - /* - * Clear selected status bits now, so we - * don't miss them next time around. - */ - Ser2HSSR0 = HSSR0_FRE | HSSR0_RAB; - } - - /* - * Deal with any receive errors. The any of the lowest - * 8 bytes in the FIFO may contain an error. We must read - * them one by one. The "error" could even be the end of - * packet! - */ - if (Ser2HSSR0 & HSSR0_EIF) - sa1100_irda_fir_error(si, dev); - - /* - * No matter what happens, we must restart reception. - */ - sa1100_irda_rx_dma_start(si); - - return IRQ_HANDLED; -} - -/* - * Set the IrDA communications speed. - */ -static int sa1100_irda_set_speed(struct sa1100_irda *si, int speed) -{ - unsigned long flags; - int brd, ret = -EINVAL; - - switch (speed) { - case 9600: case 19200: case 38400: - case 57600: case 115200: - brd = 3686400 / (16 * speed) - 1; - - /* Stop the receive DMA, and configure transmit. */ - if (IS_FIR(si)) { - dmaengine_terminate_all(si->dma_rx.chan); - dmaengine_slave_config(si->dma_tx.chan, - &sa1100_irda_sir_tx); - } - - local_irq_save(flags); - - Ser2UTCR3 = 0; - Ser2HSCR0 = HSCR0_UART; - - Ser2UTCR1 = brd >> 8; - Ser2UTCR2 = brd; - - /* - * Clear status register - */ - Ser2UTSR0 = UTSR0_REB | UTSR0_RBB | UTSR0_RID; - Ser2UTCR3 = UTCR3_RIE | UTCR3_RXE | UTCR3_TXE; - - if (si->pdata->set_speed) - si->pdata->set_speed(si->dev, speed); - - si->speed = speed; - si->tx_start = sa1100_irda_sir_tx_start; - si->irq = sa1100_irda_sir_irq; - - local_irq_restore(flags); - ret = 0; - break; - - case 4000000: - if (!IS_FIR(si)) - dmaengine_slave_config(si->dma_tx.chan, - &sa1100_irda_fir_tx); - - local_irq_save(flags); - - Ser2HSSR0 = 0xff; - Ser2HSCR0 = HSCR0_HSSP; - Ser2UTCR3 = 0; - - si->speed = speed; - si->tx_start = sa1100_irda_fir_tx_start; - si->irq = sa1100_irda_fir_irq; - - if (si->pdata->set_speed) - si->pdata->set_speed(si->dev, speed); - - sa1100_irda_rx_alloc(si); - sa1100_irda_rx_dma_start(si); - - local_irq_restore(flags); - - break; - - default: - break; - } - - return ret; -} - -/* - * Control the power state of the IrDA transmitter. - * State: - * 0 - off - * 1 - short range, lowest power - * 2 - medium range, medium power - * 3 - maximum range, high power - * - * Currently, only assabet is known to support this. - */ -static int -__sa1100_irda_set_power(struct sa1100_irda *si, unsigned int state) -{ - int ret = 0; - if (si->pdata->set_power) - ret = si->pdata->set_power(si->dev, state); - return ret; -} - -static inline int -sa1100_set_power(struct sa1100_irda *si, unsigned int state) -{ - int ret; - - ret = __sa1100_irda_set_power(si, state); - if (ret == 0) - si->power = state; - - return ret; -} - -static irqreturn_t sa1100_irda_irq(int irq, void *dev_id) -{ - struct net_device *dev = dev_id; - struct sa1100_irda *si = netdev_priv(dev); - - return si->irq(dev, si); -} - -static int sa1100_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct sa1100_irda *si = netdev_priv(dev); - int speed = irda_get_next_speed(skb); - - /* - * Does this packet contain a request to change the interface - * speed? If so, remember it until we complete the transmission - * of this frame. - */ - if (speed != si->speed && speed != -1) - si->newspeed = speed; - - /* If this is an empty frame, we can bypass a lot. */ - if (skb->len == 0) { - sa1100_irda_check_speed(si); - dev_kfree_skb(skb); - return NETDEV_TX_OK; - } - - netif_stop_queue(dev); - - /* We must not already have a skb to transmit... */ - BUG_ON(si->dma_tx.skb); - - return si->tx_start(skb, dev, si); -} - -static int -sa1100_irda_ioctl(struct net_device *dev, struct ifreq *ifreq, int cmd) -{ - struct if_irda_req *rq = (struct if_irda_req *)ifreq; - struct sa1100_irda *si = 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 (si->open) { - ret = sa1100_irda_set_speed(si, - rq->ifr_baudrate); - } else { - printk("sa1100_irda_ioctl: SIOCSBANDWIDTH: !netif_running\n"); - 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 = IS_FIR(si) ? 0 - : si->rx_buff.state != OUTSIDE_FRAME; - break; - - default: - break; - } - - return ret; -} - -static int sa1100_irda_startup(struct sa1100_irda *si) -{ - int ret; - - /* - * Ensure that the ports for this device are setup correctly. - */ - if (si->pdata->startup) { - ret = si->pdata->startup(si->dev); - if (ret) - return ret; - } - - /* - * Configure PPC for IRDA - we want to drive TXD2 low. - * We also want to drive this pin low during sleep. - */ - PPSR &= ~PPC_TXD2; - PSDR &= ~PPC_TXD2; - PPDR |= PPC_TXD2; - - /* - * Enable HP-SIR modulation, and ensure that the port is disabled. - */ - Ser2UTCR3 = 0; - Ser2HSCR0 = HSCR0_UART; - Ser2UTCR4 = si->utcr4; - Ser2UTCR0 = UTCR0_8BitData; - Ser2HSCR2 = HSCR2_TrDataH | HSCR2_RcDataL; - - /* - * Clear status register - */ - Ser2UTSR0 = UTSR0_REB | UTSR0_RBB | UTSR0_RID; - - ret = sa1100_irda_set_speed(si, si->speed = 9600); - if (ret) { - Ser2UTCR3 = 0; - Ser2HSCR0 = 0; - - if (si->pdata->shutdown) - si->pdata->shutdown(si->dev); - } - - return ret; -} - -static void sa1100_irda_shutdown(struct sa1100_irda *si) -{ - /* - * Stop all DMA activity. - */ - dmaengine_terminate_all(si->dma_rx.chan); - dmaengine_terminate_all(si->dma_tx.chan); - - /* Disable the port. */ - Ser2UTCR3 = 0; - Ser2HSCR0 = 0; - - if (si->pdata->shutdown) - si->pdata->shutdown(si->dev); -} - -static int sa1100_irda_start(struct net_device *dev) -{ - struct sa1100_irda *si = netdev_priv(dev); - int err; - - si->speed = 9600; - - err = sa1100_irda_dma_request(si->dev, &si->dma_rx, "Ser2ICPRc", - &sa1100_irda_fir_rx); - if (err) - goto err_rx_dma; - - err = sa1100_irda_dma_request(si->dev, &si->dma_tx, "Ser2ICPTr", - &sa1100_irda_sir_tx); - if (err) - goto err_tx_dma; - - /* - * Setup the serial port for the specified speed. - */ - err = sa1100_irda_startup(si); - if (err) - goto err_startup; - - /* - * Open a new IrLAP layer instance. - */ - si->irlap = irlap_open(dev, &si->qos, "sa1100"); - err = -ENOMEM; - if (!si->irlap) - goto err_irlap; - - err = request_irq(dev->irq, sa1100_irda_irq, 0, dev->name, dev); - if (err) - goto err_irq; - - /* - * Now enable the interrupt and start the queue - */ - si->open = 1; - sa1100_set_power(si, power_level); /* low power mode */ - - netif_start_queue(dev); - return 0; - -err_irq: - irlap_close(si->irlap); -err_irlap: - si->open = 0; - sa1100_irda_shutdown(si); -err_startup: - dma_release_channel(si->dma_tx.chan); -err_tx_dma: - dma_release_channel(si->dma_rx.chan); -err_rx_dma: - return err; -} - -static int sa1100_irda_stop(struct net_device *dev) -{ - struct sa1100_irda *si = netdev_priv(dev); - struct sk_buff *skb; - - netif_stop_queue(dev); - - si->open = 0; - sa1100_irda_shutdown(si); - - /* - * If we have been doing any DMA activity, make sure we - * tidy that up cleanly. - */ - skb = si->dma_rx.skb; - if (skb) { - dma_unmap_sg(si->dma_rx.dev, &si->dma_rx.sg, 1, - DMA_FROM_DEVICE); - dev_kfree_skb(skb); - si->dma_rx.skb = NULL; - } - - skb = si->dma_tx.skb; - if (skb) { - dma_unmap_sg(si->dma_tx.dev, &si->dma_tx.sg, 1, - DMA_TO_DEVICE); - dev_kfree_skb(skb); - si->dma_tx.skb = NULL; - } - - /* Stop IrLAP */ - if (si->irlap) { - irlap_close(si->irlap); - si->irlap = NULL; - } - - /* - * Free resources - */ - dma_release_channel(si->dma_tx.chan); - dma_release_channel(si->dma_rx.chan); - free_irq(dev->irq, dev); - - sa1100_set_power(si, 0); - - return 0; -} - -static int sa1100_irda_init_iobuf(iobuff_t *io, int size) -{ - io->head = kmalloc(size, GFP_KERNEL | GFP_DMA); - 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 const struct net_device_ops sa1100_irda_netdev_ops = { - .ndo_open = sa1100_irda_start, - .ndo_stop = sa1100_irda_stop, - .ndo_start_xmit = sa1100_irda_hard_xmit, - .ndo_do_ioctl = sa1100_irda_ioctl, -}; - -static int sa1100_irda_probe(struct platform_device *pdev) -{ - struct net_device *dev; - struct sa1100_irda *si; - unsigned int baudrate_mask; - int err, irq; - - if (!pdev->dev.platform_data) - return -EINVAL; - - irq = platform_get_irq(pdev, 0); - if (irq <= 0) - return irq < 0 ? irq : -ENXIO; - - err = request_mem_region(__PREG(Ser2UTCR0), 0x24, "IrDA") ? 0 : -EBUSY; - if (err) - goto err_mem_1; - err = request_mem_region(__PREG(Ser2HSCR0), 0x1c, "IrDA") ? 0 : -EBUSY; - if (err) - goto err_mem_2; - err = request_mem_region(__PREG(Ser2HSCR2), 0x04, "IrDA") ? 0 : -EBUSY; - if (err) - goto err_mem_3; - - dev = alloc_irdadev(sizeof(struct sa1100_irda)); - if (!dev) { - err = -ENOMEM; - goto err_mem_4; - } - - SET_NETDEV_DEV(dev, &pdev->dev); - - si = netdev_priv(dev); - si->dev = &pdev->dev; - si->pdata = pdev->dev.platform_data; - - sg_init_table(&si->dma_rx.sg, 1); - sg_init_table(&si->dma_tx.sg, 1); - - /* - * Initialise the HP-SIR buffers - */ - err = sa1100_irda_init_iobuf(&si->rx_buff, 14384); - if (err) - goto err_mem_5; - err = sa1100_irda_init_iobuf(&si->tx_buff, IRDA_SIR_MAX_FRAME); - if (err) - goto err_mem_5; - - dev->netdev_ops = &sa1100_irda_netdev_ops; - dev->irq = irq; - - irda_init_max_qos_capabilies(&si->qos); - - /* - * We support original IRDA up to 115k2. (we don't currently - * support 4Mbps). Min Turn Time set to 1ms or greater. - */ - baudrate_mask = IR_9600; - - switch (max_rate) { - case 4000000: baudrate_mask |= IR_4000000 << 8; - case 115200: baudrate_mask |= IR_115200; - case 57600: baudrate_mask |= IR_57600; - case 38400: baudrate_mask |= IR_38400; - case 19200: baudrate_mask |= IR_19200; - } - - si->qos.baud_rate.bits &= baudrate_mask; - si->qos.min_turn_time.bits = 7; - - irda_qos_bits_to_value(&si->qos); - - si->utcr4 = UTCR4_HPSIR; - if (tx_lpm) - si->utcr4 |= UTCR4_Z1_6us; - - /* - * Initially enable HP-SIR modulation, and ensure that the port - * is disabled. - */ - Ser2UTCR3 = 0; - Ser2UTCR4 = si->utcr4; - Ser2HSCR0 = HSCR0_UART; - - err = register_netdev(dev); - if (err == 0) - platform_set_drvdata(pdev, dev); - - if (err) { - err_mem_5: - kfree(si->tx_buff.head); - kfree(si->rx_buff.head); - free_netdev(dev); - err_mem_4: - release_mem_region(__PREG(Ser2HSCR2), 0x04); - err_mem_3: - release_mem_region(__PREG(Ser2HSCR0), 0x1c); - err_mem_2: - release_mem_region(__PREG(Ser2UTCR0), 0x24); - } - err_mem_1: - return err; -} - -static int sa1100_irda_remove(struct platform_device *pdev) -{ - struct net_device *dev = platform_get_drvdata(pdev); - - if (dev) { - struct sa1100_irda *si = netdev_priv(dev); - unregister_netdev(dev); - kfree(si->tx_buff.head); - kfree(si->rx_buff.head); - free_netdev(dev); - } - - release_mem_region(__PREG(Ser2HSCR2), 0x04); - release_mem_region(__PREG(Ser2HSCR0), 0x1c); - release_mem_region(__PREG(Ser2UTCR0), 0x24); - - return 0; -} - -#ifdef CONFIG_PM -/* - * Suspend the IrDA interface. - */ -static int sa1100_irda_suspend(struct platform_device *pdev, pm_message_t state) -{ - struct net_device *dev = platform_get_drvdata(pdev); - struct sa1100_irda *si; - - if (!dev) - return 0; - - si = netdev_priv(dev); - if (si->open) { - /* - * Stop the transmit queue - */ - netif_device_detach(dev); - disable_irq(dev->irq); - sa1100_irda_shutdown(si); - __sa1100_irda_set_power(si, 0); - } - - return 0; -} - -/* - * Resume the IrDA interface. - */ -static int sa1100_irda_resume(struct platform_device *pdev) -{ - struct net_device *dev = platform_get_drvdata(pdev); - struct sa1100_irda *si; - - if (!dev) - return 0; - - si = netdev_priv(dev); - if (si->open) { - /* - * If we missed a speed change, initialise at the new speed - * directly. It is debatable whether this is actually - * required, but in the interests of continuing from where - * we left off it is desirable. The converse argument is - * that we should re-negotiate at 9600 baud again. - */ - if (si->newspeed) { - si->speed = si->newspeed; - si->newspeed = 0; - } - - sa1100_irda_startup(si); - __sa1100_irda_set_power(si, si->power); - enable_irq(dev->irq); - - /* - * This automatically wakes up the queue - */ - netif_device_attach(dev); - } - - return 0; -} -#else -#define sa1100_irda_suspend NULL -#define sa1100_irda_resume NULL -#endif - -static struct platform_driver sa1100ir_driver = { - .probe = sa1100_irda_probe, - .remove = sa1100_irda_remove, - .suspend = sa1100_irda_suspend, - .resume = sa1100_irda_resume, - .driver = { - .name = "sa11x0-ir", - }, -}; - -static int __init sa1100_irda_init(void) -{ - /* - * Limit power level a sensible range. - */ - if (power_level < 1) - power_level = 1; - if (power_level > 3) - power_level = 3; - - return platform_driver_register(&sa1100ir_driver); -} - -static void __exit sa1100_irda_exit(void) -{ - platform_driver_unregister(&sa1100ir_driver); -} - -module_init(sa1100_irda_init); -module_exit(sa1100_irda_exit); -module_param(power_level, int, 0); -module_param(tx_lpm, int, 0); -module_param(max_rate, int, 0); - -MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>"); -MODULE_DESCRIPTION("StrongARM SA1100 IrDA driver"); -MODULE_LICENSE("GPL"); -MODULE_PARM_DESC(power_level, "IrDA power level, 1 (low) to 3 (high)"); -MODULE_PARM_DESC(tx_lpm, "Enable transmitter low power (1.6us) mode"); -MODULE_PARM_DESC(max_rate, "Maximum baud rate (4000000, 115200, 57600, 38400, 19200, 9600)"); -MODULE_ALIAS("platform:sa11x0-ir"); diff --git a/drivers/net/irda/sh_sir.c b/drivers/net/irda/sh_sir.c deleted file mode 100644 index fede6864c737..000000000000 --- a/drivers/net/irda/sh_sir.c +++ /dev/null @@ -1,810 +0,0 @@ -/* - * SuperH IrDA Driver - * - * Copyright (C) 2009 Renesas Solutions Corp. - * Kuninori Morimoto <morimoto.kuninori@renesas.com> - * - * Based on bfin_sir.c - * Copyright 2006-2009 Analog Devices Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <linux/io.h> -#include <linux/interrupt.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/slab.h> -#include <net/irda/wrapper.h> -#include <net/irda/irda_device.h> -#include <asm/clock.h> - -#define DRIVER_NAME "sh_sir" - -#define RX_PHASE (1 << 0) -#define TX_PHASE (1 << 1) -#define TX_COMP_PHASE (1 << 2) /* tx complete */ -#define NONE_PHASE (1 << 31) - -#define IRIF_RINTCLR 0x0016 /* DMA rx interrupt source clear */ -#define IRIF_TINTCLR 0x0018 /* DMA tx interrupt source clear */ -#define IRIF_SIR0 0x0020 /* IrDA-SIR10 control */ -#define IRIF_SIR1 0x0022 /* IrDA-SIR10 baudrate error correction */ -#define IRIF_SIR2 0x0024 /* IrDA-SIR10 baudrate count */ -#define IRIF_SIR3 0x0026 /* IrDA-SIR10 status */ -#define IRIF_SIR_FRM 0x0028 /* Hardware frame processing set */ -#define IRIF_SIR_EOF 0x002A /* EOF value */ -#define IRIF_SIR_FLG 0x002C /* Flag clear */ -#define IRIF_UART_STS2 0x002E /* UART status 2 */ -#define IRIF_UART0 0x0030 /* UART control */ -#define IRIF_UART1 0x0032 /* UART status */ -#define IRIF_UART2 0x0034 /* UART mode */ -#define IRIF_UART3 0x0036 /* UART transmit data */ -#define IRIF_UART4 0x0038 /* UART receive data */ -#define IRIF_UART5 0x003A /* UART interrupt mask */ -#define IRIF_UART6 0x003C /* UART baud rate error correction */ -#define IRIF_UART7 0x003E /* UART baud rate count set */ -#define IRIF_CRC0 0x0040 /* CRC engine control */ -#define IRIF_CRC1 0x0042 /* CRC engine input data */ -#define IRIF_CRC2 0x0044 /* CRC engine calculation */ -#define IRIF_CRC3 0x0046 /* CRC engine output data 1 */ -#define IRIF_CRC4 0x0048 /* CRC engine output data 2 */ - -/* IRIF_SIR0 */ -#define IRTPW (1 << 1) /* transmit pulse width select */ -#define IRERRC (1 << 0) /* Clear receive pulse width error */ - -/* IRIF_SIR3 */ -#define IRERR (1 << 0) /* received pulse width Error */ - -/* IRIF_SIR_FRM */ -#define EOFD (1 << 9) /* EOF detection flag */ -#define FRER (1 << 8) /* Frame Error bit */ -#define FRP (1 << 0) /* Frame processing set */ - -/* IRIF_UART_STS2 */ -#define IRSME (1 << 6) /* Receive Sum Error flag */ -#define IROVE (1 << 5) /* Receive Overrun Error flag */ -#define IRFRE (1 << 4) /* Receive Framing Error flag */ -#define IRPRE (1 << 3) /* Receive Parity Error flag */ - -/* IRIF_UART0_*/ -#define TBEC (1 << 2) /* Transmit Data Clear */ -#define RIE (1 << 1) /* Receive Enable */ -#define TIE (1 << 0) /* Transmit Enable */ - -/* IRIF_UART1 */ -#define URSME (1 << 6) /* Receive Sum Error Flag */ -#define UROVE (1 << 5) /* Receive Overrun Error Flag */ -#define URFRE (1 << 4) /* Receive Framing Error Flag */ -#define URPRE (1 << 3) /* Receive Parity Error Flag */ -#define RBF (1 << 2) /* Receive Buffer Full Flag */ -#define TSBE (1 << 1) /* Transmit Shift Buffer Empty Flag */ -#define TBE (1 << 0) /* Transmit Buffer Empty flag */ -#define TBCOMP (TSBE | TBE) - -/* IRIF_UART5 */ -#define RSEIM (1 << 6) /* Receive Sum Error Flag IRQ Mask */ -#define RBFIM (1 << 2) /* Receive Buffer Full Flag IRQ Mask */ -#define TSBEIM (1 << 1) /* Transmit Shift Buffer Empty Flag IRQ Mask */ -#define TBEIM (1 << 0) /* Transmit Buffer Empty Flag IRQ Mask */ -#define RX_MASK (RSEIM | RBFIM) - -/* IRIF_CRC0 */ -#define CRC_RST (1 << 15) /* CRC Engine Reset */ -#define CRC_CT_MASK 0x0FFF - -/************************************************************************ - - - structure - - -************************************************************************/ -struct sh_sir_self { - void __iomem *membase; - unsigned int irq; - struct clk *clk; - - struct net_device *ndev; - - struct irlap_cb *irlap; - struct qos_info qos; - - iobuff_t tx_buff; - iobuff_t rx_buff; -}; - -/************************************************************************ - - - common function - - -************************************************************************/ -static void sh_sir_write(struct sh_sir_self *self, u32 offset, u16 data) -{ - iowrite16(data, self->membase + offset); -} - -static u16 sh_sir_read(struct sh_sir_self *self, u32 offset) -{ - return ioread16(self->membase + offset); -} - -static void sh_sir_update_bits(struct sh_sir_self *self, u32 offset, - u16 mask, u16 data) -{ - u16 old, new; - - old = sh_sir_read(self, offset); - new = (old & ~mask) | data; - if (old != new) - sh_sir_write(self, offset, new); -} - -/************************************************************************ - - - CRC function - - -************************************************************************/ -static void sh_sir_crc_reset(struct sh_sir_self *self) -{ - sh_sir_write(self, IRIF_CRC0, CRC_RST); -} - -static void sh_sir_crc_add(struct sh_sir_self *self, u8 data) -{ - sh_sir_write(self, IRIF_CRC1, (u16)data); -} - -static u16 sh_sir_crc_cnt(struct sh_sir_self *self) -{ - return CRC_CT_MASK & sh_sir_read(self, IRIF_CRC0); -} - -static u16 sh_sir_crc_out(struct sh_sir_self *self) -{ - return sh_sir_read(self, IRIF_CRC4); -} - -static int sh_sir_crc_init(struct sh_sir_self *self) -{ - struct device *dev = &self->ndev->dev; - int ret = -EIO; - u16 val; - - sh_sir_crc_reset(self); - - sh_sir_crc_add(self, 0xCC); - sh_sir_crc_add(self, 0xF5); - sh_sir_crc_add(self, 0xF1); - sh_sir_crc_add(self, 0xA7); - - val = sh_sir_crc_cnt(self); - if (4 != val) { - dev_err(dev, "CRC count error %x\n", val); - goto crc_init_out; - } - - val = sh_sir_crc_out(self); - if (0x51DF != val) { - dev_err(dev, "CRC result error%x\n", val); - goto crc_init_out; - } - - ret = 0; - -crc_init_out: - - sh_sir_crc_reset(self); - return ret; -} - -/************************************************************************ - - - baud rate functions - - -************************************************************************/ -#define SCLK_BASE 1843200 /* 1.8432MHz */ - -static u32 sh_sir_find_sclk(struct clk *irda_clk) -{ - struct cpufreq_frequency_table *freq_table = irda_clk->freq_table; - struct cpufreq_frequency_table *pos; - struct clk *pclk = clk_get(NULL, "peripheral_clk"); - u32 limit, min = 0xffffffff, tmp; - int index = 0; - - limit = clk_get_rate(pclk); - clk_put(pclk); - - /* IrDA can not set over peripheral_clk */ - cpufreq_for_each_valid_entry(pos, freq_table) { - u32 freq = pos->frequency; - - /* IrDA should not over peripheral_clk */ - if (freq > limit) - continue; - - tmp = freq % SCLK_BASE; - if (tmp < min) { - min = tmp; - index = pos - freq_table; - } - } - - return freq_table[index].frequency; -} - -#define ERR_ROUNDING(a) ((a + 5000) / 10000) -static int sh_sir_set_baudrate(struct sh_sir_self *self, u32 baudrate) -{ - struct clk *clk; - struct device *dev = &self->ndev->dev; - u32 rate; - u16 uabca, uabc; - u16 irbca, irbc; - u32 min, rerr, tmp; - int i; - - /* Baud Rate Error Correction x 10000 */ - u32 rate_err_array[] = { - 0, 625, 1250, 1875, - 2500, 3125, 3750, 4375, - 5000, 5625, 6250, 6875, - 7500, 8125, 8750, 9375, - }; - - /* - * FIXME - * - * it support 9600 only now - */ - switch (baudrate) { - case 9600: - break; - default: - dev_err(dev, "un-supported baudrate %d\n", baudrate); - return -EIO; - } - - clk = clk_get(NULL, "irda_clk"); - if (IS_ERR(clk)) { - dev_err(dev, "can not get irda_clk\n"); - return -EIO; - } - - clk_set_rate(clk, sh_sir_find_sclk(clk)); - rate = clk_get_rate(clk); - clk_put(clk); - - dev_dbg(dev, "selected sclk = %d\n", rate); - - /* - * CALCULATION - * - * 1843200 = system rate / (irbca + (irbc + 1)) - */ - - irbc = rate / SCLK_BASE; - - tmp = rate - (SCLK_BASE * irbc); - tmp *= 10000; - - rerr = tmp / SCLK_BASE; - - min = 0xffffffff; - irbca = 0; - for (i = 0; i < ARRAY_SIZE(rate_err_array); i++) { - tmp = abs(rate_err_array[i] - rerr); - if (min > tmp) { - min = tmp; - irbca = i; - } - } - - tmp = rate / (irbc + ERR_ROUNDING(rate_err_array[irbca])); - if ((SCLK_BASE / 100) < abs(tmp - SCLK_BASE)) - dev_warn(dev, "IrDA freq error margin over %d\n", tmp); - - dev_dbg(dev, "target = %d, result = %d, infrared = %d.%d\n", - SCLK_BASE, tmp, irbc, rate_err_array[irbca]); - - irbca = (irbca & 0xF) << 4; - irbc = (irbc - 1) & 0xF; - - if (!irbc) { - dev_err(dev, "sh_sir can not set 0 in IRIF_SIR2\n"); - return -EIO; - } - - sh_sir_write(self, IRIF_SIR0, IRTPW | IRERRC); - sh_sir_write(self, IRIF_SIR1, irbca); - sh_sir_write(self, IRIF_SIR2, irbc); - - /* - * CALCULATION - * - * BaudRate[bps] = system rate / (uabca + (uabc + 1) x 16) - */ - - uabc = rate / baudrate; - uabc = (uabc / 16) - 1; - uabc = (uabc + 1) * 16; - - tmp = rate - (uabc * baudrate); - tmp *= 10000; - - rerr = tmp / baudrate; - - min = 0xffffffff; - uabca = 0; - for (i = 0; i < ARRAY_SIZE(rate_err_array); i++) { - tmp = abs(rate_err_array[i] - rerr); - if (min > tmp) { - min = tmp; - uabca = i; - } - } - - tmp = rate / (uabc + ERR_ROUNDING(rate_err_array[uabca])); - if ((baudrate / 100) < abs(tmp - baudrate)) - dev_warn(dev, "UART freq error margin over %d\n", tmp); - - dev_dbg(dev, "target = %d, result = %d, uart = %d.%d\n", - baudrate, tmp, - uabc, rate_err_array[uabca]); - - uabca = (uabca & 0xF) << 4; - uabc = (uabc / 16) - 1; - - sh_sir_write(self, IRIF_UART6, uabca); - sh_sir_write(self, IRIF_UART7, uabc); - - return 0; -} - -/************************************************************************ - - - iobuf function - - -************************************************************************/ -static int __sh_sir_init_iobuf(iobuff_t *io, int size) -{ - io->head = kmalloc(size, GFP_KERNEL); - if (!io->head) - return -ENOMEM; - - io->truesize = size; - io->in_frame = FALSE; - io->state = OUTSIDE_FRAME; - io->data = io->head; - - return 0; -} - -static void sh_sir_remove_iobuf(struct sh_sir_self *self) -{ - kfree(self->rx_buff.head); - kfree(self->tx_buff.head); - - self->rx_buff.head = NULL; - self->tx_buff.head = NULL; -} - -static int sh_sir_init_iobuf(struct sh_sir_self *self, int rxsize, int txsize) -{ - int err = -ENOMEM; - - if (self->rx_buff.head || - self->tx_buff.head) { - dev_err(&self->ndev->dev, "iobuff has already existed."); - return err; - } - - err = __sh_sir_init_iobuf(&self->rx_buff, rxsize); - if (err) - goto iobuf_err; - - err = __sh_sir_init_iobuf(&self->tx_buff, txsize); - -iobuf_err: - if (err) - sh_sir_remove_iobuf(self); - - return err; -} - -/************************************************************************ - - - status function - - -************************************************************************/ -static void sh_sir_clear_all_err(struct sh_sir_self *self) -{ - /* Clear error flag for receive pulse width */ - sh_sir_update_bits(self, IRIF_SIR0, IRERRC, IRERRC); - - /* Clear frame / EOF error flag */ - sh_sir_write(self, IRIF_SIR_FLG, 0xffff); - - /* Clear all status error */ - sh_sir_write(self, IRIF_UART_STS2, 0); -} - -static void sh_sir_set_phase(struct sh_sir_self *self, int phase) -{ - u16 uart5 = 0; - u16 uart0 = 0; - - switch (phase) { - case TX_PHASE: - uart5 = TBEIM; - uart0 = TBEC | TIE; - break; - case TX_COMP_PHASE: - uart5 = TSBEIM; - uart0 = TIE; - break; - case RX_PHASE: - uart5 = RX_MASK; - uart0 = RIE; - break; - default: - break; - } - - sh_sir_write(self, IRIF_UART5, uart5); - sh_sir_write(self, IRIF_UART0, uart0); -} - -static int sh_sir_is_which_phase(struct sh_sir_self *self) -{ - u16 val = sh_sir_read(self, IRIF_UART5); - - if (val & TBEIM) - return TX_PHASE; - - if (val & TSBEIM) - return TX_COMP_PHASE; - - if (val & RX_MASK) - return RX_PHASE; - - return NONE_PHASE; -} - -static void sh_sir_tx(struct sh_sir_self *self, int phase) -{ - switch (phase) { - case TX_PHASE: - if (0 >= self->tx_buff.len) { - sh_sir_set_phase(self, TX_COMP_PHASE); - } else { - sh_sir_write(self, IRIF_UART3, self->tx_buff.data[0]); - self->tx_buff.len--; - self->tx_buff.data++; - } - break; - case TX_COMP_PHASE: - sh_sir_set_phase(self, RX_PHASE); - netif_wake_queue(self->ndev); - break; - default: - dev_err(&self->ndev->dev, "should not happen\n"); - break; - } -} - -static int sh_sir_read_data(struct sh_sir_self *self) -{ - u16 val = 0; - int timeout = 1024; - - while (timeout--) { - val = sh_sir_read(self, IRIF_UART1); - - /* data get */ - if (val & RBF) { - if (val & (URSME | UROVE | URFRE | URPRE)) - break; - - return (int)sh_sir_read(self, IRIF_UART4); - } - - udelay(1); - } - - dev_err(&self->ndev->dev, "UART1 %04x : STATUS %04x\n", - val, sh_sir_read(self, IRIF_UART_STS2)); - - /* read data register for clear error */ - sh_sir_read(self, IRIF_UART4); - - return -1; -} - -static void sh_sir_rx(struct sh_sir_self *self) -{ - int timeout = 1024; - int data; - - while (timeout--) { - data = sh_sir_read_data(self); - if (data < 0) - break; - - async_unwrap_char(self->ndev, &self->ndev->stats, - &self->rx_buff, (u8)data); - - if (EOFD & sh_sir_read(self, IRIF_SIR_FRM)) - continue; - - break; - } -} - -static irqreturn_t sh_sir_irq(int irq, void *dev_id) -{ - struct sh_sir_self *self = dev_id; - struct device *dev = &self->ndev->dev; - int phase = sh_sir_is_which_phase(self); - - switch (phase) { - case TX_COMP_PHASE: - case TX_PHASE: - sh_sir_tx(self, phase); - break; - case RX_PHASE: - if (sh_sir_read(self, IRIF_SIR3)) - dev_err(dev, "rcv pulse width error occurred\n"); - - sh_sir_rx(self); - sh_sir_clear_all_err(self); - break; - default: - dev_err(dev, "unknown interrupt\n"); - } - - return IRQ_HANDLED; -} - -/************************************************************************ - - - net_device_ops function - - -************************************************************************/ -static int sh_sir_hard_xmit(struct sk_buff *skb, struct net_device *ndev) -{ - struct sh_sir_self *self = netdev_priv(ndev); - int speed = irda_get_next_speed(skb); - - if ((0 < speed) && - (9600 != speed)) { - dev_err(&ndev->dev, "support 9600 only (%d)\n", speed); - return -EIO; - } - - netif_stop_queue(ndev); - - self->tx_buff.data = self->tx_buff.head; - self->tx_buff.len = 0; - if (skb->len) - self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data, - self->tx_buff.truesize); - - sh_sir_set_phase(self, TX_PHASE); - dev_kfree_skb(skb); - - return 0; -} - -static int sh_sir_ioctl(struct net_device *ndev, struct ifreq *ifreq, int cmd) -{ - /* - * FIXME - * - * This function is needed for irda framework. - * But nothing to do now - */ - return 0; -} - -static struct net_device_stats *sh_sir_stats(struct net_device *ndev) -{ - struct sh_sir_self *self = netdev_priv(ndev); - - return &self->ndev->stats; -} - -static int sh_sir_open(struct net_device *ndev) -{ - struct sh_sir_self *self = netdev_priv(ndev); - int err; - - clk_enable(self->clk); - err = sh_sir_crc_init(self); - if (err) - goto open_err; - - sh_sir_set_baudrate(self, 9600); - - self->irlap = irlap_open(ndev, &self->qos, DRIVER_NAME); - if (!self->irlap) { - err = -ENODEV; - goto open_err; - } - - /* - * Now enable the interrupt then start the queue - */ - sh_sir_update_bits(self, IRIF_SIR_FRM, FRP, FRP); - sh_sir_read(self, IRIF_UART1); /* flag clear */ - sh_sir_read(self, IRIF_UART4); /* flag clear */ - sh_sir_set_phase(self, RX_PHASE); - - netif_start_queue(ndev); - - dev_info(&self->ndev->dev, "opened\n"); - - return 0; - -open_err: - clk_disable(self->clk); - - return err; -} - -static int sh_sir_stop(struct net_device *ndev) -{ - struct sh_sir_self *self = netdev_priv(ndev); - - /* Stop IrLAP */ - if (self->irlap) { - irlap_close(self->irlap); - self->irlap = NULL; - } - - netif_stop_queue(ndev); - - dev_info(&ndev->dev, "stopped\n"); - - return 0; -} - -static const struct net_device_ops sh_sir_ndo = { - .ndo_open = sh_sir_open, - .ndo_stop = sh_sir_stop, - .ndo_start_xmit = sh_sir_hard_xmit, - .ndo_do_ioctl = sh_sir_ioctl, - .ndo_get_stats = sh_sir_stats, -}; - -/************************************************************************ - - - platform_driver function - - -************************************************************************/ -static int sh_sir_probe(struct platform_device *pdev) -{ - struct net_device *ndev; - struct sh_sir_self *self; - struct resource *res; - char clk_name[8]; - int irq; - int err = -ENOMEM; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - irq = platform_get_irq(pdev, 0); - if (!res || irq < 0) { - dev_err(&pdev->dev, "Not enough platform resources.\n"); - goto exit; - } - - ndev = alloc_irdadev(sizeof(*self)); - if (!ndev) - goto exit; - - self = netdev_priv(ndev); - self->membase = ioremap_nocache(res->start, resource_size(res)); - if (!self->membase) { - err = -ENXIO; - dev_err(&pdev->dev, "Unable to ioremap.\n"); - goto err_mem_1; - } - - err = sh_sir_init_iobuf(self, IRDA_SKB_MAX_MTU, IRDA_SIR_MAX_FRAME); - if (err) - goto err_mem_2; - - snprintf(clk_name, sizeof(clk_name), "irda%d", pdev->id); - self->clk = clk_get(&pdev->dev, clk_name); - if (IS_ERR(self->clk)) { - dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name); - err = -ENODEV; - goto err_mem_3; - } - - irda_init_max_qos_capabilies(&self->qos); - - ndev->netdev_ops = &sh_sir_ndo; - ndev->irq = irq; - - self->ndev = ndev; - self->qos.baud_rate.bits &= IR_9600; /* FIXME */ - self->qos.min_turn_time.bits = 1; /* 10 ms or more */ - - irda_qos_bits_to_value(&self->qos); - - err = register_netdev(ndev); - if (err) - goto err_mem_4; - - platform_set_drvdata(pdev, ndev); - err = devm_request_irq(&pdev->dev, irq, sh_sir_irq, 0, "sh_sir", self); - if (err) { - dev_warn(&pdev->dev, "Unable to attach sh_sir interrupt\n"); - goto err_mem_4; - } - - dev_info(&pdev->dev, "SuperH IrDA probed\n"); - - goto exit; - -err_mem_4: - clk_put(self->clk); -err_mem_3: - sh_sir_remove_iobuf(self); -err_mem_2: - iounmap(self->membase); -err_mem_1: - free_netdev(ndev); -exit: - return err; -} - -static int sh_sir_remove(struct platform_device *pdev) -{ - struct net_device *ndev = platform_get_drvdata(pdev); - struct sh_sir_self *self = netdev_priv(ndev); - - if (!self) - return 0; - - unregister_netdev(ndev); - clk_put(self->clk); - sh_sir_remove_iobuf(self); - iounmap(self->membase); - free_netdev(ndev); - - return 0; -} - -static struct platform_driver sh_sir_driver = { - .probe = sh_sir_probe, - .remove = sh_sir_remove, - .driver = { - .name = DRIVER_NAME, - }, -}; - -module_platform_driver(sh_sir_driver); - -MODULE_AUTHOR("Kuninori Morimoto <morimoto.kuninori@renesas.com>"); -MODULE_DESCRIPTION("SuperH IrDA driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/net/irda/sir-dev.h b/drivers/net/irda/sir-dev.h deleted file mode 100644 index f50b9c1c0639..000000000000 --- a/drivers/net/irda/sir-dev.h +++ /dev/null @@ -1,191 +0,0 @@ -/********************************************************************* - * - * 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 <linux/workqueue.h> - -#include <net/irda/irda.h> -#include <net/irda/irda_device.h> // iobuff_t - -struct sir_fsm { - struct semaphore sem; - struct delayed_work work; - 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 */ - -int irda_register_dongle(struct dongle_driver *new); -int irda_unregister_dongle(struct dongle_driver *drv); - -struct sir_dev *sirdev_get_instance(const struct sir_driver *drv, - const char *name); -int sirdev_put_instance(struct sir_dev *self); - -int sirdev_set_dongle(struct sir_dev *dev, IRDA_DONGLE type); -void sirdev_write_complete(struct sir_dev *dev); -int sirdev_receive(struct sir_dev *dev, const unsigned char *cp, size_t count); - -/* low level helpers for SIR device/dongle setup */ -int sirdev_raw_write(struct sir_dev *dev, const char *buf, int len); -int sirdev_raw_read(struct sir_dev *dev, char *buf, int len); -int sirdev_set_dtr_rts(struct sir_dev *dev, int dtr, int rts); - -/* not exported */ - -int sirdev_get_dongle(struct sir_dev *self, IRDA_DONGLE type); -int sirdev_put_dongle(struct sir_dev *self); - -void sirdev_enable_rx(struct sir_dev *dev); -int sirdev_schedule_request(struct sir_dev *dev, int state, unsigned param); - -/* 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 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 */ diff --git a/drivers/net/irda/sir_dev.c b/drivers/net/irda/sir_dev.c deleted file mode 100644 index 6af26a7d787c..000000000000 --- a/drivers/net/irda/sir_dev.c +++ /dev/null @@ -1,987 +0,0 @@ -/********************************************************************* - * - * 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/hardirq.h> -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/init.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" - - -static struct workqueue_struct *irda_sir_wq; - -/* STATE MACHINE */ - -/* 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 sirdev_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: - net_err_ratelimited("%s - undefined state\n", __func__); - return -EINVAL; - } - fsm->substate = next_state; - } while (delay == 0); - return delay; -} - -/* - * Function sirdev_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 sirdev_config_fsm(struct work_struct *work) -{ - struct sir_dev *dev = container_of(work, struct sir_dev, fsm.work.work); - struct sir_fsm *fsm = &dev->fsm; - int next_state; - int ret = -1; - unsigned delay; - - pr_debug("%s(), <%ld>\n", __func__, jiffies); - - do { - pr_debug("%s - state=0x%04x / substate=0x%04x\n", - __func__, 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 = sirdev_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->set_speed) { - 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: - net_err_ratelimited("%s - undefined state\n", __func__); - fsm->result = -EINVAL; - /* fall thru */ - - case SIRDEV_STATE_ERROR: - net_err_ratelimited("%s - error: %d\n", - __func__, 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); - - queue_delayed_work(irda_sir_wq, &fsm->work, 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; - - pr_debug("%s - state=0x%04x / param=%u\n", __func__, - initial_state, param); - - if (down_trylock(&fsm->sem)) { - if (in_interrupt() || in_atomic() || irqs_disabled()) { - pr_debug("%s(), state machine busy!\n", __func__); - return -EWOULDBLOCK; - } else - down(&fsm->sem); - } - - if (fsm->state == SIRDEV_STATE_DEAD) { - /* race with sirdev_close should never happen */ - net_err_ratelimited("%s(), instance staled!\n", __func__); - up(&fsm->sem); - return -ESTALE; /* or better EPIPE? */ - } - - netif_stop_queue(dev->netdev); - atomic_set(&dev->enable_rx, 0); - - fsm->state = initial_state; - fsm->param = param; - fsm->result = 0; - - INIT_DELAYED_WORK(&fsm->work, sirdev_config_fsm); - queue_delayed_work(irda_sir_wq, &fsm->work, 0); - return 0; -} - - -/***************************************************************************/ - -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; - - pr_debug("%s : requesting dongle %d.\n", __func__, 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; -} -EXPORT_SYMBOL(sirdev_set_dongle); - -/* 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) { - pr_debug("%s(), raw-tx started\n", __func__); - - 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; -} -EXPORT_SYMBOL(sirdev_raw_write); - -/* 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; -} -EXPORT_SYMBOL(sirdev_raw_read); - -int sirdev_set_dtr_rts(struct sir_dev *dev, int dtr, int rts) -{ - int ret = -ENXIO; - if (dev->drv->set_dtr_rts) - ret = dev->drv->set_dtr_rts(dev, dtr, rts); - return ret; -} -EXPORT_SYMBOL(sirdev_set_dtr_rts); - -/**********************************************************************/ - -/* 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); - - pr_debug("%s() - dev->tx_buff.len = %d\n", - __func__, 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 */ - net_err_ratelimited("%s: drv->do_write failed (%d)\n", - __func__, actual); - if ((skb=dev->tx_skb) != NULL) { - dev->tx_skb = NULL; - dev_kfree_skb_any(skb); - dev->netdev->stats.tx_errors++; - dev->netdev->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. - */ - - pr_debug("%s(), raw-tx done\n", __func__); - 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. - */ - - pr_debug("%s(), finished with frame!\n", __func__); - - if ((skb=dev->tx_skb) != NULL) { - dev->tx_skb = NULL; - dev->netdev->stats.tx_packets++; - dev->netdev->stats.tx_bytes += skb->len; - dev_kfree_skb_any(skb); - } - - if (unlikely(dev->new_speed > 0)) { - pr_debug("%s(), Changing speed!\n", __func__); - err = sirdev_schedule_speed(dev, dev->new_speed); - if (unlikely(err)) { - /* should never happen - * forget the speed change and hope the stack recovers - */ - net_err_ratelimited("%s - schedule speed change failed: %d\n", - __func__, 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); -} -EXPORT_SYMBOL(sirdev_write_complete); - -/* 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) { - net_warn_ratelimited("%s(), not ready yet!\n", __func__); - return -1; - } - - if (!dev->irlap) { - net_warn_ratelimited("%s - too early: %p / %zd!\n", - __func__, 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->netdev->stats.rx_dropped++; - pr_debug("%s; rx-drop: %zd\n", __func__, 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->netdev->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; -} -EXPORT_SYMBOL(sirdev_receive); - -/**********************************************************************/ - -/* callbacks from network layer */ - -static netdev_tx_t sirdev_hard_xmit(struct sk_buff *skb, - struct net_device *ndev) -{ - struct sir_dev *dev = netdev_priv(ndev); - unsigned long flags; - int actual = 0; - int err; - s32 speed; - - IRDA_ASSERT(dev != NULL, return NETDEV_TX_OK;); - - netif_stop_queue(ndev); - - pr_debug("%s(), skb->len = %d\n", __func__, 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 NETDEV_TX_BUSY; - } - 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 NETDEV_TX_OK; - } 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)) { - pr_debug("%s(), write not completed\n", __func__); - } - - /* 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->netdev->stats.collisions++; - - actual = dev->drv->do_write(dev, dev->tx_buff.data, dev->tx_buff.len); - - if (likely(actual > 0)) { - dev->tx_skb = skb; - 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 */ - net_err_ratelimited("%s: drv->do_write failed (%d)\n", - __func__, actual); - dev_kfree_skb_any(skb); - dev->netdev->stats.tx_errors++; - dev->netdev->stats.tx_dropped++; - netif_wake_queue(ndev); - } - spin_unlock_irqrestore(&dev->tx_lock, flags); - - return NETDEV_TX_OK; -} - -/* 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 = netdev_priv(ndev); - int ret = 0; - - IRDA_ASSERT(dev != NULL, return -1;); - - pr_debug("%s(), %s, (cmd=0x%X)\n", __func__, 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 = __netdev_alloc_skb(dev->netdev, 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) -{ - kfree_skb(dev->rx_buff.skb); - 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 = netdev_priv(ndev); - 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; - - 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); - - pr_debug("%s - done, speed = %d\n", __func__, 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 = netdev_priv(ndev); - const struct sir_driver *drv; - -/* pr_debug("%s\n", __func__); */ - - 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; -} - -static const struct net_device_ops sirdev_ops = { - .ndo_start_xmit = sirdev_hard_xmit, - .ndo_open = sirdev_open, - .ndo_stop = sirdev_close, - .ndo_do_ioctl = sirdev_ioctl, -}; -/* ----------------------------------------------------------------------------- */ - -struct sir_dev * sirdev_get_instance(const struct sir_driver *drv, const char *name) -{ - struct net_device *ndev; - struct sir_dev *dev; - - pr_debug("%s - %s\n", __func__, 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) { - net_err_ratelimited("%s - Can't allocate memory for IrDA control block!\n", - __func__); - goto out; - } - dev = netdev_priv(ndev); - - 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); - sema_init(&dev->fsm.sem, 1); - - dev->drv = drv; - dev->netdev = ndev; - - /* Override the network functions we need to use */ - ndev->netdev_ops = &sirdev_ops; - - if (register_netdev(ndev)) { - net_err_ratelimited("%s(), register_netdev() failed!\n", - __func__); - goto out_freenetdev; - } - - return dev; - -out_freenetdev: - free_netdev(ndev); -out: - return NULL; -} -EXPORT_SYMBOL(sirdev_get_instance); - -int sirdev_put_instance(struct sir_dev *dev) -{ - int err = 0; - - pr_debug("%s\n", __func__); - - 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) - net_err_ratelimited("%s - error %d\n", __func__, 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; -} -EXPORT_SYMBOL(sirdev_put_instance); - -static int __init sir_wq_init(void) -{ - irda_sir_wq = create_singlethread_workqueue("irda_sir_wq"); - if (!irda_sir_wq) - return -ENOMEM; - return 0; -} - -static void __exit sir_wq_exit(void) -{ - destroy_workqueue(irda_sir_wq); -} - -module_init(sir_wq_init); -module_exit(sir_wq_exit); - -MODULE_AUTHOR("Martin Diehl <info@mdiehl.de>"); -MODULE_DESCRIPTION("IrDA SIR core"); -MODULE_LICENSE("GPL"); diff --git a/drivers/net/irda/sir_dongle.c b/drivers/net/irda/sir_dongle.c deleted file mode 100644 index 7436f73ff1bb..000000000000 --- a/drivers/net/irda/sir_dongle.c +++ /dev/null @@ -1,133 +0,0 @@ -/********************************************************************* - * - * 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/kmod.h> -#include <linux/mutex.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 DEFINE_MUTEX(dongle_list_lock); /* protects the list */ - -int irda_register_dongle(struct dongle_driver *new) -{ - struct list_head *entry; - struct dongle_driver *drv; - - pr_debug("%s : registering dongle \"%s\" (%d).\n", - __func__, new->driver_name, new->type); - - mutex_lock(&dongle_list_lock); - list_for_each(entry, &dongle_list) { - drv = list_entry(entry, struct dongle_driver, dongle_list); - if (new->type == drv->type) { - mutex_unlock(&dongle_list_lock); - return -EEXIST; - } - } - list_add(&new->dongle_list, &dongle_list); - mutex_unlock(&dongle_list_lock); - return 0; -} -EXPORT_SYMBOL(irda_register_dongle); - -int irda_unregister_dongle(struct dongle_driver *drv) -{ - mutex_lock(&dongle_list_lock); - list_del(&drv->dongle_list); - mutex_unlock(&dongle_list_lock); - return 0; -} -EXPORT_SYMBOL(irda_unregister_dongle); - -int sirdev_get_dongle(struct sir_dev *dev, IRDA_DONGLE type) -{ - struct list_head *entry; - const struct dongle_driver *drv = NULL; - int err = -EINVAL; - - request_module("irda-dongle-%d", type); - - if (dev->dongle_drv != NULL) - return -EBUSY; - - /* serialize access to the list of registered dongles */ - mutex_lock(&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 */ - - mutex_unlock(&dongle_list_lock); - return 0; - -out_reject: - dev->dongle_drv = NULL; - module_put(drv->owner); -out_unlock: - mutex_unlock(&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; -} diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c deleted file mode 100644 index 19a55cba6beb..000000000000 --- a/drivers/net/irda/smsc-ircc2.c +++ /dev/null @@ -1,3026 +0,0 @@ -/********************************************************************* - * - * Description: Driver for the SMC Infrared Communications Controller - * Author: Daniele Peri (peri@csai.unipa.it) - * Created at: - * Modified at: - * Modified by: - * - * Copyright (c) 2002 Daniele Peri - * All Rights Reserved. - * Copyright (c) 2002 Jean Tourrilhes - * Copyright (c) 2006 Linus Walleij - * - * - * Based on smc-ircc.c: - * - * Copyright (c) 2001 Stefani Seibold - * Copyright (c) 1999-2001 Dag Brattli - * Copyright (c) 1998-1999 Thomas Davis, - * - * and irport.c: - * - * Copyright (c) 1997, 1998, 1999-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. - * - * 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, see <http://www.gnu.org/licenses/>. - * - ********************************************************************/ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/skbuff.h> -#include <linux/netdevice.h> -#include <linux/ioport.h> -#include <linux/delay.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/rtnetlink.h> -#include <linux/serial_reg.h> -#include <linux/dma-mapping.h> -#include <linux/pnp.h> -#include <linux/platform_device.h> -#include <linux/gfp.h> - -#include <asm/io.h> -#include <asm/dma.h> -#include <asm/byteorder.h> - -#include <linux/spinlock.h> -#include <linux/pm.h> -#ifdef CONFIG_PCI -#include <linux/pci.h> -#endif - -#include <net/irda/wrapper.h> -#include <net/irda/irda.h> -#include <net/irda/irda_device.h> - -#include "smsc-ircc2.h" -#include "smsc-sio.h" - - -MODULE_AUTHOR("Daniele Peri <peri@csai.unipa.it>"); -MODULE_DESCRIPTION("SMC IrCC SIR/FIR controller driver"); -MODULE_LICENSE("GPL"); - -static bool smsc_nopnp = true; -module_param_named(nopnp, smsc_nopnp, bool, 0); -MODULE_PARM_DESC(nopnp, "Do not use PNP to detect controller settings, defaults to true"); - -#define DMA_INVAL 255 -static int ircc_dma = DMA_INVAL; -module_param_hw(ircc_dma, int, dma, 0); -MODULE_PARM_DESC(ircc_dma, "DMA channel"); - -#define IRQ_INVAL 255 -static int ircc_irq = IRQ_INVAL; -module_param_hw(ircc_irq, int, irq, 0); -MODULE_PARM_DESC(ircc_irq, "IRQ line"); - -static int ircc_fir; -module_param_hw(ircc_fir, int, ioport, 0); -MODULE_PARM_DESC(ircc_fir, "FIR Base Address"); - -static int ircc_sir; -module_param_hw(ircc_sir, int, ioport, 0); -MODULE_PARM_DESC(ircc_sir, "SIR Base Address"); - -static int ircc_cfg; -module_param_hw(ircc_cfg, int, ioport, 0); -MODULE_PARM_DESC(ircc_cfg, "Configuration register base address"); - -static int ircc_transceiver; -module_param(ircc_transceiver, int, 0); -MODULE_PARM_DESC(ircc_transceiver, "Transceiver type"); - -/* Types */ - -#ifdef CONFIG_PCI -struct smsc_ircc_subsystem_configuration { - unsigned short vendor; /* PCI vendor ID */ - unsigned short device; /* PCI vendor ID */ - unsigned short subvendor; /* PCI subsystem vendor ID */ - unsigned short subdevice; /* PCI subsystem device ID */ - unsigned short sir_io; /* I/O port for SIR */ - unsigned short fir_io; /* I/O port for FIR */ - unsigned char fir_irq; /* FIR IRQ */ - unsigned char fir_dma; /* FIR DMA */ - unsigned short cfg_base; /* I/O port for chip configuration */ - int (*preconfigure)(struct pci_dev *dev, struct smsc_ircc_subsystem_configuration *conf); /* Preconfig function */ - const char *name; /* name shown as info */ -}; -#endif - -struct smsc_transceiver { - char *name; - void (*set_for_speed)(int fir_base, u32 speed); - int (*probe)(int fir_base); -}; - -struct smsc_chip { - char *name; - #if 0 - u8 type; - #endif - u16 flags; - u8 devid; - u8 rev; -}; - -struct smsc_chip_address { - unsigned int cfg_base; - unsigned int type; -}; - -/* Private data for each instance */ -struct smsc_ircc_cb { - struct net_device *netdev; /* Yes! we are some kind of netdevice */ - struct irlap_cb *irlap; /* The link layer we are binded to */ - - 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; - - struct qos_info qos; /* QoS capabilities for this device */ - - spinlock_t lock; /* For serializing operations */ - - __u32 new_speed; - __u32 flags; /* Interface flags */ - - int tx_buff_offsets[10]; /* Offsets between frames in tx_buff */ - int tx_len; /* Number of frames in tx_buff */ - - int transceiver; - struct platform_device *pldev; -}; - -/* Constants */ - -#define SMSC_IRCC2_DRIVER_NAME "smsc-ircc2" - -#define SMSC_IRCC2_C_IRDA_FALLBACK_SPEED 9600 -#define SMSC_IRCC2_C_DEFAULT_TRANSCEIVER 1 -#define SMSC_IRCC2_C_NET_TIMEOUT 0 -#define SMSC_IRCC2_C_SIR_STOP 0 - -static const char *driver_name = SMSC_IRCC2_DRIVER_NAME; - -/* Prototypes */ - -static int smsc_ircc_open(unsigned int firbase, unsigned int sirbase, u8 dma, u8 irq); -static int smsc_ircc_present(unsigned int fir_base, unsigned int sir_base); -static void smsc_ircc_setup_io(struct smsc_ircc_cb *self, unsigned int fir_base, unsigned int sir_base, u8 dma, u8 irq); -static void smsc_ircc_setup_qos(struct smsc_ircc_cb *self); -static void smsc_ircc_init_chip(struct smsc_ircc_cb *self); -static int __exit smsc_ircc_close(struct smsc_ircc_cb *self); -static int smsc_ircc_dma_receive(struct smsc_ircc_cb *self); -static void smsc_ircc_dma_receive_complete(struct smsc_ircc_cb *self); -static void smsc_ircc_sir_receive(struct smsc_ircc_cb *self); -static netdev_tx_t smsc_ircc_hard_xmit_sir(struct sk_buff *skb, - struct net_device *dev); -static netdev_tx_t smsc_ircc_hard_xmit_fir(struct sk_buff *skb, - struct net_device *dev); -static void smsc_ircc_dma_xmit(struct smsc_ircc_cb *self, int bofs); -static void smsc_ircc_dma_xmit_complete(struct smsc_ircc_cb *self); -static void smsc_ircc_change_speed(struct smsc_ircc_cb *self, u32 speed); -static void smsc_ircc_set_sir_speed(struct smsc_ircc_cb *self, u32 speed); -static irqreturn_t smsc_ircc_interrupt(int irq, void *dev_id); -static irqreturn_t smsc_ircc_interrupt_sir(struct net_device *dev); -static void smsc_ircc_sir_start(struct smsc_ircc_cb *self); -#if SMSC_IRCC2_C_SIR_STOP -static void smsc_ircc_sir_stop(struct smsc_ircc_cb *self); -#endif -static void smsc_ircc_sir_write_wakeup(struct smsc_ircc_cb *self); -static int smsc_ircc_sir_write(int iobase, int fifo_size, __u8 *buf, int len); -static int smsc_ircc_net_open(struct net_device *dev); -static int smsc_ircc_net_close(struct net_device *dev); -static int smsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); -#if SMSC_IRCC2_C_NET_TIMEOUT -static void smsc_ircc_timeout(struct net_device *dev); -#endif -static int smsc_ircc_is_receiving(struct smsc_ircc_cb *self); -static void smsc_ircc_probe_transceiver(struct smsc_ircc_cb *self); -static void smsc_ircc_set_transceiver_for_speed(struct smsc_ircc_cb *self, u32 speed); -static void smsc_ircc_sir_wait_hw_transmitter_finish(struct smsc_ircc_cb *self); - -/* Probing */ -static int __init smsc_ircc_look_for_chips(void); -static const struct smsc_chip * __init smsc_ircc_probe(unsigned short cfg_base, u8 reg, const struct smsc_chip *chip, char *type); -static int __init smsc_superio_flat(const struct smsc_chip *chips, unsigned short cfg_base, char *type); -static int __init smsc_superio_paged(const struct smsc_chip *chips, unsigned short cfg_base, char *type); -static int __init smsc_superio_fdc(unsigned short cfg_base); -static int __init smsc_superio_lpc(unsigned short cfg_base); -#ifdef CONFIG_PCI -static int __init preconfigure_smsc_chip(struct smsc_ircc_subsystem_configuration *conf); -static int __init preconfigure_through_82801(struct pci_dev *dev, struct smsc_ircc_subsystem_configuration *conf); -static void __init preconfigure_ali_port(struct pci_dev *dev, - unsigned short port); -static int __init preconfigure_through_ali(struct pci_dev *dev, struct smsc_ircc_subsystem_configuration *conf); -static int __init smsc_ircc_preconfigure_subsystems(unsigned short ircc_cfg, - unsigned short ircc_fir, - unsigned short ircc_sir, - unsigned char ircc_dma, - unsigned char ircc_irq); -#endif - -/* Transceivers specific functions */ - -static void smsc_ircc_set_transceiver_toshiba_sat1800(int fir_base, u32 speed); -static int smsc_ircc_probe_transceiver_toshiba_sat1800(int fir_base); -static void smsc_ircc_set_transceiver_smsc_ircc_fast_pin_select(int fir_base, u32 speed); -static int smsc_ircc_probe_transceiver_smsc_ircc_fast_pin_select(int fir_base); -static void smsc_ircc_set_transceiver_smsc_ircc_atc(int fir_base, u32 speed); -static int smsc_ircc_probe_transceiver_smsc_ircc_atc(int fir_base); - -/* Power Management */ - -static int smsc_ircc_suspend(struct platform_device *dev, pm_message_t state); -static int smsc_ircc_resume(struct platform_device *dev); - -static struct platform_driver smsc_ircc_driver = { - .suspend = smsc_ircc_suspend, - .resume = smsc_ircc_resume, - .driver = { - .name = SMSC_IRCC2_DRIVER_NAME, - }, -}; - -/* Transceivers for SMSC-ircc */ - -static struct smsc_transceiver smsc_transceivers[] = -{ - { "Toshiba Satellite 1800 (GP data pin select)", smsc_ircc_set_transceiver_toshiba_sat1800, smsc_ircc_probe_transceiver_toshiba_sat1800 }, - { "Fast pin select", smsc_ircc_set_transceiver_smsc_ircc_fast_pin_select, smsc_ircc_probe_transceiver_smsc_ircc_fast_pin_select }, - { "ATC IRMode", smsc_ircc_set_transceiver_smsc_ircc_atc, smsc_ircc_probe_transceiver_smsc_ircc_atc }, - { NULL, NULL } -}; -#define SMSC_IRCC2_C_NUMBER_OF_TRANSCEIVERS (ARRAY_SIZE(smsc_transceivers) - 1) - -/* SMC SuperIO chipsets definitions */ - -#define KEY55_1 0 /* SuperIO Configuration mode with Key <0x55> */ -#define KEY55_2 1 /* SuperIO Configuration mode with Key <0x55,0x55> */ -#define NoIRDA 2 /* SuperIO Chip has no IRDA Port */ -#define SIR 0 /* SuperIO Chip has only slow IRDA */ -#define FIR 4 /* SuperIO Chip has fast IRDA */ -#define SERx4 8 /* SuperIO Chip supports 115,2 KBaud * 4=460,8 KBaud */ - -static struct smsc_chip __initdata fdc_chips_flat[] = -{ - /* Base address 0x3f0 or 0x370 */ - { "37C44", KEY55_1|NoIRDA, 0x00, 0x00 }, /* This chip cannot be detected */ - { "37C665GT", KEY55_2|NoIRDA, 0x65, 0x01 }, - { "37C665GT", KEY55_2|NoIRDA, 0x66, 0x01 }, - { "37C669", KEY55_2|SIR|SERx4, 0x03, 0x02 }, - { "37C669", KEY55_2|SIR|SERx4, 0x04, 0x02 }, /* ID? */ - { "37C78", KEY55_2|NoIRDA, 0x78, 0x00 }, - { "37N769", KEY55_1|FIR|SERx4, 0x28, 0x00 }, - { "37N869", KEY55_1|FIR|SERx4, 0x29, 0x00 }, - { NULL } -}; - -static struct smsc_chip __initdata fdc_chips_paged[] = -{ - /* Base address 0x3f0 or 0x370 */ - { "37B72X", KEY55_1|SIR|SERx4, 0x4c, 0x00 }, - { "37B77X", KEY55_1|SIR|SERx4, 0x43, 0x00 }, - { "37B78X", KEY55_1|SIR|SERx4, 0x44, 0x00 }, - { "37B80X", KEY55_1|SIR|SERx4, 0x42, 0x00 }, - { "37C67X", KEY55_1|FIR|SERx4, 0x40, 0x00 }, - { "37C93X", KEY55_2|SIR|SERx4, 0x02, 0x01 }, - { "37C93XAPM", KEY55_1|SIR|SERx4, 0x30, 0x01 }, - { "37C93XFR", KEY55_2|FIR|SERx4, 0x03, 0x01 }, - { "37M707", KEY55_1|SIR|SERx4, 0x42, 0x00 }, - { "37M81X", KEY55_1|SIR|SERx4, 0x4d, 0x00 }, - { "37N958FR", KEY55_1|FIR|SERx4, 0x09, 0x04 }, - { "37N971", KEY55_1|FIR|SERx4, 0x0a, 0x00 }, - { "37N972", KEY55_1|FIR|SERx4, 0x0b, 0x00 }, - { NULL } -}; - -static struct smsc_chip __initdata lpc_chips_flat[] = -{ - /* Base address 0x2E or 0x4E */ - { "47N227", KEY55_1|FIR|SERx4, 0x5a, 0x00 }, - { "47N227", KEY55_1|FIR|SERx4, 0x7a, 0x00 }, - { "47N267", KEY55_1|FIR|SERx4, 0x5e, 0x00 }, - { NULL } -}; - -static struct smsc_chip __initdata lpc_chips_paged[] = -{ - /* Base address 0x2E or 0x4E */ - { "47B27X", KEY55_1|SIR|SERx4, 0x51, 0x00 }, - { "47B37X", KEY55_1|SIR|SERx4, 0x52, 0x00 }, - { "47M10X", KEY55_1|SIR|SERx4, 0x59, 0x00 }, - { "47M120", KEY55_1|NoIRDA|SERx4, 0x5c, 0x00 }, - { "47M13X", KEY55_1|SIR|SERx4, 0x59, 0x00 }, - { "47M14X", KEY55_1|SIR|SERx4, 0x5f, 0x00 }, - { "47N252", KEY55_1|FIR|SERx4, 0x0e, 0x00 }, - { "47S42X", KEY55_1|SIR|SERx4, 0x57, 0x00 }, - { NULL } -}; - -#define SMSCSIO_TYPE_FDC 1 -#define SMSCSIO_TYPE_LPC 2 -#define SMSCSIO_TYPE_FLAT 4 -#define SMSCSIO_TYPE_PAGED 8 - -static struct smsc_chip_address __initdata possible_addresses[] = -{ - { 0x3f0, SMSCSIO_TYPE_FDC|SMSCSIO_TYPE_FLAT|SMSCSIO_TYPE_PAGED }, - { 0x370, SMSCSIO_TYPE_FDC|SMSCSIO_TYPE_FLAT|SMSCSIO_TYPE_PAGED }, - { 0xe0, SMSCSIO_TYPE_FDC|SMSCSIO_TYPE_FLAT|SMSCSIO_TYPE_PAGED }, - { 0x2e, SMSCSIO_TYPE_LPC|SMSCSIO_TYPE_FLAT|SMSCSIO_TYPE_PAGED }, - { 0x4e, SMSCSIO_TYPE_LPC|SMSCSIO_TYPE_FLAT|SMSCSIO_TYPE_PAGED }, - { 0, 0 } -}; - -/* Globals */ - -static struct smsc_ircc_cb *dev_self[] = { NULL, NULL }; -static unsigned short dev_count; - -static inline void register_bank(int iobase, int bank) -{ - outb(((inb(iobase + IRCC_MASTER) & 0xf0) | (bank & 0x07)), - iobase + IRCC_MASTER); -} - -/* PNP hotplug support */ -static const struct pnp_device_id smsc_ircc_pnp_table[] = { - { .id = "SMCf010", .driver_data = 0 }, - /* and presumably others */ - { } -}; -MODULE_DEVICE_TABLE(pnp, smsc_ircc_pnp_table); - -static int pnp_driver_registered; - -#ifdef CONFIG_PNP -static int smsc_ircc_pnp_probe(struct pnp_dev *dev, - const struct pnp_device_id *dev_id) -{ - unsigned int firbase, sirbase; - u8 dma, irq; - - if (!(pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) && - pnp_dma_valid(dev, 0) && pnp_irq_valid(dev, 0))) - return -EINVAL; - - sirbase = pnp_port_start(dev, 0); - firbase = pnp_port_start(dev, 1); - dma = pnp_dma(dev, 0); - irq = pnp_irq(dev, 0); - - if (smsc_ircc_open(firbase, sirbase, dma, irq)) - return -ENODEV; - - return 0; -} - -static struct pnp_driver smsc_ircc_pnp_driver = { - .name = "smsc-ircc2", - .id_table = smsc_ircc_pnp_table, - .probe = smsc_ircc_pnp_probe, -}; -#else /* CONFIG_PNP */ -static struct pnp_driver smsc_ircc_pnp_driver; -#endif - -/******************************************************************************* - * - * - * SMSC-ircc stuff - * - * - *******************************************************************************/ - -static int __init smsc_ircc_legacy_probe(void) -{ - int ret = 0; - -#ifdef CONFIG_PCI - if (smsc_ircc_preconfigure_subsystems(ircc_cfg, ircc_fir, ircc_sir, ircc_dma, ircc_irq) < 0) { - /* Ignore errors from preconfiguration */ - net_err_ratelimited("%s, Preconfiguration failed !\n", - driver_name); - } -#endif - - if (ircc_fir > 0 && ircc_sir > 0) { - net_info_ratelimited(" Overriding FIR address 0x%04x\n", - ircc_fir); - net_info_ratelimited(" Overriding SIR address 0x%04x\n", - ircc_sir); - - if (smsc_ircc_open(ircc_fir, ircc_sir, ircc_dma, ircc_irq)) - ret = -ENODEV; - } else { - ret = -ENODEV; - - /* try user provided configuration register base address */ - if (ircc_cfg > 0) { - net_info_ratelimited(" Overriding configuration address 0x%04x\n", - ircc_cfg); - if (!smsc_superio_fdc(ircc_cfg)) - ret = 0; - if (!smsc_superio_lpc(ircc_cfg)) - ret = 0; - } - - if (smsc_ircc_look_for_chips() > 0) - ret = 0; - } - return ret; -} - -/* - * Function smsc_ircc_init () - * - * Initialize chip. Just try to find out how many chips we are dealing with - * and where they are - */ -static int __init smsc_ircc_init(void) -{ - int ret; - - pr_debug("%s\n", __func__); - - ret = platform_driver_register(&smsc_ircc_driver); - if (ret) { - net_err_ratelimited("%s, Can't register driver!\n", - driver_name); - return ret; - } - - dev_count = 0; - - if (smsc_nopnp || !pnp_platform_devices || - ircc_cfg || ircc_fir || ircc_sir || - ircc_dma != DMA_INVAL || ircc_irq != IRQ_INVAL) { - ret = smsc_ircc_legacy_probe(); - } else { - if (pnp_register_driver(&smsc_ircc_pnp_driver) == 0) - pnp_driver_registered = 1; - } - - if (ret) { - if (pnp_driver_registered) - pnp_unregister_driver(&smsc_ircc_pnp_driver); - platform_driver_unregister(&smsc_ircc_driver); - } - - return ret; -} - -static netdev_tx_t smsc_ircc_net_xmit(struct sk_buff *skb, - struct net_device *dev) -{ - struct smsc_ircc_cb *self = netdev_priv(dev); - - if (self->io.speed > 115200) - return smsc_ircc_hard_xmit_fir(skb, dev); - else - return smsc_ircc_hard_xmit_sir(skb, dev); -} - -static const struct net_device_ops smsc_ircc_netdev_ops = { - .ndo_open = smsc_ircc_net_open, - .ndo_stop = smsc_ircc_net_close, - .ndo_do_ioctl = smsc_ircc_net_ioctl, - .ndo_start_xmit = smsc_ircc_net_xmit, -#if SMSC_IRCC2_C_NET_TIMEOUT - .ndo_tx_timeout = smsc_ircc_timeout, -#endif -}; - -/* - * Function smsc_ircc_open (firbase, sirbase, dma, irq) - * - * Try to open driver instance - * - */ -static int smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u8 dma, u8 irq) -{ - struct smsc_ircc_cb *self; - struct net_device *dev; - int err; - - pr_debug("%s\n", __func__); - - err = smsc_ircc_present(fir_base, sir_base); - if (err) - goto err_out; - - err = -ENOMEM; - if (dev_count >= ARRAY_SIZE(dev_self)) { - net_warn_ratelimited("%s(), too many devices!\n", __func__); - goto err_out1; - } - - /* - * Allocate new instance of the driver - */ - dev = alloc_irdadev(sizeof(struct smsc_ircc_cb)); - if (!dev) { - net_warn_ratelimited("%s() can't allocate net device\n", - __func__); - goto err_out1; - } - -#if SMSC_IRCC2_C_NET_TIMEOUT - dev->watchdog_timeo = HZ * 2; /* Allow enough time for speed change */ -#endif - dev->netdev_ops = &smsc_ircc_netdev_ops; - - self = netdev_priv(dev); - self->netdev = dev; - - /* Make ifconfig display some details */ - dev->base_addr = self->io.fir_base = fir_base; - dev->irq = self->io.irq = irq; - - /* Need to store self somewhere */ - dev_self[dev_count] = self; - spin_lock_init(&self->lock); - - self->rx_buff.truesize = SMSC_IRCC2_RX_BUFF_TRUESIZE; - self->tx_buff.truesize = SMSC_IRCC2_TX_BUFF_TRUESIZE; - - self->rx_buff.head = - dma_zalloc_coherent(NULL, self->rx_buff.truesize, - &self->rx_buff_dma, GFP_KERNEL); - if (self->rx_buff.head == NULL) - goto err_out2; - - self->tx_buff.head = - dma_zalloc_coherent(NULL, self->tx_buff.truesize, - &self->tx_buff_dma, GFP_KERNEL); - if (self->tx_buff.head == NULL) - goto err_out3; - - self->rx_buff.in_frame = FALSE; - self->rx_buff.state = OUTSIDE_FRAME; - self->tx_buff.data = self->tx_buff.head; - self->rx_buff.data = self->rx_buff.head; - - smsc_ircc_setup_io(self, fir_base, sir_base, dma, irq); - smsc_ircc_setup_qos(self); - smsc_ircc_init_chip(self); - - if (ircc_transceiver > 0 && - ircc_transceiver < SMSC_IRCC2_C_NUMBER_OF_TRANSCEIVERS) - self->transceiver = ircc_transceiver; - else - smsc_ircc_probe_transceiver(self); - - err = register_netdev(self->netdev); - if (err) { - net_err_ratelimited("%s, Network device registration failed!\n", - driver_name); - goto err_out4; - } - - self->pldev = platform_device_register_simple(SMSC_IRCC2_DRIVER_NAME, - dev_count, NULL, 0); - if (IS_ERR(self->pldev)) { - err = PTR_ERR(self->pldev); - goto err_out5; - } - platform_set_drvdata(self->pldev, self); - - net_info_ratelimited("IrDA: Registered device %s\n", dev->name); - dev_count++; - - return 0; - - err_out5: - unregister_netdev(self->netdev); - - err_out4: - dma_free_coherent(NULL, self->tx_buff.truesize, - self->tx_buff.head, self->tx_buff_dma); - err_out3: - dma_free_coherent(NULL, self->rx_buff.truesize, - self->rx_buff.head, self->rx_buff_dma); - err_out2: - free_netdev(self->netdev); - dev_self[dev_count] = NULL; - err_out1: - release_region(fir_base, SMSC_IRCC2_FIR_CHIP_IO_EXTENT); - release_region(sir_base, SMSC_IRCC2_SIR_CHIP_IO_EXTENT); - err_out: - return err; -} - -/* - * Function smsc_ircc_present(fir_base, sir_base) - * - * Check the smsc-ircc chip presence - * - */ -static int smsc_ircc_present(unsigned int fir_base, unsigned int sir_base) -{ - unsigned char low, high, chip, config, dma, irq, version; - - if (!request_region(fir_base, SMSC_IRCC2_FIR_CHIP_IO_EXTENT, - driver_name)) { - net_warn_ratelimited("%s: can't get fir_base of 0x%03x\n", - __func__, fir_base); - goto out1; - } - - if (!request_region(sir_base, SMSC_IRCC2_SIR_CHIP_IO_EXTENT, - driver_name)) { - net_warn_ratelimited("%s: can't get sir_base of 0x%03x\n", - __func__, sir_base); - goto out2; - } - - register_bank(fir_base, 3); - - high = inb(fir_base + IRCC_ID_HIGH); - low = inb(fir_base + IRCC_ID_LOW); - chip = inb(fir_base + IRCC_CHIP_ID); - version = inb(fir_base + IRCC_VERSION); - config = inb(fir_base + IRCC_INTERFACE); - dma = config & IRCC_INTERFACE_DMA_MASK; - irq = (config & IRCC_INTERFACE_IRQ_MASK) >> 4; - - if (high != 0x10 || low != 0xb8 || (chip != 0xf1 && chip != 0xf2)) { - net_warn_ratelimited("%s(), addr 0x%04x - no device found!\n", - __func__, fir_base); - goto out3; - } - net_info_ratelimited("SMsC IrDA Controller found\n IrCC version %d.%d, firport 0x%03x, sirport 0x%03x dma=%d, irq=%d\n", - chip & 0x0f, version, - fir_base, sir_base, dma, irq); - - return 0; - - out3: - release_region(sir_base, SMSC_IRCC2_SIR_CHIP_IO_EXTENT); - out2: - release_region(fir_base, SMSC_IRCC2_FIR_CHIP_IO_EXTENT); - out1: - return -ENODEV; -} - -/* - * Function smsc_ircc_setup_io(self, fir_base, sir_base, dma, irq) - * - * Setup I/O - * - */ -static void smsc_ircc_setup_io(struct smsc_ircc_cb *self, - unsigned int fir_base, unsigned int sir_base, - u8 dma, u8 irq) -{ - unsigned char config, chip_dma, chip_irq; - - register_bank(fir_base, 3); - config = inb(fir_base + IRCC_INTERFACE); - chip_dma = config & IRCC_INTERFACE_DMA_MASK; - chip_irq = (config & IRCC_INTERFACE_IRQ_MASK) >> 4; - - self->io.fir_base = fir_base; - self->io.sir_base = sir_base; - self->io.fir_ext = SMSC_IRCC2_FIR_CHIP_IO_EXTENT; - self->io.sir_ext = SMSC_IRCC2_SIR_CHIP_IO_EXTENT; - self->io.fifo_size = SMSC_IRCC2_FIFO_SIZE; - self->io.speed = SMSC_IRCC2_C_IRDA_FALLBACK_SPEED; - - if (irq != IRQ_INVAL) { - if (irq != chip_irq) - net_info_ratelimited("%s, Overriding IRQ - chip says %d, using %d\n", - driver_name, chip_irq, irq); - self->io.irq = irq; - } else - self->io.irq = chip_irq; - - if (dma != DMA_INVAL) { - if (dma != chip_dma) - net_info_ratelimited("%s, Overriding DMA - chip says %d, using %d\n", - driver_name, chip_dma, dma); - self->io.dma = dma; - } else - self->io.dma = chip_dma; - -} - -/* - * Function smsc_ircc_setup_qos(self) - * - * Setup qos - * - */ -static void smsc_ircc_setup_qos(struct smsc_ircc_cb *self) -{ - /* Initialize QoS for this device */ - irda_init_max_qos_capabilies(&self->qos); - - self->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600| - IR_115200|IR_576000|IR_1152000|(IR_4000000 << 8); - - self->qos.min_turn_time.bits = SMSC_IRCC2_MIN_TURN_TIME; - self->qos.window_size.bits = SMSC_IRCC2_WINDOW_SIZE; - irda_qos_bits_to_value(&self->qos); -} - -/* - * Function smsc_ircc_init_chip(self) - * - * Init chip - * - */ -static void smsc_ircc_init_chip(struct smsc_ircc_cb *self) -{ - int iobase = self->io.fir_base; - - register_bank(iobase, 0); - outb(IRCC_MASTER_RESET, iobase + IRCC_MASTER); - outb(0x00, iobase + IRCC_MASTER); - - register_bank(iobase, 1); - outb(((inb(iobase + IRCC_SCE_CFGA) & 0x87) | IRCC_CFGA_IRDA_SIR_A), - iobase + IRCC_SCE_CFGA); - -#ifdef smsc_669 /* Uses pin 88/89 for Rx/Tx */ - outb(((inb(iobase + IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_COM), - iobase + IRCC_SCE_CFGB); -#else - outb(((inb(iobase + IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_IR), - iobase + IRCC_SCE_CFGB); -#endif - (void) inb(iobase + IRCC_FIFO_THRESHOLD); - outb(SMSC_IRCC2_FIFO_THRESHOLD, iobase + IRCC_FIFO_THRESHOLD); - - register_bank(iobase, 4); - outb((inb(iobase + IRCC_CONTROL) & 0x30), iobase + IRCC_CONTROL); - - register_bank(iobase, 0); - outb(0, iobase + IRCC_LCR_A); - - smsc_ircc_set_sir_speed(self, SMSC_IRCC2_C_IRDA_FALLBACK_SPEED); - - /* Power on device */ - outb(0x00, iobase + IRCC_MASTER); -} - -/* - * Function smsc_ircc_net_ioctl (dev, rq, cmd) - * - * Process IOCTL commands for this device - * - */ -static int smsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct if_irda_req *irq = (struct if_irda_req *) rq; - struct smsc_ircc_cb *self; - unsigned long flags; - int ret = 0; - - IRDA_ASSERT(dev != NULL, return -1;); - - self = netdev_priv(dev); - - IRDA_ASSERT(self != NULL, return -1;); - - pr_debug("%s(), %s, (cmd=0x%X)\n", __func__, dev->name, cmd); - - switch (cmd) { - case SIOCSBANDWIDTH: /* Set bandwidth */ - if (!capable(CAP_NET_ADMIN)) - ret = -EPERM; - else { - /* Make sure we are the only one touching - * self->io.speed and the hardware - Jean II */ - spin_lock_irqsave(&self->lock, flags); - smsc_ircc_change_speed(self, irq->ifr_baudrate); - spin_unlock_irqrestore(&self->lock, flags); - } - break; - case SIOCSMEDIABUSY: /* Set media busy */ - if (!capable(CAP_NET_ADMIN)) { - ret = -EPERM; - break; - } - - irda_device_set_media_busy(self->netdev, TRUE); - break; - case SIOCGRECEIVING: /* Check if we are receiving right now */ - irq->ifr_receiving = smsc_ircc_is_receiving(self); - break; - #if 0 - case SIOCSDTRRTS: - if (!capable(CAP_NET_ADMIN)) { - ret = -EPERM; - break; - } - smsc_ircc_sir_set_dtr_rts(dev, irq->ifr_dtr, irq->ifr_rts); - break; - #endif - default: - ret = -EOPNOTSUPP; - } - - return ret; -} - -#if SMSC_IRCC2_C_NET_TIMEOUT -/* - * Function smsc_ircc_timeout (struct net_device *dev) - * - * The networking timeout management. - * - */ - -static void smsc_ircc_timeout(struct net_device *dev) -{ - struct smsc_ircc_cb *self = netdev_priv(dev); - unsigned long flags; - - net_warn_ratelimited("%s: transmit timed out, changing speed to: %d\n", - dev->name, self->io.speed); - spin_lock_irqsave(&self->lock, flags); - smsc_ircc_sir_start(self); - smsc_ircc_change_speed(self, self->io.speed); - netif_trans_update(dev); /* prevent tx timeout */ - netif_wake_queue(dev); - spin_unlock_irqrestore(&self->lock, flags); -} -#endif - -/* - * Function smsc_ircc_hard_xmit_sir (struct sk_buff *skb, struct net_device *dev) - * - * Transmits the current frame until FIFO is full, then - * waits until the next transmit interrupt, and continues until the - * frame is transmitted. - */ -static netdev_tx_t smsc_ircc_hard_xmit_sir(struct sk_buff *skb, - struct net_device *dev) -{ - struct smsc_ircc_cb *self; - unsigned long flags; - s32 speed; - - pr_debug("%s\n", __func__); - - IRDA_ASSERT(dev != NULL, return NETDEV_TX_OK;); - - self = netdev_priv(dev); - IRDA_ASSERT(self != NULL, return NETDEV_TX_OK;); - - netif_stop_queue(dev); - - /* Make sure test of self->io.speed & speed change are atomic */ - spin_lock_irqsave(&self->lock, flags); - - /* Check if we need to change the speed */ - speed = irda_get_next_speed(skb); - if (speed != self->io.speed && speed != -1) { - /* Check for empty frame */ - if (!skb->len) { - /* - * We send frames one by one in SIR mode (no - * pipelining), so at this point, if we were sending - * a previous frame, we just received the interrupt - * telling us it is finished (UART_IIR_THRI). - * Therefore, waiting for the transmitter to really - * finish draining the fifo won't take too long. - * And the interrupt handler is not expected to run. - * - Jean II */ - smsc_ircc_sir_wait_hw_transmitter_finish(self); - smsc_ircc_change_speed(self, speed); - spin_unlock_irqrestore(&self->lock, flags); - dev_kfree_skb(skb); - return NETDEV_TX_OK; - } - self->new_speed = speed; - } - - /* Init tx buffer */ - self->tx_buff.data = self->tx_buff.head; - - /* Copy skb to tx_buff while wrapping, stuffing and making CRC */ - self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data, - self->tx_buff.truesize); - - dev->stats.tx_bytes += self->tx_buff.len; - - /* Turn on transmit finished interrupt. Will fire immediately! */ - outb(UART_IER_THRI, self->io.sir_base + UART_IER); - - spin_unlock_irqrestore(&self->lock, flags); - - dev_kfree_skb(skb); - - return NETDEV_TX_OK; -} - -/* - * Function smsc_ircc_set_fir_speed (self, baud) - * - * Change the speed of the device - * - */ -static void smsc_ircc_set_fir_speed(struct smsc_ircc_cb *self, u32 speed) -{ - int fir_base, ir_mode, ctrl, fast; - - IRDA_ASSERT(self != NULL, return;); - fir_base = self->io.fir_base; - - self->io.speed = speed; - - switch (speed) { - default: - case 576000: - ir_mode = IRCC_CFGA_IRDA_HDLC; - ctrl = IRCC_CRC; - fast = 0; - pr_debug("%s(), handling baud of 576000\n", __func__); - break; - case 1152000: - ir_mode = IRCC_CFGA_IRDA_HDLC; - ctrl = IRCC_1152 | IRCC_CRC; - fast = IRCC_LCR_A_FAST | IRCC_LCR_A_GP_DATA; - pr_debug("%s(), handling baud of 1152000\n", - __func__); - break; - case 4000000: - ir_mode = IRCC_CFGA_IRDA_4PPM; - ctrl = IRCC_CRC; - fast = IRCC_LCR_A_FAST; - pr_debug("%s(), handling baud of 4000000\n", - __func__); - break; - } - #if 0 - Now in tranceiver! - /* This causes an interrupt */ - register_bank(fir_base, 0); - outb((inb(fir_base + IRCC_LCR_A) & 0xbf) | fast, fir_base + IRCC_LCR_A); - #endif - - register_bank(fir_base, 1); - outb(((inb(fir_base + IRCC_SCE_CFGA) & IRCC_SCE_CFGA_BLOCK_CTRL_BITS_MASK) | ir_mode), fir_base + IRCC_SCE_CFGA); - - register_bank(fir_base, 4); - outb((inb(fir_base + IRCC_CONTROL) & 0x30) | ctrl, fir_base + IRCC_CONTROL); -} - -/* - * Function smsc_ircc_fir_start(self) - * - * Change the speed of the device - * - */ -static void smsc_ircc_fir_start(struct smsc_ircc_cb *self) -{ - struct net_device *dev; - int fir_base; - - pr_debug("%s\n", __func__); - - IRDA_ASSERT(self != NULL, return;); - dev = self->netdev; - IRDA_ASSERT(dev != NULL, return;); - - fir_base = self->io.fir_base; - - /* Reset everything */ - - /* Clear FIFO */ - outb(inb(fir_base + IRCC_LCR_A) | IRCC_LCR_A_FIFO_RESET, fir_base + IRCC_LCR_A); - - /* Enable interrupt */ - /*outb(IRCC_IER_ACTIVE_FRAME|IRCC_IER_EOM, fir_base + IRCC_IER);*/ - - register_bank(fir_base, 1); - - /* Select the TX/RX interface */ -#ifdef SMSC_669 /* Uses pin 88/89 for Rx/Tx */ - outb(((inb(fir_base + IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_COM), - fir_base + IRCC_SCE_CFGB); -#else - outb(((inb(fir_base + IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_IR), - fir_base + IRCC_SCE_CFGB); -#endif - (void) inb(fir_base + IRCC_FIFO_THRESHOLD); - - /* Enable SCE interrupts */ - outb(0, fir_base + IRCC_MASTER); - register_bank(fir_base, 0); - outb(IRCC_IER_ACTIVE_FRAME | IRCC_IER_EOM, fir_base + IRCC_IER); - outb(IRCC_MASTER_INT_EN, fir_base + IRCC_MASTER); -} - -/* - * Function smsc_ircc_fir_stop(self, baud) - * - * Change the speed of the device - * - */ -static void smsc_ircc_fir_stop(struct smsc_ircc_cb *self) -{ - int fir_base; - - pr_debug("%s\n", __func__); - - IRDA_ASSERT(self != NULL, return;); - - fir_base = self->io.fir_base; - register_bank(fir_base, 0); - /*outb(IRCC_MASTER_RESET, fir_base + IRCC_MASTER);*/ - outb(inb(fir_base + IRCC_LCR_B) & IRCC_LCR_B_SIP_ENABLE, fir_base + IRCC_LCR_B); -} - - -/* - * Function smsc_ircc_change_speed(self, baud) - * - * Change the speed of the device - * - * This function *must* be called with spinlock held, because it may - * be called from the irq handler. - Jean II - */ -static void smsc_ircc_change_speed(struct smsc_ircc_cb *self, u32 speed) -{ - struct net_device *dev; - int last_speed_was_sir; - - pr_debug("%s() changing speed to: %d\n", __func__, speed); - - IRDA_ASSERT(self != NULL, return;); - dev = self->netdev; - - last_speed_was_sir = self->io.speed <= SMSC_IRCC2_MAX_SIR_SPEED; - - #if 0 - /* Temp Hack */ - speed= 1152000; - self->io.speed = speed; - last_speed_was_sir = 0; - smsc_ircc_fir_start(self); - #endif - - if (self->io.speed == 0) - smsc_ircc_sir_start(self); - - #if 0 - if (!last_speed_was_sir) speed = self->io.speed; - #endif - - if (self->io.speed != speed) - smsc_ircc_set_transceiver_for_speed(self, speed); - - self->io.speed = speed; - - if (speed <= SMSC_IRCC2_MAX_SIR_SPEED) { - if (!last_speed_was_sir) { - smsc_ircc_fir_stop(self); - smsc_ircc_sir_start(self); - } - smsc_ircc_set_sir_speed(self, speed); - } else { - if (last_speed_was_sir) { - #if SMSC_IRCC2_C_SIR_STOP - smsc_ircc_sir_stop(self); - #endif - smsc_ircc_fir_start(self); - } - smsc_ircc_set_fir_speed(self, speed); - - #if 0 - self->tx_buff.len = 10; - self->tx_buff.data = self->tx_buff.head; - - smsc_ircc_dma_xmit(self, 4000); - #endif - /* Be ready for incoming frames */ - smsc_ircc_dma_receive(self); - } - - netif_wake_queue(dev); -} - -/* - * Function smsc_ircc_set_sir_speed (self, speed) - * - * Set speed of IrDA port to specified baudrate - * - */ -static void smsc_ircc_set_sir_speed(struct smsc_ircc_cb *self, __u32 speed) -{ - int iobase; - int fcr; /* FIFO control reg */ - int lcr; /* Line control reg */ - int divisor; - - pr_debug("%s(), Setting speed to: %d\n", __func__, speed); - - IRDA_ASSERT(self != NULL, return;); - iobase = self->io.sir_base; - - /* Update accounting for new speed */ - self->io.speed = speed; - - /* Turn off interrupts */ - outb(0, iobase + UART_IER); - - divisor = SMSC_IRCC2_MAX_SIR_SPEED / speed; - - fcr = UART_FCR_ENABLE_FIFO; - - /* - * Use trigger level 1 to avoid 3 ms. timeout delay at 9600 bps, and - * almost 1,7 ms at 19200 bps. At speeds above that we can just forget - * about this timeout since it will always be fast enough. - */ - fcr |= self->io.speed < 38400 ? - UART_FCR_TRIGGER_1 : UART_FCR_TRIGGER_14; - - /* IrDA ports use 8N1 */ - lcr = UART_LCR_WLEN8; - - outb(UART_LCR_DLAB | lcr, iobase + UART_LCR); /* Set DLAB */ - outb(divisor & 0xff, iobase + UART_DLL); /* Set speed */ - outb(divisor >> 8, iobase + UART_DLM); - outb(lcr, iobase + UART_LCR); /* Set 8N1 */ - outb(fcr, iobase + UART_FCR); /* Enable FIFO's */ - - /* Turn on interrups */ - outb(UART_IER_RLSI | UART_IER_RDI | UART_IER_THRI, iobase + UART_IER); - - pr_debug("%s() speed changed to: %d\n", __func__, speed); -} - - -/* - * Function smsc_ircc_hard_xmit_fir (skb, dev) - * - * Transmit the frame! - * - */ -static netdev_tx_t smsc_ircc_hard_xmit_fir(struct sk_buff *skb, - struct net_device *dev) -{ - struct smsc_ircc_cb *self; - unsigned long flags; - s32 speed; - int mtt; - - IRDA_ASSERT(dev != NULL, return NETDEV_TX_OK;); - self = netdev_priv(dev); - IRDA_ASSERT(self != NULL, return NETDEV_TX_OK;); - - netif_stop_queue(dev); - - /* Make sure test of self->io.speed & speed change are atomic */ - spin_lock_irqsave(&self->lock, flags); - - /* Check if we need to change the speed after this frame */ - speed = irda_get_next_speed(skb); - if (speed != self->io.speed && speed != -1) { - /* Check for empty frame */ - if (!skb->len) { - /* Note : you should make sure that speed changes - * are not going to corrupt any outgoing frame. - * Look at nsc-ircc for the gory details - Jean II */ - smsc_ircc_change_speed(self, speed); - spin_unlock_irqrestore(&self->lock, flags); - dev_kfree_skb(skb); - return NETDEV_TX_OK; - } - - self->new_speed = speed; - } - - skb_copy_from_linear_data(skb, self->tx_buff.head, skb->len); - - self->tx_buff.len = skb->len; - self->tx_buff.data = self->tx_buff.head; - - mtt = irda_get_mtt(skb); - if (mtt) { - int bofs; - - /* - * Compute how many BOFs (STA or PA's) we need to waste the - * min turn time given the speed of the link. - */ - bofs = mtt * (self->io.speed / 1000) / 8000; - if (bofs > 4095) - bofs = 4095; - - smsc_ircc_dma_xmit(self, bofs); - } else { - /* Transmit frame */ - smsc_ircc_dma_xmit(self, 0); - } - - spin_unlock_irqrestore(&self->lock, flags); - dev_kfree_skb(skb); - - return NETDEV_TX_OK; -} - -/* - * Function smsc_ircc_dma_xmit (self, bofs) - * - * Transmit data using DMA - * - */ -static void smsc_ircc_dma_xmit(struct smsc_ircc_cb *self, int bofs) -{ - int iobase = self->io.fir_base; - u8 ctrl; - - pr_debug("%s\n", __func__); -#if 1 - /* Disable Rx */ - register_bank(iobase, 0); - outb(0x00, iobase + IRCC_LCR_B); -#endif - register_bank(iobase, 1); - outb(inb(iobase + IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE, - iobase + IRCC_SCE_CFGB); - - self->io.direction = IO_XMIT; - - /* Set BOF additional count for generating the min turn time */ - register_bank(iobase, 4); - outb(bofs & 0xff, iobase + IRCC_BOF_COUNT_LO); - ctrl = inb(iobase + IRCC_CONTROL) & 0xf0; - outb(ctrl | ((bofs >> 8) & 0x0f), iobase + IRCC_BOF_COUNT_HI); - - /* Set max Tx frame size */ - outb(self->tx_buff.len >> 8, iobase + IRCC_TX_SIZE_HI); - outb(self->tx_buff.len & 0xff, iobase + IRCC_TX_SIZE_LO); - - /*outb(UART_MCR_OUT2, self->io.sir_base + UART_MCR);*/ - - /* Enable burst mode chip Tx DMA */ - register_bank(iobase, 1); - outb(inb(iobase + IRCC_SCE_CFGB) | IRCC_CFGB_DMA_ENABLE | - IRCC_CFGB_DMA_BURST, iobase + IRCC_SCE_CFGB); - - /* Setup DMA controller (must be done after enabling chip DMA) */ - irda_setup_dma(self->io.dma, self->tx_buff_dma, self->tx_buff.len, - DMA_TX_MODE); - - /* Enable interrupt */ - - register_bank(iobase, 0); - outb(IRCC_IER_ACTIVE_FRAME | IRCC_IER_EOM, iobase + IRCC_IER); - outb(IRCC_MASTER_INT_EN, iobase + IRCC_MASTER); - - /* Enable transmit */ - outb(IRCC_LCR_B_SCE_TRANSMIT | IRCC_LCR_B_SIP_ENABLE, iobase + IRCC_LCR_B); -} - -/* - * Function smsc_ircc_dma_xmit_complete (self) - * - * The transfer of a frame in finished. This function will only be called - * by the interrupt handler - * - */ -static void smsc_ircc_dma_xmit_complete(struct smsc_ircc_cb *self) -{ - int iobase = self->io.fir_base; - - pr_debug("%s\n", __func__); -#if 0 - /* Disable Tx */ - register_bank(iobase, 0); - outb(0x00, iobase + IRCC_LCR_B); -#endif - register_bank(iobase, 1); - outb(inb(iobase + IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE, - iobase + IRCC_SCE_CFGB); - - /* Check for underrun! */ - register_bank(iobase, 0); - if (inb(iobase + IRCC_LSR) & IRCC_LSR_UNDERRUN) { - self->netdev->stats.tx_errors++; - self->netdev->stats.tx_fifo_errors++; - - /* Reset error condition */ - register_bank(iobase, 0); - outb(IRCC_MASTER_ERROR_RESET, iobase + IRCC_MASTER); - outb(0x00, iobase + IRCC_MASTER); - } else { - self->netdev->stats.tx_packets++; - self->netdev->stats.tx_bytes += self->tx_buff.len; - } - - /* Check if it's time to change the speed */ - if (self->new_speed) { - smsc_ircc_change_speed(self, self->new_speed); - self->new_speed = 0; - } - - netif_wake_queue(self->netdev); -} - -/* - * Function smsc_ircc_dma_receive(self) - * - * Get ready for receiving a frame. The device will initiate a DMA - * if it starts to receive a frame. - * - */ -static int smsc_ircc_dma_receive(struct smsc_ircc_cb *self) -{ - int iobase = self->io.fir_base; -#if 0 - /* Turn off chip DMA */ - register_bank(iobase, 1); - outb(inb(iobase + IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE, - iobase + IRCC_SCE_CFGB); -#endif - - /* Disable Tx */ - register_bank(iobase, 0); - outb(0x00, iobase + IRCC_LCR_B); - - /* Turn off chip DMA */ - register_bank(iobase, 1); - outb(inb(iobase + IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE, - iobase + IRCC_SCE_CFGB); - - self->io.direction = IO_RECV; - self->rx_buff.data = self->rx_buff.head; - - /* Set max Rx frame size */ - register_bank(iobase, 4); - outb((2050 >> 8) & 0x0f, iobase + IRCC_RX_SIZE_HI); - outb(2050 & 0xff, iobase + IRCC_RX_SIZE_LO); - - /* Setup DMA controller */ - irda_setup_dma(self->io.dma, self->rx_buff_dma, self->rx_buff.truesize, - DMA_RX_MODE); - - /* Enable burst mode chip Rx DMA */ - register_bank(iobase, 1); - outb(inb(iobase + IRCC_SCE_CFGB) | IRCC_CFGB_DMA_ENABLE | - IRCC_CFGB_DMA_BURST, iobase + IRCC_SCE_CFGB); - - /* Enable interrupt */ - register_bank(iobase, 0); - outb(IRCC_IER_ACTIVE_FRAME | IRCC_IER_EOM, iobase + IRCC_IER); - outb(IRCC_MASTER_INT_EN, iobase + IRCC_MASTER); - - /* Enable receiver */ - register_bank(iobase, 0); - outb(IRCC_LCR_B_SCE_RECEIVE | IRCC_LCR_B_SIP_ENABLE, - iobase + IRCC_LCR_B); - - return 0; -} - -/* - * Function smsc_ircc_dma_receive_complete(self) - * - * Finished with receiving frames - * - */ -static void smsc_ircc_dma_receive_complete(struct smsc_ircc_cb *self) -{ - struct sk_buff *skb; - int len, msgcnt, lsr; - int iobase = self->io.fir_base; - - register_bank(iobase, 0); - - pr_debug("%s\n", __func__); -#if 0 - /* Disable Rx */ - register_bank(iobase, 0); - outb(0x00, iobase + IRCC_LCR_B); -#endif - register_bank(iobase, 0); - outb(inb(iobase + IRCC_LSAR) & ~IRCC_LSAR_ADDRESS_MASK, iobase + IRCC_LSAR); - lsr= inb(iobase + IRCC_LSR); - msgcnt = inb(iobase + IRCC_LCR_B) & 0x08; - - pr_debug("%s: dma count = %d\n", __func__, - get_dma_residue(self->io.dma)); - - len = self->rx_buff.truesize - get_dma_residue(self->io.dma); - - /* Look for errors */ - if (lsr & (IRCC_LSR_FRAME_ERROR | IRCC_LSR_CRC_ERROR | IRCC_LSR_SIZE_ERROR)) { - self->netdev->stats.rx_errors++; - if (lsr & IRCC_LSR_FRAME_ERROR) - self->netdev->stats.rx_frame_errors++; - if (lsr & IRCC_LSR_CRC_ERROR) - self->netdev->stats.rx_crc_errors++; - if (lsr & IRCC_LSR_SIZE_ERROR) - self->netdev->stats.rx_length_errors++; - if (lsr & (IRCC_LSR_UNDERRUN | IRCC_LSR_OVERRUN)) - self->netdev->stats.rx_length_errors++; - return; - } - - /* Remove CRC */ - len -= self->io.speed < 4000000 ? 2 : 4; - - if (len < 2 || len > 2050) { - net_warn_ratelimited("%s(), bogus len=%d\n", __func__, len); - return; - } - pr_debug("%s: msgcnt = %d, len=%d\n", __func__, msgcnt, len); - - skb = dev_alloc_skb(len + 1); - if (!skb) - return; - - /* Make sure IP header gets aligned */ - skb_reserve(skb, 1); - - skb_put_data(skb, self->rx_buff.data, len); - self->netdev->stats.rx_packets++; - self->netdev->stats.rx_bytes += len; - - skb->dev = self->netdev; - skb_reset_mac_header(skb); - skb->protocol = htons(ETH_P_IRDA); - netif_rx(skb); -} - -/* - * Function smsc_ircc_sir_receive (self) - * - * Receive one frame from the infrared port - * - */ -static void smsc_ircc_sir_receive(struct smsc_ircc_cb *self) -{ - int boguscount = 0; - int iobase; - - IRDA_ASSERT(self != NULL, return;); - - iobase = self->io.sir_base; - - /* - * Receive all characters in Rx FIFO, unwrap and unstuff them. - * async_unwrap_char will deliver all found frames - */ - do { - async_unwrap_char(self->netdev, &self->netdev->stats, &self->rx_buff, - inb(iobase + UART_RX)); - - /* Make sure we don't stay here to long */ - if (boguscount++ > 32) { - pr_debug("%s(), breaking!\n", __func__); - break; - } - } while (inb(iobase + UART_LSR) & UART_LSR_DR); -} - - -/* - * Function smsc_ircc_interrupt (irq, dev_id, regs) - * - * An interrupt from the chip has arrived. Time to do some work - * - */ -static irqreturn_t smsc_ircc_interrupt(int dummy, void *dev_id) -{ - struct net_device *dev = dev_id; - struct smsc_ircc_cb *self = netdev_priv(dev); - int iobase, iir, lcra, lsr; - irqreturn_t ret = IRQ_NONE; - - /* Serialise the interrupt handler in various CPUs, stop Tx path */ - spin_lock(&self->lock); - - /* Check if we should use the SIR interrupt handler */ - if (self->io.speed <= SMSC_IRCC2_MAX_SIR_SPEED) { - ret = smsc_ircc_interrupt_sir(dev); - goto irq_ret_unlock; - } - - iobase = self->io.fir_base; - - register_bank(iobase, 0); - iir = inb(iobase + IRCC_IIR); - if (iir == 0) - goto irq_ret_unlock; - ret = IRQ_HANDLED; - - /* Disable interrupts */ - outb(0, iobase + IRCC_IER); - lcra = inb(iobase + IRCC_LCR_A); - lsr = inb(iobase + IRCC_LSR); - - pr_debug("%s(), iir = 0x%02x\n", __func__, iir); - - if (iir & IRCC_IIR_EOM) { - if (self->io.direction == IO_RECV) - smsc_ircc_dma_receive_complete(self); - else - smsc_ircc_dma_xmit_complete(self); - - smsc_ircc_dma_receive(self); - } - - if (iir & IRCC_IIR_ACTIVE_FRAME) { - /*printk(KERN_WARNING "%s(): Active Frame\n", __func__);*/ - } - - /* Enable interrupts again */ - - register_bank(iobase, 0); - outb(IRCC_IER_ACTIVE_FRAME | IRCC_IER_EOM, iobase + IRCC_IER); - - irq_ret_unlock: - spin_unlock(&self->lock); - - return ret; -} - -/* - * Function irport_interrupt_sir (irq, dev_id) - * - * Interrupt handler for SIR modes - */ -static irqreturn_t smsc_ircc_interrupt_sir(struct net_device *dev) -{ - struct smsc_ircc_cb *self = netdev_priv(dev); - int boguscount = 0; - int iobase; - int iir, lsr; - - /* Already locked coming here in smsc_ircc_interrupt() */ - /*spin_lock(&self->lock);*/ - - iobase = self->io.sir_base; - - iir = inb(iobase + UART_IIR) & UART_IIR_ID; - if (iir == 0) - return IRQ_NONE; - while (iir) { - /* Clear interrupt */ - lsr = inb(iobase + UART_LSR); - - pr_debug("%s(), iir=%02x, lsr=%02x, iobase=%#x\n", - __func__, iir, lsr, iobase); - - switch (iir) { - case UART_IIR_RLSI: - pr_debug("%s(), RLSI\n", __func__); - break; - case UART_IIR_RDI: - /* Receive interrupt */ - smsc_ircc_sir_receive(self); - break; - case UART_IIR_THRI: - if (lsr & UART_LSR_THRE) - /* Transmitter ready for data */ - smsc_ircc_sir_write_wakeup(self); - break; - default: - pr_debug("%s(), unhandled IIR=%#x\n", - __func__, iir); - break; - } - - /* Make sure we don't stay here to long */ - if (boguscount++ > 100) - break; - - iir = inb(iobase + UART_IIR) & UART_IIR_ID; - } - /*spin_unlock(&self->lock);*/ - return IRQ_HANDLED; -} - - -#if 0 /* unused */ -/* - * Function ircc_is_receiving (self) - * - * Return TRUE is we are currently receiving a frame - * - */ -static int ircc_is_receiving(struct smsc_ircc_cb *self) -{ - int status = FALSE; - /* int iobase; */ - - pr_debug("%s\n", __func__); - - IRDA_ASSERT(self != NULL, return FALSE;); - - pr_debug("%s: dma count = %d\n", __func__, - get_dma_residue(self->io.dma)); - - status = (self->rx_buff.state != OUTSIDE_FRAME); - - return status; -} -#endif /* unused */ - -static int smsc_ircc_request_irq(struct smsc_ircc_cb *self) -{ - int error; - - error = request_irq(self->io.irq, smsc_ircc_interrupt, 0, - self->netdev->name, self->netdev); - if (error) - pr_debug("%s(), unable to allocate irq=%d, err=%d\n", - __func__, self->io.irq, error); - - return error; -} - -static void smsc_ircc_start_interrupts(struct smsc_ircc_cb *self) -{ - unsigned long flags; - - spin_lock_irqsave(&self->lock, flags); - - self->io.speed = 0; - smsc_ircc_change_speed(self, SMSC_IRCC2_C_IRDA_FALLBACK_SPEED); - - spin_unlock_irqrestore(&self->lock, flags); -} - -static void smsc_ircc_stop_interrupts(struct smsc_ircc_cb *self) -{ - int iobase = self->io.fir_base; - unsigned long flags; - - spin_lock_irqsave(&self->lock, flags); - - register_bank(iobase, 0); - outb(0, iobase + IRCC_IER); - outb(IRCC_MASTER_RESET, iobase + IRCC_MASTER); - outb(0x00, iobase + IRCC_MASTER); - - spin_unlock_irqrestore(&self->lock, flags); -} - - -/* - * Function smsc_ircc_net_open (dev) - * - * Start the device - * - */ -static int smsc_ircc_net_open(struct net_device *dev) -{ - struct smsc_ircc_cb *self; - char hwname[16]; - - pr_debug("%s\n", __func__); - - IRDA_ASSERT(dev != NULL, return -1;); - self = netdev_priv(dev); - IRDA_ASSERT(self != NULL, return 0;); - - if (self->io.suspended) { - pr_debug("%s(), device is suspended\n", __func__); - return -EAGAIN; - } - - if (request_irq(self->io.irq, smsc_ircc_interrupt, 0, dev->name, - (void *) dev)) { - pr_debug("%s(), unable to allocate irq=%d\n", - __func__, self->io.irq); - return -EAGAIN; - } - - smsc_ircc_start_interrupts(self); - - /* Give self a hardware name */ - /* It would be cool to offer the chip revision here - Jean II */ - sprintf(hwname, "SMSC @ 0x%03x", self->io.fir_base); - - /* - * Open new IrLAP layer instance, now that everything should be - * initialized properly - */ - self->irlap = irlap_open(dev, &self->qos, hwname); - - /* - * Always allocate the DMA channel after the IRQ, - * and clean up on failure. - */ - if (request_dma(self->io.dma, dev->name)) { - smsc_ircc_net_close(dev); - - net_warn_ratelimited("%s(), unable to allocate DMA=%d\n", - __func__, self->io.dma); - return -EAGAIN; - } - - netif_start_queue(dev); - - return 0; -} - -/* - * Function smsc_ircc_net_close (dev) - * - * Stop the device - * - */ -static int smsc_ircc_net_close(struct net_device *dev) -{ - struct smsc_ircc_cb *self; - - pr_debug("%s\n", __func__); - - IRDA_ASSERT(dev != NULL, return -1;); - self = netdev_priv(dev); - IRDA_ASSERT(self != NULL, return 0;); - - /* Stop device */ - netif_stop_queue(dev); - - /* Stop and remove instance of IrLAP */ - if (self->irlap) - irlap_close(self->irlap); - self->irlap = NULL; - - smsc_ircc_stop_interrupts(self); - - /* if we are called from smsc_ircc_resume we don't have IRQ reserved */ - if (!self->io.suspended) - free_irq(self->io.irq, dev); - - disable_dma(self->io.dma); - free_dma(self->io.dma); - - return 0; -} - -static int smsc_ircc_suspend(struct platform_device *dev, pm_message_t state) -{ - struct smsc_ircc_cb *self = platform_get_drvdata(dev); - - if (!self->io.suspended) { - pr_debug("%s, Suspending\n", driver_name); - - rtnl_lock(); - if (netif_running(self->netdev)) { - netif_device_detach(self->netdev); - smsc_ircc_stop_interrupts(self); - free_irq(self->io.irq, self->netdev); - disable_dma(self->io.dma); - } - self->io.suspended = 1; - rtnl_unlock(); - } - - return 0; -} - -static int smsc_ircc_resume(struct platform_device *dev) -{ - struct smsc_ircc_cb *self = platform_get_drvdata(dev); - - if (self->io.suspended) { - pr_debug("%s, Waking up\n", driver_name); - - rtnl_lock(); - smsc_ircc_init_chip(self); - if (netif_running(self->netdev)) { - if (smsc_ircc_request_irq(self)) { - /* - * Don't fail resume process, just kill this - * network interface - */ - unregister_netdevice(self->netdev); - } else { - enable_dma(self->io.dma); - smsc_ircc_start_interrupts(self); - netif_device_attach(self->netdev); - } - } - self->io.suspended = 0; - rtnl_unlock(); - } - return 0; -} - -/* - * Function smsc_ircc_close (self) - * - * Close driver instance - * - */ -static int __exit smsc_ircc_close(struct smsc_ircc_cb *self) -{ - pr_debug("%s\n", __func__); - - IRDA_ASSERT(self != NULL, return -1;); - - platform_device_unregister(self->pldev); - - /* Remove netdevice */ - unregister_netdev(self->netdev); - - smsc_ircc_stop_interrupts(self); - - /* Release the PORTS that this driver is using */ - pr_debug("%s(), releasing 0x%03x\n", __func__, - self->io.fir_base); - - release_region(self->io.fir_base, self->io.fir_ext); - - pr_debug("%s(), releasing 0x%03x\n", __func__, - self->io.sir_base); - - release_region(self->io.sir_base, self->io.sir_ext); - - if (self->tx_buff.head) - dma_free_coherent(NULL, self->tx_buff.truesize, - self->tx_buff.head, self->tx_buff_dma); - - if (self->rx_buff.head) - dma_free_coherent(NULL, self->rx_buff.truesize, - self->rx_buff.head, self->rx_buff_dma); - - free_netdev(self->netdev); - - return 0; -} - -static void __exit smsc_ircc_cleanup(void) -{ - int i; - - pr_debug("%s\n", __func__); - - for (i = 0; i < 2; i++) { - if (dev_self[i]) - smsc_ircc_close(dev_self[i]); - } - - if (pnp_driver_registered) - pnp_unregister_driver(&smsc_ircc_pnp_driver); - - platform_driver_unregister(&smsc_ircc_driver); -} - -/* - * Start SIR operations - * - * This function *must* be called with spinlock held, because it may - * be called from the irq handler (via smsc_ircc_change_speed()). - Jean II - */ -static void smsc_ircc_sir_start(struct smsc_ircc_cb *self) -{ - struct net_device *dev; - int fir_base, sir_base; - - pr_debug("%s\n", __func__); - - IRDA_ASSERT(self != NULL, return;); - dev = self->netdev; - IRDA_ASSERT(dev != NULL, return;); - - fir_base = self->io.fir_base; - sir_base = self->io.sir_base; - - /* Reset everything */ - outb(IRCC_MASTER_RESET, fir_base + IRCC_MASTER); - - #if SMSC_IRCC2_C_SIR_STOP - /*smsc_ircc_sir_stop(self);*/ - #endif - - register_bank(fir_base, 1); - outb(((inb(fir_base + IRCC_SCE_CFGA) & IRCC_SCE_CFGA_BLOCK_CTRL_BITS_MASK) | IRCC_CFGA_IRDA_SIR_A), fir_base + IRCC_SCE_CFGA); - - /* Initialize UART */ - outb(UART_LCR_WLEN8, sir_base + UART_LCR); /* Reset DLAB */ - outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), sir_base + UART_MCR); - - /* Turn on interrups */ - outb(UART_IER_RLSI | UART_IER_RDI |UART_IER_THRI, sir_base + UART_IER); - - pr_debug("%s() - exit\n", __func__); - - outb(0x00, fir_base + IRCC_MASTER); -} - -#if SMSC_IRCC2_C_SIR_STOP -void smsc_ircc_sir_stop(struct smsc_ircc_cb *self) -{ - int iobase; - - pr_debug("%s\n", __func__); - iobase = self->io.sir_base; - - /* Reset UART */ - outb(0, iobase + UART_MCR); - - /* Turn off interrupts */ - outb(0, iobase + UART_IER); -} -#endif - -/* - * Function smsc_sir_write_wakeup (self) - * - * Called by the SIR interrupt handler when there's room for more data. - * If we have more packets to send, we send them here. - * - */ -static void smsc_ircc_sir_write_wakeup(struct smsc_ircc_cb *self) -{ - int actual = 0; - int iobase; - int fcr; - - IRDA_ASSERT(self != NULL, return;); - - pr_debug("%s\n", __func__); - - iobase = self->io.sir_base; - - /* Finished with frame? */ - if (self->tx_buff.len > 0) { - /* Write data left in transmit buffer */ - actual = smsc_ircc_sir_write(iobase, self->io.fifo_size, - self->tx_buff.data, self->tx_buff.len); - self->tx_buff.data += actual; - self->tx_buff.len -= actual; - } else { - - /*if (self->tx_buff.len ==0) {*/ - - /* - * Now serial buffer is almost free & we can start - * transmission of another packet. But first we must check - * if we need to change the speed of the hardware - */ - if (self->new_speed) { - pr_debug("%s(), Changing speed to %d.\n", - __func__, self->new_speed); - smsc_ircc_sir_wait_hw_transmitter_finish(self); - smsc_ircc_change_speed(self, self->new_speed); - self->new_speed = 0; - } else { - /* Tell network layer that we want more frames */ - netif_wake_queue(self->netdev); - } - self->netdev->stats.tx_packets++; - - if (self->io.speed <= 115200) { - /* - * Reset Rx FIFO to make sure that all reflected transmit data - * is discarded. This is needed for half duplex operation - */ - fcr = UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR; - fcr |= self->io.speed < 38400 ? - UART_FCR_TRIGGER_1 : UART_FCR_TRIGGER_14; - - outb(fcr, iobase + UART_FCR); - - /* Turn on receive interrupts */ - outb(UART_IER_RDI, iobase + UART_IER); - } - } -} - -/* - * Function smsc_ircc_sir_write (iobase, fifo_size, buf, len) - * - * Fill Tx FIFO with transmit data - * - */ -static int smsc_ircc_sir_write(int iobase, int fifo_size, __u8 *buf, int len) -{ - int actual = 0; - - /* Tx FIFO should be empty! */ - if (!(inb(iobase + UART_LSR) & UART_LSR_THRE)) { - net_warn_ratelimited("%s(), failed, fifo not empty!\n", - __func__); - return 0; - } - - /* Fill FIFO with current frame */ - while (fifo_size-- > 0 && actual < len) { - /* Transmit next byte */ - outb(buf[actual], iobase + UART_TX); - actual++; - } - return actual; -} - -/* - * Function smsc_ircc_is_receiving (self) - * - * Returns true is we are currently receiving data - * - */ -static int smsc_ircc_is_receiving(struct smsc_ircc_cb *self) -{ - return self->rx_buff.state != OUTSIDE_FRAME; -} - - -/* - * Function smsc_ircc_probe_transceiver(self) - * - * Tries to find the used Transceiver - * - */ -static void smsc_ircc_probe_transceiver(struct smsc_ircc_cb *self) -{ - unsigned int i; - - IRDA_ASSERT(self != NULL, return;); - - for (i = 0; smsc_transceivers[i].name != NULL; i++) - if (smsc_transceivers[i].probe(self->io.fir_base)) { - net_info_ratelimited(" %s transceiver found\n", - smsc_transceivers[i].name); - self->transceiver= i + 1; - return; - } - - net_info_ratelimited("No transceiver found. Defaulting to %s\n", - smsc_transceivers[SMSC_IRCC2_C_DEFAULT_TRANSCEIVER].name); - - self->transceiver = SMSC_IRCC2_C_DEFAULT_TRANSCEIVER; -} - - -/* - * Function smsc_ircc_set_transceiver_for_speed(self, speed) - * - * Set the transceiver according to the speed - * - */ -static void smsc_ircc_set_transceiver_for_speed(struct smsc_ircc_cb *self, u32 speed) -{ - unsigned int trx; - - trx = self->transceiver; - if (trx > 0) - smsc_transceivers[trx - 1].set_for_speed(self->io.fir_base, speed); -} - -/* - * Function smsc_ircc_wait_hw_transmitter_finish () - * - * Wait for the real end of HW transmission - * - * The UART is a strict FIFO, and we get called only when we have finished - * pushing data to the FIFO, so the maximum amount of time we must wait - * is only for the FIFO to drain out. - * - * We use a simple calibrated loop. We may need to adjust the loop - * delay (udelay) to balance I/O traffic and latency. And we also need to - * adjust the maximum timeout. - * It would probably be better to wait for the proper interrupt, - * but it doesn't seem to be available. - * - * We can't use jiffies or kernel timers because : - * 1) We are called from the interrupt handler, which disable softirqs, - * so jiffies won't be increased - * 2) Jiffies granularity is usually very coarse (10ms), and we don't - * want to wait that long to detect stuck hardware. - * Jean II - */ - -static void smsc_ircc_sir_wait_hw_transmitter_finish(struct smsc_ircc_cb *self) -{ - int iobase = self->io.sir_base; - int count = SMSC_IRCC2_HW_TRANSMITTER_TIMEOUT_US; - - /* Calibrated busy loop */ - while (count-- > 0 && !(inb(iobase + UART_LSR) & UART_LSR_TEMT)) - udelay(1); - - if (count < 0) - pr_debug("%s(): stuck transmitter\n", __func__); -} - - -/* PROBING - * - * REVISIT we can be told about the device by PNP, and should use that info - * instead of probing hardware and creating a platform_device ... - */ - -static int __init smsc_ircc_look_for_chips(void) -{ - struct smsc_chip_address *address; - char *type; - unsigned int cfg_base, found; - - found = 0; - address = possible_addresses; - - while (address->cfg_base) { - cfg_base = address->cfg_base; - - /*printk(KERN_WARNING "%s(): probing: 0x%02x for: 0x%02x\n", __func__, cfg_base, address->type);*/ - - if (address->type & SMSCSIO_TYPE_FDC) { - type = "FDC"; - if (address->type & SMSCSIO_TYPE_FLAT) - if (!smsc_superio_flat(fdc_chips_flat, cfg_base, type)) - found++; - - if (address->type & SMSCSIO_TYPE_PAGED) - if (!smsc_superio_paged(fdc_chips_paged, cfg_base, type)) - found++; - } - if (address->type & SMSCSIO_TYPE_LPC) { - type = "LPC"; - if (address->type & SMSCSIO_TYPE_FLAT) - if (!smsc_superio_flat(lpc_chips_flat, cfg_base, type)) - found++; - - if (address->type & SMSCSIO_TYPE_PAGED) - if (!smsc_superio_paged(lpc_chips_paged, cfg_base, type)) - found++; - } - address++; - } - return found; -} - -/* - * Function smsc_superio_flat (chip, base, type) - * - * Try to get configuration of a smc SuperIO chip with flat register model - * - */ -static int __init smsc_superio_flat(const struct smsc_chip *chips, unsigned short cfgbase, char *type) -{ - unsigned short firbase, sirbase; - u8 mode, dma, irq; - int ret = -ENODEV; - - pr_debug("%s\n", __func__); - - if (smsc_ircc_probe(cfgbase, SMSCSIOFLAT_DEVICEID_REG, chips, type) == NULL) - return ret; - - outb(SMSCSIOFLAT_UARTMODE0C_REG, cfgbase); - mode = inb(cfgbase + 1); - - /*printk(KERN_WARNING "%s(): mode: 0x%02x\n", __func__, mode);*/ - - if (!(mode & SMSCSIOFLAT_UART2MODE_VAL_IRDA)) - net_warn_ratelimited("%s(): IrDA not enabled\n", __func__); - - outb(SMSCSIOFLAT_UART2BASEADDR_REG, cfgbase); - sirbase = inb(cfgbase + 1) << 2; - - /* FIR iobase */ - outb(SMSCSIOFLAT_FIRBASEADDR_REG, cfgbase); - firbase = inb(cfgbase + 1) << 3; - - /* DMA */ - outb(SMSCSIOFLAT_FIRDMASELECT_REG, cfgbase); - dma = inb(cfgbase + 1) & SMSCSIOFLAT_FIRDMASELECT_MASK; - - /* IRQ */ - outb(SMSCSIOFLAT_UARTIRQSELECT_REG, cfgbase); - irq = inb(cfgbase + 1) & SMSCSIOFLAT_UART2IRQSELECT_MASK; - - net_info_ratelimited("%s(): fir: 0x%02x, sir: 0x%02x, dma: %02d, irq: %d, mode: 0x%02x\n", - __func__, firbase, sirbase, dma, irq, mode); - - if (firbase && smsc_ircc_open(firbase, sirbase, dma, irq) == 0) - ret = 0; - - /* Exit configuration */ - outb(SMSCSIO_CFGEXITKEY, cfgbase); - - return ret; -} - -/* - * Function smsc_superio_paged (chip, base, type) - * - * Try to get configuration of a smc SuperIO chip with paged register model - * - */ -static int __init smsc_superio_paged(const struct smsc_chip *chips, unsigned short cfg_base, char *type) -{ - unsigned short fir_io, sir_io; - int ret = -ENODEV; - - pr_debug("%s\n", __func__); - - if (smsc_ircc_probe(cfg_base, 0x20, chips, type) == NULL) - return ret; - - /* Select logical device (UART2) */ - outb(0x07, cfg_base); - outb(0x05, cfg_base + 1); - - /* SIR iobase */ - outb(0x60, cfg_base); - sir_io = inb(cfg_base + 1) << 8; - outb(0x61, cfg_base); - sir_io |= inb(cfg_base + 1); - - /* Read FIR base */ - outb(0x62, cfg_base); - fir_io = inb(cfg_base + 1) << 8; - outb(0x63, cfg_base); - fir_io |= inb(cfg_base + 1); - outb(0x2b, cfg_base); /* ??? */ - - if (fir_io && smsc_ircc_open(fir_io, sir_io, ircc_dma, ircc_irq) == 0) - ret = 0; - - /* Exit configuration */ - outb(SMSCSIO_CFGEXITKEY, cfg_base); - - return ret; -} - - -static int __init smsc_access(unsigned short cfg_base, unsigned char reg) -{ - pr_debug("%s\n", __func__); - - outb(reg, cfg_base); - return inb(cfg_base) != reg ? -1 : 0; -} - -static const struct smsc_chip * __init smsc_ircc_probe(unsigned short cfg_base, u8 reg, const struct smsc_chip *chip, char *type) -{ - u8 devid, xdevid, rev; - - pr_debug("%s\n", __func__); - - /* Leave configuration */ - - outb(SMSCSIO_CFGEXITKEY, cfg_base); - - if (inb(cfg_base) == SMSCSIO_CFGEXITKEY) /* not a smc superio chip */ - return NULL; - - outb(reg, cfg_base); - - xdevid = inb(cfg_base + 1); - - /* Enter configuration */ - - outb(SMSCSIO_CFGACCESSKEY, cfg_base); - - #if 0 - if (smsc_access(cfg_base,0x55)) /* send second key and check */ - return NULL; - #endif - - /* probe device ID */ - - if (smsc_access(cfg_base, reg)) - return NULL; - - devid = inb(cfg_base + 1); - - if (devid == 0 || devid == 0xff) /* typical values for unused port */ - return NULL; - - /* probe revision ID */ - - if (smsc_access(cfg_base, reg + 1)) - return NULL; - - rev = inb(cfg_base + 1); - - if (rev >= 128) /* i think this will make no sense */ - return NULL; - - if (devid == xdevid) /* protection against false positives */ - return NULL; - - /* Check for expected device ID; are there others? */ - - while (chip->devid != devid) { - - chip++; - - if (chip->name == NULL) - return NULL; - } - - net_info_ratelimited("found SMC SuperIO Chip (devid=0x%02x rev=%02X base=0x%04x): %s%s\n", - devid, rev, cfg_base, type, chip->name); - - if (chip->rev > rev) { - net_info_ratelimited("Revision higher than expected\n"); - return NULL; - } - - if (chip->flags & NoIRDA) - net_info_ratelimited("chipset does not support IRDA\n"); - - return chip; -} - -static int __init smsc_superio_fdc(unsigned short cfg_base) -{ - int ret = -1; - - if (!request_region(cfg_base, 2, driver_name)) { - net_warn_ratelimited("%s: can't get cfg_base of 0x%03x\n", - __func__, cfg_base); - } else { - if (!smsc_superio_flat(fdc_chips_flat, cfg_base, "FDC") || - !smsc_superio_paged(fdc_chips_paged, cfg_base, "FDC")) - ret = 0; - - release_region(cfg_base, 2); - } - - return ret; -} - -static int __init smsc_superio_lpc(unsigned short cfg_base) -{ - int ret = -1; - - if (!request_region(cfg_base, 2, driver_name)) { - net_warn_ratelimited("%s: can't get cfg_base of 0x%03x\n", - __func__, cfg_base); - } else { - if (!smsc_superio_flat(lpc_chips_flat, cfg_base, "LPC") || - !smsc_superio_paged(lpc_chips_paged, cfg_base, "LPC")) - ret = 0; - - release_region(cfg_base, 2); - } - return ret; -} - -/* - * Look for some specific subsystem setups that need - * pre-configuration not properly done by the BIOS (especially laptops) - * This code is based in part on smcinit.c, tosh1800-smcinit.c - * and tosh2450-smcinit.c. The table lists the device entries - * for ISA bridges with an LPC (Low Pin Count) controller which - * handles the communication with the SMSC device. After the LPC - * controller is initialized through PCI, the SMSC device is initialized - * through a dedicated port in the ISA port-mapped I/O area, this latter - * area is used to configure the SMSC device with default - * SIR and FIR I/O ports, DMA and IRQ. Different vendors have - * used different sets of parameters and different control port - * addresses making a subsystem device table necessary. - */ -#ifdef CONFIG_PCI -static struct smsc_ircc_subsystem_configuration subsystem_configurations[] __initdata = { - /* - * Subsystems needing entries: - * 0x10b9:0x1533 0x103c:0x0850 HP nx9010 family - * 0x10b9:0x1533 0x0e11:0x005a Compaq nc4000 family - * 0x8086:0x24cc 0x0e11:0x002a HP nx9000 family - */ - { - /* Guessed entry */ - .vendor = PCI_VENDOR_ID_INTEL, /* Intel 82801DBM LPC bridge */ - .device = 0x24cc, - .subvendor = 0x103c, - .subdevice = 0x08bc, - .sir_io = 0x02f8, - .fir_io = 0x0130, - .fir_irq = 0x05, - .fir_dma = 0x03, - .cfg_base = 0x004e, - .preconfigure = preconfigure_through_82801, - .name = "HP nx5000 family", - }, - { - .vendor = PCI_VENDOR_ID_INTEL, /* Intel 82801DBM LPC bridge */ - .device = 0x24cc, - .subvendor = 0x103c, - .subdevice = 0x088c, - /* Quite certain these are the same for nc8000 as for nc6000 */ - .sir_io = 0x02f8, - .fir_io = 0x0130, - .fir_irq = 0x05, - .fir_dma = 0x03, - .cfg_base = 0x004e, - .preconfigure = preconfigure_through_82801, - .name = "HP nc8000 family", - }, - { - .vendor = PCI_VENDOR_ID_INTEL, /* Intel 82801DBM LPC bridge */ - .device = 0x24cc, - .subvendor = 0x103c, - .subdevice = 0x0890, - .sir_io = 0x02f8, - .fir_io = 0x0130, - .fir_irq = 0x05, - .fir_dma = 0x03, - .cfg_base = 0x004e, - .preconfigure = preconfigure_through_82801, - .name = "HP nc6000 family", - }, - { - .vendor = PCI_VENDOR_ID_INTEL, /* Intel 82801DBM LPC bridge */ - .device = 0x24cc, - .subvendor = 0x0e11, - .subdevice = 0x0860, - /* I assume these are the same for x1000 as for the others */ - .sir_io = 0x02e8, - .fir_io = 0x02f8, - .fir_irq = 0x07, - .fir_dma = 0x03, - .cfg_base = 0x002e, - .preconfigure = preconfigure_through_82801, - .name = "Compaq x1000 family", - }, - { - /* Intel 82801DB/DBL (ICH4/ICH4-L) LPC Interface Bridge */ - .vendor = PCI_VENDOR_ID_INTEL, - .device = 0x24c0, - .subvendor = 0x1179, - .subdevice = 0xffff, /* 0xffff is "any" */ - .sir_io = 0x03f8, - .fir_io = 0x0130, - .fir_irq = 0x07, - .fir_dma = 0x01, - .cfg_base = 0x002e, - .preconfigure = preconfigure_through_82801, - .name = "Toshiba laptop with Intel 82801DB/DBL LPC bridge", - }, - { - .vendor = PCI_VENDOR_ID_INTEL, /* Intel 82801CAM ISA bridge */ - .device = 0x248c, - .subvendor = 0x1179, - .subdevice = 0xffff, /* 0xffff is "any" */ - .sir_io = 0x03f8, - .fir_io = 0x0130, - .fir_irq = 0x03, - .fir_dma = 0x03, - .cfg_base = 0x002e, - .preconfigure = preconfigure_through_82801, - .name = "Toshiba laptop with Intel 82801CAM ISA bridge", - }, - { - /* 82801DBM (ICH4-M) LPC Interface Bridge */ - .vendor = PCI_VENDOR_ID_INTEL, - .device = 0x24cc, - .subvendor = 0x1179, - .subdevice = 0xffff, /* 0xffff is "any" */ - .sir_io = 0x03f8, - .fir_io = 0x0130, - .fir_irq = 0x03, - .fir_dma = 0x03, - .cfg_base = 0x002e, - .preconfigure = preconfigure_through_82801, - .name = "Toshiba laptop with Intel 8281DBM LPC bridge", - }, - { - /* ALi M1533/M1535 PCI to ISA Bridge [Aladdin IV/V/V+] */ - .vendor = PCI_VENDOR_ID_AL, - .device = 0x1533, - .subvendor = 0x1179, - .subdevice = 0xffff, /* 0xffff is "any" */ - .sir_io = 0x02e8, - .fir_io = 0x02f8, - .fir_irq = 0x07, - .fir_dma = 0x03, - .cfg_base = 0x002e, - .preconfigure = preconfigure_through_ali, - .name = "Toshiba laptop with ALi ISA bridge", - }, - { } // Terminator -}; - - -/* - * This sets up the basic SMSC parameters - * (FIR port, SIR port, FIR DMA, FIR IRQ) - * through the chip configuration port. - */ -static int __init preconfigure_smsc_chip(struct - smsc_ircc_subsystem_configuration - *conf) -{ - unsigned short iobase = conf->cfg_base; - unsigned char tmpbyte; - - outb(LPC47N227_CFGACCESSKEY, iobase); // enter configuration state - outb(SMSCSIOFLAT_DEVICEID_REG, iobase); // set for device ID - tmpbyte = inb(iobase +1); // Read device ID - pr_debug("Detected Chip id: 0x%02x, setting up registers...\n", - tmpbyte); - - /* Disable UART1 and set up SIR I/O port */ - outb(0x24, iobase); // select CR24 - UART1 base addr - outb(0x00, iobase + 1); // disable UART1 - outb(SMSCSIOFLAT_UART2BASEADDR_REG, iobase); // select CR25 - UART2 base addr - outb( (conf->sir_io >> 2), iobase + 1); // bits 2-9 of 0x3f8 - tmpbyte = inb(iobase + 1); - if (tmpbyte != (conf->sir_io >> 2) ) { - net_warn_ratelimited("ERROR: could not configure SIR ioport\n"); - net_warn_ratelimited("Try to supply ircc_cfg argument\n"); - return -ENXIO; - } - - /* Set up FIR IRQ channel for UART2 */ - outb(SMSCSIOFLAT_UARTIRQSELECT_REG, iobase); // select CR28 - UART1,2 IRQ select - tmpbyte = inb(iobase + 1); - tmpbyte &= SMSCSIOFLAT_UART1IRQSELECT_MASK; // Do not touch the UART1 portion - tmpbyte |= (conf->fir_irq & SMSCSIOFLAT_UART2IRQSELECT_MASK); - outb(tmpbyte, iobase + 1); - tmpbyte = inb(iobase + 1) & SMSCSIOFLAT_UART2IRQSELECT_MASK; - if (tmpbyte != conf->fir_irq) { - net_warn_ratelimited("ERROR: could not configure FIR IRQ channel\n"); - return -ENXIO; - } - - /* Set up FIR I/O port */ - outb(SMSCSIOFLAT_FIRBASEADDR_REG, iobase); // CR2B - SCE (FIR) base addr - outb((conf->fir_io >> 3), iobase + 1); - tmpbyte = inb(iobase + 1); - if (tmpbyte != (conf->fir_io >> 3) ) { - net_warn_ratelimited("ERROR: could not configure FIR I/O port\n"); - return -ENXIO; - } - - /* Set up FIR DMA channel */ - outb(SMSCSIOFLAT_FIRDMASELECT_REG, iobase); // CR2C - SCE (FIR) DMA select - outb((conf->fir_dma & LPC47N227_FIRDMASELECT_MASK), iobase + 1); // DMA - tmpbyte = inb(iobase + 1) & LPC47N227_FIRDMASELECT_MASK; - if (tmpbyte != (conf->fir_dma & LPC47N227_FIRDMASELECT_MASK)) { - net_warn_ratelimited("ERROR: could not configure FIR DMA channel\n"); - return -ENXIO; - } - - outb(SMSCSIOFLAT_UARTMODE0C_REG, iobase); // CR0C - UART mode - tmpbyte = inb(iobase + 1); - tmpbyte &= ~SMSCSIOFLAT_UART2MODE_MASK | - SMSCSIOFLAT_UART2MODE_VAL_IRDA; - outb(tmpbyte, iobase + 1); // enable IrDA (HPSIR) mode, high speed - - outb(LPC47N227_APMBOOTDRIVE_REG, iobase); // CR07 - Auto Pwr Mgt/boot drive sel - tmpbyte = inb(iobase + 1); - outb(tmpbyte | LPC47N227_UART2AUTOPWRDOWN_MASK, iobase + 1); // enable UART2 autopower down - - /* This one was not part of tosh1800 */ - outb(0x0a, iobase); // CR0a - ecp fifo / ir mux - tmpbyte = inb(iobase + 1); - outb(tmpbyte | 0x40, iobase + 1); // send active device to ir port - - outb(LPC47N227_UART12POWER_REG, iobase); // CR02 - UART 1,2 power - tmpbyte = inb(iobase + 1); - outb(tmpbyte | LPC47N227_UART2POWERDOWN_MASK, iobase + 1); // UART2 power up mode, UART1 power down - - outb(LPC47N227_FDCPOWERVALIDCONF_REG, iobase); // CR00 - FDC Power/valid config cycle - tmpbyte = inb(iobase + 1); - outb(tmpbyte | LPC47N227_VALID_MASK, iobase + 1); // valid config cycle done - - outb(LPC47N227_CFGEXITKEY, iobase); // Exit configuration - - return 0; -} - -/* 82801CAM generic registers */ -#define VID 0x00 -#define DID 0x02 -#define PIRQ_A_D_ROUT 0x60 -#define SIRQ_CNTL 0x64 -#define PIRQ_E_H_ROUT 0x68 -#define PCI_DMA_C 0x90 -/* LPC-specific registers */ -#define COM_DEC 0xe0 -#define GEN1_DEC 0xe4 -#define LPC_EN 0xe6 -#define GEN2_DEC 0xec -/* - * Sets up the I/O range using the 82801CAM ISA bridge, 82801DBM LPC bridge - * or Intel 82801DB/DBL (ICH4/ICH4-L) LPC Interface Bridge. - * They all work the same way! - */ -static int __init preconfigure_through_82801(struct pci_dev *dev, - struct - smsc_ircc_subsystem_configuration - *conf) -{ - unsigned short tmpword; - unsigned char tmpbyte; - - net_info_ratelimited("Setting up Intel 82801 controller and SMSC device\n"); - /* - * Select the range for the COMA COM port (SIR) - * Register COM_DEC: - * Bit 7: reserved - * Bit 6-4, COMB decode range - * Bit 3: reserved - * Bit 2-0, COMA decode range - * - * Decode ranges: - * 000 = 0x3f8-0x3ff (COM1) - * 001 = 0x2f8-0x2ff (COM2) - * 010 = 0x220-0x227 - * 011 = 0x228-0x22f - * 100 = 0x238-0x23f - * 101 = 0x2e8-0x2ef (COM4) - * 110 = 0x338-0x33f - * 111 = 0x3e8-0x3ef (COM3) - */ - pci_read_config_byte(dev, COM_DEC, &tmpbyte); - tmpbyte &= 0xf8; /* mask COMA bits */ - switch(conf->sir_io) { - case 0x3f8: - tmpbyte |= 0x00; - break; - case 0x2f8: - tmpbyte |= 0x01; - break; - case 0x220: - tmpbyte |= 0x02; - break; - case 0x228: - tmpbyte |= 0x03; - break; - case 0x238: - tmpbyte |= 0x04; - break; - case 0x2e8: - tmpbyte |= 0x05; - break; - case 0x338: - tmpbyte |= 0x06; - break; - case 0x3e8: - tmpbyte |= 0x07; - break; - default: - tmpbyte |= 0x01; /* COM2 default */ - } - pr_debug("COM_DEC (write): 0x%02x\n", tmpbyte); - pci_write_config_byte(dev, COM_DEC, tmpbyte); - - /* Enable Low Pin Count interface */ - pci_read_config_word(dev, LPC_EN, &tmpword); - /* These seem to be set up at all times, - * just make sure it is properly set. - */ - switch(conf->cfg_base) { - case 0x04e: - tmpword |= 0x2000; - break; - case 0x02e: - tmpword |= 0x1000; - break; - case 0x062: - tmpword |= 0x0800; - break; - case 0x060: - tmpword |= 0x0400; - break; - default: - net_warn_ratelimited("Uncommon I/O base address: 0x%04x\n", - conf->cfg_base); - break; - } - tmpword &= 0xfffd; /* disable LPC COMB */ - tmpword |= 0x0001; /* set bit 0 : enable LPC COMA addr range (GEN2) */ - pr_debug("LPC_EN (write): 0x%04x\n", tmpword); - pci_write_config_word(dev, LPC_EN, tmpword); - - /* - * Configure LPC DMA channel - * PCI_DMA_C bits: - * Bit 15-14: DMA channel 7 select - * Bit 13-12: DMA channel 6 select - * Bit 11-10: DMA channel 5 select - * Bit 9-8: Reserved - * Bit 7-6: DMA channel 3 select - * Bit 5-4: DMA channel 2 select - * Bit 3-2: DMA channel 1 select - * Bit 1-0: DMA channel 0 select - * 00 = Reserved value - * 01 = PC/PCI DMA - * 10 = Reserved value - * 11 = LPC I/F DMA - */ - pci_read_config_word(dev, PCI_DMA_C, &tmpword); - switch(conf->fir_dma) { - case 0x07: - tmpword |= 0xc000; - break; - case 0x06: - tmpword |= 0x3000; - break; - case 0x05: - tmpword |= 0x0c00; - break; - case 0x03: - tmpword |= 0x00c0; - break; - case 0x02: - tmpword |= 0x0030; - break; - case 0x01: - tmpword |= 0x000c; - break; - case 0x00: - tmpword |= 0x0003; - break; - default: - break; /* do not change settings */ - } - pr_debug("PCI_DMA_C (write): 0x%04x\n", tmpword); - pci_write_config_word(dev, PCI_DMA_C, tmpword); - - /* - * GEN2_DEC bits: - * Bit 15-4: Generic I/O range - * Bit 3-1: reserved (read as 0) - * Bit 0: enable GEN2 range on LPC I/F - */ - tmpword = conf->fir_io & 0xfff8; - tmpword |= 0x0001; - pr_debug("GEN2_DEC (write): 0x%04x\n", tmpword); - pci_write_config_word(dev, GEN2_DEC, tmpword); - - /* Pre-configure chip */ - return preconfigure_smsc_chip(conf); -} - -/* - * Pre-configure a certain port on the ALi 1533 bridge. - * This is based on reverse-engineering since ALi does not - * provide any data sheet for the 1533 chip. - */ -static void __init preconfigure_ali_port(struct pci_dev *dev, - unsigned short port) -{ - unsigned char reg; - /* These bits obviously control the different ports */ - unsigned char mask; - unsigned char tmpbyte; - - switch(port) { - case 0x0130: - case 0x0178: - reg = 0xb0; - mask = 0x80; - break; - case 0x03f8: - reg = 0xb4; - mask = 0x80; - break; - case 0x02f8: - reg = 0xb4; - mask = 0x30; - break; - case 0x02e8: - reg = 0xb4; - mask = 0x08; - break; - default: - net_err_ratelimited("Failed to configure unsupported port on ALi 1533 bridge: 0x%04x\n", - port); - return; - } - - pci_read_config_byte(dev, reg, &tmpbyte); - /* Turn on the right bits */ - tmpbyte |= mask; - pci_write_config_byte(dev, reg, tmpbyte); - net_info_ratelimited("Activated ALi 1533 ISA bridge port 0x%04x\n", - port); -} - -static int __init preconfigure_through_ali(struct pci_dev *dev, - struct - smsc_ircc_subsystem_configuration - *conf) -{ - /* Configure the two ports on the ALi 1533 */ - preconfigure_ali_port(dev, conf->sir_io); - preconfigure_ali_port(dev, conf->fir_io); - - /* Pre-configure chip */ - return preconfigure_smsc_chip(conf); -} - -static int __init smsc_ircc_preconfigure_subsystems(unsigned short ircc_cfg, - unsigned short ircc_fir, - unsigned short ircc_sir, - unsigned char ircc_dma, - unsigned char ircc_irq) -{ - struct pci_dev *dev = NULL; - unsigned short ss_vendor = 0x0000; - unsigned short ss_device = 0x0000; - int ret = 0; - - for_each_pci_dev(dev) { - struct smsc_ircc_subsystem_configuration *conf; - - /* - * Cache the subsystem vendor/device: - * some manufacturers fail to set this for all components, - * so we save it in case there is just 0x0000 0x0000 on the - * device we want to check. - */ - if (dev->subsystem_vendor != 0x0000U) { - ss_vendor = dev->subsystem_vendor; - ss_device = dev->subsystem_device; - } - conf = subsystem_configurations; - for( ; conf->subvendor; conf++) { - if(conf->vendor == dev->vendor && - conf->device == dev->device && - conf->subvendor == ss_vendor && - /* Sometimes these are cached values */ - (conf->subdevice == ss_device || - conf->subdevice == 0xffff)) { - struct smsc_ircc_subsystem_configuration - tmpconf; - - memcpy(&tmpconf, conf, - sizeof(struct smsc_ircc_subsystem_configuration)); - - /* - * Override the default values with anything - * passed in as parameter - */ - if (ircc_cfg != 0) - tmpconf.cfg_base = ircc_cfg; - if (ircc_fir != 0) - tmpconf.fir_io = ircc_fir; - if (ircc_sir != 0) - tmpconf.sir_io = ircc_sir; - if (ircc_dma != DMA_INVAL) - tmpconf.fir_dma = ircc_dma; - if (ircc_irq != IRQ_INVAL) - tmpconf.fir_irq = ircc_irq; - - net_info_ratelimited("Detected unconfigured %s SMSC IrDA chip, pre-configuring device\n", - conf->name); - if (conf->preconfigure) - ret = conf->preconfigure(dev, &tmpconf); - else - ret = -ENODEV; - } - } - } - - return ret; -} -#endif // CONFIG_PCI - -/************************************************ - * - * Transceivers specific functions - * - ************************************************/ - - -/* - * Function smsc_ircc_set_transceiver_smsc_ircc_atc(fir_base, speed) - * - * Program transceiver through smsc-ircc ATC circuitry - * - */ - -static void smsc_ircc_set_transceiver_smsc_ircc_atc(int fir_base, u32 speed) -{ - unsigned long jiffies_now, jiffies_timeout; - u8 val; - - jiffies_now = jiffies; - jiffies_timeout = jiffies + SMSC_IRCC2_ATC_PROGRAMMING_TIMEOUT_JIFFIES; - - /* ATC */ - register_bank(fir_base, 4); - outb((inb(fir_base + IRCC_ATC) & IRCC_ATC_MASK) | IRCC_ATC_nPROGREADY|IRCC_ATC_ENABLE, - fir_base + IRCC_ATC); - - while ((val = (inb(fir_base + IRCC_ATC) & IRCC_ATC_nPROGREADY)) && - !time_after(jiffies, jiffies_timeout)) - /* empty */; - - if (val) - net_warn_ratelimited("%s(): ATC: 0x%02x\n", - __func__, inb(fir_base + IRCC_ATC)); -} - -/* - * Function smsc_ircc_probe_transceiver_smsc_ircc_atc(fir_base) - * - * Probe transceiver smsc-ircc ATC circuitry - * - */ - -static int smsc_ircc_probe_transceiver_smsc_ircc_atc(int fir_base) -{ - return 0; -} - -/* - * Function smsc_ircc_set_transceiver_smsc_ircc_fast_pin_select(self, speed) - * - * Set transceiver - * - */ - -static void smsc_ircc_set_transceiver_smsc_ircc_fast_pin_select(int fir_base, u32 speed) -{ - u8 fast_mode; - - switch (speed) { - default: - case 576000 : - fast_mode = 0; - break; - case 1152000 : - case 4000000 : - fast_mode = IRCC_LCR_A_FAST; - break; - } - register_bank(fir_base, 0); - outb((inb(fir_base + IRCC_LCR_A) & 0xbf) | fast_mode, fir_base + IRCC_LCR_A); -} - -/* - * Function smsc_ircc_probe_transceiver_smsc_ircc_fast_pin_select(fir_base) - * - * Probe transceiver - * - */ - -static int smsc_ircc_probe_transceiver_smsc_ircc_fast_pin_select(int fir_base) -{ - return 0; -} - -/* - * Function smsc_ircc_set_transceiver_toshiba_sat1800(fir_base, speed) - * - * Set transceiver - * - */ - -static void smsc_ircc_set_transceiver_toshiba_sat1800(int fir_base, u32 speed) -{ - u8 fast_mode; - - switch (speed) { - default: - case 576000 : - fast_mode = 0; - break; - case 1152000 : - case 4000000 : - fast_mode = /*IRCC_LCR_A_FAST |*/ IRCC_LCR_A_GP_DATA; - break; - - } - /* This causes an interrupt */ - register_bank(fir_base, 0); - outb((inb(fir_base + IRCC_LCR_A) & 0xbf) | fast_mode, fir_base + IRCC_LCR_A); -} - -/* - * Function smsc_ircc_probe_transceiver_toshiba_sat1800(fir_base) - * - * Probe transceiver - * - */ - -static int smsc_ircc_probe_transceiver_toshiba_sat1800(int fir_base) -{ - return 0; -} - - -module_init(smsc_ircc_init); -module_exit(smsc_ircc_cleanup); diff --git a/drivers/net/irda/smsc-ircc2.h b/drivers/net/irda/smsc-ircc2.h deleted file mode 100644 index 4829fa22cb29..000000000000 --- a/drivers/net/irda/smsc-ircc2.h +++ /dev/null @@ -1,191 +0,0 @@ -/********************************************************************* - * - * 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, see <http://www.gnu.org/licenses/>. - * - ********************************************************************/ - -#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 */ diff --git a/drivers/net/irda/smsc-sio.h b/drivers/net/irda/smsc-sio.h deleted file mode 100644 index 59e20e653ebe..000000000000 --- a/drivers/net/irda/smsc-sio.h +++ /dev/null @@ -1,100 +0,0 @@ -#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 diff --git a/drivers/net/irda/stir4200.c b/drivers/net/irda/stir4200.c deleted file mode 100644 index ee2cb70b688d..000000000000 --- a/drivers/net/irda/stir4200.c +++ /dev/null @@ -1,1134 +0,0 @@ -/***************************************************************************** -* -* Filename: stir4200.c -* Version: 0.4 -* Description: Irda SigmaTel USB Dongle -* Status: Experimental -* Author: Stephen Hemminger <shemminger@osdl.org> -* -* Based on earlier driver by Paul Stewart <stewart@parc.com> -* -* Copyright (C) 2000, Roman Weissgaerber <weissg@vienna.at> -* Copyright (C) 2001, Dag Brattli <dag@brattli.net> -* Copyright (C) 2001, Jean Tourrilhes <jt@hpl.hp.com> -* Copyright (C) 2004, Stephen Hemminger <shemminger@osdl.org> -* -* 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. -* -* 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. -* -*****************************************************************************/ - -/* - * This dongle does no framing, and requires polling to receive the - * data. The STIr4200 has bulk in and out endpoints just like - * usr-irda devices, but the data it sends and receives is raw; like - * irtty, it needs to call the wrap and unwrap functions to add and - * remove SOF/BOF and escape characters to/from the frame. - */ - -#include <linux/module.h> -#include <linux/moduleparam.h> - -#include <linux/kernel.h> -#include <linux/sched/signal.h> -#include <linux/ktime.h> -#include <linux/types.h> -#include <linux/time.h> -#include <linux/skbuff.h> -#include <linux/netdevice.h> -#include <linux/slab.h> -#include <linux/delay.h> -#include <linux/usb.h> -#include <linux/crc32.h> -#include <linux/kthread.h> -#include <linux/freezer.h> -#include <net/irda/irda.h> -#include <net/irda/irda_device.h> -#include <net/irda/wrapper.h> -#include <net/irda/crc.h> -#include <asm/byteorder.h> -#include <asm/unaligned.h> - -MODULE_AUTHOR("Stephen Hemminger <shemminger@linux-foundation.org>"); -MODULE_DESCRIPTION("IrDA-USB Dongle Driver for SigmaTel STIr4200"); -MODULE_LICENSE("GPL"); - -static int qos_mtt_bits = 0x07; /* 1 ms or more */ -module_param(qos_mtt_bits, int, 0); -MODULE_PARM_DESC(qos_mtt_bits, "Minimum Turn Time"); - -static int rx_sensitivity = 1; /* FIR 0..4, SIR 0..6 */ -module_param(rx_sensitivity, int, 0); -MODULE_PARM_DESC(rx_sensitivity, "Set Receiver sensitivity (0-6, 0 is most sensitive)"); - -static int tx_power = 0; /* 0 = highest ... 3 = lowest */ -module_param(tx_power, int, 0); -MODULE_PARM_DESC(tx_power, "Set Transmitter power (0-3, 0 is highest power)"); - -#define STIR_IRDA_HEADER 4 -#define CTRL_TIMEOUT 100 /* milliseconds */ -#define TRANSMIT_TIMEOUT 200 /* milliseconds */ -#define STIR_FIFO_SIZE 4096 -#define FIFO_REGS_SIZE 3 - -enum FirChars { - FIR_CE = 0x7d, - FIR_XBOF = 0x7f, - FIR_EOF = 0x7e, -}; - -enum StirRequests { - REQ_WRITE_REG = 0x00, - REQ_READ_REG = 0x01, - REQ_READ_ROM = 0x02, - REQ_WRITE_SINGLE = 0x03, -}; - -/* Register offsets */ -enum StirRegs { - REG_RSVD=0, - REG_MODE, - REG_PDCLK, - REG_CTRL1, - REG_CTRL2, - REG_FIFOCTL, - REG_FIFOLSB, - REG_FIFOMSB, - REG_DPLL, - REG_IRDIG, - REG_TEST=15, -}; - -enum StirModeMask { - MODE_FIR = 0x80, - MODE_SIR = 0x20, - MODE_ASK = 0x10, - MODE_FASTRX = 0x08, - MODE_FFRSTEN = 0x04, - MODE_NRESET = 0x02, - MODE_2400 = 0x01, -}; - -enum StirPdclkMask { - PDCLK_4000000 = 0x02, - PDCLK_115200 = 0x09, - PDCLK_57600 = 0x13, - PDCLK_38400 = 0x1D, - PDCLK_19200 = 0x3B, - PDCLK_9600 = 0x77, - PDCLK_2400 = 0xDF, -}; - -enum StirCtrl1Mask { - CTRL1_SDMODE = 0x80, - CTRL1_RXSLOW = 0x40, - CTRL1_TXPWD = 0x10, - CTRL1_RXPWD = 0x08, - CTRL1_SRESET = 0x01, -}; - -enum StirCtrl2Mask { - CTRL2_SPWIDTH = 0x08, - CTRL2_REVID = 0x03, -}; - -enum StirFifoCtlMask { - FIFOCTL_DIR = 0x10, - FIFOCTL_CLR = 0x08, - FIFOCTL_EMPTY = 0x04, -}; - -enum StirDiagMask { - IRDIG_RXHIGH = 0x80, - IRDIG_RXLOW = 0x40, -}; - -enum StirTestMask { - TEST_PLLDOWN = 0x80, - TEST_LOOPIR = 0x40, - TEST_LOOPUSB = 0x20, - TEST_TSTENA = 0x10, - TEST_TSTOSC = 0x0F, -}; - -struct stir_cb { - struct usb_device *usbdev; /* init: probe_irda */ - struct net_device *netdev; /* network layer */ - struct irlap_cb *irlap; /* The link layer we are binded to */ - - struct qos_info qos; - unsigned speed; /* Current speed */ - - struct task_struct *thread; /* transmit thread */ - - struct sk_buff *tx_pending; - void *io_buf; /* transmit/receive buffer */ - __u8 *fifo_status; - - iobuff_t rx_buff; /* receive unwrap state machine */ - ktime_t rx_time; - int receiving; - struct urb *rx_urb; -}; - - -/* These are the currently known USB ids */ -static const struct usb_device_id dongles[] = { - /* SigmaTel, Inc, STIr4200 IrDA/USB Bridge */ - { USB_DEVICE(0x066f, 0x4200) }, - { } -}; - -MODULE_DEVICE_TABLE(usb, dongles); - -/* Send control message to set dongle register */ -static int write_reg(struct stir_cb *stir, __u16 reg, __u8 value) -{ - struct usb_device *dev = stir->usbdev; - - pr_debug("%s: write reg %d = 0x%x\n", - stir->netdev->name, reg, value); - return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - REQ_WRITE_SINGLE, - USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_DEVICE, - value, reg, NULL, 0, - CTRL_TIMEOUT); -} - -/* Send control message to read multiple registers */ -static inline int read_reg(struct stir_cb *stir, __u16 reg, - __u8 *data, __u16 count) -{ - struct usb_device *dev = stir->usbdev; - - return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - REQ_READ_REG, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, reg, data, count, - CTRL_TIMEOUT); -} - -static inline int isfir(u32 speed) -{ - return speed == 4000000; -} - -/* - * Prepare a FIR IrDA frame for transmission to the USB dongle. The - * FIR transmit frame is documented in the datasheet. It consists of - * a two byte 0x55 0xAA sequence, two little-endian length bytes, a - * sequence of exactly 16 XBOF bytes of 0x7E, two BOF bytes of 0x7E, - * then the data escaped as follows: - * - * 0x7D -> 0x7D 0x5D - * 0x7E -> 0x7D 0x5E - * 0x7F -> 0x7D 0x5F - * - * Then, 4 bytes of little endian (stuffed) FCS follow, then two - * trailing EOF bytes of 0x7E. - */ -static inline __u8 *stuff_fir(__u8 *p, __u8 c) -{ - switch(c) { - case 0x7d: - case 0x7e: - case 0x7f: - *p++ = 0x7d; - c ^= IRDA_TRANS; - /* fall through */ - default: - *p++ = c; - } - return p; -} - -/* Take raw data in skb and put it wrapped into buf */ -static unsigned wrap_fir_skb(const struct sk_buff *skb, __u8 *buf) -{ - __u8 *ptr = buf; - __u32 fcs = ~(crc32_le(~0, skb->data, skb->len)); - __u16 wraplen; - int i; - - /* Header */ - buf[0] = 0x55; - buf[1] = 0xAA; - - ptr = buf + STIR_IRDA_HEADER; - memset(ptr, 0x7f, 16); - ptr += 16; - - /* BOF */ - *ptr++ = 0x7e; - *ptr++ = 0x7e; - - /* Address / Control / Information */ - for (i = 0; i < skb->len; i++) - ptr = stuff_fir(ptr, skb->data[i]); - - /* FCS */ - ptr = stuff_fir(ptr, fcs & 0xff); - ptr = stuff_fir(ptr, (fcs >> 8) & 0xff); - ptr = stuff_fir(ptr, (fcs >> 16) & 0xff); - ptr = stuff_fir(ptr, (fcs >> 24) & 0xff); - - /* EOFs */ - *ptr++ = 0x7e; - *ptr++ = 0x7e; - - /* Total length, minus the header */ - wraplen = (ptr - buf) - STIR_IRDA_HEADER; - buf[2] = wraplen & 0xff; - buf[3] = (wraplen >> 8) & 0xff; - - return wraplen + STIR_IRDA_HEADER; -} - -static unsigned wrap_sir_skb(struct sk_buff *skb, __u8 *buf) -{ - __u16 wraplen; - - wraplen = async_wrap_skb(skb, buf + STIR_IRDA_HEADER, - STIR_FIFO_SIZE - STIR_IRDA_HEADER); - buf[0] = 0x55; - buf[1] = 0xAA; - buf[2] = wraplen & 0xff; - buf[3] = (wraplen >> 8) & 0xff; - - return wraplen + STIR_IRDA_HEADER; -} - -/* - * Frame is fully formed in the rx_buff so check crc - * and pass up to irlap - * setup for next receive - */ -static void fir_eof(struct stir_cb *stir) -{ - iobuff_t *rx_buff = &stir->rx_buff; - int len = rx_buff->len - 4; - struct sk_buff *skb, *nskb; - __u32 fcs; - - if (unlikely(len <= 0)) { - pr_debug("%s: short frame len %d\n", - stir->netdev->name, len); - - ++stir->netdev->stats.rx_errors; - ++stir->netdev->stats.rx_length_errors; - return; - } - - fcs = ~(crc32_le(~0, rx_buff->data, len)); - if (fcs != get_unaligned_le32(rx_buff->data + len)) { - pr_debug("crc error calc 0x%x len %d\n", fcs, len); - stir->netdev->stats.rx_errors++; - stir->netdev->stats.rx_crc_errors++; - return; - } - - /* if frame is short then just copy it */ - if (len < IRDA_RX_COPY_THRESHOLD) { - nskb = dev_alloc_skb(len + 1); - if (unlikely(!nskb)) { - ++stir->netdev->stats.rx_dropped; - return; - } - skb_reserve(nskb, 1); - skb = nskb; - skb_copy_to_linear_data(nskb, rx_buff->data, len); - } else { - nskb = dev_alloc_skb(rx_buff->truesize); - if (unlikely(!nskb)) { - ++stir->netdev->stats.rx_dropped; - return; - } - skb_reserve(nskb, 1); - skb = rx_buff->skb; - rx_buff->skb = nskb; - rx_buff->head = nskb->data; - } - - skb_put(skb, len); - - skb_reset_mac_header(skb); - skb->protocol = htons(ETH_P_IRDA); - skb->dev = stir->netdev; - - netif_rx(skb); - - stir->netdev->stats.rx_packets++; - stir->netdev->stats.rx_bytes += len; - - rx_buff->data = rx_buff->head; - rx_buff->len = 0; -} - -/* Unwrap FIR stuffed data and bump it to IrLAP */ -static void stir_fir_chars(struct stir_cb *stir, - const __u8 *bytes, int len) -{ - iobuff_t *rx_buff = &stir->rx_buff; - int i; - - for (i = 0; i < len; i++) { - __u8 byte = bytes[i]; - - switch(rx_buff->state) { - case OUTSIDE_FRAME: - /* ignore garbage till start of frame */ - if (unlikely(byte != FIR_EOF)) - continue; - /* Now receiving frame */ - rx_buff->state = BEGIN_FRAME; - - /* Time to initialize receive buffer */ - rx_buff->data = rx_buff->head; - rx_buff->len = 0; - continue; - - case LINK_ESCAPE: - if (byte == FIR_EOF) { - pr_debug("%s: got EOF after escape\n", - stir->netdev->name); - goto frame_error; - } - rx_buff->state = INSIDE_FRAME; - byte ^= IRDA_TRANS; - break; - - case BEGIN_FRAME: - /* ignore multiple BOF/EOF */ - if (byte == FIR_EOF) - continue; - rx_buff->state = INSIDE_FRAME; - rx_buff->in_frame = TRUE; - - /* fall through */ - case INSIDE_FRAME: - switch(byte) { - case FIR_CE: - rx_buff->state = LINK_ESCAPE; - continue; - case FIR_XBOF: - /* 0x7f is not used in this framing */ - pr_debug("%s: got XBOF without escape\n", - stir->netdev->name); - goto frame_error; - case FIR_EOF: - rx_buff->state = OUTSIDE_FRAME; - rx_buff->in_frame = FALSE; - fir_eof(stir); - continue; - } - break; - } - - /* add byte to rx buffer */ - if (unlikely(rx_buff->len >= rx_buff->truesize)) { - pr_debug("%s: fir frame exceeds %d\n", - stir->netdev->name, rx_buff->truesize); - ++stir->netdev->stats.rx_over_errors; - goto error_recovery; - } - - rx_buff->data[rx_buff->len++] = byte; - continue; - - frame_error: - ++stir->netdev->stats.rx_frame_errors; - - error_recovery: - ++stir->netdev->stats.rx_errors; - rx_buff->state = OUTSIDE_FRAME; - rx_buff->in_frame = FALSE; - } -} - -/* Unwrap SIR stuffed data and bump it up to IrLAP */ -static void stir_sir_chars(struct stir_cb *stir, - const __u8 *bytes, int len) -{ - int i; - - for (i = 0; i < len; i++) - async_unwrap_char(stir->netdev, &stir->netdev->stats, - &stir->rx_buff, bytes[i]); -} - -static inline void unwrap_chars(struct stir_cb *stir, - const __u8 *bytes, int length) -{ - if (isfir(stir->speed)) - stir_fir_chars(stir, bytes, length); - else - stir_sir_chars(stir, bytes, length); -} - -/* Mode parameters for each speed */ -static const struct { - unsigned speed; - __u8 pdclk; -} stir_modes[] = { - { 2400, PDCLK_2400 }, - { 9600, PDCLK_9600 }, - { 19200, PDCLK_19200 }, - { 38400, PDCLK_38400 }, - { 57600, PDCLK_57600 }, - { 115200, PDCLK_115200 }, - { 4000000, PDCLK_4000000 }, -}; - - -/* - * Setup chip for speed. - * Called at startup to initialize the chip - * and on speed changes. - * - * Note: Write multiple registers doesn't appear to work - */ -static int change_speed(struct stir_cb *stir, unsigned speed) -{ - int i, err; - __u8 mode; - - for (i = 0; i < ARRAY_SIZE(stir_modes); ++i) { - if (speed == stir_modes[i].speed) - goto found; - } - - dev_warn(&stir->netdev->dev, "invalid speed %d\n", speed); - return -EINVAL; - - found: - pr_debug("speed change from %d to %d\n", stir->speed, speed); - - /* Reset modulator */ - err = write_reg(stir, REG_CTRL1, CTRL1_SRESET); - if (err) - goto out; - - /* Undocumented magic to tweak the DPLL */ - err = write_reg(stir, REG_DPLL, 0x15); - if (err) - goto out; - - /* Set clock */ - err = write_reg(stir, REG_PDCLK, stir_modes[i].pdclk); - if (err) - goto out; - - mode = MODE_NRESET | MODE_FASTRX; - if (isfir(speed)) - mode |= MODE_FIR | MODE_FFRSTEN; - else - mode |= MODE_SIR; - - if (speed == 2400) - mode |= MODE_2400; - - err = write_reg(stir, REG_MODE, mode); - if (err) - goto out; - - /* This resets TEMIC style transceiver if any. */ - err = write_reg(stir, REG_CTRL1, - CTRL1_SDMODE | (tx_power & 3) << 1); - if (err) - goto out; - - err = write_reg(stir, REG_CTRL1, (tx_power & 3) << 1); - if (err) - goto out; - - /* Reset sensitivity */ - err = write_reg(stir, REG_CTRL2, (rx_sensitivity & 7) << 5); - out: - stir->speed = speed; - return err; -} - -/* - * Called from net/core when new frame is available. - */ -static netdev_tx_t stir_hard_xmit(struct sk_buff *skb, - struct net_device *netdev) -{ - struct stir_cb *stir = netdev_priv(netdev); - - netif_stop_queue(netdev); - - /* the IRDA wrapping routines don't deal with non linear skb */ - SKB_LINEAR_ASSERT(skb); - - skb = xchg(&stir->tx_pending, skb); - wake_up_process(stir->thread); - - /* this should never happen unless stop/wakeup problem */ - if (unlikely(skb)) { - WARN_ON(1); - dev_kfree_skb(skb); - } - - return NETDEV_TX_OK; -} - -/* - * Wait for the transmit FIFO to have space for next data - * - * If space < 0 then wait till FIFO completely drains. - * FYI: can take up to 13 seconds at 2400baud. - */ -static int fifo_txwait(struct stir_cb *stir, int space) -{ - int err; - unsigned long count, status; - unsigned long prev_count = 0x1fff; - - /* Read FIFO status and count */ - for (;; prev_count = count) { - err = read_reg(stir, REG_FIFOCTL, stir->fifo_status, - FIFO_REGS_SIZE); - if (unlikely(err != FIFO_REGS_SIZE)) { - dev_warn(&stir->netdev->dev, - "FIFO register read error: %d\n", err); - - return err; - } - - status = stir->fifo_status[0]; - count = (unsigned)(stir->fifo_status[2] & 0x1f) << 8 - | stir->fifo_status[1]; - - pr_debug("fifo status 0x%lx count %lu\n", status, count); - - /* is fifo receiving already, or empty */ - if (!(status & FIFOCTL_DIR) || - (status & FIFOCTL_EMPTY)) - return 0; - - if (signal_pending(current)) - return -EINTR; - - /* shutting down? */ - if (!netif_running(stir->netdev) || - !netif_device_present(stir->netdev)) - return -ESHUTDOWN; - - /* only waiting for some space */ - if (space >= 0 && STIR_FIFO_SIZE - 4 > space + count) - return 0; - - /* queue confused */ - if (prev_count < count) - break; - - /* estimate transfer time for remaining chars */ - msleep((count * 8000) / stir->speed); - } - - err = write_reg(stir, REG_FIFOCTL, FIFOCTL_CLR); - if (err) - return err; - err = write_reg(stir, REG_FIFOCTL, 0); - if (err) - return err; - - return 0; -} - - -/* Wait for turnaround delay before starting transmit. */ -static void turnaround_delay(const struct stir_cb *stir, long us) -{ - long ticks; - - if (us <= 0) - return; - - us -= ktime_us_delta(ktime_get(), stir->rx_time); - - if (us < 10) - return; - - ticks = us / (1000000 / HZ); - if (ticks > 0) - schedule_timeout_interruptible(1 + ticks); - else - udelay(us); -} - -/* - * Start receiver by submitting a request to the receive pipe. - * If nothing is available it will return after rx_interval. - */ -static int receive_start(struct stir_cb *stir) -{ - /* reset state */ - stir->receiving = 1; - - stir->rx_buff.in_frame = FALSE; - stir->rx_buff.state = OUTSIDE_FRAME; - - stir->rx_urb->status = 0; - return usb_submit_urb(stir->rx_urb, GFP_KERNEL); -} - -/* Stop all pending receive Urb's */ -static void receive_stop(struct stir_cb *stir) -{ - stir->receiving = 0; - usb_kill_urb(stir->rx_urb); - - if (stir->rx_buff.in_frame) - stir->netdev->stats.collisions++; -} -/* - * Wrap data in socket buffer and send it. - */ -static void stir_send(struct stir_cb *stir, struct sk_buff *skb) -{ - unsigned wraplen; - int first_frame = 0; - - /* if receiving, need to turnaround */ - if (stir->receiving) { - receive_stop(stir); - turnaround_delay(stir, irda_get_mtt(skb)); - first_frame = 1; - } - - if (isfir(stir->speed)) - wraplen = wrap_fir_skb(skb, stir->io_buf); - else - wraplen = wrap_sir_skb(skb, stir->io_buf); - - /* check for space available in fifo */ - if (!first_frame) - fifo_txwait(stir, wraplen); - - stir->netdev->stats.tx_packets++; - stir->netdev->stats.tx_bytes += skb->len; - netif_trans_update(stir->netdev); - pr_debug("send %d (%d)\n", skb->len, wraplen); - - if (usb_bulk_msg(stir->usbdev, usb_sndbulkpipe(stir->usbdev, 1), - stir->io_buf, wraplen, - NULL, TRANSMIT_TIMEOUT)) - stir->netdev->stats.tx_errors++; -} - -/* - * Transmit state machine thread - */ -static int stir_transmit_thread(void *arg) -{ - struct stir_cb *stir = arg; - struct net_device *dev = stir->netdev; - struct sk_buff *skb; - - while (!kthread_should_stop()) { -#ifdef CONFIG_PM - /* if suspending, then power off and wait */ - if (unlikely(freezing(current))) { - if (stir->receiving) - receive_stop(stir); - else - fifo_txwait(stir, -1); - - write_reg(stir, REG_CTRL1, CTRL1_TXPWD|CTRL1_RXPWD); - - try_to_freeze(); - - if (change_speed(stir, stir->speed)) - break; - } -#endif - - /* if something to send? */ - skb = xchg(&stir->tx_pending, NULL); - if (skb) { - unsigned new_speed = irda_get_next_speed(skb); - netif_wake_queue(dev); - - if (skb->len > 0) - stir_send(stir, skb); - dev_kfree_skb(skb); - - if ((new_speed != -1) && (stir->speed != new_speed)) { - if (fifo_txwait(stir, -1) || - change_speed(stir, new_speed)) - break; - } - continue; - } - - /* nothing to send? start receiving */ - if (!stir->receiving && - irda_device_txqueue_empty(dev)) { - /* Wait otherwise chip gets confused. */ - if (fifo_txwait(stir, -1)) - break; - - if (unlikely(receive_start(stir))) { - if (net_ratelimit()) - dev_info(&dev->dev, - "%s: receive usb submit failed\n", - stir->netdev->name); - stir->receiving = 0; - msleep(10); - continue; - } - } - - /* sleep if nothing to send */ - set_current_state(TASK_INTERRUPTIBLE); - schedule(); - - } - return 0; -} - - -/* - * USB bulk receive completion callback. - * Wakes up every ms (usb round trip) with wrapped - * data. - */ -static void stir_rcv_irq(struct urb *urb) -{ - struct stir_cb *stir = urb->context; - int err; - - /* in process of stopping, just drop data */ - if (!netif_running(stir->netdev)) - return; - - /* unlink, shutdown, unplug, other nasties */ - if (urb->status != 0) - return; - - if (urb->actual_length > 0) { - pr_debug("receive %d\n", urb->actual_length); - unwrap_chars(stir, urb->transfer_buffer, - urb->actual_length); - - stir->rx_time = ktime_get(); - } - - /* kernel thread is stopping receiver don't resubmit */ - if (!stir->receiving) - return; - - /* resubmit existing urb */ - err = usb_submit_urb(urb, GFP_ATOMIC); - - /* in case of error, the kernel thread will restart us */ - if (err) { - dev_warn(&stir->netdev->dev, "usb receive submit error: %d\n", - err); - stir->receiving = 0; - wake_up_process(stir->thread); - } -} - -/* - * Function stir_net_open (dev) - * - * Network device is taken up. Usually this is done by "ifconfig irda0 up" - */ -static int stir_net_open(struct net_device *netdev) -{ - struct stir_cb *stir = netdev_priv(netdev); - int err; - char hwname[16]; - - err = usb_clear_halt(stir->usbdev, usb_sndbulkpipe(stir->usbdev, 1)); - if (err) - goto err_out1; - err = usb_clear_halt(stir->usbdev, usb_rcvbulkpipe(stir->usbdev, 2)); - if (err) - goto err_out1; - - err = change_speed(stir, 9600); - if (err) - goto err_out1; - - err = -ENOMEM; - - /* Initialize for SIR/FIR to copy data directly into skb. */ - stir->receiving = 0; - stir->rx_buff.truesize = IRDA_SKB_MAX_MTU; - stir->rx_buff.skb = dev_alloc_skb(IRDA_SKB_MAX_MTU); - if (!stir->rx_buff.skb) - goto err_out1; - - skb_reserve(stir->rx_buff.skb, 1); - stir->rx_buff.head = stir->rx_buff.skb->data; - stir->rx_time = ktime_get(); - - stir->rx_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!stir->rx_urb) - goto err_out2; - - stir->io_buf = kmalloc(STIR_FIFO_SIZE, GFP_KERNEL); - if (!stir->io_buf) - goto err_out3; - - usb_fill_bulk_urb(stir->rx_urb, stir->usbdev, - usb_rcvbulkpipe(stir->usbdev, 2), - stir->io_buf, STIR_FIFO_SIZE, - stir_rcv_irq, stir); - - stir->fifo_status = kmalloc(FIFO_REGS_SIZE, GFP_KERNEL); - if (!stir->fifo_status) - goto err_out4; - - /* - * Now that everything should be initialized properly, - * Open new IrLAP layer instance to take care of us... - * Note : will send immediately a speed change... - */ - sprintf(hwname, "usb#%d", stir->usbdev->devnum); - stir->irlap = irlap_open(netdev, &stir->qos, hwname); - if (!stir->irlap) { - dev_err(&stir->usbdev->dev, "irlap_open failed\n"); - goto err_out5; - } - - /** Start kernel thread for transmit. */ - stir->thread = kthread_run(stir_transmit_thread, stir, - "%s", stir->netdev->name); - if (IS_ERR(stir->thread)) { - err = PTR_ERR(stir->thread); - dev_err(&stir->usbdev->dev, "unable to start kernel thread\n"); - goto err_out6; - } - - netif_start_queue(netdev); - - return 0; - - err_out6: - irlap_close(stir->irlap); - err_out5: - kfree(stir->fifo_status); - err_out4: - kfree(stir->io_buf); - err_out3: - usb_free_urb(stir->rx_urb); - err_out2: - kfree_skb(stir->rx_buff.skb); - err_out1: - return err; -} - -/* - * Function stir_net_close (stir) - * - * Network device is taken down. Usually this is done by - * "ifconfig irda0 down" - */ -static int stir_net_close(struct net_device *netdev) -{ - struct stir_cb *stir = netdev_priv(netdev); - - /* Stop transmit processing */ - netif_stop_queue(netdev); - - /* Kill transmit thread */ - kthread_stop(stir->thread); - kfree(stir->fifo_status); - - /* Mop up receive urb's */ - usb_kill_urb(stir->rx_urb); - - kfree(stir->io_buf); - usb_free_urb(stir->rx_urb); - kfree_skb(stir->rx_buff.skb); - - /* Stop and remove instance of IrLAP */ - if (stir->irlap) - irlap_close(stir->irlap); - - stir->irlap = NULL; - - return 0; -} - -/* - * IOCTLs : Extra out-of-band network commands... - */ -static int stir_net_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) -{ - struct if_irda_req *irq = (struct if_irda_req *) rq; - struct stir_cb *stir = netdev_priv(netdev); - int ret = 0; - - switch (cmd) { - case SIOCSBANDWIDTH: /* Set bandwidth */ - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - /* Check if the device is still there */ - if (netif_device_present(stir->netdev)) - ret = change_speed(stir, irq->ifr_baudrate); - break; - - case SIOCSMEDIABUSY: /* Set media busy */ - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - /* Check if the IrDA stack is still there */ - if (netif_running(stir->netdev)) - irda_device_set_media_busy(stir->netdev, TRUE); - break; - - case SIOCGRECEIVING: - /* Only approximately true */ - irq->ifr_receiving = stir->receiving; - break; - - default: - ret = -EOPNOTSUPP; - } - - return ret; -} - -static const struct net_device_ops stir_netdev_ops = { - .ndo_open = stir_net_open, - .ndo_stop = stir_net_close, - .ndo_start_xmit = stir_hard_xmit, - .ndo_do_ioctl = stir_net_ioctl, -}; - -/* - * This routine is called by the USB subsystem for each new device - * in the system. We need to check if the device is ours, and in - * this case start handling it. - * Note : it might be worth protecting this function by a global - * spinlock... Or not, because maybe USB already deal with that... - */ -static int stir_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct usb_device *dev = interface_to_usbdev(intf); - struct stir_cb *stir = NULL; - struct net_device *net; - int ret = -ENOMEM; - - /* Allocate network device container. */ - net = alloc_irdadev(sizeof(*stir)); - if(!net) - goto err_out1; - - SET_NETDEV_DEV(net, &intf->dev); - stir = netdev_priv(net); - stir->netdev = net; - stir->usbdev = dev; - - ret = usb_reset_configuration(dev); - if (ret != 0) { - dev_err(&intf->dev, "usb reset configuration failed\n"); - goto err_out2; - } - - printk(KERN_INFO "SigmaTel STIr4200 IRDA/USB found at address %d, " - "Vendor: %x, Product: %x\n", - dev->devnum, le16_to_cpu(dev->descriptor.idVendor), - le16_to_cpu(dev->descriptor.idProduct)); - - /* Initialize QoS for this device */ - irda_init_max_qos_capabilies(&stir->qos); - - /* That's the Rx capability. */ - stir->qos.baud_rate.bits &= IR_2400 | IR_9600 | IR_19200 | - IR_38400 | IR_57600 | IR_115200 | - (IR_4000000 << 8); - stir->qos.min_turn_time.bits &= qos_mtt_bits; - irda_qos_bits_to_value(&stir->qos); - - /* Override the network functions we need to use */ - net->netdev_ops = &stir_netdev_ops; - - ret = register_netdev(net); - if (ret != 0) - goto err_out2; - - dev_info(&intf->dev, "IrDA: Registered SigmaTel device %s\n", - net->name); - - usb_set_intfdata(intf, stir); - - return 0; - -err_out2: - free_netdev(net); -err_out1: - return ret; -} - -/* - * The current device is removed, the USB layer tell us to shut it down... - */ -static void stir_disconnect(struct usb_interface *intf) -{ - struct stir_cb *stir = usb_get_intfdata(intf); - - if (!stir) - return; - - unregister_netdev(stir->netdev); - free_netdev(stir->netdev); - - usb_set_intfdata(intf, NULL); -} - -#ifdef CONFIG_PM -/* USB suspend, so power off the transmitter/receiver */ -static int stir_suspend(struct usb_interface *intf, pm_message_t message) -{ - struct stir_cb *stir = usb_get_intfdata(intf); - - netif_device_detach(stir->netdev); - return 0; -} - -/* Coming out of suspend, so reset hardware */ -static int stir_resume(struct usb_interface *intf) -{ - struct stir_cb *stir = usb_get_intfdata(intf); - - netif_device_attach(stir->netdev); - - /* receiver restarted when send thread wakes up */ - return 0; -} -#endif - -/* - * USB device callbacks - */ -static struct usb_driver irda_driver = { - .name = "stir4200", - .probe = stir_probe, - .disconnect = stir_disconnect, - .id_table = dongles, -#ifdef CONFIG_PM - .suspend = stir_suspend, - .resume = stir_resume, -#endif -}; - -module_usb_driver(irda_driver); diff --git a/drivers/net/irda/tekram-sir.c b/drivers/net/irda/tekram-sir.c deleted file mode 100644 index 9dcf0c103b9d..000000000000 --- a/drivers/net/irda/tekram-sir.c +++ /dev/null @@ -1,225 +0,0 @@ -/********************************************************************* - * - * 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ø 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; - pr_debug("%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; - - 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) -{ - /* 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; - - 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: - net_err_ratelimited("%s - undefined state %d\n", - __func__, 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) -{ - /* 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); diff --git a/drivers/net/irda/toim3232-sir.c b/drivers/net/irda/toim3232-sir.c deleted file mode 100644 index b977d6d33e74..000000000000 --- a/drivers/net/irda/toim3232-sir.c +++ /dev/null @@ -1,358 +0,0 @@ -/********************************************************************* - * - * Filename: toim3232-sir.c - * Version: 1.0 - * Description: Implementation of dongles based on the Vishay/Temic - * TOIM3232 SIR Endec chipset. Currently only the - * IRWave IR320ST-2 is tested, although it should work - * with any TOIM3232 or TOIM4232 chipset based RS232 - * dongle with minimal modification. - * Based heavily on the Tekram driver (tekram.c), - * with thanks to Dag Brattli and Martin Diehl. - * Status: Experimental. - * Author: David Basden <davidb-irda@rcpt.to> - * Created at: Thu Feb 09 23:47:32 2006 - * - * Copyright (c) 2006 David Basden. - * 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ø admit liability nor - * provide warranty for any of this software. This material is - * provided "AS-IS" and at no charge. - * - ********************************************************************/ - -/* - * This driver has currently only been tested on the IRWave IR320ST-2 - * - * PROTOCOL: - * - * The protocol for talking to the TOIM3232 is quite easy, and is - * designed to interface with RS232 with only level convertors. The - * BR/~D line on the chip is brought high to signal 'command mode', - * where a command byte is sent to select the baudrate of the RS232 - * interface and the pulse length of the IRDA output. When BR/~D - * is brought low, the dongle then changes to the selected baudrate, - * and the RS232 interface is used for data until BR/~D is brought - * high again. The initial speed for the TOIMx323 after RESET is - * 9600 baud. The baudrate for command-mode is the last selected - * baud-rate, or 9600 after a RESET. - * - * The dongle I have (below) adds some extra hardware on the front end, - * but this is mostly directed towards pariasitic power from the RS232 - * line rather than changing very much about how to communicate with - * the TOIM3232. - * - * The protocol to talk to the TOIM4232 chipset seems to be almost - * identical to the TOIM3232 (and the 4232 datasheet is more detailed) - * so this code will probably work on that as well, although I haven't - * tested it on that hardware. - * - * Target dongle variations that might be common: - * - * DTR and RTS function: - * The data sheet for the 4232 has a sample implementation that hooks the - * DTR and RTS lines to the RESET and BaudRate/~Data lines of the - * chip (through line-converters). Given both DTR and RTS would have to - * be held low in normal operation, and the TOIMx232 requires +5V to - * signal ground, most dongle designers would almost certainly choose - * an implementation that kept at least one of DTR or RTS high in - * normal operation to provide power to the dongle, but will likely - * vary between designs. - * - * User specified command bits: - * There are two user-controllable output lines from the TOIMx232 that - * can be set low or high by setting the appropriate bits in the - * high-nibble of the command byte (when setting speed and pulse length). - * These might be used to switch on and off added hardware or extra - * dongle features. - * - * - * Target hardware: IRWave IR320ST-2 - * - * The IRWave IR320ST-2 is a simple dongle based on the Vishay/Temic - * TOIM3232 SIR Endec and the Vishay/Temic TFDS4500 SIR IRDA transceiver. - * It uses a hex inverter and some discrete components to buffer and - * line convert the RS232 down to 5V. - * - * The dongle is powered through a voltage regulator, fed by a large - * capacitor. To switch the dongle on, DTR is brought high to charge - * the capacitor and drive the voltage regulator. DTR isn't associated - * with any control lines on the TOIM3232. Parisitic power is also taken - * from the RTS, TD and RD lines when brought high, but through resistors. - * When DTR is low, the circuit might lose power even with RTS high. - * - * RTS is inverted and attached to the BR/~D input pin. When RTS - * is high, BR/~D is low, and the TOIM3232 is in the normal 'data' mode. - * RTS is brought low, BR/~D is high, and the TOIM3232 is in 'command - * mode'. - * - * For some unknown reason, the RESET line isn't actually connected - * to anything. This means to reset the dongle to get it to a known - * state (9600 baud) you must drop DTR and RTS low, wait for the power - * capacitor to discharge, and then bring DTR (and RTS for data mode) - * high again, and wait for the capacitor to charge, the power supply - * to stabilise, and the oscillator clock to stabilise. - * - * Fortunately, if the current baudrate is known, the chipset can - * easily change speed by entering command mode without having to - * reset the dongle first. - * - * Major Components: - * - * - Vishay/Temic TOIM3232 SIR Endec to change RS232 pulse timings - * to IRDA pulse timings - * - 3.6864MHz crystal to drive TOIM3232 clock oscillator - * - DM74lS04M Inverting Hex line buffer for RS232 input buffering - * and level conversion - * - PJ2951AC 150mA voltage regulator - * - Vishay/Temic TFDS4500 SIR IRDA front-end transceiver - * - */ - -#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 toim3232delay = 150; /* default is 150 ms */ -module_param(toim3232delay, int, 0); -MODULE_PARM_DESC(toim3232delay, "toim3232 dongle write complete delay"); - -static int toim3232_open(struct sir_dev *); -static int toim3232_close(struct sir_dev *); -static int toim3232_change_speed(struct sir_dev *, unsigned); -static int toim3232_reset(struct sir_dev *); - -#define TOIM3232_115200 0x00 -#define TOIM3232_57600 0x01 -#define TOIM3232_38400 0x02 -#define TOIM3232_19200 0x03 -#define TOIM3232_9600 0x06 -#define TOIM3232_2400 0x0A - -#define TOIM3232_PW 0x10 /* Pulse select bit */ - -static struct dongle_driver toim3232 = { - .owner = THIS_MODULE, - .driver_name = "Vishay TOIM3232", - .type = IRDA_TOIM3232_DONGLE, - .open = toim3232_open, - .close = toim3232_close, - .reset = toim3232_reset, - .set_speed = toim3232_change_speed, -}; - -static int __init toim3232_sir_init(void) -{ - if (toim3232delay < 1 || toim3232delay > 500) - toim3232delay = 200; - pr_debug("%s - using %d ms delay\n", - toim3232.driver_name, toim3232delay); - return irda_register_dongle(&toim3232); -} - -static void __exit toim3232_sir_cleanup(void) -{ - irda_unregister_dongle(&toim3232); -} - -static int toim3232_open(struct sir_dev *dev) -{ - struct qos_info *qos = &dev->qos; - - /* Pull the lines high to start with. - * - * For the IR320ST-2, we need to charge the main supply capacitor to - * switch the device on. We keep DTR high throughout to do this. - * When RTS, TD and RD are high, they will also trickle-charge the - * cap. RTS is high for data transmission, and low for baud rate select. - * -- DGB - */ - sirdev_set_dtr_rts(dev, TRUE, TRUE); - - /* The TOI3232 supports many speeds between 1200bps and 115000bps. - * We really only care about those supported by the IRDA spec, but - * 38400 seems to be implemented in many places */ - qos->baud_rate.bits &= IR_2400|IR_9600|IR_19200|IR_38400|IR_57600|IR_115200; - - /* From the tekram driver. Not sure what a reasonable value is -- DGB */ - 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 toim3232_close(struct sir_dev *dev) -{ - /* Power off dongle */ - sirdev_set_dtr_rts(dev, FALSE, FALSE); - - return 0; -} - -/* - * Function toim3232change_speed (dev, state, speed) - * - * Set the speed for the TOIM3232 based dongle. Warning, this - * function must be called with a process context! - * - * Algorithm - * 1. keep DTR high but clear RTS to bring into baud programming mode - * 2. wait at least 7us to enter programming mode - * 3. send control word to set baud rate and timing - * 4. wait at least 1us - * 5. bring RTS high to enter DATA mode (RS232 is passed through to transceiver) - * 6. should take effect immediately (although probably worth waiting) - */ - -#define TOIM3232_STATE_WAIT_SPEED (SIRDEV_STATE_DONGLE_SPEED + 1) - -static int toim3232_change_speed(struct sir_dev *dev, unsigned speed) -{ - unsigned state = dev->fsm.substate; - unsigned delay = 0; - u8 byte; - static int ret = 0; - - switch(state) { - case SIRDEV_STATE_DONGLE_SPEED: - - /* Figure out what we are going to send as a control byte */ - switch (speed) { - case 2400: - byte = TOIM3232_PW|TOIM3232_2400; - break; - default: - speed = 9600; - ret = -EINVAL; - /* fall thru */ - case 9600: - byte = TOIM3232_PW|TOIM3232_9600; - break; - case 19200: - byte = TOIM3232_PW|TOIM3232_19200; - break; - case 38400: - byte = TOIM3232_PW|TOIM3232_38400; - break; - case 57600: - byte = TOIM3232_PW|TOIM3232_57600; - break; - case 115200: - byte = TOIM3232_115200; - break; - } - - /* Set DTR, Clear RTS: Go into baud programming mode */ - 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 = TOIM3232_STATE_WAIT_SPEED; - delay = toim3232delay; - break; - - case TOIM3232_STATE_WAIT_SPEED: - /* Have transmitted control byte * Wait for 'at least 1us' */ - udelay(14); - - /* Set DTR, Set RTS: Go into normal data mode */ - sirdev_set_dtr_rts(dev, TRUE, TRUE); - - /* Wait (TODO: check this is needed) */ - udelay(50); - break; - - default: - printk(KERN_ERR "%s - undefined state %d\n", __func__, state); - ret = -EINVAL; - break; - } - - dev->fsm.substate = state; - return (delay > 0) ? delay : ret; -} - -/* - * Function toim3232reset (driver) - * - * This function resets the toim3232 dongle. Warning, this function - * must be called with a process context!! - * - * What we should do is: - * 0. Pull RESET high - * 1. Wait for at least 7us - * 2. Pull RESET low - * 3. Wait for at least 7us - * 4. Pull BR/~D high - * 5. Wait for at least 7us - * 6. Send control byte to set baud rate - * 7. Wait at least 1us after stop bit - * 8. Pull BR/~D low - * 9. Should then be in data mode - * - * Because the IR320ST-2 doesn't have the RESET line connected for some reason, - * we'll have to do something else. - * - * The default speed after a RESET is 9600, so lets try just bringing it up in - * data mode after switching it off, waiting for the supply capacitor to - * discharge, and then switch it back on. This isn't actually pulling RESET - * high, but it seems to have the same effect. - * - * This behaviour will probably work on dongles that have the RESET line connected, - * but if not, add a flag for the IR320ST-2, and implment the above-listed proper - * behaviour. - * - * RTS is inverted and then fed to BR/~D, so to put it in programming mode, we - * need to have pull RTS low - */ - -static int toim3232_reset(struct sir_dev *dev) -{ - /* Switch off both DTR and RTS to switch off dongle */ - sirdev_set_dtr_rts(dev, FALSE, FALSE); - - /* Should sleep a while. This might be evil doing it this way.*/ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(msecs_to_jiffies(50)); - - /* Set DTR, Set RTS (data mode) */ - sirdev_set_dtr_rts(dev, TRUE, TRUE); - - /* Wait at least 10 ms for power to stabilize again */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(msecs_to_jiffies(10)); - - /* Speed should now be 9600 */ - dev->speed = 9600; - - return 0; -} - -MODULE_AUTHOR("David Basden <davidb-linux@rcpt.to>"); -MODULE_DESCRIPTION("Vishay/Temic TOIM3232 based dongle driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("irda-dongle-12"); /* IRDA_TOIM3232_DONGLE */ - -module_init(toim3232_sir_init); -module_exit(toim3232_sir_cleanup); diff --git a/drivers/net/irda/via-ircc.c b/drivers/net/irda/via-ircc.c deleted file mode 100644 index ca4442a9d631..000000000000 --- a/drivers/net/irda/via-ircc.c +++ /dev/null @@ -1,1593 +0,0 @@ -/******************************************************************** - Filename: via-ircc.c - 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, see <http://www.gnu.org/licenses/>. - -F01 Oct/02/02: Modify code for V0.11(move out back to back transfer) -F02 Oct/28/02: Add SB device ID for 3147 and 3177. - Comment : - 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 . - -2004-02-16: <sda@bdit.de> -- Removed unneeded 'legacy' pci stuff. -- Make sure SIR mode is set (hw_init()) before calling mode-dependent stuff. -- On speed change from core, don't send SIR frame with new speed. - Use current speed and change speeds later. -- Make module-param dongle_id actually work. -- New dongle_id 17 (0x11): TDFS4500. Single-ended SIR only. - Tested with home-grown PCB on EPIA boards. -- Code cleanup. - - ********************************************************************/ -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/skbuff.h> -#include <linux/netdevice.h> -#include <linux/ioport.h> -#include <linux/delay.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/rtnetlink.h> -#include <linux/pci.h> -#include <linux/dma-mapping.h> -#include <linux/gfp.h> - -#include <asm/io.h> -#include <asm/dma.h> -#include <asm/byteorder.h> - -#include <linux/pm.h> - -#include <net/irda/wrapper.h> -#include <net/irda/irda.h> -#include <net/irda/irda_device.h> - -#include "via-ircc.h" - -#define VIA_MODULE_NAME "via-ircc" -#define CHIP_IO_EXTENT 0x40 - -static char *driver_name = VIA_MODULE_NAME; - -/* Module parameters */ -static int qos_mtt_bits = 0x07; /* 1 ms or more */ -static int dongle_id = 0; /* default: probe */ - -/* We can't guess the type of connected dongle, user *must* supply it. */ -module_param(dongle_id, int, 0); - -/* Some prototypes */ -static int via_ircc_open(struct pci_dev *pdev, chipio_t *info, - unsigned int id); -static int via_ircc_dma_receive(struct via_ircc_cb *self); -static int via_ircc_dma_receive_complete(struct via_ircc_cb *self, - int iobase); -static netdev_tx_t via_ircc_hard_xmit_sir(struct sk_buff *skb, - struct net_device *dev); -static netdev_tx_t via_ircc_hard_xmit_fir(struct sk_buff *skb, - struct net_device *dev); -static void via_hw_init(struct via_ircc_cb *self); -static void via_ircc_change_speed(struct via_ircc_cb *self, __u32 baud); -static irqreturn_t via_ircc_interrupt(int irq, void *dev_id); -static int via_ircc_is_receiving(struct via_ircc_cb *self); -static int via_ircc_read_dongle_id(int iobase); - -static int via_ircc_net_open(struct net_device *dev); -static int via_ircc_net_close(struct net_device *dev); -static int via_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, - int cmd); -static void via_ircc_change_dongle_speed(int iobase, int speed, - int dongle_id); -static int RxTimerHandler(struct via_ircc_cb *self, int iobase); -static void hwreset(struct via_ircc_cb *self); -static int via_ircc_dma_xmit(struct via_ircc_cb *self, u16 iobase); -static int upload_rxdata(struct via_ircc_cb *self, int iobase); -static int via_init_one(struct pci_dev *pcidev, const struct pci_device_id *id); -static void via_remove_one(struct pci_dev *pdev); - -/* FIXME : Should use udelay() instead, even if we are x86 only - Jean II */ -static void iodelay(int udelay) -{ - u8 data; - int i; - - for (i = 0; i < udelay; i++) { - data = inb(0x80); - } -} - -static const struct pci_device_id via_pci_tbl[] = { - { PCI_VENDOR_ID_VIA, 0x8231, PCI_ANY_ID, PCI_ANY_ID,0,0,0 }, - { PCI_VENDOR_ID_VIA, 0x3109, PCI_ANY_ID, PCI_ANY_ID,0,0,1 }, - { PCI_VENDOR_ID_VIA, 0x3074, PCI_ANY_ID, PCI_ANY_ID,0,0,2 }, - { PCI_VENDOR_ID_VIA, 0x3147, PCI_ANY_ID, PCI_ANY_ID,0,0,3 }, - { PCI_VENDOR_ID_VIA, 0x3177, PCI_ANY_ID, PCI_ANY_ID,0,0,4 }, - { 0, } -}; - -MODULE_DEVICE_TABLE(pci,via_pci_tbl); - - -static struct pci_driver via_driver = { - .name = VIA_MODULE_NAME, - .id_table = via_pci_tbl, - .probe = via_init_one, - .remove = via_remove_one, -}; - - -/* - * Function via_ircc_init () - * - * Initialize chip. Just find out chip type and resource. - */ -static int __init via_ircc_init(void) -{ - int rc; - - rc = pci_register_driver(&via_driver); - if (rc < 0) { - pr_debug("%s(): error rc = %d, returning -ENODEV...\n", - __func__, rc); - return -ENODEV; - } - return 0; -} - -static int via_init_one(struct pci_dev *pcidev, const struct pci_device_id *id) -{ - int rc; - u8 temp,oldPCI_40,oldPCI_44,bTmp,bTmp1; - u16 Chipset,FirDRQ1,FirDRQ0,FirIRQ,FirIOBase; - chipio_t info; - - pr_debug("%s(): Device ID=(0X%X)\n", __func__, id->device); - - rc = pci_enable_device (pcidev); - if (rc) { - pr_debug("%s(): error rc = %d\n", __func__, rc); - return -ENODEV; - } - - // South Bridge exist - if ( ReadLPCReg(0x20) != 0x3C ) - Chipset=0x3096; - else - Chipset=0x3076; - - if (Chipset==0x3076) { - pr_debug("%s(): Chipset = 3076\n", __func__); - - WriteLPCReg(7,0x0c ); - temp=ReadLPCReg(0x30);//check if BIOS Enable Fir - if((temp&0x01)==1) { // BIOS close or no FIR - WriteLPCReg(0x1d, 0x82 ); - WriteLPCReg(0x23,0x18); - temp=ReadLPCReg(0xF0); - if((temp&0x01)==0) { - temp=(ReadLPCReg(0x74)&0x03); //DMA - FirDRQ0=temp + 4; - temp=(ReadLPCReg(0x74)&0x0C) >> 2; - FirDRQ1=temp + 4; - } else { - temp=(ReadLPCReg(0x74)&0x0C) >> 2; //DMA - FirDRQ0=temp + 4; - FirDRQ1=FirDRQ0; - } - FirIRQ=(ReadLPCReg(0x70)&0x0f); //IRQ - FirIOBase=ReadLPCReg(0x60 ) << 8; //IO Space :high byte - FirIOBase=FirIOBase| ReadLPCReg(0x61) ; //low byte - FirIOBase=FirIOBase ; - info.fir_base=FirIOBase; - info.irq=FirIRQ; - info.dma=FirDRQ1; - info.dma2=FirDRQ0; - pci_read_config_byte(pcidev,0x40,&bTmp); - pci_write_config_byte(pcidev,0x40,((bTmp | 0x08) & 0xfe)); - pci_read_config_byte(pcidev,0x42,&bTmp); - pci_write_config_byte(pcidev,0x42,(bTmp | 0xf0)); - pci_write_config_byte(pcidev,0x5a,0xc0); - WriteLPCReg(0x28, 0x70 ); - rc = via_ircc_open(pcidev, &info, 0x3076); - } else - rc = -ENODEV; //IR not turn on - } else { //Not VT1211 - pr_debug("%s(): Chipset = 3096\n", __func__); - - pci_read_config_byte(pcidev,0x67,&bTmp);//check if BIOS Enable Fir - if((bTmp&0x01)==1) { // BIOS enable FIR - //Enable Double DMA clock - pci_read_config_byte(pcidev,0x42,&oldPCI_40); - pci_write_config_byte(pcidev,0x42,oldPCI_40 | 0x80); - pci_read_config_byte(pcidev,0x40,&oldPCI_40); - pci_write_config_byte(pcidev,0x40,oldPCI_40 & 0xf7); - pci_read_config_byte(pcidev,0x44,&oldPCI_44); - pci_write_config_byte(pcidev,0x44,0x4e); - //---------- read configuration from Function0 of south bridge - if((bTmp&0x02)==0) { - pci_read_config_byte(pcidev,0x44,&bTmp1); //DMA - FirDRQ0 = (bTmp1 & 0x30) >> 4; - pci_read_config_byte(pcidev,0x44,&bTmp1); - FirDRQ1 = (bTmp1 & 0xc0) >> 6; - } else { - pci_read_config_byte(pcidev,0x44,&bTmp1); //DMA - FirDRQ0 = (bTmp1 & 0x30) >> 4 ; - FirDRQ1=0; - } - pci_read_config_byte(pcidev,0x47,&bTmp1); //IRQ - FirIRQ = bTmp1 & 0x0f; - - pci_read_config_byte(pcidev,0x69,&bTmp); - FirIOBase = bTmp << 8;//hight byte - pci_read_config_byte(pcidev,0x68,&bTmp); - FirIOBase = (FirIOBase | bTmp ) & 0xfff0; - //------------------------- - info.fir_base=FirIOBase; - info.irq=FirIRQ; - info.dma=FirDRQ1; - info.dma2=FirDRQ0; - rc = via_ircc_open(pcidev, &info, 0x3096); - } else - rc = -ENODEV; //IR not turn on !!!!! - }//Not VT1211 - - pr_debug("%s(): End - rc = %d\n", __func__, rc); - return rc; -} - -static void __exit via_ircc_cleanup(void) -{ - /* Cleanup all instances of the driver */ - pci_unregister_driver (&via_driver); -} - -static const struct net_device_ops via_ircc_sir_ops = { - .ndo_start_xmit = via_ircc_hard_xmit_sir, - .ndo_open = via_ircc_net_open, - .ndo_stop = via_ircc_net_close, - .ndo_do_ioctl = via_ircc_net_ioctl, -}; -static const struct net_device_ops via_ircc_fir_ops = { - .ndo_start_xmit = via_ircc_hard_xmit_fir, - .ndo_open = via_ircc_net_open, - .ndo_stop = via_ircc_net_close, - .ndo_do_ioctl = via_ircc_net_ioctl, -}; - -/* - * Function via_ircc_open(pdev, iobase, irq) - * - * Open driver instance - * - */ -static int via_ircc_open(struct pci_dev *pdev, chipio_t *info, unsigned int id) -{ - struct net_device *dev; - struct via_ircc_cb *self; - int err; - - /* Allocate new instance of the driver */ - dev = alloc_irdadev(sizeof(struct via_ircc_cb)); - if (dev == NULL) - return -ENOMEM; - - self = netdev_priv(dev); - self->netdev = dev; - spin_lock_init(&self->lock); - - pci_set_drvdata(pdev, self); - - /* Initialize Resource */ - self->io.cfg_base = info->cfg_base; - self->io.fir_base = info->fir_base; - self->io.irq = info->irq; - self->io.fir_ext = CHIP_IO_EXTENT; - self->io.dma = info->dma; - self->io.dma2 = info->dma2; - self->io.fifo_size = 32; - self->chip_id = id; - self->st_fifo.len = 0; - self->RxDataReady = 0; - - /* Reserve the ioports that we need */ - if (!request_region(self->io.fir_base, self->io.fir_ext, driver_name)) { - pr_debug("%s(), can't get iobase of 0x%03x\n", - __func__, self->io.fir_base); - err = -ENODEV; - goto err_out1; - } - - /* Initialize QoS for this device */ - irda_init_max_qos_capabilies(&self->qos); - - /* Check if user has supplied the dongle id or not */ - if (!dongle_id) - dongle_id = via_ircc_read_dongle_id(self->io.fir_base); - self->io.dongle_id = dongle_id; - - /* The only value we must override it the baudrate */ - /* Maximum speeds and capabilities are dongle-dependent. */ - switch( self->io.dongle_id ){ - case 0x0d: - self->qos.baud_rate.bits = - IR_9600 | IR_19200 | IR_38400 | IR_57600 | IR_115200 | - IR_576000 | IR_1152000 | (IR_4000000 << 8); - break; - default: - self->qos.baud_rate.bits = - IR_9600 | IR_19200 | IR_38400 | IR_57600 | IR_115200; - break; - } - - /* Following was used for testing: - * - * self->qos.baud_rate.bits = IR_9600; - * - * Is is no good, as it prohibits (error-prone) speed-changes. - */ - - self->qos.min_turn_time.bits = qos_mtt_bits; - irda_qos_bits_to_value(&self->qos); - - /* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */ - self->rx_buff.truesize = 14384 + 2048; - self->tx_buff.truesize = 14384 + 2048; - - /* Allocate memory if needed */ - self->rx_buff.head = - dma_zalloc_coherent(&pdev->dev, self->rx_buff.truesize, - &self->rx_buff_dma, GFP_KERNEL); - if (self->rx_buff.head == NULL) { - err = -ENOMEM; - goto err_out2; - } - - self->tx_buff.head = - dma_zalloc_coherent(&pdev->dev, self->tx_buff.truesize, - &self->tx_buff_dma, GFP_KERNEL); - if (self->tx_buff.head == NULL) { - err = -ENOMEM; - goto err_out3; - } - - self->rx_buff.in_frame = FALSE; - self->rx_buff.state = OUTSIDE_FRAME; - self->tx_buff.data = self->tx_buff.head; - self->rx_buff.data = self->rx_buff.head; - - /* Reset Tx queue info */ - self->tx_fifo.len = self->tx_fifo.ptr = self->tx_fifo.free = 0; - self->tx_fifo.tail = self->tx_buff.head; - - /* Override the network functions we need to use */ - dev->netdev_ops = &via_ircc_sir_ops; - - err = register_netdev(dev); - if (err) - goto err_out4; - - net_info_ratelimited("IrDA: Registered device %s (via-ircc)\n", - dev->name); - - /* Initialise the hardware.. - */ - self->io.speed = 9600; - via_hw_init(self); - return 0; - err_out4: - dma_free_coherent(&pdev->dev, self->tx_buff.truesize, - self->tx_buff.head, self->tx_buff_dma); - err_out3: - dma_free_coherent(&pdev->dev, self->rx_buff.truesize, - self->rx_buff.head, self->rx_buff_dma); - err_out2: - release_region(self->io.fir_base, self->io.fir_ext); - err_out1: - free_netdev(dev); - return err; -} - -/* - * Function via_remove_one(pdev) - * - * Close driver instance - * - */ -static void via_remove_one(struct pci_dev *pdev) -{ - struct via_ircc_cb *self = pci_get_drvdata(pdev); - int iobase; - - iobase = self->io.fir_base; - - ResetChip(iobase, 5); //hardware reset. - /* Remove netdevice */ - unregister_netdev(self->netdev); - - /* Release the PORT that this driver is using */ - pr_debug("%s(), Releasing Region %03x\n", - __func__, self->io.fir_base); - release_region(self->io.fir_base, self->io.fir_ext); - if (self->tx_buff.head) - dma_free_coherent(&pdev->dev, self->tx_buff.truesize, - self->tx_buff.head, self->tx_buff_dma); - if (self->rx_buff.head) - dma_free_coherent(&pdev->dev, self->rx_buff.truesize, - self->rx_buff.head, self->rx_buff_dma); - - free_netdev(self->netdev); - - pci_disable_device(pdev); -} - -/* - * Function via_hw_init(self) - * - * Returns non-negative on success. - * - * Formerly via_ircc_setup - */ -static void via_hw_init(struct via_ircc_cb *self) -{ - int iobase = self->io.fir_base; - - SetMaxRxPacketSize(iobase, 0x0fff); //set to max:4095 - // FIFO Init - EnRXFIFOReadyInt(iobase, OFF); - EnRXFIFOHalfLevelInt(iobase, OFF); - EnTXFIFOHalfLevelInt(iobase, OFF); - EnTXFIFOUnderrunEOMInt(iobase, ON); - EnTXFIFOReadyInt(iobase, OFF); - InvertTX(iobase, OFF); - InvertRX(iobase, OFF); - - if (ReadLPCReg(0x20) == 0x3c) - WriteLPCReg(0xF0, 0); // for VT1211 - /* Int Init */ - EnRXSpecInt(iobase, ON); - - /* The following is basically hwreset */ - /* If this is the case, why not just call hwreset() ? Jean II */ - ResetChip(iobase, 5); - EnableDMA(iobase, OFF); - EnableTX(iobase, OFF); - EnableRX(iobase, OFF); - EnRXDMA(iobase, OFF); - EnTXDMA(iobase, OFF); - RXStart(iobase, OFF); - TXStart(iobase, OFF); - InitCard(iobase); - CommonInit(iobase); - SIRFilter(iobase, ON); - SetSIR(iobase, ON); - CRC16(iobase, ON); - EnTXCRC(iobase, 0); - WriteReg(iobase, I_ST_CT_0, 0x00); - SetBaudRate(iobase, 9600); - SetPulseWidth(iobase, 12); - SetSendPreambleCount(iobase, 0); - - self->io.speed = 9600; - self->st_fifo.len = 0; - - via_ircc_change_dongle_speed(iobase, self->io.speed, - self->io.dongle_id); - - WriteReg(iobase, I_ST_CT_0, 0x80); -} - -/* - * Function via_ircc_read_dongle_id (void) - * - */ -static int via_ircc_read_dongle_id(int iobase) -{ - net_err_ratelimited("via-ircc: dongle probing not supported, please specify dongle_id module parameter\n"); - return 9; /* Default to IBM */ -} - -/* - * Function via_ircc_change_dongle_speed (iobase, speed, dongle_id) - * Change speed of the attach dongle - * only implement two type of dongle currently. - */ -static void via_ircc_change_dongle_speed(int iobase, int speed, - int dongle_id) -{ - u8 mode = 0; - - /* speed is unused, as we use IsSIROn()/IsMIROn() */ - speed = speed; - - pr_debug("%s(): change_dongle_speed to %d for 0x%x, %d\n", - __func__, speed, iobase, dongle_id); - - switch (dongle_id) { - - /* Note: The dongle_id's listed here are derived from - * nsc-ircc.c */ - - case 0x08: /* HP HSDL-2300, HP HSDL-3600/HSDL-3610 */ - UseOneRX(iobase, ON); // use one RX pin RX1,RX2 - InvertTX(iobase, OFF); - InvertRX(iobase, OFF); - - EnRX2(iobase, ON); //sir to rx2 - EnGPIOtoRX2(iobase, OFF); - - if (IsSIROn(iobase)) { //sir - // Mode select Off - SlowIRRXLowActive(iobase, ON); - udelay(1000); - SlowIRRXLowActive(iobase, OFF); - } else { - if (IsMIROn(iobase)) { //mir - // Mode select On - SlowIRRXLowActive(iobase, OFF); - udelay(20); - } else { // fir - if (IsFIROn(iobase)) { //fir - // Mode select On - SlowIRRXLowActive(iobase, OFF); - udelay(20); - } - } - } - break; - - case 0x09: /* IBM31T1100 or Temic TFDS6000/TFDS6500 */ - UseOneRX(iobase, ON); //use ONE RX....RX1 - InvertTX(iobase, OFF); - InvertRX(iobase, OFF); // invert RX pin - - EnRX2(iobase, ON); - EnGPIOtoRX2(iobase, OFF); - if (IsSIROn(iobase)) { //sir - // Mode select On - SlowIRRXLowActive(iobase, ON); - udelay(20); - // Mode select Off - SlowIRRXLowActive(iobase, OFF); - } - if (IsMIROn(iobase)) { //mir - // Mode select On - SlowIRRXLowActive(iobase, OFF); - udelay(20); - // Mode select Off - SlowIRRXLowActive(iobase, ON); - } else { // fir - if (IsFIROn(iobase)) { //fir - // Mode select On - SlowIRRXLowActive(iobase, OFF); - // TX On - WriteTX(iobase, ON); - udelay(20); - // Mode select OFF - SlowIRRXLowActive(iobase, ON); - udelay(20); - // TX Off - WriteTX(iobase, OFF); - } - } - break; - - case 0x0d: - UseOneRX(iobase, OFF); // use two RX pin RX1,RX2 - InvertTX(iobase, OFF); - InvertRX(iobase, OFF); - SlowIRRXLowActive(iobase, OFF); - if (IsSIROn(iobase)) { //sir - EnGPIOtoRX2(iobase, OFF); - WriteGIO(iobase, OFF); - EnRX2(iobase, OFF); //sir to rx2 - } else { // fir mir - EnGPIOtoRX2(iobase, OFF); - WriteGIO(iobase, OFF); - EnRX2(iobase, OFF); //fir to rx - } - break; - - case 0x11: /* Temic TFDS4500 */ - - pr_debug("%s: Temic TFDS4500: One RX pin, TX normal, RX inverted\n", - __func__); - - UseOneRX(iobase, ON); //use ONE RX....RX1 - InvertTX(iobase, OFF); - InvertRX(iobase, ON); // invert RX pin - - EnRX2(iobase, ON); //sir to rx2 - EnGPIOtoRX2(iobase, OFF); - - if( IsSIROn(iobase) ){ //sir - - // Mode select On - SlowIRRXLowActive(iobase, ON); - udelay(20); - // Mode select Off - SlowIRRXLowActive(iobase, OFF); - - } else{ - pr_debug("%s: Warning: TFDS4500 not running in SIR mode !\n", - __func__); - } - break; - - case 0x0ff: /* Vishay */ - if (IsSIROn(iobase)) - mode = 0; - else if (IsMIROn(iobase)) - mode = 1; - else if (IsFIROn(iobase)) - mode = 2; - else if (IsVFIROn(iobase)) - mode = 5; //VFIR-16 - SI_SetMode(iobase, mode); - break; - - default: - net_err_ratelimited("%s: Error: dongle_id %d unsupported !\n", - __func__, dongle_id); - } -} - -/* - * Function via_ircc_change_speed (self, baud) - * - * Change the speed of the device - * - */ -static void via_ircc_change_speed(struct via_ircc_cb *self, __u32 speed) -{ - struct net_device *dev = self->netdev; - u16 iobase; - u8 value = 0, bTmp; - - iobase = self->io.fir_base; - /* Update accounting for new speed */ - self->io.speed = speed; - pr_debug("%s: change_speed to %d bps.\n", __func__, speed); - - WriteReg(iobase, I_ST_CT_0, 0x0); - - /* Controller mode sellection */ - switch (speed) { - case 2400: - case 9600: - case 19200: - case 38400: - case 57600: - case 115200: - value = (115200/speed)-1; - SetSIR(iobase, ON); - CRC16(iobase, ON); - break; - case 576000: - /* FIXME: this can't be right, as it's the same as 115200, - * and 576000 is MIR, not SIR. */ - value = 0; - SetSIR(iobase, ON); - CRC16(iobase, ON); - break; - case 1152000: - value = 0; - SetMIR(iobase, ON); - /* FIXME: CRC ??? */ - break; - case 4000000: - value = 0; - SetFIR(iobase, ON); - SetPulseWidth(iobase, 0); - SetSendPreambleCount(iobase, 14); - CRC16(iobase, OFF); - EnTXCRC(iobase, ON); - break; - case 16000000: - value = 0; - SetVFIR(iobase, ON); - /* FIXME: CRC ??? */ - break; - default: - value = 0; - break; - } - - /* Set baudrate to 0x19[2..7] */ - bTmp = (ReadReg(iobase, I_CF_H_1) & 0x03); - bTmp |= value << 2; - WriteReg(iobase, I_CF_H_1, bTmp); - - /* Some dongles may need to be informed about speed changes. */ - via_ircc_change_dongle_speed(iobase, speed, self->io.dongle_id); - - /* Set FIFO size to 64 */ - SetFIFO(iobase, 64); - - /* Enable IR */ - WriteReg(iobase, I_ST_CT_0, 0x80); - - // EnTXFIFOHalfLevelInt(iobase,ON); - - /* Enable some interrupts so we can receive frames */ - //EnAllInt(iobase,ON); - - if (IsSIROn(iobase)) { - SIRFilter(iobase, ON); - SIRRecvAny(iobase, ON); - } else { - SIRFilter(iobase, OFF); - SIRRecvAny(iobase, OFF); - } - - if (speed > 115200) { - /* Install FIR xmit handler */ - dev->netdev_ops = &via_ircc_fir_ops; - via_ircc_dma_receive(self); - } else { - /* Install SIR xmit handler */ - dev->netdev_ops = &via_ircc_sir_ops; - } - netif_wake_queue(dev); -} - -/* - * Function via_ircc_hard_xmit (skb, dev) - * - * Transmit the frame! - * - */ -static netdev_tx_t via_ircc_hard_xmit_sir(struct sk_buff *skb, - struct net_device *dev) -{ - struct via_ircc_cb *self; - unsigned long flags; - u16 iobase; - __u32 speed; - - self = netdev_priv(dev); - IRDA_ASSERT(self != NULL, return NETDEV_TX_OK;); - iobase = self->io.fir_base; - - netif_stop_queue(dev); - /* Check if we need to change the speed */ - speed = irda_get_next_speed(skb); - if ((speed != self->io.speed) && (speed != -1)) { - /* Check for empty frame */ - if (!skb->len) { - via_ircc_change_speed(self, speed); - netif_trans_update(dev); - dev_kfree_skb(skb); - return NETDEV_TX_OK; - } else - self->new_speed = speed; - } - InitCard(iobase); - CommonInit(iobase); - SIRFilter(iobase, ON); - SetSIR(iobase, ON); - CRC16(iobase, ON); - EnTXCRC(iobase, 0); - WriteReg(iobase, I_ST_CT_0, 0x00); - - spin_lock_irqsave(&self->lock, flags); - self->tx_buff.data = self->tx_buff.head; - self->tx_buff.len = - async_wrap_skb(skb, self->tx_buff.data, - self->tx_buff.truesize); - - dev->stats.tx_bytes += self->tx_buff.len; - /* Send this frame with old speed */ - SetBaudRate(iobase, self->io.speed); - SetPulseWidth(iobase, 12); - SetSendPreambleCount(iobase, 0); - WriteReg(iobase, I_ST_CT_0, 0x80); - - EnableTX(iobase, ON); - EnableRX(iobase, OFF); - - ResetChip(iobase, 0); - ResetChip(iobase, 1); - ResetChip(iobase, 2); - ResetChip(iobase, 3); - ResetChip(iobase, 4); - - EnAllInt(iobase, ON); - EnTXDMA(iobase, ON); - EnRXDMA(iobase, OFF); - - irda_setup_dma(self->io.dma, self->tx_buff_dma, self->tx_buff.len, - DMA_TX_MODE); - - SetSendByte(iobase, self->tx_buff.len); - RXStart(iobase, OFF); - TXStart(iobase, ON); - - netif_trans_update(dev); - spin_unlock_irqrestore(&self->lock, flags); - dev_kfree_skb(skb); - return NETDEV_TX_OK; -} - -static netdev_tx_t via_ircc_hard_xmit_fir(struct sk_buff *skb, - struct net_device *dev) -{ - struct via_ircc_cb *self; - u16 iobase; - __u32 speed; - unsigned long flags; - - self = netdev_priv(dev); - iobase = self->io.fir_base; - - if (self->st_fifo.len) - return NETDEV_TX_OK; - if (self->chip_id == 0x3076) - iodelay(1500); - else - udelay(1500); - netif_stop_queue(dev); - speed = irda_get_next_speed(skb); - if ((speed != self->io.speed) && (speed != -1)) { - if (!skb->len) { - via_ircc_change_speed(self, speed); - netif_trans_update(dev); - dev_kfree_skb(skb); - return NETDEV_TX_OK; - } else - self->new_speed = speed; - } - spin_lock_irqsave(&self->lock, flags); - self->tx_fifo.queue[self->tx_fifo.free].start = self->tx_fifo.tail; - self->tx_fifo.queue[self->tx_fifo.free].len = skb->len; - - self->tx_fifo.tail += skb->len; - dev->stats.tx_bytes += skb->len; - skb_copy_from_linear_data(skb, - self->tx_fifo.queue[self->tx_fifo.free].start, skb->len); - self->tx_fifo.len++; - self->tx_fifo.free++; -//F01 if (self->tx_fifo.len == 1) { - via_ircc_dma_xmit(self, iobase); -//F01 } -//F01 if (self->tx_fifo.free < (MAX_TX_WINDOW -1 )) netif_wake_queue(self->netdev); - netif_trans_update(dev); - dev_kfree_skb(skb); - spin_unlock_irqrestore(&self->lock, flags); - return NETDEV_TX_OK; - -} - -static int via_ircc_dma_xmit(struct via_ircc_cb *self, u16 iobase) -{ - EnTXDMA(iobase, OFF); - self->io.direction = IO_XMIT; - EnPhys(iobase, ON); - EnableTX(iobase, ON); - EnableRX(iobase, OFF); - ResetChip(iobase, 0); - ResetChip(iobase, 1); - ResetChip(iobase, 2); - ResetChip(iobase, 3); - ResetChip(iobase, 4); - EnAllInt(iobase, ON); - EnTXDMA(iobase, ON); - EnRXDMA(iobase, OFF); - irda_setup_dma(self->io.dma, - ((u8 *)self->tx_fifo.queue[self->tx_fifo.ptr].start - - self->tx_buff.head) + self->tx_buff_dma, - self->tx_fifo.queue[self->tx_fifo.ptr].len, DMA_TX_MODE); - pr_debug("%s: tx_fifo.ptr=%x,len=%x,tx_fifo.len=%x..\n", - __func__, self->tx_fifo.ptr, - self->tx_fifo.queue[self->tx_fifo.ptr].len, - self->tx_fifo.len); - - SetSendByte(iobase, self->tx_fifo.queue[self->tx_fifo.ptr].len); - RXStart(iobase, OFF); - TXStart(iobase, ON); - return 0; - -} - -/* - * Function via_ircc_dma_xmit_complete (self) - * - * The transfer of a frame in finished. This function will only be called - * by the interrupt handler - * - */ -static int via_ircc_dma_xmit_complete(struct via_ircc_cb *self) -{ - int iobase; - u8 Tx_status; - - iobase = self->io.fir_base; - /* Disable DMA */ -// DisableDmaChannel(self->io.dma); - /* Check for underrun! */ - /* Clear bit, by writing 1 into it */ - Tx_status = GetTXStatus(iobase); - if (Tx_status & 0x08) { - self->netdev->stats.tx_errors++; - self->netdev->stats.tx_fifo_errors++; - hwreset(self); - /* how to clear underrun? */ - } else { - self->netdev->stats.tx_packets++; - ResetChip(iobase, 3); - ResetChip(iobase, 4); - } - /* Check if we need to change the speed */ - if (self->new_speed) { - via_ircc_change_speed(self, self->new_speed); - self->new_speed = 0; - } - - /* Finished with this frame, so prepare for next */ - if (IsFIROn(iobase)) { - if (self->tx_fifo.len) { - self->tx_fifo.len--; - self->tx_fifo.ptr++; - } - } - pr_debug("%s: tx_fifo.len=%x ,tx_fifo.ptr=%x,tx_fifo.free=%x...\n", - __func__, - self->tx_fifo.len, self->tx_fifo.ptr, self->tx_fifo.free); -/* F01_S - // Any frames to be sent back-to-back? - if (self->tx_fifo.len) { - // Not finished yet! - via_ircc_dma_xmit(self, iobase); - ret = FALSE; - } else { -F01_E*/ - // Reset Tx FIFO info - self->tx_fifo.len = self->tx_fifo.ptr = self->tx_fifo.free = 0; - self->tx_fifo.tail = self->tx_buff.head; -//F01 } - - // Make sure we have room for more frames -//F01 if (self->tx_fifo.free < (MAX_TX_WINDOW -1 )) { - // Not busy transmitting anymore - // Tell the network layer, that we can accept more frames - netif_wake_queue(self->netdev); -//F01 } - return TRUE; -} - -/* - * Function via_ircc_dma_receive (self) - * - * Set configuration for receive a frame. - * - */ -static int via_ircc_dma_receive(struct via_ircc_cb *self) -{ - int iobase; - - iobase = self->io.fir_base; - - self->tx_fifo.len = self->tx_fifo.ptr = self->tx_fifo.free = 0; - self->tx_fifo.tail = self->tx_buff.head; - self->RxDataReady = 0; - self->io.direction = IO_RECV; - self->rx_buff.data = self->rx_buff.head; - self->st_fifo.len = self->st_fifo.pending_bytes = 0; - self->st_fifo.tail = self->st_fifo.head = 0; - - EnPhys(iobase, ON); - EnableTX(iobase, OFF); - EnableRX(iobase, ON); - - ResetChip(iobase, 0); - ResetChip(iobase, 1); - ResetChip(iobase, 2); - ResetChip(iobase, 3); - ResetChip(iobase, 4); - - EnAllInt(iobase, ON); - EnTXDMA(iobase, OFF); - EnRXDMA(iobase, ON); - irda_setup_dma(self->io.dma2, self->rx_buff_dma, - self->rx_buff.truesize, DMA_RX_MODE); - TXStart(iobase, OFF); - RXStart(iobase, ON); - - return 0; -} - -/* - * Function via_ircc_dma_receive_complete (self) - * - * Controller Finished with receiving frames, - * and this routine is call by ISR - * - */ -static int via_ircc_dma_receive_complete(struct via_ircc_cb *self, - int iobase) -{ - struct st_fifo *st_fifo; - struct sk_buff *skb; - int len, i; - u8 status = 0; - - iobase = self->io.fir_base; - st_fifo = &self->st_fifo; - - if (self->io.speed < 4000000) { //Speed below FIR - len = GetRecvByte(iobase, self); - skb = dev_alloc_skb(len + 1); - if (skb == NULL) - return FALSE; - // Make sure IP header gets aligned - skb_reserve(skb, 1); - skb_put(skb, len - 2); - if (self->chip_id == 0x3076) { - for (i = 0; i < len - 2; i++) - skb->data[i] = self->rx_buff.data[i * 2]; - } else { - if (self->chip_id == 0x3096) { - for (i = 0; i < len - 2; i++) - skb->data[i] = - self->rx_buff.data[i]; - } - } - // Move to next frame - self->rx_buff.data += len; - self->netdev->stats.rx_bytes += len; - self->netdev->stats.rx_packets++; - skb->dev = self->netdev; - skb_reset_mac_header(skb); - skb->protocol = htons(ETH_P_IRDA); - netif_rx(skb); - return TRUE; - } - - else { //FIR mode - len = GetRecvByte(iobase, self); - if (len == 0) - return TRUE; //interrupt only, data maybe move by RxT - if (((len - 4) < 2) || ((len - 4) > 2048)) { - pr_debug("%s(): Trouble:len=%x,CurCount=%x,LastCount=%x\n", - __func__, len, RxCurCount(iobase, self), - self->RxLastCount); - hwreset(self); - return FALSE; - } - pr_debug("%s(): fifo.len=%x,len=%x,CurCount=%x..\n", - __func__, - st_fifo->len, len - 4, RxCurCount(iobase, self)); - - st_fifo->entries[st_fifo->tail].status = status; - st_fifo->entries[st_fifo->tail].len = len; - st_fifo->pending_bytes += len; - st_fifo->tail++; - st_fifo->len++; - if (st_fifo->tail > MAX_RX_WINDOW) - st_fifo->tail = 0; - self->RxDataReady = 0; - - // It maybe have MAX_RX_WINDOW package receive by - // receive_complete before Timer IRQ -/* F01_S - if (st_fifo->len < (MAX_RX_WINDOW+2 )) { - RXStart(iobase,ON); - SetTimer(iobase,4); - } - else { -F01_E */ - EnableRX(iobase, OFF); - EnRXDMA(iobase, OFF); - RXStart(iobase, OFF); -//F01_S - // Put this entry back in fifo - if (st_fifo->head > MAX_RX_WINDOW) - st_fifo->head = 0; - status = st_fifo->entries[st_fifo->head].status; - len = st_fifo->entries[st_fifo->head].len; - st_fifo->head++; - st_fifo->len--; - - skb = dev_alloc_skb(len + 1 - 4); - /* - * if frame size, data ptr, or skb ptr are wrong, then get next - * entry. - */ - if ((skb == NULL) || (skb->data == NULL) || - (self->rx_buff.data == NULL) || (len < 6)) { - self->netdev->stats.rx_dropped++; - kfree_skb(skb); - return TRUE; - } - skb_reserve(skb, 1); - skb_put(skb, len - 4); - - skb_copy_to_linear_data(skb, self->rx_buff.data, len - 4); - pr_debug("%s(): len=%x.rx_buff=%p\n", __func__, - len - 4, self->rx_buff.data); - - // Move to next frame - self->rx_buff.data += len; - self->netdev->stats.rx_bytes += len; - self->netdev->stats.rx_packets++; - skb->dev = self->netdev; - skb_reset_mac_header(skb); - skb->protocol = htons(ETH_P_IRDA); - netif_rx(skb); - -//F01_E - } //FIR - return TRUE; - -} - -/* - * if frame is received , but no INT ,then use this routine to upload frame. - */ -static int upload_rxdata(struct via_ircc_cb *self, int iobase) -{ - struct sk_buff *skb; - int len; - struct st_fifo *st_fifo; - st_fifo = &self->st_fifo; - - len = GetRecvByte(iobase, self); - - pr_debug("%s(): len=%x\n", __func__, len); - - if ((len - 4) < 2) { - self->netdev->stats.rx_dropped++; - return FALSE; - } - - skb = dev_alloc_skb(len + 1); - if (skb == NULL) { - self->netdev->stats.rx_dropped++; - return FALSE; - } - skb_reserve(skb, 1); - skb_put(skb, len - 4 + 1); - skb_copy_to_linear_data(skb, self->rx_buff.data, len - 4 + 1); - st_fifo->tail++; - st_fifo->len++; - if (st_fifo->tail > MAX_RX_WINDOW) - st_fifo->tail = 0; - // Move to next frame - self->rx_buff.data += len; - self->netdev->stats.rx_bytes += len; - self->netdev->stats.rx_packets++; - skb->dev = self->netdev; - skb_reset_mac_header(skb); - skb->protocol = htons(ETH_P_IRDA); - netif_rx(skb); - if (st_fifo->len < (MAX_RX_WINDOW + 2)) { - RXStart(iobase, ON); - } else { - EnableRX(iobase, OFF); - EnRXDMA(iobase, OFF); - RXStart(iobase, OFF); - } - return TRUE; -} - -/* - * Implement back to back receive , use this routine to upload data. - */ - -static int RxTimerHandler(struct via_ircc_cb *self, int iobase) -{ - struct st_fifo *st_fifo; - struct sk_buff *skb; - int len; - u8 status; - - st_fifo = &self->st_fifo; - - if (CkRxRecv(iobase, self)) { - // if still receiving ,then return ,don't upload frame - self->RetryCount = 0; - SetTimer(iobase, 20); - self->RxDataReady++; - return FALSE; - } else - self->RetryCount++; - - if ((self->RetryCount >= 1) || - ((st_fifo->pending_bytes + 2048) > self->rx_buff.truesize) || - (st_fifo->len >= (MAX_RX_WINDOW))) { - while (st_fifo->len > 0) { //upload frame - // Put this entry back in fifo - if (st_fifo->head > MAX_RX_WINDOW) - st_fifo->head = 0; - status = st_fifo->entries[st_fifo->head].status; - len = st_fifo->entries[st_fifo->head].len; - st_fifo->head++; - st_fifo->len--; - - skb = dev_alloc_skb(len + 1 - 4); - /* - * if frame size, data ptr, or skb ptr are wrong, - * then get next entry. - */ - if ((skb == NULL) || (skb->data == NULL) || - (self->rx_buff.data == NULL) || (len < 6)) { - self->netdev->stats.rx_dropped++; - continue; - } - skb_reserve(skb, 1); - skb_put(skb, len - 4); - skb_copy_to_linear_data(skb, self->rx_buff.data, len - 4); - - pr_debug("%s(): len=%x.head=%x\n", __func__, - len - 4, st_fifo->head); - - // Move to next frame - self->rx_buff.data += len; - self->netdev->stats.rx_bytes += len; - self->netdev->stats.rx_packets++; - skb->dev = self->netdev; - skb_reset_mac_header(skb); - skb->protocol = htons(ETH_P_IRDA); - netif_rx(skb); - } //while - self->RetryCount = 0; - - pr_debug("%s(): End of upload HostStatus=%x,RxStatus=%x\n", - __func__, GetHostStatus(iobase), GetRXStatus(iobase)); - - /* - * if frame is receive complete at this routine ,then upload - * frame. - */ - if ((GetRXStatus(iobase) & 0x10) && - (RxCurCount(iobase, self) != self->RxLastCount)) { - upload_rxdata(self, iobase); - if (irda_device_txqueue_empty(self->netdev)) - via_ircc_dma_receive(self); - } - } // timer detect complete - else - SetTimer(iobase, 4); - return TRUE; - -} - - - -/* - * Function via_ircc_interrupt (irq, dev_id) - * - * An interrupt from the chip has arrived. Time to do some work - * - */ -static irqreturn_t via_ircc_interrupt(int dummy, void *dev_id) -{ - struct net_device *dev = dev_id; - struct via_ircc_cb *self = netdev_priv(dev); - int iobase; - u8 iHostIntType, iRxIntType, iTxIntType; - - iobase = self->io.fir_base; - spin_lock(&self->lock); - iHostIntType = GetHostStatus(iobase); - - pr_debug("%s(): iHostIntType %02x: %s %s %s %02x\n", - __func__, iHostIntType, - (iHostIntType & 0x40) ? "Timer" : "", - (iHostIntType & 0x20) ? "Tx" : "", - (iHostIntType & 0x10) ? "Rx" : "", - (iHostIntType & 0x0e) >> 1); - - if ((iHostIntType & 0x40) != 0) { //Timer Event - self->EventFlag.TimeOut++; - ClearTimerInt(iobase, 1); - if (self->io.direction == IO_XMIT) { - via_ircc_dma_xmit(self, iobase); - } - if (self->io.direction == IO_RECV) { - /* - * frame ready hold too long, must reset. - */ - if (self->RxDataReady > 30) { - hwreset(self); - if (irda_device_txqueue_empty(self->netdev)) { - via_ircc_dma_receive(self); - } - } else { // call this to upload frame. - RxTimerHandler(self, iobase); - } - } //RECV - } //Timer Event - if ((iHostIntType & 0x20) != 0) { //Tx Event - iTxIntType = GetTXStatus(iobase); - - pr_debug("%s(): iTxIntType %02x: %s %s %s %s\n", - __func__, iTxIntType, - (iTxIntType & 0x08) ? "FIFO underr." : "", - (iTxIntType & 0x04) ? "EOM" : "", - (iTxIntType & 0x02) ? "FIFO ready" : "", - (iTxIntType & 0x01) ? "Early EOM" : ""); - - if (iTxIntType & 0x4) { - self->EventFlag.EOMessage++; // read and will auto clean - if (via_ircc_dma_xmit_complete(self)) { - if (irda_device_txqueue_empty - (self->netdev)) { - via_ircc_dma_receive(self); - } - } else { - self->EventFlag.Unknown++; - } - } //EOP - } //Tx Event - //---------------------------------------- - if ((iHostIntType & 0x10) != 0) { //Rx Event - /* Check if DMA has finished */ - iRxIntType = GetRXStatus(iobase); - - pr_debug("%s(): iRxIntType %02x: %s %s %s %s %s %s %s\n", - __func__, iRxIntType, - (iRxIntType & 0x80) ? "PHY err." : "", - (iRxIntType & 0x40) ? "CRC err" : "", - (iRxIntType & 0x20) ? "FIFO overr." : "", - (iRxIntType & 0x10) ? "EOF" : "", - (iRxIntType & 0x08) ? "RxData" : "", - (iRxIntType & 0x02) ? "RxMaxLen" : "", - (iRxIntType & 0x01) ? "SIR bad" : ""); - if (!iRxIntType) - pr_debug("%s(): RxIRQ =0\n", __func__); - - if (iRxIntType & 0x10) { - if (via_ircc_dma_receive_complete(self, iobase)) { -//F01 if(!(IsFIROn(iobase))) via_ircc_dma_receive(self); - via_ircc_dma_receive(self); - } - } // No ERR - else { //ERR - pr_debug("%s(): RxIRQ ERR:iRxIntType=%x,HostIntType=%x,CurCount=%x,RxLastCount=%x_____\n", - __func__, iRxIntType, iHostIntType, - RxCurCount(iobase, self), self->RxLastCount); - - if (iRxIntType & 0x20) { //FIFO OverRun ERR - ResetChip(iobase, 0); - ResetChip(iobase, 1); - } else { //PHY,CRC ERR - - if (iRxIntType != 0x08) - hwreset(self); //F01 - } - via_ircc_dma_receive(self); - } //ERR - - } //Rx Event - spin_unlock(&self->lock); - return IRQ_RETVAL(iHostIntType); -} - -static void hwreset(struct via_ircc_cb *self) -{ - int iobase; - iobase = self->io.fir_base; - - ResetChip(iobase, 5); - EnableDMA(iobase, OFF); - EnableTX(iobase, OFF); - EnableRX(iobase, OFF); - EnRXDMA(iobase, OFF); - EnTXDMA(iobase, OFF); - RXStart(iobase, OFF); - TXStart(iobase, OFF); - InitCard(iobase); - CommonInit(iobase); - SIRFilter(iobase, ON); - SetSIR(iobase, ON); - CRC16(iobase, ON); - EnTXCRC(iobase, 0); - WriteReg(iobase, I_ST_CT_0, 0x00); - SetBaudRate(iobase, 9600); - SetPulseWidth(iobase, 12); - SetSendPreambleCount(iobase, 0); - WriteReg(iobase, I_ST_CT_0, 0x80); - - /* Restore speed. */ - via_ircc_change_speed(self, self->io.speed); - - self->st_fifo.len = 0; -} - -/* - * Function via_ircc_is_receiving (self) - * - * Return TRUE is we are currently receiving a frame - * - */ -static int via_ircc_is_receiving(struct via_ircc_cb *self) -{ - int status = FALSE; - int iobase; - - IRDA_ASSERT(self != NULL, return FALSE;); - - iobase = self->io.fir_base; - if (CkRxRecv(iobase, self)) - status = TRUE; - - pr_debug("%s(): status=%x....\n", __func__, status); - - return status; -} - - -/* - * Function via_ircc_net_open (dev) - * - * Start the device - * - */ -static int via_ircc_net_open(struct net_device *dev) -{ - struct via_ircc_cb *self; - int iobase; - char hwname[32]; - - IRDA_ASSERT(dev != NULL, return -1;); - self = netdev_priv(dev); - dev->stats.rx_packets = 0; - IRDA_ASSERT(self != NULL, return 0;); - iobase = self->io.fir_base; - if (request_irq(self->io.irq, via_ircc_interrupt, 0, dev->name, dev)) { - net_warn_ratelimited("%s, unable to allocate irq=%d\n", - driver_name, self->io.irq); - return -EAGAIN; - } - /* - * Always allocate the DMA channel after the IRQ, and clean up on - * failure. - */ - if (request_dma(self->io.dma, dev->name)) { - net_warn_ratelimited("%s, unable to allocate dma=%d\n", - driver_name, self->io.dma); - free_irq(self->io.irq, dev); - return -EAGAIN; - } - if (self->io.dma2 != self->io.dma) { - if (request_dma(self->io.dma2, dev->name)) { - net_warn_ratelimited("%s, unable to allocate dma2=%d\n", - driver_name, self->io.dma2); - free_irq(self->io.irq, dev); - free_dma(self->io.dma); - return -EAGAIN; - } - } - - - /* turn on interrupts */ - EnAllInt(iobase, ON); - EnInternalLoop(iobase, OFF); - EnExternalLoop(iobase, OFF); - - /* */ - via_ircc_dma_receive(self); - - /* Ready to play! */ - netif_start_queue(dev); - - /* - * Open new IrLAP layer instance, now that everything should be - * initialized properly - */ - sprintf(hwname, "VIA @ 0x%x", iobase); - self->irlap = irlap_open(dev, &self->qos, hwname); - - self->RxLastCount = 0; - - return 0; -} - -/* - * Function via_ircc_net_close (dev) - * - * Stop the device - * - */ -static int via_ircc_net_close(struct net_device *dev) -{ - struct via_ircc_cb *self; - int iobase; - - IRDA_ASSERT(dev != NULL, return -1;); - self = netdev_priv(dev); - IRDA_ASSERT(self != NULL, return 0;); - - /* Stop device */ - netif_stop_queue(dev); - /* Stop and remove instance of IrLAP */ - if (self->irlap) - irlap_close(self->irlap); - self->irlap = NULL; - iobase = self->io.fir_base; - EnTXDMA(iobase, OFF); - EnRXDMA(iobase, OFF); - DisableDmaChannel(self->io.dma); - - /* Disable interrupts */ - EnAllInt(iobase, OFF); - free_irq(self->io.irq, dev); - free_dma(self->io.dma); - if (self->io.dma2 != self->io.dma) - free_dma(self->io.dma2); - - return 0; -} - -/* - * Function via_ircc_net_ioctl (dev, rq, cmd) - * - * Process IOCTL commands for this device - * - */ -static int via_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, - int cmd) -{ - struct if_irda_req *irq = (struct if_irda_req *) rq; - struct via_ircc_cb *self; - unsigned long flags; - int ret = 0; - - IRDA_ASSERT(dev != NULL, return -1;); - self = netdev_priv(dev); - IRDA_ASSERT(self != NULL, return -1;); - pr_debug("%s(), %s, (cmd=0x%X)\n", __func__, dev->name, - cmd); - /* Disable interrupts & save flags */ - spin_lock_irqsave(&self->lock, flags); - switch (cmd) { - case SIOCSBANDWIDTH: /* Set bandwidth */ - if (!capable(CAP_NET_ADMIN)) { - ret = -EPERM; - goto out; - } - via_ircc_change_speed(self, irq->ifr_baudrate); - break; - case SIOCSMEDIABUSY: /* Set media busy */ - if (!capable(CAP_NET_ADMIN)) { - ret = -EPERM; - goto out; - } - irda_device_set_media_busy(self->netdev, TRUE); - break; - case SIOCGRECEIVING: /* Check if we are receiving right now */ - irq->ifr_receiving = via_ircc_is_receiving(self); - break; - default: - ret = -EOPNOTSUPP; - } - out: - spin_unlock_irqrestore(&self->lock, flags); - return ret; -} - -MODULE_AUTHOR("VIA Technologies,inc"); -MODULE_DESCRIPTION("VIA IrDA Device Driver"); -MODULE_LICENSE("GPL"); - -module_init(via_ircc_init); -module_exit(via_ircc_cleanup); diff --git a/drivers/net/irda/via-ircc.h b/drivers/net/irda/via-ircc.h deleted file mode 100644 index ac1525573398..000000000000 --- a/drivers/net/irda/via-ircc.h +++ /dev/null @@ -1,846 +0,0 @@ -/********************************************************************* - * - * 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, see <http://www.gnu.org/licenses/>. - - * 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/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; /* Length 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; /* Length 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 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 */ - - spinlock_t lock; /* For serializing operations */ - - __u32 flags; /* Interface flags */ - __u32 new_speed; - int index; /* Instance index */ - - struct eventflag EventFlag; - 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; - } -} - -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 */ diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c deleted file mode 100644 index 6638784c082e..000000000000 --- a/drivers/net/irda/vlsi_ir.c +++ /dev/null @@ -1,1872 +0,0 @@ -/********************************************************************* - * - * vlsi_ir.c: VLSI82C147 PCI IrDA controller driver for Linux - * - * 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, see <http://www.gnu.org/licenses/>. - * - ********************************************************************/ - -#include <linux/module.h> - -#define DRIVER_NAME "vlsi_ir" -#define DRIVER_VERSION "v0.5" -#define DRIVER_DESCRIPTION "IrDA SIR/MIR/FIR driver for VLSI 82C147" -#define DRIVER_AUTHOR "Martin Diehl <info@mdiehl.de>" - -MODULE_DESCRIPTION(DRIVER_DESCRIPTION); -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_LICENSE("GPL"); - -/********************************************************/ - -#include <linux/kernel.h> -#include <linux/ktime.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/pci.h> -#include <linux/slab.h> -#include <linux/netdevice.h> -#include <linux/skbuff.h> -#include <linux/delay.h> -#include <linux/proc_fs.h> -#include <linux/seq_file.h> -#include <linux/math64.h> -#include <linux/mutex.h> -#include <linux/uaccess.h> -#include <asm/byteorder.h> - -#include <net/irda/irda.h> -#include <net/irda/irda_device.h> -#include <net/irda/wrapper.h> -#include <net/irda/crc.h> - -#include "vlsi_ir.h" - -/********************************************************/ - -static /* const */ char drivername[] = DRIVER_NAME; - -static const struct pci_device_id vlsi_irda_table[] = { - { - .class = PCI_CLASS_WIRELESS_IRDA << 8, - .class_mask = PCI_CLASS_SUBCLASS_MASK << 8, - .vendor = PCI_VENDOR_ID_VLSI, - .device = PCI_DEVICE_ID_VLSI_82C147, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - }, - { /* all zeroes */ } -}; - -MODULE_DEVICE_TABLE(pci, vlsi_irda_table); - -/********************************************************/ - -/* clksrc: which clock source to be used - * 0: auto - try PLL, fallback to 40MHz XCLK - * 1: on-chip 48MHz PLL - * 2: external 48MHz XCLK - * 3: external 40MHz XCLK (HP OB-800) - */ - -static int clksrc = 0; /* default is 0(auto) */ -module_param(clksrc, int, 0); -MODULE_PARM_DESC(clksrc, "clock input source selection"); - -/* ringsize: size of the tx and rx descriptor rings - * independent for tx and rx - * specify as ringsize=tx[,rx] - * allowed values: 4, 8, 16, 32, 64 - * Due to the IrDA 1.x max. allowed window size=7, - * there should be no gain when using rings larger than 8 - */ - -static int ringsize[] = {8,8}; /* default is tx=8 / rx=8 */ -module_param_array(ringsize, int, NULL, 0); -MODULE_PARM_DESC(ringsize, "TX, RX ring descriptor size"); - -/* sirpulse: tuning of the SIR pulse width within IrPHY 1.3 limits - * 0: very short, 1.5us (exception: 6us at 2.4 kbaud) - * 1: nominal 3/16 bittime width - * note: IrDA compliant peer devices should be happy regardless - * which one is used. Primary goal is to save some power - * on the sender's side - at 9.6kbaud for example the short - * pulse width saves more than 90% of the transmitted IR power. - */ - -static int sirpulse = 1; /* default is 3/16 bittime */ -module_param(sirpulse, int, 0); -MODULE_PARM_DESC(sirpulse, "SIR pulse width tuning"); - -/* qos_mtt_bits: encoded min-turn-time value we require the peer device - * to use before transmitting to us. "Type 1" (per-station) - * bitfield according to IrLAP definition (section 6.6.8) - * Don't know which transceiver is used by my OB800 - the - * pretty common HP HDLS-1100 requires 1 msec - so lets use this. - */ - -static int qos_mtt_bits = 0x07; /* default is 1 ms or more */ -module_param(qos_mtt_bits, int, 0); -MODULE_PARM_DESC(qos_mtt_bits, "IrLAP bitfield representing min-turn-time"); - -/********************************************************/ - -static void vlsi_reg_debug(unsigned iobase, const char *s) -{ - int i; - - printk(KERN_DEBUG "%s: ", s); - for (i = 0; i < 0x20; i++) - printk("%02x", (unsigned)inb((iobase+i))); - printk("\n"); -} - -static void vlsi_ring_debug(struct vlsi_ring *r) -{ - struct ring_descr *rd; - unsigned i; - - printk(KERN_DEBUG "%s - ring %p / size %u / mask 0x%04x / len %u / dir %d / hw %p\n", - __func__, r, r->size, r->mask, r->len, r->dir, r->rd[0].hw); - printk(KERN_DEBUG "%s - head = %d / tail = %d\n", __func__, - atomic_read(&r->head) & r->mask, atomic_read(&r->tail) & r->mask); - for (i = 0; i < r->size; i++) { - rd = &r->rd[i]; - printk(KERN_DEBUG "%s - ring descr %u: ", __func__, i); - printk("skb=%p data=%p hw=%p\n", rd->skb, rd->buf, rd->hw); - printk(KERN_DEBUG "%s - hw: status=%02x count=%u addr=0x%08x\n", - __func__, (unsigned) rd_get_status(rd), - (unsigned) rd_get_count(rd), (unsigned) rd_get_addr(rd)); - } -} - -/********************************************************/ - -/* needed regardless of CONFIG_PROC_FS */ -static struct proc_dir_entry *vlsi_proc_root = NULL; - -#ifdef CONFIG_PROC_FS - -static void vlsi_proc_pdev(struct seq_file *seq, struct pci_dev *pdev) -{ - unsigned iobase = pci_resource_start(pdev, 0); - unsigned i; - - seq_printf(seq, "\n%s (vid/did: [%04x:%04x])\n", - pci_name(pdev), (int)pdev->vendor, (int)pdev->device); - seq_printf(seq, "pci-power-state: %u\n", (unsigned) pdev->current_state); - seq_printf(seq, "resources: irq=%u / io=0x%04x / dma_mask=0x%016Lx\n", - pdev->irq, (unsigned)pci_resource_start(pdev, 0), (unsigned long long)pdev->dma_mask); - seq_printf(seq, "hw registers: "); - for (i = 0; i < 0x20; i++) - seq_printf(seq, "%02x", (unsigned)inb((iobase+i))); - seq_printf(seq, "\n"); -} - -static void vlsi_proc_ndev(struct seq_file *seq, struct net_device *ndev) -{ - vlsi_irda_dev_t *idev = netdev_priv(ndev); - u8 byte; - u16 word; - s32 sec, usec; - unsigned iobase = ndev->base_addr; - - seq_printf(seq, "\n%s link state: %s / %s / %s / %s\n", ndev->name, - netif_device_present(ndev) ? "attached" : "detached", - netif_running(ndev) ? "running" : "not running", - netif_carrier_ok(ndev) ? "carrier ok" : "no carrier", - netif_queue_stopped(ndev) ? "queue stopped" : "queue running"); - - if (!netif_running(ndev)) - return; - - seq_printf(seq, "\nhw-state:\n"); - pci_read_config_byte(idev->pdev, VLSI_PCI_IRMISC, &byte); - seq_printf(seq, "IRMISC:%s%s%s uart%s", - (byte&IRMISC_IRRAIL) ? " irrail" : "", - (byte&IRMISC_IRPD) ? " irpd" : "", - (byte&IRMISC_UARTTST) ? " uarttest" : "", - (byte&IRMISC_UARTEN) ? "@" : " disabled\n"); - if (byte&IRMISC_UARTEN) { - seq_printf(seq, "0x%s\n", - (byte&2) ? ((byte&1) ? "3e8" : "2e8") - : ((byte&1) ? "3f8" : "2f8")); - } - pci_read_config_byte(idev->pdev, VLSI_PCI_CLKCTL, &byte); - seq_printf(seq, "CLKCTL: PLL %s%s%s / clock %s / wakeup %s\n", - (byte&CLKCTL_PD_INV) ? "powered" : "down", - (byte&CLKCTL_LOCK) ? " locked" : "", - (byte&CLKCTL_EXTCLK) ? ((byte&CLKCTL_XCKSEL)?" / 40 MHz XCLK":" / 48 MHz XCLK") : "", - (byte&CLKCTL_CLKSTP) ? "stopped" : "running", - (byte&CLKCTL_WAKE) ? "enabled" : "disabled"); - pci_read_config_byte(idev->pdev, VLSI_PCI_MSTRPAGE, &byte); - seq_printf(seq, "MSTRPAGE: 0x%02x\n", (unsigned)byte); - - byte = inb(iobase+VLSI_PIO_IRINTR); - seq_printf(seq, "IRINTR:%s%s%s%s%s%s%s%s\n", - (byte&IRINTR_ACTEN) ? " ACTEN" : "", - (byte&IRINTR_RPKTEN) ? " RPKTEN" : "", - (byte&IRINTR_TPKTEN) ? " TPKTEN" : "", - (byte&IRINTR_OE_EN) ? " OE_EN" : "", - (byte&IRINTR_ACTIVITY) ? " ACTIVITY" : "", - (byte&IRINTR_RPKTINT) ? " RPKTINT" : "", - (byte&IRINTR_TPKTINT) ? " TPKTINT" : "", - (byte&IRINTR_OE_INT) ? " OE_INT" : ""); - word = inw(iobase+VLSI_PIO_RINGPTR); - seq_printf(seq, "RINGPTR: rx=%u / tx=%u\n", RINGPTR_GET_RX(word), RINGPTR_GET_TX(word)); - word = inw(iobase+VLSI_PIO_RINGBASE); - seq_printf(seq, "RINGBASE: busmap=0x%08x\n", - ((unsigned)word << 10)|(MSTRPAGE_VALUE<<24)); - word = inw(iobase+VLSI_PIO_RINGSIZE); - seq_printf(seq, "RINGSIZE: rx=%u / tx=%u\n", RINGSIZE_TO_RXSIZE(word), - RINGSIZE_TO_TXSIZE(word)); - - word = inw(iobase+VLSI_PIO_IRCFG); - seq_printf(seq, "IRCFG:%s%s%s%s%s%s%s%s%s%s%s%s%s\n", - (word&IRCFG_LOOP) ? " LOOP" : "", - (word&IRCFG_ENTX) ? " ENTX" : "", - (word&IRCFG_ENRX) ? " ENRX" : "", - (word&IRCFG_MSTR) ? " MSTR" : "", - (word&IRCFG_RXANY) ? " RXANY" : "", - (word&IRCFG_CRC16) ? " CRC16" : "", - (word&IRCFG_FIR) ? " FIR" : "", - (word&IRCFG_MIR) ? " MIR" : "", - (word&IRCFG_SIR) ? " SIR" : "", - (word&IRCFG_SIRFILT) ? " SIRFILT" : "", - (word&IRCFG_SIRTEST) ? " SIRTEST" : "", - (word&IRCFG_TXPOL) ? " TXPOL" : "", - (word&IRCFG_RXPOL) ? " RXPOL" : ""); - word = inw(iobase+VLSI_PIO_IRENABLE); - seq_printf(seq, "IRENABLE:%s%s%s%s%s%s%s%s\n", - (word&IRENABLE_PHYANDCLOCK) ? " PHYANDCLOCK" : "", - (word&IRENABLE_CFGER) ? " CFGERR" : "", - (word&IRENABLE_FIR_ON) ? " FIR_ON" : "", - (word&IRENABLE_MIR_ON) ? " MIR_ON" : "", - (word&IRENABLE_SIR_ON) ? " SIR_ON" : "", - (word&IRENABLE_ENTXST) ? " ENTXST" : "", - (word&IRENABLE_ENRXST) ? " ENRXST" : "", - (word&IRENABLE_CRC16_ON) ? " CRC16_ON" : ""); - word = inw(iobase+VLSI_PIO_PHYCTL); - seq_printf(seq, "PHYCTL: baud-divisor=%u / pulsewidth=%u / preamble=%u\n", - (unsigned)PHYCTL_TO_BAUD(word), - (unsigned)PHYCTL_TO_PLSWID(word), - (unsigned)PHYCTL_TO_PREAMB(word)); - word = inw(iobase+VLSI_PIO_NPHYCTL); - seq_printf(seq, "NPHYCTL: baud-divisor=%u / pulsewidth=%u / preamble=%u\n", - (unsigned)PHYCTL_TO_BAUD(word), - (unsigned)PHYCTL_TO_PLSWID(word), - (unsigned)PHYCTL_TO_PREAMB(word)); - word = inw(iobase+VLSI_PIO_MAXPKT); - seq_printf(seq, "MAXPKT: max. rx packet size = %u\n", word); - word = inw(iobase+VLSI_PIO_RCVBCNT) & RCVBCNT_MASK; - seq_printf(seq, "RCVBCNT: rx-fifo filling level = %u\n", word); - - seq_printf(seq, "\nsw-state:\n"); - seq_printf(seq, "IrPHY setup: %d baud - %s encoding\n", idev->baud, - (idev->mode==IFF_SIR)?"SIR":((idev->mode==IFF_MIR)?"MIR":"FIR")); - sec = div_s64_rem(ktime_us_delta(ktime_get(), idev->last_rx), - USEC_PER_SEC, &usec); - seq_printf(seq, "last rx: %ul.%06u sec\n", sec, usec); - - seq_printf(seq, "RX: packets=%lu / bytes=%lu / errors=%lu / dropped=%lu", - ndev->stats.rx_packets, ndev->stats.rx_bytes, ndev->stats.rx_errors, - ndev->stats.rx_dropped); - seq_printf(seq, " / overrun=%lu / length=%lu / frame=%lu / crc=%lu\n", - ndev->stats.rx_over_errors, ndev->stats.rx_length_errors, - ndev->stats.rx_frame_errors, ndev->stats.rx_crc_errors); - seq_printf(seq, "TX: packets=%lu / bytes=%lu / errors=%lu / dropped=%lu / fifo=%lu\n", - ndev->stats.tx_packets, ndev->stats.tx_bytes, ndev->stats.tx_errors, - ndev->stats.tx_dropped, ndev->stats.tx_fifo_errors); - -} - -static void vlsi_proc_ring(struct seq_file *seq, struct vlsi_ring *r) -{ - struct ring_descr *rd; - unsigned i, j; - int h, t; - - seq_printf(seq, "size %u / mask 0x%04x / len %u / dir %d / hw %p\n", - r->size, r->mask, r->len, r->dir, r->rd[0].hw); - h = atomic_read(&r->head) & r->mask; - t = atomic_read(&r->tail) & r->mask; - seq_printf(seq, "head = %d / tail = %d ", h, t); - if (h == t) - seq_printf(seq, "(empty)\n"); - else { - if (((t+1)&r->mask) == h) - seq_printf(seq, "(full)\n"); - else - seq_printf(seq, "(level = %d)\n", ((unsigned)(t-h) & r->mask)); - rd = &r->rd[h]; - j = (unsigned) rd_get_count(rd); - seq_printf(seq, "current: rd = %d / status = %02x / len = %u\n", - h, (unsigned)rd_get_status(rd), j); - if (j > 0) { - seq_printf(seq, " data: %*ph\n", - min_t(unsigned, j, 20), rd->buf); - } - } - for (i = 0; i < r->size; i++) { - rd = &r->rd[i]; - seq_printf(seq, "> ring descr %u: ", i); - seq_printf(seq, "skb=%p data=%p hw=%p\n", rd->skb, rd->buf, rd->hw); - seq_printf(seq, " hw: status=%02x count=%u busaddr=0x%08x\n", - (unsigned) rd_get_status(rd), - (unsigned) rd_get_count(rd), (unsigned) rd_get_addr(rd)); - } -} - -static int vlsi_seq_show(struct seq_file *seq, void *v) -{ - struct net_device *ndev = seq->private; - vlsi_irda_dev_t *idev = netdev_priv(ndev); - unsigned long flags; - - seq_printf(seq, "\n%s %s\n\n", DRIVER_NAME, DRIVER_VERSION); - seq_printf(seq, "clksrc: %s\n", - (clksrc>=2) ? ((clksrc==3)?"40MHz XCLK":"48MHz XCLK") - : ((clksrc==1)?"48MHz PLL":"autodetect")); - seq_printf(seq, "ringsize: tx=%d / rx=%d\n", - ringsize[0], ringsize[1]); - seq_printf(seq, "sirpulse: %s\n", (sirpulse)?"3/16 bittime":"short"); - seq_printf(seq, "qos_mtt_bits: 0x%02x\n", (unsigned)qos_mtt_bits); - - spin_lock_irqsave(&idev->lock, flags); - if (idev->pdev != NULL) { - vlsi_proc_pdev(seq, idev->pdev); - - if (idev->pdev->current_state == 0) - vlsi_proc_ndev(seq, ndev); - else - seq_printf(seq, "\nPCI controller down - resume_ok = %d\n", - idev->resume_ok); - if (netif_running(ndev) && idev->rx_ring && idev->tx_ring) { - seq_printf(seq, "\n--------- RX ring -----------\n\n"); - vlsi_proc_ring(seq, idev->rx_ring); - seq_printf(seq, "\n--------- TX ring -----------\n\n"); - vlsi_proc_ring(seq, idev->tx_ring); - } - } - seq_printf(seq, "\n"); - spin_unlock_irqrestore(&idev->lock, flags); - - return 0; -} - -static int vlsi_seq_open(struct inode *inode, struct file *file) -{ - return single_open(file, vlsi_seq_show, PDE_DATA(inode)); -} - -static const struct file_operations vlsi_proc_fops = { - .owner = THIS_MODULE, - .open = vlsi_seq_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -#define VLSI_PROC_FOPS (&vlsi_proc_fops) - -#else /* CONFIG_PROC_FS */ -#define VLSI_PROC_FOPS NULL -#endif - -/********************************************************/ - -static struct vlsi_ring *vlsi_alloc_ring(struct pci_dev *pdev, struct ring_descr_hw *hwmap, - unsigned size, unsigned len, int dir) -{ - struct vlsi_ring *r; - struct ring_descr *rd; - unsigned i, j; - dma_addr_t busaddr; - - if (!size || ((size-1)&size)!=0) /* must be >0 and power of 2 */ - return NULL; - - r = kmalloc(sizeof(*r) + size * sizeof(struct ring_descr), GFP_KERNEL); - if (!r) - return NULL; - memset(r, 0, sizeof(*r)); - - r->pdev = pdev; - r->dir = dir; - r->len = len; - r->rd = (struct ring_descr *)(r+1); - r->mask = size - 1; - r->size = size; - atomic_set(&r->head, 0); - atomic_set(&r->tail, 0); - - for (i = 0; i < size; i++) { - rd = r->rd + i; - memset(rd, 0, sizeof(*rd)); - rd->hw = hwmap + i; - rd->buf = kmalloc(len, GFP_KERNEL|GFP_DMA); - if (rd->buf) - busaddr = pci_map_single(pdev, rd->buf, len, dir); - if (rd->buf == NULL || pci_dma_mapping_error(pdev, busaddr)) { - if (rd->buf) { - net_err_ratelimited("%s: failed to create PCI-MAP for %p\n", - __func__, rd->buf); - kfree(rd->buf); - rd->buf = NULL; - } - for (j = 0; j < i; j++) { - rd = r->rd + j; - busaddr = rd_get_addr(rd); - rd_set_addr_status(rd, 0, 0); - pci_unmap_single(pdev, busaddr, len, dir); - kfree(rd->buf); - rd->buf = NULL; - } - kfree(r); - return NULL; - } - rd_set_addr_status(rd, busaddr, 0); - /* initially, the dma buffer is owned by the CPU */ - rd->skb = NULL; - } - return r; -} - -static int vlsi_free_ring(struct vlsi_ring *r) -{ - struct ring_descr *rd; - unsigned i; - dma_addr_t busaddr; - - for (i = 0; i < r->size; i++) { - rd = r->rd + i; - if (rd->skb) - dev_kfree_skb_any(rd->skb); - busaddr = rd_get_addr(rd); - rd_set_addr_status(rd, 0, 0); - if (busaddr) - pci_unmap_single(r->pdev, busaddr, r->len, r->dir); - kfree(rd->buf); - } - kfree(r); - return 0; -} - -static int vlsi_create_hwif(vlsi_irda_dev_t *idev) -{ - char *ringarea; - struct ring_descr_hw *hwmap; - - idev->virtaddr = NULL; - idev->busaddr = 0; - - ringarea = pci_zalloc_consistent(idev->pdev, HW_RING_AREA_SIZE, - &idev->busaddr); - if (!ringarea) - goto out; - - hwmap = (struct ring_descr_hw *)ringarea; - idev->rx_ring = vlsi_alloc_ring(idev->pdev, hwmap, ringsize[1], - XFER_BUF_SIZE, PCI_DMA_FROMDEVICE); - if (idev->rx_ring == NULL) - goto out_unmap; - - hwmap += MAX_RING_DESCR; - idev->tx_ring = vlsi_alloc_ring(idev->pdev, hwmap, ringsize[0], - XFER_BUF_SIZE, PCI_DMA_TODEVICE); - if (idev->tx_ring == NULL) - goto out_free_rx; - - idev->virtaddr = ringarea; - return 0; - -out_free_rx: - vlsi_free_ring(idev->rx_ring); -out_unmap: - idev->rx_ring = idev->tx_ring = NULL; - pci_free_consistent(idev->pdev, HW_RING_AREA_SIZE, ringarea, idev->busaddr); - idev->busaddr = 0; -out: - return -ENOMEM; -} - -static int vlsi_destroy_hwif(vlsi_irda_dev_t *idev) -{ - vlsi_free_ring(idev->rx_ring); - vlsi_free_ring(idev->tx_ring); - idev->rx_ring = idev->tx_ring = NULL; - - if (idev->busaddr) - pci_free_consistent(idev->pdev,HW_RING_AREA_SIZE,idev->virtaddr,idev->busaddr); - - idev->virtaddr = NULL; - idev->busaddr = 0; - - return 0; -} - -/********************************************************/ - -static int vlsi_process_rx(struct vlsi_ring *r, struct ring_descr *rd) -{ - u16 status; - int crclen, len = 0; - struct sk_buff *skb; - int ret = 0; - struct net_device *ndev = pci_get_drvdata(r->pdev); - vlsi_irda_dev_t *idev = netdev_priv(ndev); - - pci_dma_sync_single_for_cpu(r->pdev, rd_get_addr(rd), r->len, r->dir); - /* dma buffer now owned by the CPU */ - status = rd_get_status(rd); - if (status & RD_RX_ERROR) { - if (status & RD_RX_OVER) - ret |= VLSI_RX_OVER; - if (status & RD_RX_LENGTH) - ret |= VLSI_RX_LENGTH; - if (status & RD_RX_PHYERR) - ret |= VLSI_RX_FRAME; - if (status & RD_RX_CRCERR) - ret |= VLSI_RX_CRC; - goto done; - } - - len = rd_get_count(rd); - crclen = (idev->mode==IFF_FIR) ? sizeof(u32) : sizeof(u16); - len -= crclen; /* remove trailing CRC */ - if (len <= 0) { - pr_debug("%s: strange frame (len=%d)\n", __func__, len); - ret |= VLSI_RX_DROP; - goto done; - } - - if (idev->mode == IFF_SIR) { /* hw checks CRC in MIR, FIR mode */ - - /* rd->buf is a streaming PCI_DMA_FROMDEVICE map. Doing the - * endian-adjustment there just in place will dirty a cache line - * which belongs to the map and thus we must be sure it will - * get flushed before giving the buffer back to hardware. - * vlsi_fill_rx() will do this anyway - but here we rely on. - */ - le16_to_cpus(rd->buf+len); - if (irda_calc_crc16(INIT_FCS,rd->buf,len+crclen) != GOOD_FCS) { - pr_debug("%s: crc error\n", __func__); - ret |= VLSI_RX_CRC; - goto done; - } - } - - if (!rd->skb) { - net_warn_ratelimited("%s: rx packet lost\n", __func__); - ret |= VLSI_RX_DROP; - goto done; - } - - skb = rd->skb; - rd->skb = NULL; - skb->dev = ndev; - skb_put_data(skb, rd->buf, len); - skb_reset_mac_header(skb); - if (in_interrupt()) - netif_rx(skb); - else - netif_rx_ni(skb); - -done: - rd_set_status(rd, 0); - rd_set_count(rd, 0); - /* buffer still owned by CPU */ - - return (ret) ? -ret : len; -} - -static void vlsi_fill_rx(struct vlsi_ring *r) -{ - struct ring_descr *rd; - - for (rd = ring_last(r); rd != NULL; rd = ring_put(r)) { - if (rd_is_active(rd)) { - net_warn_ratelimited("%s: driver bug: rx descr race with hw\n", - __func__); - vlsi_ring_debug(r); - break; - } - if (!rd->skb) { - rd->skb = dev_alloc_skb(IRLAP_SKB_ALLOCSIZE); - if (rd->skb) { - skb_reserve(rd->skb,1); - rd->skb->protocol = htons(ETH_P_IRDA); - } - else - break; /* probably not worth logging? */ - } - /* give dma buffer back to busmaster */ - pci_dma_sync_single_for_device(r->pdev, rd_get_addr(rd), r->len, r->dir); - rd_activate(rd); - } -} - -static void vlsi_rx_interrupt(struct net_device *ndev) -{ - vlsi_irda_dev_t *idev = netdev_priv(ndev); - struct vlsi_ring *r = idev->rx_ring; - struct ring_descr *rd; - int ret; - - for (rd = ring_first(r); rd != NULL; rd = ring_get(r)) { - - if (rd_is_active(rd)) - break; - - ret = vlsi_process_rx(r, rd); - - if (ret < 0) { - ret = -ret; - ndev->stats.rx_errors++; - if (ret & VLSI_RX_DROP) - ndev->stats.rx_dropped++; - if (ret & VLSI_RX_OVER) - ndev->stats.rx_over_errors++; - if (ret & VLSI_RX_LENGTH) - ndev->stats.rx_length_errors++; - if (ret & VLSI_RX_FRAME) - ndev->stats.rx_frame_errors++; - if (ret & VLSI_RX_CRC) - ndev->stats.rx_crc_errors++; - } - else if (ret > 0) { - ndev->stats.rx_packets++; - ndev->stats.rx_bytes += ret; - } - } - - idev->last_rx = ktime_get(); /* remember "now" for later mtt delay */ - - vlsi_fill_rx(r); - - if (ring_first(r) == NULL) { - /* we are in big trouble, if this should ever happen */ - net_err_ratelimited("%s: rx ring exhausted!\n", __func__); - vlsi_ring_debug(r); - } - else - outw(0, ndev->base_addr+VLSI_PIO_PROMPT); -} - -/* caller must have stopped the controller from busmastering */ - -static void vlsi_unarm_rx(vlsi_irda_dev_t *idev) -{ - struct net_device *ndev = pci_get_drvdata(idev->pdev); - struct vlsi_ring *r = idev->rx_ring; - struct ring_descr *rd; - int ret; - - for (rd = ring_first(r); rd != NULL; rd = ring_get(r)) { - - ret = 0; - if (rd_is_active(rd)) { - rd_set_status(rd, 0); - if (rd_get_count(rd)) { - pr_debug("%s - dropping rx packet\n", __func__); - ret = -VLSI_RX_DROP; - } - rd_set_count(rd, 0); - pci_dma_sync_single_for_cpu(r->pdev, rd_get_addr(rd), r->len, r->dir); - if (rd->skb) { - dev_kfree_skb_any(rd->skb); - rd->skb = NULL; - } - } - else - ret = vlsi_process_rx(r, rd); - - if (ret < 0) { - ret = -ret; - ndev->stats.rx_errors++; - if (ret & VLSI_RX_DROP) - ndev->stats.rx_dropped++; - if (ret & VLSI_RX_OVER) - ndev->stats.rx_over_errors++; - if (ret & VLSI_RX_LENGTH) - ndev->stats.rx_length_errors++; - if (ret & VLSI_RX_FRAME) - ndev->stats.rx_frame_errors++; - if (ret & VLSI_RX_CRC) - ndev->stats.rx_crc_errors++; - } - else if (ret > 0) { - ndev->stats.rx_packets++; - ndev->stats.rx_bytes += ret; - } - } -} - -/********************************************************/ - -static int vlsi_process_tx(struct vlsi_ring *r, struct ring_descr *rd) -{ - u16 status; - int len; - int ret; - - pci_dma_sync_single_for_cpu(r->pdev, rd_get_addr(rd), r->len, r->dir); - /* dma buffer now owned by the CPU */ - status = rd_get_status(rd); - if (status & RD_TX_UNDRN) - ret = VLSI_TX_FIFO; - else - ret = 0; - rd_set_status(rd, 0); - - if (rd->skb) { - len = rd->skb->len; - dev_kfree_skb_any(rd->skb); - rd->skb = NULL; - } - else /* tx-skb already freed? - should never happen */ - len = rd_get_count(rd); /* incorrect for SIR! (due to wrapping) */ - - rd_set_count(rd, 0); - /* dma buffer still owned by the CPU */ - - return (ret) ? -ret : len; -} - -static int vlsi_set_baud(vlsi_irda_dev_t *idev, unsigned iobase) -{ - u16 nphyctl; - u16 config; - unsigned mode; - int ret; - int baudrate; - int fifocnt; - - baudrate = idev->new_baud; - pr_debug("%s: %d -> %d\n", __func__, idev->baud, idev->new_baud); - if (baudrate == 4000000) { - mode = IFF_FIR; - config = IRCFG_FIR; - nphyctl = PHYCTL_FIR; - } - else if (baudrate == 1152000) { - mode = IFF_MIR; - config = IRCFG_MIR | IRCFG_CRC16; - nphyctl = PHYCTL_MIR(clksrc==3); - } - else { - mode = IFF_SIR; - config = IRCFG_SIR | IRCFG_SIRFILT | IRCFG_RXANY; - switch(baudrate) { - default: - net_warn_ratelimited("%s: undefined baudrate %d - fallback to 9600!\n", - __func__, baudrate); - baudrate = 9600; - /* fallthru */ - case 2400: - case 9600: - case 19200: - case 38400: - case 57600: - case 115200: - nphyctl = PHYCTL_SIR(baudrate,sirpulse,clksrc==3); - break; - } - } - config |= IRCFG_MSTR | IRCFG_ENRX; - - fifocnt = inw(iobase+VLSI_PIO_RCVBCNT) & RCVBCNT_MASK; - if (fifocnt != 0) { - pr_debug("%s: rx fifo not empty(%d)\n", __func__, fifocnt); - } - - outw(0, iobase+VLSI_PIO_IRENABLE); - outw(config, iobase+VLSI_PIO_IRCFG); - outw(nphyctl, iobase+VLSI_PIO_NPHYCTL); - wmb(); - outw(IRENABLE_PHYANDCLOCK, iobase+VLSI_PIO_IRENABLE); - mb(); - - udelay(1); /* chip applies IRCFG on next rising edge of its 8MHz clock */ - - /* read back settings for validation */ - - config = inw(iobase+VLSI_PIO_IRENABLE) & IRENABLE_MASK; - - if (mode == IFF_FIR) - config ^= IRENABLE_FIR_ON; - else if (mode == IFF_MIR) - config ^= (IRENABLE_MIR_ON|IRENABLE_CRC16_ON); - else - config ^= IRENABLE_SIR_ON; - - if (config != (IRENABLE_PHYANDCLOCK|IRENABLE_ENRXST)) { - net_warn_ratelimited("%s: failed to set %s mode!\n", - __func__, - mode == IFF_SIR ? "SIR" : - mode == IFF_MIR ? "MIR" : "FIR"); - ret = -1; - } - else { - if (inw(iobase+VLSI_PIO_PHYCTL) != nphyctl) { - net_warn_ratelimited("%s: failed to apply baudrate %d\n", - __func__, baudrate); - ret = -1; - } - else { - idev->mode = mode; - idev->baud = baudrate; - idev->new_baud = 0; - ret = 0; - } - } - - if (ret) - vlsi_reg_debug(iobase,__func__); - - return ret; -} - -static netdev_tx_t vlsi_hard_start_xmit(struct sk_buff *skb, - struct net_device *ndev) -{ - vlsi_irda_dev_t *idev = netdev_priv(ndev); - struct vlsi_ring *r = idev->tx_ring; - struct ring_descr *rd; - unsigned long flags; - unsigned iobase = ndev->base_addr; - u8 status; - u16 config; - int mtt, diff; - int len, speed; - char *msg = NULL; - - speed = irda_get_next_speed(skb); - spin_lock_irqsave(&idev->lock, flags); - if (speed != -1 && speed != idev->baud) { - netif_stop_queue(ndev); - idev->new_baud = speed; - status = RD_TX_CLRENTX; /* stop tx-ring after this frame */ - } - else - status = 0; - - if (skb->len == 0) { - /* handle zero packets - should be speed change */ - if (status == 0) { - msg = "bogus zero-length packet"; - goto drop_unlock; - } - - /* due to the completely asynch tx operation we might have - * IrLAP racing with the hardware here, f.e. if the controller - * is just sending the last packet with current speed while - * the LAP is already switching the speed using synchronous - * len=0 packet. Immediate execution would lead to hw lockup - * requiring a powercycle to reset. Good candidate to trigger - * this is the final UA:RSP packet after receiving a DISC:CMD - * when getting the LAP down. - * Note that we are not protected by the queue_stop approach - * because the final UA:RSP arrives _without_ request to apply - * new-speed-after-this-packet - hence the driver doesn't know - * this was the last packet and doesn't stop the queue. So the - * forced switch to default speed from LAP gets through as fast - * as only some 10 usec later while the UA:RSP is still processed - * by the hardware and we would get screwed. - */ - - if (ring_first(idev->tx_ring) == NULL) { - /* no race - tx-ring already empty */ - vlsi_set_baud(idev, iobase); - netif_wake_queue(ndev); - } - else - ; - /* keep the speed change pending like it would - * for any len>0 packet. tx completion interrupt - * will apply it when the tx ring becomes empty. - */ - spin_unlock_irqrestore(&idev->lock, flags); - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; - } - - /* sanity checks - simply drop the packet */ - - rd = ring_last(r); - if (!rd) { - msg = "ring full, but queue wasn't stopped"; - goto drop_unlock; - } - - if (rd_is_active(rd)) { - msg = "entry still owned by hw"; - goto drop_unlock; - } - - if (!rd->buf) { - msg = "tx ring entry without pci buffer"; - goto drop_unlock; - } - - if (rd->skb) { - msg = "ring entry with old skb still attached"; - goto drop_unlock; - } - - /* no need for serialization or interrupt disable during mtt */ - spin_unlock_irqrestore(&idev->lock, flags); - - if ((mtt = irda_get_mtt(skb)) > 0) { - diff = ktime_us_delta(ktime_get(), idev->last_rx); - if (mtt > diff) - udelay(mtt - diff); - /* must not sleep here - called under netif_tx_lock! */ - } - - /* tx buffer already owned by CPU due to pci_dma_sync_single_for_cpu() - * after subsequent tx-completion - */ - - if (idev->mode == IFF_SIR) { - status |= RD_TX_DISCRC; /* no hw-crc creation */ - len = async_wrap_skb(skb, rd->buf, r->len); - - /* Some rare worst case situation in SIR mode might lead to - * potential buffer overflow. The wrapper detects this, returns - * with a shortened frame (without FCS/EOF) but doesn't provide - * any error indication about the invalid packet which we are - * going to transmit. - * Therefore we log if the buffer got filled to the point, where the - * wrapper would abort, i.e. when there are less than 5 bytes left to - * allow appending the FCS/EOF. - */ - - if (len >= r->len-5) - net_warn_ratelimited("%s: possible buffer overflow with SIR wrapping!\n", - __func__); - } - else { - /* hw deals with MIR/FIR mode wrapping */ - status |= RD_TX_PULSE; /* send 2 us highspeed indication pulse */ - len = skb->len; - if (len > r->len) { - msg = "frame exceeds tx buffer length"; - goto drop; - } - else - skb_copy_from_linear_data(skb, rd->buf, len); - } - - rd->skb = skb; /* remember skb for tx-complete stats */ - - rd_set_count(rd, len); - rd_set_status(rd, status); /* not yet active! */ - - /* give dma buffer back to busmaster-hw (flush caches to make - * CPU-driven changes visible from the pci bus). - */ - - pci_dma_sync_single_for_device(r->pdev, rd_get_addr(rd), r->len, r->dir); - -/* Switching to TX mode here races with the controller - * which may stop TX at any time when fetching an inactive descriptor - * or one with CLR_ENTX set. So we switch on TX only, if TX was not running - * _after_ the new descriptor was activated on the ring. This ensures - * we will either find TX already stopped or we can be sure, there - * will be a TX-complete interrupt even if the chip stopped doing - * TX just after we found it still running. The ISR will then find - * the non-empty ring and restart TX processing. The enclosing - * spinlock provides the correct serialization to prevent race with isr. - */ - - spin_lock_irqsave(&idev->lock,flags); - - rd_activate(rd); - - if (!(inw(iobase+VLSI_PIO_IRENABLE) & IRENABLE_ENTXST)) { - int fifocnt; - - fifocnt = inw(ndev->base_addr+VLSI_PIO_RCVBCNT) & RCVBCNT_MASK; - if (fifocnt != 0) { - pr_debug("%s: rx fifo not empty(%d)\n", - __func__, fifocnt); - } - - config = inw(iobase+VLSI_PIO_IRCFG); - mb(); - outw(config | IRCFG_ENTX, iobase+VLSI_PIO_IRCFG); - wmb(); - outw(0, iobase+VLSI_PIO_PROMPT); - } - - if (ring_put(r) == NULL) { - netif_stop_queue(ndev); - pr_debug("%s: tx ring full - queue stopped\n", __func__); - } - spin_unlock_irqrestore(&idev->lock, flags); - - return NETDEV_TX_OK; - -drop_unlock: - spin_unlock_irqrestore(&idev->lock, flags); -drop: - net_warn_ratelimited("%s: dropping packet - %s\n", __func__, msg); - dev_kfree_skb_any(skb); - ndev->stats.tx_errors++; - ndev->stats.tx_dropped++; - /* Don't even think about returning NET_XMIT_DROP (=1) here! - * In fact any retval!=0 causes the packet scheduler to requeue the - * packet for later retry of transmission - which isn't exactly - * what we want after we've just called dev_kfree_skb_any ;-) - */ - return NETDEV_TX_OK; -} - -static void vlsi_tx_interrupt(struct net_device *ndev) -{ - vlsi_irda_dev_t *idev = netdev_priv(ndev); - struct vlsi_ring *r = idev->tx_ring; - struct ring_descr *rd; - unsigned iobase; - int ret; - u16 config; - - for (rd = ring_first(r); rd != NULL; rd = ring_get(r)) { - - if (rd_is_active(rd)) - break; - - ret = vlsi_process_tx(r, rd); - - if (ret < 0) { - ret = -ret; - ndev->stats.tx_errors++; - if (ret & VLSI_TX_DROP) - ndev->stats.tx_dropped++; - if (ret & VLSI_TX_FIFO) - ndev->stats.tx_fifo_errors++; - } - else if (ret > 0){ - ndev->stats.tx_packets++; - ndev->stats.tx_bytes += ret; - } - } - - iobase = ndev->base_addr; - - if (idev->new_baud && rd == NULL) /* tx ring empty and speed change pending */ - vlsi_set_baud(idev, iobase); - - config = inw(iobase+VLSI_PIO_IRCFG); - if (rd == NULL) /* tx ring empty: re-enable rx */ - outw((config & ~IRCFG_ENTX) | IRCFG_ENRX, iobase+VLSI_PIO_IRCFG); - - else if (!(inw(iobase+VLSI_PIO_IRENABLE) & IRENABLE_ENTXST)) { - int fifocnt; - - fifocnt = inw(iobase+VLSI_PIO_RCVBCNT) & RCVBCNT_MASK; - if (fifocnt != 0) { - pr_debug("%s: rx fifo not empty(%d)\n", - __func__, fifocnt); - } - outw(config | IRCFG_ENTX, iobase+VLSI_PIO_IRCFG); - } - - outw(0, iobase+VLSI_PIO_PROMPT); - - if (netif_queue_stopped(ndev) && !idev->new_baud) { - netif_wake_queue(ndev); - pr_debug("%s: queue awoken\n", __func__); - } -} - -/* caller must have stopped the controller from busmastering */ - -static void vlsi_unarm_tx(vlsi_irda_dev_t *idev) -{ - struct net_device *ndev = pci_get_drvdata(idev->pdev); - struct vlsi_ring *r = idev->tx_ring; - struct ring_descr *rd; - int ret; - - for (rd = ring_first(r); rd != NULL; rd = ring_get(r)) { - - ret = 0; - if (rd_is_active(rd)) { - rd_set_status(rd, 0); - rd_set_count(rd, 0); - pci_dma_sync_single_for_cpu(r->pdev, rd_get_addr(rd), r->len, r->dir); - if (rd->skb) { - dev_kfree_skb_any(rd->skb); - rd->skb = NULL; - } - pr_debug("%s - dropping tx packet\n", __func__); - ret = -VLSI_TX_DROP; - } - else - ret = vlsi_process_tx(r, rd); - - if (ret < 0) { - ret = -ret; - ndev->stats.tx_errors++; - if (ret & VLSI_TX_DROP) - ndev->stats.tx_dropped++; - if (ret & VLSI_TX_FIFO) - ndev->stats.tx_fifo_errors++; - } - else if (ret > 0){ - ndev->stats.tx_packets++; - ndev->stats.tx_bytes += ret; - } - } - -} - -/********************************************************/ - -static int vlsi_start_clock(struct pci_dev *pdev) -{ - u8 clkctl, lock; - int i, count; - - if (clksrc < 2) { /* auto or PLL: try PLL */ - clkctl = CLKCTL_PD_INV | CLKCTL_CLKSTP; - pci_write_config_byte(pdev, VLSI_PCI_CLKCTL, clkctl); - - /* procedure to detect PLL lock synchronisation: - * after 0.5 msec initial delay we expect to find 3 PLL lock - * indications within 10 msec for successful PLL detection. - */ - udelay(500); - count = 0; - for (i = 500; i <= 10000; i += 50) { /* max 10 msec */ - pci_read_config_byte(pdev, VLSI_PCI_CLKCTL, &lock); - if (lock&CLKCTL_LOCK) { - if (++count >= 3) - break; - } - udelay(50); - } - if (count < 3) { - if (clksrc == 1) { /* explicitly asked for PLL hence bail out */ - net_err_ratelimited("%s: no PLL or failed to lock!\n", - __func__); - clkctl = CLKCTL_CLKSTP; - pci_write_config_byte(pdev, VLSI_PCI_CLKCTL, clkctl); - return -1; - } - else /* was: clksrc=0(auto) */ - clksrc = 3; /* fallback to 40MHz XCLK (OB800) */ - - pr_debug("%s: PLL not locked, fallback to clksrc=%d\n", - __func__, clksrc); - } - else - clksrc = 1; /* got successful PLL lock */ - } - - if (clksrc != 1) { - /* we get here if either no PLL detected in auto-mode or - an external clock source was explicitly specified */ - - clkctl = CLKCTL_EXTCLK | CLKCTL_CLKSTP; - if (clksrc == 3) - clkctl |= CLKCTL_XCKSEL; - pci_write_config_byte(pdev, VLSI_PCI_CLKCTL, clkctl); - - /* no way to test for working XCLK */ - } - else - pci_read_config_byte(pdev, VLSI_PCI_CLKCTL, &clkctl); - - /* ok, now going to connect the chip with the clock source */ - - clkctl &= ~CLKCTL_CLKSTP; - pci_write_config_byte(pdev, VLSI_PCI_CLKCTL, clkctl); - - return 0; -} - -static void vlsi_stop_clock(struct pci_dev *pdev) -{ - u8 clkctl; - - /* disconnect chip from clock source */ - pci_read_config_byte(pdev, VLSI_PCI_CLKCTL, &clkctl); - clkctl |= CLKCTL_CLKSTP; - pci_write_config_byte(pdev, VLSI_PCI_CLKCTL, clkctl); - - /* disable all clock sources */ - clkctl &= ~(CLKCTL_EXTCLK | CLKCTL_PD_INV); - pci_write_config_byte(pdev, VLSI_PCI_CLKCTL, clkctl); -} - -/********************************************************/ - -/* writing all-zero to the VLSI PCI IO register area seems to prevent - * some occasional situations where the hardware fails (symptoms are - * what appears as stalled tx/rx state machines, i.e. everything ok for - * receive or transmit but hw makes no progress or is unable to access - * the bus memory locations). - * Best place to call this is immediately after/before the internal clock - * gets started/stopped. - */ - -static inline void vlsi_clear_regs(unsigned iobase) -{ - unsigned i; - const unsigned chip_io_extent = 32; - - for (i = 0; i < chip_io_extent; i += sizeof(u16)) - outw(0, iobase + i); -} - -static int vlsi_init_chip(struct pci_dev *pdev) -{ - struct net_device *ndev = pci_get_drvdata(pdev); - vlsi_irda_dev_t *idev = netdev_priv(ndev); - unsigned iobase; - u16 ptr; - - /* start the clock and clean the registers */ - - if (vlsi_start_clock(pdev)) { - net_err_ratelimited("%s: no valid clock source\n", __func__); - return -1; - } - iobase = ndev->base_addr; - vlsi_clear_regs(iobase); - - outb(IRINTR_INT_MASK, iobase+VLSI_PIO_IRINTR); /* w/c pending IRQ, disable all INT */ - - outw(0, iobase+VLSI_PIO_IRENABLE); /* disable IrPHY-interface */ - - /* disable everything, particularly IRCFG_MSTR - (also resetting the RING_PTR) */ - - outw(0, iobase+VLSI_PIO_IRCFG); - wmb(); - - outw(MAX_PACKET_LENGTH, iobase+VLSI_PIO_MAXPKT); /* max possible value=0x0fff */ - - outw(BUS_TO_RINGBASE(idev->busaddr), iobase+VLSI_PIO_RINGBASE); - - outw(TX_RX_TO_RINGSIZE(idev->tx_ring->size, idev->rx_ring->size), - iobase+VLSI_PIO_RINGSIZE); - - ptr = inw(iobase+VLSI_PIO_RINGPTR); - atomic_set(&idev->rx_ring->head, RINGPTR_GET_RX(ptr)); - atomic_set(&idev->rx_ring->tail, RINGPTR_GET_RX(ptr)); - atomic_set(&idev->tx_ring->head, RINGPTR_GET_TX(ptr)); - atomic_set(&idev->tx_ring->tail, RINGPTR_GET_TX(ptr)); - - vlsi_set_baud(idev, iobase); /* idev->new_baud used as provided by caller */ - - outb(IRINTR_INT_MASK, iobase+VLSI_PIO_IRINTR); /* just in case - w/c pending IRQ's */ - wmb(); - - /* DO NOT BLINDLY ENABLE IRINTR_ACTEN! - * basically every received pulse fires an ACTIVITY-INT - * leading to >>1000 INT's per second instead of few 10 - */ - - outb(IRINTR_RPKTEN|IRINTR_TPKTEN, iobase+VLSI_PIO_IRINTR); - - return 0; -} - -static int vlsi_start_hw(vlsi_irda_dev_t *idev) -{ - struct pci_dev *pdev = idev->pdev; - struct net_device *ndev = pci_get_drvdata(pdev); - unsigned iobase = ndev->base_addr; - u8 byte; - - /* we don't use the legacy UART, disable its address decoding */ - - pci_read_config_byte(pdev, VLSI_PCI_IRMISC, &byte); - byte &= ~(IRMISC_UARTEN | IRMISC_UARTTST); - pci_write_config_byte(pdev, VLSI_PCI_IRMISC, byte); - - /* enable PCI busmaster access to our 16MB page */ - - pci_write_config_byte(pdev, VLSI_PCI_MSTRPAGE, MSTRPAGE_VALUE); - pci_set_master(pdev); - - if (vlsi_init_chip(pdev) < 0) { - pci_disable_device(pdev); - return -1; - } - - vlsi_fill_rx(idev->rx_ring); - - idev->last_rx = ktime_get(); /* first mtt may start from now on */ - - outw(0, iobase+VLSI_PIO_PROMPT); /* kick hw state machine */ - - return 0; -} - -static int vlsi_stop_hw(vlsi_irda_dev_t *idev) -{ - struct pci_dev *pdev = idev->pdev; - struct net_device *ndev = pci_get_drvdata(pdev); - unsigned iobase = ndev->base_addr; - unsigned long flags; - - spin_lock_irqsave(&idev->lock,flags); - outw(0, iobase+VLSI_PIO_IRENABLE); - outw(0, iobase+VLSI_PIO_IRCFG); /* disable everything */ - - /* disable and w/c irqs */ - outb(0, iobase+VLSI_PIO_IRINTR); - wmb(); - outb(IRINTR_INT_MASK, iobase+VLSI_PIO_IRINTR); - spin_unlock_irqrestore(&idev->lock,flags); - - vlsi_unarm_tx(idev); - vlsi_unarm_rx(idev); - - vlsi_clear_regs(iobase); - vlsi_stop_clock(pdev); - - pci_disable_device(pdev); - - return 0; -} - -/**************************************************************/ - -static void vlsi_tx_timeout(struct net_device *ndev) -{ - vlsi_irda_dev_t *idev = netdev_priv(ndev); - - - vlsi_reg_debug(ndev->base_addr, __func__); - vlsi_ring_debug(idev->tx_ring); - - if (netif_running(ndev)) - netif_stop_queue(ndev); - - vlsi_stop_hw(idev); - - /* now simply restart the whole thing */ - - if (!idev->new_baud) - idev->new_baud = idev->baud; /* keep current baudrate */ - - if (vlsi_start_hw(idev)) - net_err_ratelimited("%s: failed to restart hw - %s(%s) unusable!\n", - __func__, pci_name(idev->pdev), ndev->name); - else - netif_start_queue(ndev); -} - -static int vlsi_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) -{ - vlsi_irda_dev_t *idev = netdev_priv(ndev); - struct if_irda_req *irq = (struct if_irda_req *) rq; - unsigned long flags; - u16 fifocnt; - int ret = 0; - - switch (cmd) { - case SIOCSBANDWIDTH: - if (!capable(CAP_NET_ADMIN)) { - ret = -EPERM; - break; - } - spin_lock_irqsave(&idev->lock, flags); - idev->new_baud = irq->ifr_baudrate; - /* when called from userland there might be a minor race window here - * if the stack tries to change speed concurrently - which would be - * pretty strange anyway with the userland having full control... - */ - vlsi_set_baud(idev, ndev->base_addr); - spin_unlock_irqrestore(&idev->lock, flags); - break; - case SIOCSMEDIABUSY: - if (!capable(CAP_NET_ADMIN)) { - ret = -EPERM; - break; - } - irda_device_set_media_busy(ndev, TRUE); - break; - case SIOCGRECEIVING: - /* the best we can do: check whether there are any bytes in rx fifo. - * The trustable window (in case some data arrives just afterwards) - * may be as short as 1usec or so at 4Mbps. - */ - fifocnt = inw(ndev->base_addr+VLSI_PIO_RCVBCNT) & RCVBCNT_MASK; - irq->ifr_receiving = (fifocnt!=0) ? 1 : 0; - break; - default: - net_warn_ratelimited("%s: notsupp - cmd=%04x\n", - __func__, cmd); - ret = -EOPNOTSUPP; - } - - return ret; -} - -/********************************************************/ - -static irqreturn_t vlsi_interrupt(int irq, void *dev_instance) -{ - struct net_device *ndev = dev_instance; - vlsi_irda_dev_t *idev = netdev_priv(ndev); - unsigned iobase; - u8 irintr; - int boguscount = 5; - unsigned long flags; - int handled = 0; - - iobase = ndev->base_addr; - spin_lock_irqsave(&idev->lock,flags); - do { - irintr = inb(iobase+VLSI_PIO_IRINTR); - mb(); - outb(irintr, iobase+VLSI_PIO_IRINTR); /* acknowledge asap */ - - if (!(irintr&=IRINTR_INT_MASK)) /* not our INT - probably shared */ - break; - - handled = 1; - - if (unlikely(!(irintr & ~IRINTR_ACTIVITY))) - break; /* nothing todo if only activity */ - - if (irintr&IRINTR_RPKTINT) - vlsi_rx_interrupt(ndev); - - if (irintr&IRINTR_TPKTINT) - vlsi_tx_interrupt(ndev); - - } while (--boguscount > 0); - spin_unlock_irqrestore(&idev->lock,flags); - - if (boguscount <= 0) - net_info_ratelimited("%s: too much work in interrupt!\n", - __func__); - return IRQ_RETVAL(handled); -} - -/********************************************************/ - -static int vlsi_open(struct net_device *ndev) -{ - vlsi_irda_dev_t *idev = netdev_priv(ndev); - int err = -EAGAIN; - char hwname[32]; - - if (pci_request_regions(idev->pdev, drivername)) { - net_warn_ratelimited("%s: io resource busy\n", __func__); - goto errout; - } - ndev->base_addr = pci_resource_start(idev->pdev,0); - ndev->irq = idev->pdev->irq; - - /* under some rare occasions the chip apparently comes up with - * IRQ's pending. We better w/c pending IRQ and disable them all - */ - - outb(IRINTR_INT_MASK, ndev->base_addr+VLSI_PIO_IRINTR); - - if (request_irq(ndev->irq, vlsi_interrupt, IRQF_SHARED, - drivername, ndev)) { - net_warn_ratelimited("%s: couldn't get IRQ: %d\n", - __func__, ndev->irq); - goto errout_io; - } - - if ((err = vlsi_create_hwif(idev)) != 0) - goto errout_irq; - - sprintf(hwname, "VLSI-FIR @ 0x%04x", (unsigned)ndev->base_addr); - idev->irlap = irlap_open(ndev,&idev->qos,hwname); - if (!idev->irlap) - goto errout_free_ring; - - idev->last_rx = ktime_get(); /* first mtt may start from now on */ - - idev->new_baud = 9600; /* start with IrPHY using 9600(SIR) mode */ - - if ((err = vlsi_start_hw(idev)) != 0) - goto errout_close_irlap; - - netif_start_queue(ndev); - - net_info_ratelimited("%s: device %s operational\n", - __func__, ndev->name); - - return 0; - -errout_close_irlap: - irlap_close(idev->irlap); -errout_free_ring: - vlsi_destroy_hwif(idev); -errout_irq: - free_irq(ndev->irq,ndev); -errout_io: - pci_release_regions(idev->pdev); -errout: - return err; -} - -static int vlsi_close(struct net_device *ndev) -{ - vlsi_irda_dev_t *idev = netdev_priv(ndev); - - netif_stop_queue(ndev); - - if (idev->irlap) - irlap_close(idev->irlap); - idev->irlap = NULL; - - vlsi_stop_hw(idev); - - vlsi_destroy_hwif(idev); - - free_irq(ndev->irq,ndev); - - pci_release_regions(idev->pdev); - - net_info_ratelimited("%s: device %s stopped\n", __func__, ndev->name); - - return 0; -} - -static const struct net_device_ops vlsi_netdev_ops = { - .ndo_open = vlsi_open, - .ndo_stop = vlsi_close, - .ndo_start_xmit = vlsi_hard_start_xmit, - .ndo_do_ioctl = vlsi_ioctl, - .ndo_tx_timeout = vlsi_tx_timeout, -}; - -static int vlsi_irda_init(struct net_device *ndev) -{ - vlsi_irda_dev_t *idev = netdev_priv(ndev); - struct pci_dev *pdev = idev->pdev; - - ndev->irq = pdev->irq; - ndev->base_addr = pci_resource_start(pdev,0); - - /* PCI busmastering - * see include file for details why we need these 2 masks, in this order! - */ - - if (pci_set_dma_mask(pdev,DMA_MASK_USED_BY_HW) || - pci_set_dma_mask(pdev,DMA_MASK_MSTRPAGE)) { - net_err_ratelimited("%s: aborting due to PCI BM-DMA address limitations\n", - __func__); - return -1; - } - - irda_init_max_qos_capabilies(&idev->qos); - - /* the VLSI82C147 does not support 576000! */ - - idev->qos.baud_rate.bits = IR_2400 | IR_9600 - | IR_19200 | IR_38400 | IR_57600 | IR_115200 - | IR_1152000 | (IR_4000000 << 8); - - idev->qos.min_turn_time.bits = qos_mtt_bits; - - irda_qos_bits_to_value(&idev->qos); - - /* currently no public media definitions for IrDA */ - - ndev->flags |= IFF_PORTSEL | IFF_AUTOMEDIA; - ndev->if_port = IF_PORT_UNKNOWN; - - ndev->netdev_ops = &vlsi_netdev_ops; - ndev->watchdog_timeo = 500*HZ/1000; /* max. allowed turn time for IrLAP */ - - SET_NETDEV_DEV(ndev, &pdev->dev); - - return 0; -} - -/**************************************************************/ - -static int -vlsi_irda_probe(struct pci_dev *pdev, const struct pci_device_id *id) -{ - struct net_device *ndev; - vlsi_irda_dev_t *idev; - - if (pci_enable_device(pdev)) - goto out; - else - pdev->current_state = 0; /* hw must be running now */ - - net_info_ratelimited("%s: IrDA PCI controller %s detected\n", - drivername, pci_name(pdev)); - - if ( !pci_resource_start(pdev,0) || - !(pci_resource_flags(pdev,0) & IORESOURCE_IO) ) { - net_err_ratelimited("%s: bar 0 invalid", __func__); - goto out_disable; - } - - ndev = alloc_irdadev(sizeof(*idev)); - if (ndev==NULL) { - net_err_ratelimited("%s: Unable to allocate device memory.\n", - __func__); - goto out_disable; - } - - idev = netdev_priv(ndev); - - spin_lock_init(&idev->lock); - mutex_init(&idev->mtx); - mutex_lock(&idev->mtx); - idev->pdev = pdev; - - if (vlsi_irda_init(ndev) < 0) - goto out_freedev; - - if (register_netdev(ndev) < 0) { - net_err_ratelimited("%s: register_netdev failed\n", __func__); - goto out_freedev; - } - - if (vlsi_proc_root != NULL) { - struct proc_dir_entry *ent; - - ent = proc_create_data(ndev->name, S_IFREG|S_IRUGO, - vlsi_proc_root, VLSI_PROC_FOPS, ndev); - if (!ent) { - net_warn_ratelimited("%s: failed to create proc entry\n", - __func__); - } else { - proc_set_size(ent, 0); - } - idev->proc_entry = ent; - } - net_info_ratelimited("%s: registered device %s\n", - drivername, ndev->name); - - pci_set_drvdata(pdev, ndev); - mutex_unlock(&idev->mtx); - - return 0; - -out_freedev: - mutex_unlock(&idev->mtx); - free_netdev(ndev); -out_disable: - pci_disable_device(pdev); -out: - return -ENODEV; -} - -static void vlsi_irda_remove(struct pci_dev *pdev) -{ - struct net_device *ndev = pci_get_drvdata(pdev); - vlsi_irda_dev_t *idev; - - if (!ndev) { - net_err_ratelimited("%s: lost netdevice?\n", drivername); - return; - } - - unregister_netdev(ndev); - - idev = netdev_priv(ndev); - mutex_lock(&idev->mtx); - if (idev->proc_entry) { - remove_proc_entry(ndev->name, vlsi_proc_root); - idev->proc_entry = NULL; - } - mutex_unlock(&idev->mtx); - - free_netdev(ndev); - - net_info_ratelimited("%s: %s removed\n", drivername, pci_name(pdev)); -} - -#ifdef CONFIG_PM - -/* The Controller doesn't provide PCI PM capabilities as defined by PCI specs. - * Some of the Linux PCI-PM code however depends on this, for example in - * pci_set_power_state(). So we have to take care to perform the required - * operations on our own (particularly reflecting the pdev->current_state) - * otherwise we might get cheated by pci-pm. - */ - - -static int vlsi_irda_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *ndev = pci_get_drvdata(pdev); - vlsi_irda_dev_t *idev; - - if (!ndev) { - net_err_ratelimited("%s - %s: no netdevice\n", - __func__, pci_name(pdev)); - return 0; - } - idev = netdev_priv(ndev); - mutex_lock(&idev->mtx); - if (pdev->current_state != 0) { /* already suspended */ - if (state.event > pdev->current_state) { /* simply go deeper */ - pci_set_power_state(pdev, pci_choose_state(pdev, state)); - pdev->current_state = state.event; - } - else - net_err_ratelimited("%s - %s: invalid suspend request %u -> %u\n", - __func__, pci_name(pdev), - pdev->current_state, state.event); - mutex_unlock(&idev->mtx); - return 0; - } - - if (netif_running(ndev)) { - netif_device_detach(ndev); - vlsi_stop_hw(idev); - pci_save_state(pdev); - if (!idev->new_baud) - /* remember speed settings to restore on resume */ - idev->new_baud = idev->baud; - } - - pci_set_power_state(pdev, pci_choose_state(pdev, state)); - pdev->current_state = state.event; - idev->resume_ok = 1; - mutex_unlock(&idev->mtx); - return 0; -} - -static int vlsi_irda_resume(struct pci_dev *pdev) -{ - struct net_device *ndev = pci_get_drvdata(pdev); - vlsi_irda_dev_t *idev; - - if (!ndev) { - net_err_ratelimited("%s - %s: no netdevice\n", - __func__, pci_name(pdev)); - return 0; - } - idev = netdev_priv(ndev); - mutex_lock(&idev->mtx); - if (pdev->current_state == 0) { - mutex_unlock(&idev->mtx); - net_warn_ratelimited("%s - %s: already resumed\n", - __func__, pci_name(pdev)); - return 0; - } - - pci_set_power_state(pdev, PCI_D0); - pdev->current_state = PM_EVENT_ON; - - if (!idev->resume_ok) { - /* should be obsolete now - but used to happen due to: - * - pci layer initially setting pdev->current_state = 4 (unknown) - * - pci layer did not walk the save_state-tree (might be APM problem) - * so we could not refuse to suspend from undefined state - * - vlsi_irda_suspend detected invalid state and refused to save - * configuration for resume - but was too late to stop suspending - * - vlsi_irda_resume got screwed when trying to resume from garbage - * - * now we explicitly set pdev->current_state = 0 after enabling the - * device and independently resume_ok should catch any garbage config. - */ - net_warn_ratelimited("%s - hm, nothing to resume?\n", __func__); - mutex_unlock(&idev->mtx); - return 0; - } - - if (netif_running(ndev)) { - pci_restore_state(pdev); - vlsi_start_hw(idev); - netif_device_attach(ndev); - } - idev->resume_ok = 0; - mutex_unlock(&idev->mtx); - return 0; -} - -#endif /* CONFIG_PM */ - -/*********************************************************/ - -static struct pci_driver vlsi_irda_driver = { - .name = drivername, - .id_table = vlsi_irda_table, - .probe = vlsi_irda_probe, - .remove = vlsi_irda_remove, -#ifdef CONFIG_PM - .suspend = vlsi_irda_suspend, - .resume = vlsi_irda_resume, -#endif -}; - -#define PROC_DIR ("driver/" DRIVER_NAME) - -static int __init vlsi_mod_init(void) -{ - int i, ret; - - if (clksrc < 0 || clksrc > 3) { - net_err_ratelimited("%s: invalid clksrc=%d\n", - drivername, clksrc); - return -1; - } - - for (i = 0; i < 2; i++) { - switch(ringsize[i]) { - case 4: - case 8: - case 16: - case 32: - case 64: - break; - default: - net_warn_ratelimited("%s: invalid %s ringsize %d, using default=8\n", - drivername, - i ? "rx" : "tx", - ringsize[i]); - ringsize[i] = 8; - break; - } - } - - sirpulse = !!sirpulse; - - /* proc_mkdir returns NULL if !CONFIG_PROC_FS. - * Failure to create the procfs entry is handled like running - * without procfs - it's not required for the driver to work. - */ - vlsi_proc_root = proc_mkdir(PROC_DIR, NULL); - - ret = pci_register_driver(&vlsi_irda_driver); - - if (ret && vlsi_proc_root) - remove_proc_entry(PROC_DIR, NULL); - return ret; - -} - -static void __exit vlsi_mod_exit(void) -{ - pci_unregister_driver(&vlsi_irda_driver); - if (vlsi_proc_root) - remove_proc_entry(PROC_DIR, NULL); -} - -module_init(vlsi_mod_init); -module_exit(vlsi_mod_exit); diff --git a/drivers/net/irda/vlsi_ir.h b/drivers/net/irda/vlsi_ir.h deleted file mode 100644 index f9db2ce4c5c6..000000000000 --- a/drivers/net/irda/vlsi_ir.h +++ /dev/null @@ -1,757 +0,0 @@ - -/********************************************************************* - * - * 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, see <http://www.gnu.org/licenses/>. - * - ********************************************************************/ - -#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 - -/* ================================================================ */ - -/* 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 transferred 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 __le16 rd_count; /* tx/rx count [11:0] */ - __le16 reserved; - union { - __le32 addr; /* [23:0] of the buffer's busaddress */ - struct { - u8 addr_res[3]; - volatile u8 status; /* descriptor status */ - } __packed rd_s; - } __packed rd_u; -} __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) { - net_err_ratelimited("%s: pci busaddr inconsistency!\n", - __func__); - 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 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; - - ktime_t last_rx; - - spinlock_t lock; - struct mutex mtx; - - 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 transferred 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 */ - diff --git a/drivers/net/irda/w83977af.h b/drivers/net/irda/w83977af.h deleted file mode 100644 index 04476c2e9121..000000000000 --- a/drivers/net/irda/w83977af.h +++ /dev/null @@ -1,53 +0,0 @@ -#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 diff --git a/drivers/net/irda/w83977af_ir.c b/drivers/net/irda/w83977af_ir.c deleted file mode 100644 index 282b6c9ae05b..000000000000 --- a/drivers/net/irda/w83977af_ir.c +++ /dev/null @@ -1,1285 +0,0 @@ -/********************************************************************* - * - * Filename: w83977af_ir.c - * Version: 1.0 - * Description: FIR driver for the Winbond W83977AF Super I/O chip - * Status: Experimental. - * Author: Paul VanderSpek - * Created at: Wed Nov 4 11:46:16 1998 - * Modified at: Fri Jan 28 12:10:59 2000 - * Modified by: Dag Brattli <dagb@cs.uit.no> - * - * Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no> - * Copyright (c) 1998-1999 Rebel.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. - * - * Neither Paul VanderSpek nor Rebel.com admit liability nor provide - * warranty for any of this software. This material is provided "AS-IS" - * and at no charge. - * - * If you find bugs in this file, its very likely that the same bug - * will also be in pc87108.c since the implementations are quite - * similar. - * - * Notice that all functions that needs to access the chip in _any_ - * way, must save BSR register on entry, and restore it on exit. - * It is _very_ important to follow this policy! - * - * __u8 bank; - * - * bank = inb( iobase+BSR); - * - * do_your_stuff_here(); - * - * outb( bank, iobase+BSR); - * - ********************************************************************/ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/skbuff.h> -#include <linux/netdevice.h> -#include <linux/ioport.h> -#include <linux/delay.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/rtnetlink.h> -#include <linux/dma-mapping.h> -#include <linux/gfp.h> - -#include <asm/io.h> -#include <asm/dma.h> -#include <asm/byteorder.h> - -#include <net/irda/irda.h> -#include <net/irda/wrapper.h> -#include <net/irda/irda_device.h> -#include "w83977af.h" -#include "w83977af_ir.h" - -#define CONFIG_USE_W977_PNP /* Currently needed */ -#define PIO_MAX_SPEED 115200 - -static char *driver_name = "w83977af_ir"; -static int qos_mtt_bits = 0x07; /* 1 ms or more */ - -#define CHIP_IO_EXTENT 8 - -static unsigned int io[] = { 0x180, ~0, ~0, ~0 }; -#ifdef CONFIG_ARCH_NETWINDER /* Adjust to NetWinder differences */ -static unsigned int irq[] = { 6, 0, 0, 0 }; -#else -static unsigned int irq[] = { 11, 0, 0, 0 }; -#endif -static unsigned int dma[] = { 1, 0, 0, 0 }; -static unsigned int efbase[] = { W977_EFIO_BASE, W977_EFIO2_BASE }; -static unsigned int efio = W977_EFIO_BASE; - -static struct w83977af_ir *dev_self[] = { NULL, NULL, NULL, NULL}; - -/* Some prototypes */ -static int w83977af_open(int i, unsigned int iobase, unsigned int irq, - unsigned int dma); -static int w83977af_close(struct w83977af_ir *self); -static int w83977af_probe(int iobase, int irq, int dma); -static int w83977af_dma_receive(struct w83977af_ir *self); -static int w83977af_dma_receive_complete(struct w83977af_ir *self); -static netdev_tx_t w83977af_hard_xmit(struct sk_buff *skb, - struct net_device *dev); -static int w83977af_pio_write(int iobase, __u8 *buf, int len, int fifo_size); -static void w83977af_dma_write(struct w83977af_ir *self, int iobase); -static void w83977af_change_speed(struct w83977af_ir *self, __u32 speed); -static int w83977af_is_receiving(struct w83977af_ir *self); - -static int w83977af_net_open(struct net_device *dev); -static int w83977af_net_close(struct net_device *dev); -static int w83977af_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); - -/* - * Function w83977af_init () - * - * Initialize chip. Just try to find out how many chips we are dealing with - * and where they are - */ -static int __init w83977af_init(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(dev_self) && io[i] < 2000; i++) { - if (w83977af_open(i, io[i], irq[i], dma[i]) == 0) - return 0; - } - return -ENODEV; -} - -/* - * Function w83977af_cleanup () - * - * Close all configured chips - * - */ -static void __exit w83977af_cleanup(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(dev_self); i++) { - if (dev_self[i]) - w83977af_close(dev_self[i]); - } -} - -static const struct net_device_ops w83977_netdev_ops = { - .ndo_open = w83977af_net_open, - .ndo_stop = w83977af_net_close, - .ndo_start_xmit = w83977af_hard_xmit, - .ndo_do_ioctl = w83977af_net_ioctl, -}; - -/* - * Function w83977af_open (iobase, irq) - * - * Open driver instance - * - */ -static int w83977af_open(int i, unsigned int iobase, unsigned int irq, - unsigned int dma) -{ - struct net_device *dev; - struct w83977af_ir *self; - int err; - - /* Lock the port that we need */ - if (!request_region(iobase, CHIP_IO_EXTENT, driver_name)) { - pr_debug("%s: can't get iobase of 0x%03x\n", - __func__, iobase); - return -ENODEV; - } - - if (w83977af_probe(iobase, irq, dma) == -1) { - err = -1; - goto err_out; - } - /* - * Allocate new instance of the driver - */ - dev = alloc_irdadev(sizeof(struct w83977af_ir)); - if (!dev) { - pr_err("IrDA: Can't allocate memory for IrDA control block!\n"); - err = -ENOMEM; - goto err_out; - } - - self = netdev_priv(dev); - spin_lock_init(&self->lock); - - /* Initialize IO */ - self->io.fir_base = iobase; - self->io.irq = irq; - self->io.fir_ext = CHIP_IO_EXTENT; - self->io.dma = dma; - self->io.fifo_size = 32; - - /* Initialize QoS for this device */ - irda_init_max_qos_capabilies(&self->qos); - - /* The only value we must override it the baudrate */ - - /* FIXME: The HP HDLS-1100 does not support 1152000! */ - self->qos.baud_rate.bits = IR_9600 | IR_19200 | IR_38400 | IR_57600 | - IR_115200 | IR_576000 | IR_1152000 | (IR_4000000 << 8); - - /* The HP HDLS-1100 needs 1 ms according to the specs */ - self->qos.min_turn_time.bits = qos_mtt_bits; - irda_qos_bits_to_value(&self->qos); - - /* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */ - self->rx_buff.truesize = 14384; - self->tx_buff.truesize = 4000; - - /* Allocate memory if needed */ - self->rx_buff.head = - dma_zalloc_coherent(NULL, self->rx_buff.truesize, - &self->rx_buff_dma, GFP_KERNEL); - if (!self->rx_buff.head) { - err = -ENOMEM; - goto err_out1; - } - - self->tx_buff.head = - dma_zalloc_coherent(NULL, self->tx_buff.truesize, - &self->tx_buff_dma, GFP_KERNEL); - if (!self->tx_buff.head) { - err = -ENOMEM; - goto err_out2; - } - - self->rx_buff.in_frame = FALSE; - self->rx_buff.state = OUTSIDE_FRAME; - self->tx_buff.data = self->tx_buff.head; - self->rx_buff.data = self->rx_buff.head; - self->netdev = dev; - - dev->netdev_ops = &w83977_netdev_ops; - - err = register_netdev(dev); - if (err) { - net_err_ratelimited("%s:, register_netdevice() failed!\n", - __func__); - goto err_out3; - } - net_info_ratelimited("IrDA: Registered device %s\n", dev->name); - - /* Need to store self somewhere */ - dev_self[i] = self; - - return 0; -err_out3: - dma_free_coherent(NULL, self->tx_buff.truesize, - self->tx_buff.head, self->tx_buff_dma); -err_out2: - dma_free_coherent(NULL, self->rx_buff.truesize, - self->rx_buff.head, self->rx_buff_dma); -err_out1: - free_netdev(dev); -err_out: - release_region(iobase, CHIP_IO_EXTENT); - return err; -} - -/* - * Function w83977af_close (self) - * - * Close driver instance - * - */ -static int w83977af_close(struct w83977af_ir *self) -{ - int iobase; - - iobase = self->io.fir_base; - -#ifdef CONFIG_USE_W977_PNP - /* enter PnP configuration mode */ - w977_efm_enter(efio); - - w977_select_device(W977_DEVICE_IR, efio); - - /* Deactivate device */ - w977_write_reg(0x30, 0x00, efio); - - w977_efm_exit(efio); -#endif /* CONFIG_USE_W977_PNP */ - - /* Remove netdevice */ - unregister_netdev(self->netdev); - - /* Release the PORT that this driver is using */ - pr_debug("%s: Releasing Region %03x\n", __func__, self->io.fir_base); - release_region(self->io.fir_base, self->io.fir_ext); - - if (self->tx_buff.head) - dma_free_coherent(NULL, self->tx_buff.truesize, - self->tx_buff.head, self->tx_buff_dma); - - if (self->rx_buff.head) - dma_free_coherent(NULL, self->rx_buff.truesize, - self->rx_buff.head, self->rx_buff_dma); - - free_netdev(self->netdev); - - return 0; -} - -static int w83977af_probe(int iobase, int irq, int dma) -{ - int version; - int i; - - for (i = 0; i < 2; i++) { -#ifdef CONFIG_USE_W977_PNP - /* Enter PnP configuration mode */ - w977_efm_enter(efbase[i]); - - w977_select_device(W977_DEVICE_IR, efbase[i]); - - /* Configure PnP port, IRQ, and DMA channel */ - w977_write_reg(0x60, (iobase >> 8) & 0xff, efbase[i]); - w977_write_reg(0x61, (iobase) & 0xff, efbase[i]); - - w977_write_reg(0x70, irq, efbase[i]); -#ifdef CONFIG_ARCH_NETWINDER - /* Netwinder uses 1 higher than Linux */ - w977_write_reg(0x74, dma + 1, efbase[i]); -#else - w977_write_reg(0x74, dma, efbase[i]); -#endif /* CONFIG_ARCH_NETWINDER */ - w977_write_reg(0x75, 0x04, efbase[i]);/* Disable Tx DMA */ - - /* Set append hardware CRC, enable IR bank selection */ - w977_write_reg(0xf0, APEDCRC | ENBNKSEL, efbase[i]); - - /* Activate device */ - w977_write_reg(0x30, 0x01, efbase[i]); - - w977_efm_exit(efbase[i]); -#endif /* CONFIG_USE_W977_PNP */ - /* Disable Advanced mode */ - switch_bank(iobase, SET2); - outb(iobase + 2, 0x00); - - /* Turn on UART (global) interrupts */ - switch_bank(iobase, SET0); - outb(HCR_EN_IRQ, iobase + HCR); - - /* Switch to advanced mode */ - switch_bank(iobase, SET2); - outb(inb(iobase + ADCR1) | ADCR1_ADV_SL, iobase + ADCR1); - - /* Set default IR-mode */ - switch_bank(iobase, SET0); - outb(HCR_SIR, iobase + HCR); - - /* Read the Advanced IR ID */ - switch_bank(iobase, SET3); - version = inb(iobase + AUID); - - /* Should be 0x1? */ - if (0x10 == (version & 0xf0)) { - efio = efbase[i]; - - /* Set FIFO size to 32 */ - switch_bank(iobase, SET2); - outb(ADCR2_RXFS32 | ADCR2_TXFS32, iobase + ADCR2); - - /* Set FIFO threshold to TX17, RX16 */ - switch_bank(iobase, SET0); - outb(UFR_RXTL | UFR_TXTL | UFR_TXF_RST | UFR_RXF_RST | - UFR_EN_FIFO, iobase + UFR); - - /* Receiver frame length */ - switch_bank(iobase, SET4); - outb(2048 & 0xff, iobase + 6); - outb((2048 >> 8) & 0x1f, iobase + 7); - - /* - * Init HP HSDL-1100 transceiver. - * - * Set IRX_MSL since we have 2 * receive paths IRRX, - * and IRRXH. Clear IRSL0D since we want IRSL0 * to - * be a input pin used for IRRXH - * - * IRRX pin 37 connected to receiver - * IRTX pin 38 connected to transmitter - * FIRRX pin 39 connected to receiver (IRSL0) - * CIRRX pin 40 connected to pin 37 - */ - switch_bank(iobase, SET7); - outb(0x40, iobase + 7); - - net_info_ratelimited("W83977AF (IR) driver loaded. Version: 0x%02x\n", - version); - - return 0; - } else { - /* Try next extented function register address */ - pr_debug("%s: Wrong chip version\n", __func__); - } - } - return -1; -} - -static void w83977af_change_speed(struct w83977af_ir *self, __u32 speed) -{ - int ir_mode = HCR_SIR; - int iobase; - __u8 set; - - iobase = self->io.fir_base; - - /* Update accounting for new speed */ - self->io.speed = speed; - - /* Save current bank */ - set = inb(iobase + SSR); - - /* Disable interrupts */ - switch_bank(iobase, SET0); - outb(0, iobase + ICR); - - /* Select Set 2 */ - switch_bank(iobase, SET2); - outb(0x00, iobase + ABHL); - - switch (speed) { - case 9600: outb(0x0c, iobase + ABLL); break; - case 19200: outb(0x06, iobase + ABLL); break; - case 38400: outb(0x03, iobase + ABLL); break; - case 57600: outb(0x02, iobase + ABLL); break; - case 115200: outb(0x01, iobase + ABLL); break; - case 576000: - ir_mode = HCR_MIR_576; - pr_debug("%s: handling baud of 576000\n", __func__); - break; - case 1152000: - ir_mode = HCR_MIR_1152; - pr_debug("%s: handling baud of 1152000\n", __func__); - break; - case 4000000: - ir_mode = HCR_FIR; - pr_debug("%s: handling baud of 4000000\n", __func__); - break; - default: - ir_mode = HCR_FIR; - pr_debug("%s: unknown baud rate of %d\n", __func__, speed); - break; - } - - /* Set speed mode */ - switch_bank(iobase, SET0); - outb(ir_mode, iobase + HCR); - - /* set FIFO size to 32 */ - switch_bank(iobase, SET2); - outb(ADCR2_RXFS32 | ADCR2_TXFS32, iobase + ADCR2); - - /* set FIFO threshold to TX17, RX16 */ - switch_bank(iobase, SET0); - outb(0x00, iobase + UFR); /* Reset */ - outb(UFR_EN_FIFO, iobase + UFR); /* First we must enable FIFO */ - outb(0xa7, iobase + UFR); - - netif_wake_queue(self->netdev); - - /* Enable some interrupts so we can receive frames */ - switch_bank(iobase, SET0); - if (speed > PIO_MAX_SPEED) { - outb(ICR_EFSFI, iobase + ICR); - w83977af_dma_receive(self); - } else { - outb(ICR_ERBRI, iobase + ICR); - } - - /* Restore SSR */ - outb(set, iobase + SSR); -} - -/* - * Function w83977af_hard_xmit (skb, dev) - * - * Sets up a DMA transfer to send the current frame. - * - */ -static netdev_tx_t w83977af_hard_xmit(struct sk_buff *skb, - struct net_device *dev) -{ - struct w83977af_ir *self; - __s32 speed; - int iobase; - __u8 set; - int mtt; - - self = netdev_priv(dev); - - iobase = self->io.fir_base; - - pr_debug("%s: %ld, skb->len=%d\n", __func__, jiffies, (int)skb->len); - - /* Lock transmit buffer */ - netif_stop_queue(dev); - - /* Check if we need to change the speed */ - speed = irda_get_next_speed(skb); - if ((speed != self->io.speed) && (speed != -1)) { - /* Check for empty frame */ - if (!skb->len) { - w83977af_change_speed(self, speed); - dev_kfree_skb(skb); - return NETDEV_TX_OK; - } - self->new_speed = speed; - } - - /* Save current set */ - set = inb(iobase + SSR); - - /* Decide if we should use PIO or DMA transfer */ - if (self->io.speed > PIO_MAX_SPEED) { - self->tx_buff.data = self->tx_buff.head; - skb_copy_from_linear_data(skb, self->tx_buff.data, skb->len); - self->tx_buff.len = skb->len; - - mtt = irda_get_mtt(skb); - pr_debug("%s: %ld, mtt=%d\n", __func__, jiffies, mtt); - if (mtt > 1000) - mdelay(mtt / 1000); - else if (mtt) - udelay(mtt); - - /* Enable DMA interrupt */ - switch_bank(iobase, SET0); - outb(ICR_EDMAI, iobase + ICR); - w83977af_dma_write(self, iobase); - } else { - self->tx_buff.data = self->tx_buff.head; - self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data, - self->tx_buff.truesize); - - /* Add interrupt on tx low level (will fire immediately) */ - switch_bank(iobase, SET0); - outb(ICR_ETXTHI, iobase + ICR); - } - dev_kfree_skb(skb); - - /* Restore set register */ - outb(set, iobase + SSR); - - return NETDEV_TX_OK; -} - -/* - * Function w83977af_dma_write (self, iobase) - * - * Send frame using DMA - * - */ -static void w83977af_dma_write(struct w83977af_ir *self, int iobase) -{ - __u8 set; - - pr_debug("%s: len=%d\n", __func__, self->tx_buff.len); - - /* Save current set */ - set = inb(iobase + SSR); - - /* Disable DMA */ - switch_bank(iobase, SET0); - outb(inb(iobase + HCR) & ~HCR_EN_DMA, iobase + HCR); - - /* Choose transmit DMA channel */ - switch_bank(iobase, SET2); - outb(ADCR1_D_CHSW | /*ADCR1_DMA_F|*/ADCR1_ADV_SL, iobase + ADCR1); - irda_setup_dma(self->io.dma, self->tx_buff_dma, self->tx_buff.len, - DMA_MODE_WRITE); - self->io.direction = IO_XMIT; - - /* Enable DMA */ - switch_bank(iobase, SET0); - outb(inb(iobase + HCR) | HCR_EN_DMA | HCR_TX_WT, iobase + HCR); - - /* Restore set register */ - outb(set, iobase + SSR); -} - -/* - * Function w83977af_pio_write (iobase, buf, len, fifo_size) - * - * - * - */ -static int w83977af_pio_write(int iobase, __u8 *buf, int len, int fifo_size) -{ - int actual = 0; - __u8 set; - - /* Save current bank */ - set = inb(iobase + SSR); - - switch_bank(iobase, SET0); - if (!(inb_p(iobase + USR) & USR_TSRE)) { - pr_debug("%s: warning, FIFO not empty yet!\n", __func__); - - fifo_size -= 17; - pr_debug("%s: %d bytes left in tx fifo\n", __func__, fifo_size); - } - - /* Fill FIFO with current frame */ - while ((fifo_size-- > 0) && (actual < len)) { - /* Transmit next byte */ - outb(buf[actual++], iobase + TBR); - } - - pr_debug("%s: fifo_size %d ; %d sent of %d\n", - __func__, fifo_size, actual, len); - - /* Restore bank */ - outb(set, iobase + SSR); - - return actual; -} - -/* - * Function w83977af_dma_xmit_complete (self) - * - * The transfer of a frame in finished. So do the necessary things - * - * - */ -static void w83977af_dma_xmit_complete(struct w83977af_ir *self) -{ - int iobase; - __u8 set; - - pr_debug("%s: %ld\n", __func__, jiffies); - - IRDA_ASSERT(self, return;); - - iobase = self->io.fir_base; - - /* Save current set */ - set = inb(iobase + SSR); - - /* Disable DMA */ - switch_bank(iobase, SET0); - outb(inb(iobase + HCR) & ~HCR_EN_DMA, iobase + HCR); - - /* Check for underrun! */ - if (inb(iobase + AUDR) & AUDR_UNDR) { - pr_debug("%s: Transmit underrun!\n", __func__); - - self->netdev->stats.tx_errors++; - self->netdev->stats.tx_fifo_errors++; - - /* Clear bit, by writing 1 to it */ - outb(AUDR_UNDR, iobase + AUDR); - } else { - self->netdev->stats.tx_packets++; - } - - if (self->new_speed) { - w83977af_change_speed(self, self->new_speed); - self->new_speed = 0; - } - - /* Unlock tx_buff and request another frame */ - /* Tell the network layer, that we want more frames */ - netif_wake_queue(self->netdev); - - /* Restore set */ - outb(set, iobase + SSR); -} - -/* - * Function w83977af_dma_receive (self) - * - * Get ready for receiving a frame. The device will initiate a DMA - * if it starts to receive a frame. - * - */ -static int w83977af_dma_receive(struct w83977af_ir *self) -{ - int iobase; - __u8 set; -#ifdef CONFIG_ARCH_NETWINDER - unsigned long flags; - __u8 hcr; -#endif - IRDA_ASSERT(self, return -1;); - - pr_debug("%s\n", __func__); - - iobase = self->io.fir_base; - - /* Save current set */ - set = inb(iobase + SSR); - - /* Disable DMA */ - switch_bank(iobase, SET0); - outb(inb(iobase + HCR) & ~HCR_EN_DMA, iobase + HCR); - - /* Choose DMA Rx, DMA Fairness, and Advanced mode */ - switch_bank(iobase, SET2); - outb((inb(iobase + ADCR1) & ~ADCR1_D_CHSW)/*|ADCR1_DMA_F*/ | ADCR1_ADV_SL, - iobase + ADCR1); - - self->io.direction = IO_RECV; - self->rx_buff.data = self->rx_buff.head; - -#ifdef CONFIG_ARCH_NETWINDER - spin_lock_irqsave(&self->lock, flags); - - disable_dma(self->io.dma); - clear_dma_ff(self->io.dma); - set_dma_mode(self->io.dma, DMA_MODE_READ); - set_dma_addr(self->io.dma, self->rx_buff_dma); - set_dma_count(self->io.dma, self->rx_buff.truesize); -#else - irda_setup_dma(self->io.dma, self->rx_buff_dma, self->rx_buff.truesize, - DMA_MODE_READ); -#endif - /* - * Reset Rx FIFO. This will also flush the ST_FIFO, it's very - * important that we don't reset the Tx FIFO since it might not - * be finished transmitting yet - */ - switch_bank(iobase, SET0); - outb(UFR_RXTL | UFR_TXTL | UFR_RXF_RST | UFR_EN_FIFO, iobase + UFR); - self->st_fifo.len = self->st_fifo.tail = self->st_fifo.head = 0; - - /* Enable DMA */ - switch_bank(iobase, SET0); -#ifdef CONFIG_ARCH_NETWINDER - hcr = inb(iobase + HCR); - outb(hcr | HCR_EN_DMA, iobase + HCR); - enable_dma(self->io.dma); - spin_unlock_irqrestore(&self->lock, flags); -#else - outb(inb(iobase + HCR) | HCR_EN_DMA, iobase + HCR); -#endif - /* Restore set */ - outb(set, iobase + SSR); - - return 0; -} - -/* - * Function w83977af_receive_complete (self) - * - * Finished with receiving a frame - * - */ -static int w83977af_dma_receive_complete(struct w83977af_ir *self) -{ - struct sk_buff *skb; - struct st_fifo *st_fifo; - int len; - int iobase; - __u8 set; - __u8 status; - - pr_debug("%s\n", __func__); - - st_fifo = &self->st_fifo; - - iobase = self->io.fir_base; - - /* Save current set */ - set = inb(iobase + SSR); - - iobase = self->io.fir_base; - - /* Read status FIFO */ - switch_bank(iobase, SET5); - while ((status = inb(iobase + FS_FO)) & FS_FO_FSFDR) { - st_fifo->entries[st_fifo->tail].status = status; - - st_fifo->entries[st_fifo->tail].len = inb(iobase + RFLFL); - st_fifo->entries[st_fifo->tail].len |= inb(iobase + RFLFH) << 8; - - st_fifo->tail++; - st_fifo->len++; - } - - while (st_fifo->len) { - /* Get first entry */ - status = st_fifo->entries[st_fifo->head].status; - len = st_fifo->entries[st_fifo->head].len; - st_fifo->head++; - st_fifo->len--; - - /* Check for errors */ - if (status & FS_FO_ERR_MSK) { - if (status & FS_FO_LST_FR) { - /* Add number of lost frames to stats */ - self->netdev->stats.rx_errors += len; - } else { - /* Skip frame */ - self->netdev->stats.rx_errors++; - - self->rx_buff.data += len; - - if (status & FS_FO_MX_LEX) - self->netdev->stats.rx_length_errors++; - - if (status & FS_FO_PHY_ERR) - self->netdev->stats.rx_frame_errors++; - - if (status & FS_FO_CRC_ERR) - self->netdev->stats.rx_crc_errors++; - } - /* The errors below can be reported in both cases */ - if (status & FS_FO_RX_OV) - self->netdev->stats.rx_fifo_errors++; - - if (status & FS_FO_FSF_OV) - self->netdev->stats.rx_fifo_errors++; - - } else { - /* Check if we have transferred all data to memory */ - switch_bank(iobase, SET0); - if (inb(iobase + USR) & USR_RDR) - udelay(80); /* Should be enough!? */ - - skb = dev_alloc_skb(len + 1); - if (!skb) { - pr_info("%s: memory squeeze, dropping frame\n", - __func__); - /* Restore set register */ - outb(set, iobase + SSR); - - return FALSE; - } - - /* Align to 20 bytes */ - skb_reserve(skb, 1); - - /* Copy frame without CRC */ - if (self->io.speed < 4000000) { - skb_put(skb, len - 2); - skb_copy_to_linear_data(skb, - self->rx_buff.data, - len - 2); - } else { - skb_put(skb, len - 4); - skb_copy_to_linear_data(skb, - self->rx_buff.data, - len - 4); - } - - /* Move to next frame */ - self->rx_buff.data += len; - self->netdev->stats.rx_packets++; - - skb->dev = self->netdev; - skb_reset_mac_header(skb); - skb->protocol = htons(ETH_P_IRDA); - netif_rx(skb); - } - } - /* Restore set register */ - outb(set, iobase + SSR); - - return TRUE; -} - -/* - * Function pc87108_pio_receive (self) - * - * Receive all data in receiver FIFO - * - */ -static void w83977af_pio_receive(struct w83977af_ir *self) -{ - __u8 byte = 0x00; - int iobase; - - IRDA_ASSERT(self, return;); - - iobase = self->io.fir_base; - - /* Receive all characters in Rx FIFO */ - do { - byte = inb(iobase + RBR); - async_unwrap_char(self->netdev, &self->netdev->stats, &self->rx_buff, - byte); - } while (inb(iobase + USR) & USR_RDR); /* Data available */ -} - -/* - * Function w83977af_sir_interrupt (self, eir) - * - * Handle SIR interrupt - * - */ -static __u8 w83977af_sir_interrupt(struct w83977af_ir *self, int isr) -{ - int actual; - __u8 new_icr = 0; - __u8 set; - int iobase; - - pr_debug("%s: isr=%#x\n", __func__, isr); - - iobase = self->io.fir_base; - /* Transmit FIFO low on data */ - if (isr & ISR_TXTH_I) { - /* Write data left in transmit buffer */ - actual = w83977af_pio_write(self->io.fir_base, - self->tx_buff.data, - self->tx_buff.len, - self->io.fifo_size); - - self->tx_buff.data += actual; - self->tx_buff.len -= actual; - - self->io.direction = IO_XMIT; - - /* Check if finished */ - if (self->tx_buff.len > 0) { - new_icr |= ICR_ETXTHI; - } else { - set = inb(iobase + SSR); - switch_bank(iobase, SET0); - outb(AUDR_SFEND, iobase + AUDR); - outb(set, iobase + SSR); - - self->netdev->stats.tx_packets++; - - /* Feed me more packets */ - netif_wake_queue(self->netdev); - new_icr |= ICR_ETBREI; - } - } - /* Check if transmission has completed */ - if (isr & ISR_TXEMP_I) { - /* Check if we need to change the speed? */ - if (self->new_speed) { - pr_debug("%s: Changing speed!\n", __func__); - w83977af_change_speed(self, self->new_speed); - self->new_speed = 0; - } - - /* Turn around and get ready to receive some data */ - self->io.direction = IO_RECV; - new_icr |= ICR_ERBRI; - } - - /* Rx FIFO threshold or timeout */ - if (isr & ISR_RXTH_I) { - w83977af_pio_receive(self); - - /* Keep receiving */ - new_icr |= ICR_ERBRI; - } - return new_icr; -} - -/* - * Function pc87108_fir_interrupt (self, eir) - * - * Handle MIR/FIR interrupt - * - */ -static __u8 w83977af_fir_interrupt(struct w83977af_ir *self, int isr) -{ - __u8 new_icr = 0; - __u8 set; - int iobase; - - iobase = self->io.fir_base; - set = inb(iobase + SSR); - - /* End of frame detected in FIFO */ - if (isr & (ISR_FEND_I | ISR_FSF_I)) { - if (w83977af_dma_receive_complete(self)) { - /* Wait for next status FIFO interrupt */ - new_icr |= ICR_EFSFI; - } else { - /* DMA not finished yet */ - - /* Set timer value, resolution 1 ms */ - switch_bank(iobase, SET4); - outb(0x01, iobase + TMRL); /* 1 ms */ - outb(0x00, iobase + TMRH); - - /* Start timer */ - outb(IR_MSL_EN_TMR, iobase + IR_MSL); - - new_icr |= ICR_ETMRI; - } - } - /* Timer finished */ - if (isr & ISR_TMR_I) { - /* Disable timer */ - switch_bank(iobase, SET4); - outb(0, iobase + IR_MSL); - - /* Clear timer event */ - /* switch_bank(iobase, SET0); */ -/* outb(ASCR_CTE, iobase+ASCR); */ - - /* Check if this is a TX timer interrupt */ - if (self->io.direction == IO_XMIT) { - w83977af_dma_write(self, iobase); - - new_icr |= ICR_EDMAI; - } else { - /* Check if DMA has now finished */ - w83977af_dma_receive_complete(self); - - new_icr |= ICR_EFSFI; - } - } - /* Finished with DMA */ - if (isr & ISR_DMA_I) { - w83977af_dma_xmit_complete(self); - - /* Check if there are more frames to be transmitted */ - /* if (irda_device_txqueue_empty(self)) { */ - - /* Prepare for receive - * - * ** Netwinder Tx DMA likes that we do this anyway ** - */ - w83977af_dma_receive(self); - new_icr = ICR_EFSFI; - /* } */ - } - - /* Restore set */ - outb(set, iobase + SSR); - - return new_icr; -} - -/* - * Function w83977af_interrupt (irq, dev_id, regs) - * - * An interrupt from the chip has arrived. Time to do some work - * - */ -static irqreturn_t w83977af_interrupt(int irq, void *dev_id) -{ - struct net_device *dev = dev_id; - struct w83977af_ir *self; - __u8 set, icr, isr; - int iobase; - - self = netdev_priv(dev); - - iobase = self->io.fir_base; - - /* Save current bank */ - set = inb(iobase + SSR); - switch_bank(iobase, SET0); - - icr = inb(iobase + ICR); - isr = inb(iobase + ISR) & icr; /* Mask out the interesting ones */ - - outb(0, iobase + ICR); /* Disable interrupts */ - - if (isr) { - /* Dispatch interrupt handler for the current speed */ - if (self->io.speed > PIO_MAX_SPEED) - icr = w83977af_fir_interrupt(self, isr); - else - icr = w83977af_sir_interrupt(self, isr); - } - - outb(icr, iobase + ICR); /* Restore (new) interrupts */ - outb(set, iobase + SSR); /* Restore bank register */ - return IRQ_RETVAL(isr); -} - -/* - * Function w83977af_is_receiving (self) - * - * Return TRUE is we are currently receiving a frame - * - */ -static int w83977af_is_receiving(struct w83977af_ir *self) -{ - int status = FALSE; - int iobase; - __u8 set; - - IRDA_ASSERT(self, return FALSE;); - - if (self->io.speed > 115200) { - iobase = self->io.fir_base; - - /* Check if rx FIFO is not empty */ - set = inb(iobase + SSR); - switch_bank(iobase, SET2); - if ((inb(iobase + RXFDTH) & 0x3f) != 0) { - /* We are receiving something */ - status = TRUE; - } - outb(set, iobase + SSR); - } else { - status = (self->rx_buff.state != OUTSIDE_FRAME); - } - - return status; -} - -/* - * Function w83977af_net_open (dev) - * - * Start the device - * - */ -static int w83977af_net_open(struct net_device *dev) -{ - struct w83977af_ir *self; - int iobase; - char hwname[32]; - __u8 set; - - IRDA_ASSERT(dev, return -1;); - self = netdev_priv(dev); - - IRDA_ASSERT(self, return 0;); - - iobase = self->io.fir_base; - - if (request_irq(self->io.irq, w83977af_interrupt, 0, dev->name, - (void *)dev)) { - return -EAGAIN; - } - /* - * Always allocate the DMA channel after the IRQ, - * and clean up on failure. - */ - if (request_dma(self->io.dma, dev->name)) { - free_irq(self->io.irq, dev); - return -EAGAIN; - } - - /* Save current set */ - set = inb(iobase + SSR); - - /* Enable some interrupts so we can receive frames again */ - switch_bank(iobase, SET0); - if (self->io.speed > 115200) { - outb(ICR_EFSFI, iobase + ICR); - w83977af_dma_receive(self); - } else { - outb(ICR_ERBRI, iobase + ICR); - } - - /* Restore bank register */ - outb(set, iobase + SSR); - - /* Ready to play! */ - netif_start_queue(dev); - - /* Give self a hardware name */ - sprintf(hwname, "w83977af @ 0x%03x", self->io.fir_base); - - /* - * Open new IrLAP layer instance, now that everything should be - * initialized properly - */ - self->irlap = irlap_open(dev, &self->qos, hwname); - - return 0; -} - -/* - * Function w83977af_net_close (dev) - * - * Stop the device - * - */ -static int w83977af_net_close(struct net_device *dev) -{ - struct w83977af_ir *self; - int iobase; - __u8 set; - - IRDA_ASSERT(dev, return -1;); - - self = netdev_priv(dev); - - IRDA_ASSERT(self, return 0;); - - iobase = self->io.fir_base; - - /* Stop device */ - netif_stop_queue(dev); - - /* Stop and remove instance of IrLAP */ - if (self->irlap) - irlap_close(self->irlap); - self->irlap = NULL; - - disable_dma(self->io.dma); - - /* Save current set */ - set = inb(iobase + SSR); - - /* Disable interrupts */ - switch_bank(iobase, SET0); - outb(0, iobase + ICR); - - free_irq(self->io.irq, dev); - free_dma(self->io.dma); - - /* Restore bank register */ - outb(set, iobase + SSR); - - return 0; -} - -/* - * Function w83977af_net_ioctl (dev, rq, cmd) - * - * Process IOCTL commands for this device - * - */ -static int w83977af_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct if_irda_req *irq = (struct if_irda_req *)rq; - struct w83977af_ir *self; - unsigned long flags; - int ret = 0; - - IRDA_ASSERT(dev, return -1;); - - self = netdev_priv(dev); - - IRDA_ASSERT(self, return -1;); - - pr_debug("%s: %s, (cmd=0x%X)\n", __func__, dev->name, cmd); - - spin_lock_irqsave(&self->lock, flags); - - switch (cmd) { - case SIOCSBANDWIDTH: /* Set bandwidth */ - if (!capable(CAP_NET_ADMIN)) { - ret = -EPERM; - goto out; - } - w83977af_change_speed(self, irq->ifr_baudrate); - break; - case SIOCSMEDIABUSY: /* Set media busy */ - if (!capable(CAP_NET_ADMIN)) { - ret = -EPERM; - goto out; - } - irda_device_set_media_busy(self->netdev, TRUE); - break; - case SIOCGRECEIVING: /* Check if we are receiving right now */ - irq->ifr_receiving = w83977af_is_receiving(self); - break; - default: - ret = -EOPNOTSUPP; - } -out: - spin_unlock_irqrestore(&self->lock, flags); - return ret; -} - -MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>"); -MODULE_DESCRIPTION("Winbond W83977AF IrDA Device Driver"); -MODULE_LICENSE("GPL"); - -module_param(qos_mtt_bits, int, 0); -MODULE_PARM_DESC(qos_mtt_bits, "Mimimum Turn Time"); -module_param_hw_array(io, int, ioport, NULL, 0); -MODULE_PARM_DESC(io, "Base I/O addresses"); -module_param_hw_array(irq, int, irq, NULL, 0); -MODULE_PARM_DESC(irq, "IRQ lines"); - -/* - * Function init_module (void) - * - * - * - */ -module_init(w83977af_init); - -/* - * Function cleanup_module (void) - * - * - * - */ -module_exit(w83977af_cleanup); diff --git a/drivers/net/irda/w83977af_ir.h b/drivers/net/irda/w83977af_ir.h deleted file mode 100644 index fefe9b11e200..000000000000 --- a/drivers/net/irda/w83977af_ir.h +++ /dev/null @@ -1,198 +0,0 @@ -/********************************************************************* - * - * 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ø 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 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 |