diff --git a/[refs] b/[refs]
index 33f347ed5db6..7dbf018a6bcd 100644
--- a/[refs]
+++ b/[refs]
@@ -1,2 +1,2 @@
---
-refs/heads/master: c8b6de16d9434405e5832b8772e4f986ddd5118e
+refs/heads/master: 5bb983b0cce9b7b281af15730f7019116dd42568
diff --git a/trunk/Documentation/DocBook/scsi.tmpl b/trunk/Documentation/DocBook/scsi.tmpl
index 10a150ae2a7e..f299ab182bbe 100644
--- a/trunk/Documentation/DocBook/scsi.tmpl
+++ b/trunk/Documentation/DocBook/scsi.tmpl
@@ -12,7 +12,7 @@
Bottomley
- James.Bottomley@hansenpartnership.com
+ James.Bottomley@steeleye.com
diff --git a/trunk/Documentation/input/input-programming.txt b/trunk/Documentation/input/input-programming.txt
index 81905e81585e..47fc86830cd7 100644
--- a/trunk/Documentation/input/input-programming.txt
+++ b/trunk/Documentation/input/input-programming.txt
@@ -22,7 +22,7 @@ static struct input_dev *button_dev;
static void button_interrupt(int irq, void *dummy, struct pt_regs *fp)
{
- input_report_key(button_dev, BTN_0, inb(BUTTON_PORT) & 1);
+ input_report_key(button_dev, BTN_1, inb(BUTTON_PORT) & 1);
input_sync(button_dev);
}
diff --git a/trunk/Documentation/scsi/ChangeLog.arcmsr b/trunk/Documentation/scsi/ChangeLog.arcmsr
index de2bcacfa870..cd8403a33ee6 100644
--- a/trunk/Documentation/scsi/ChangeLog.arcmsr
+++ b/trunk/Documentation/scsi/ChangeLog.arcmsr
@@ -68,45 +68,4 @@
** 2. modify the arcmsr_pci_slot_reset function
** 3. modify the arcmsr_pci_ers_disconnect_forepart function
** 4. modify the arcmsr_pci_ers_need_reset_forepart function
-** 1.20.00.15 09/27/2007 Erich Chen & Nick Cheng
-** 1. add arcmsr_enable_eoi_mode() on adapter Type B
-** 2. add readl(reg->iop2drv_doorbell_reg) in arcmsr_handle_hbb_isr()
-** in case of the doorbell interrupt clearance is cached
-** 1.20.00.15 10/01/2007 Erich Chen & Nick Cheng
-** 1. modify acb->devstate[i][j]
-** as ARECA_RAID_GOOD instead of
-** ARECA_RAID_GONE in arcmsr_alloc_ccb_pool
-** 1.20.00.15 11/06/2007 Erich Chen & Nick Cheng
-** 1. add conditional declaration for
-** arcmsr_pci_error_detected() and
-** arcmsr_pci_slot_reset
-** 1.20.00.15 11/23/2007 Erich Chen & Nick Cheng
-** 1.check if the sg list member number
-** exceeds arcmsr default limit in arcmsr_build_ccb()
-** 2.change the returned value type of arcmsr_build_ccb()
-** from "void" to "int"
-** 3.add the conditional check if arcmsr_build_ccb()
-** returns FAILED
-** 1.20.00.15 12/04/2007 Erich Chen & Nick Cheng
-** 1. modify arcmsr_drain_donequeue() to ignore unknown
-** command and let kernel process command timeout.
-** This could handle IO request violating max. segments
-** while Linux XFS over DM-CRYPT.
-** Thanks to Milan Broz's comments
-** 1.20.00.15 12/24/2007 Erich Chen & Nick Cheng
-** 1.fix the portability problems
-** 2.fix type B where we should _not_ iounmap() acb->pmu;
-** it's not ioremapped.
-** 3.add return -ENOMEM if ioremap() fails
-** 4.transfer IS_SG64_ADDR w/ cpu_to_le32()
-** in arcmsr_build_ccb
-** 5. modify acb->devstate[i][j] as ARECA_RAID_GONE instead of
-** ARECA_RAID_GOOD in arcmsr_alloc_ccb_pool()
-** 6.fix arcmsr_cdb->Context as (unsigned long)arcmsr_cdb
-** 7.add the checking state of
-** (outbound_intstatus & ARCMSR_MU_OUTBOUND_HANDLE_INT) == 0
-** in arcmsr_handle_hba_isr
-** 8.replace pci_alloc_consistent()/pci_free_consistent() with kmalloc()/kfree() in arcmsr_iop_message_xfer()
-** 9. fix the release of dma memory for type B in arcmsr_free_ccb_pool()
-** 10.fix the arcmsr_polling_hbb_ccbdone()
**************************************************************************
diff --git a/trunk/Documentation/scsi/scsi_mid_low_api.txt b/trunk/Documentation/scsi/scsi_mid_low_api.txt
index a6d5354639b2..6f70f2b9327e 100644
--- a/trunk/Documentation/scsi/scsi_mid_low_api.txt
+++ b/trunk/Documentation/scsi/scsi_mid_low_api.txt
@@ -1407,7 +1407,7 @@ Credits
=======
The following people have contributed to this document:
Mike Anderson
- James Bottomley
+ James Bottomley
Patrick Mansfield
Christoph Hellwig
Doug Ledford
diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS
index 2cdb591ac080..aefd23f892ba 100644
--- a/trunk/MAINTAINERS
+++ b/trunk/MAINTAINERS
@@ -2150,14 +2150,6 @@ M: acme@ghostprotocols.net
L: netdev@vger.kernel.org
S: Maintained
-IPWIRELES DRIVER
-P: Jiri Kosina
-M: jkosina@suse.cz
-P: David Sterba
-M: dsterba@suse.cz
-S: Maintained
-T: git://git.kernel.org/pub/scm/linux/kernel/git/jikos/ipwireless_cs.git
-
IRDA SUBSYSTEM
P: Samuel Ortiz
M: samuel@sortiz.org
diff --git a/trunk/arch/arm/mach-pxa/tosa.c b/trunk/arch/arm/mach-pxa/tosa.c
index f99112d50b41..9b26fa5edad6 100644
--- a/trunk/arch/arm/mach-pxa/tosa.c
+++ b/trunk/arch/arm/mach-pxa/tosa.c
@@ -21,8 +21,6 @@
#include
#include
#include
-#include
-#include
#include
#include
@@ -248,46 +246,6 @@ static struct platform_device tosakbd_device = {
.id = -1,
};
-static struct gpio_keys_button tosa_gpio_keys[] = {
- {
- .type = EV_PWR,
- .code = KEY_SUSPEND,
- .gpio = TOSA_GPIO_ON_KEY,
- .desc = "On key",
- .wakeup = 1,
- .active_low = 1,
- },
- {
- .type = EV_KEY,
- .code = TOSA_KEY_RECORD,
- .gpio = TOSA_GPIO_RECORD_BTN,
- .desc = "Record Button",
- .wakeup = 1,
- .active_low = 1,
- },
- {
- .type = EV_KEY,
- .code = TOSA_KEY_SYNC,
- .gpio = TOSA_GPIO_SYNC,
- .desc = "Sync Button",
- .wakeup = 1,
- .active_low = 1,
- },
-};
-
-static struct gpio_keys_platform_data tosa_gpio_keys_platform_data = {
- .buttons = tosa_gpio_keys,
- .nbuttons = ARRAY_SIZE(tosa_gpio_keys),
-};
-
-static struct platform_device tosa_gpio_keys_device = {
- .name = "gpio-keys",
- .id = -1,
- .dev = {
- .platform_data = &tosa_gpio_keys_platform_data,
- },
-};
-
/*
* Tosa LEDs
*/
@@ -300,7 +258,6 @@ static struct platform_device *devices[] __initdata = {
&tosascoop_device,
&tosascoop_jc_device,
&tosakbd_device,
- &tosa_gpio_keys_device,
&tosaled_device,
};
diff --git a/trunk/arch/m68k/kernel/process.c b/trunk/arch/m68k/kernel/process.c
index f85b928ffac4..3ee918695215 100644
--- a/trunk/arch/m68k/kernel/process.c
+++ b/trunk/arch/m68k/kernel/process.c
@@ -335,7 +335,7 @@ void dump_thread(struct pt_regs * regs, struct user * dump)
if (dump->start_stack < TASK_SIZE)
dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT;
- dump->u_ar0 = offsetof(struct user, regs);
+ dump->u_ar0 = (struct user_regs_struct *)((int)&dump->regs - (int)dump);
sw = ((struct switch_stack *)regs) - 1;
dump->regs.d1 = regs->d1;
dump->regs.d2 = regs->d2;
diff --git a/trunk/arch/powerpc/kernel/asm-offsets.c b/trunk/arch/powerpc/kernel/asm-offsets.c
index 4b749c416464..e6e49289f788 100644
--- a/trunk/arch/powerpc/kernel/asm-offsets.c
+++ b/trunk/arch/powerpc/kernel/asm-offsets.c
@@ -313,7 +313,7 @@ int main(void)
DEFINE(CLOCK_REALTIME, CLOCK_REALTIME);
DEFINE(CLOCK_MONOTONIC, CLOCK_MONOTONIC);
DEFINE(NSEC_PER_SEC, NSEC_PER_SEC);
- DEFINE(CLOCK_REALTIME_RES, MONOTONIC_RES_NSEC);
+ DEFINE(CLOCK_REALTIME_RES, (KTIME_MONOTONIC_RES).tv64);
#ifdef CONFIG_BUG
DEFINE(BUG_ENTRY_SIZE, sizeof(struct bug_entry));
diff --git a/trunk/drivers/base/firmware_class.c b/trunk/drivers/base/firmware_class.c
index 4a1b9bfc5471..0295855a3eef 100644
--- a/trunk/drivers/base/firmware_class.c
+++ b/trunk/drivers/base/firmware_class.c
@@ -292,8 +292,7 @@ firmware_class_timeout(u_long data)
static inline void fw_setup_device_id(struct device *f_dev, struct device *dev)
{
- /* XXX warning we should watch out for name collisions */
- strlcpy(f_dev->bus_id, dev->bus_id, BUS_ID_SIZE);
+ snprintf(f_dev->bus_id, BUS_ID_SIZE, "firmware-%s", dev->bus_id);
}
static int fw_register_device(struct device **dev_p, const char *fw_name,
diff --git a/trunk/drivers/char/drm/i915_drv.h b/trunk/drivers/char/drm/i915_drv.h
index f8308bfb2613..37bbf6729b4e 100644
--- a/trunk/drivers/char/drm/i915_drv.h
+++ b/trunk/drivers/char/drm/i915_drv.h
@@ -187,7 +187,7 @@ typedef struct drm_i915_private {
u32 saveSWF2[3];
u8 saveMSR;
u8 saveSR[8];
- u8 saveGR[25];
+ u8 saveGR[24];
u8 saveAR_INDEX;
u8 saveAR[20];
u8 saveDACMASK;
diff --git a/trunk/drivers/char/keyboard.c b/trunk/drivers/char/keyboard.c
index 4dbd3425e928..fc54d234507a 100644
--- a/trunk/drivers/char/keyboard.c
+++ b/trunk/drivers/char/keyboard.c
@@ -38,6 +38,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -193,7 +194,7 @@ int getkeycode(unsigned int scancode)
int error = -ENODEV;
list_for_each_entry(handle, &kbd_handler.h_list, h_node) {
- error = input_get_keycode(handle->dev, scancode, &keycode);
+ error = handle->dev->getkeycode(handle->dev, scancode, &keycode);
if (!error)
return keycode;
}
@@ -207,7 +208,7 @@ int setkeycode(unsigned int scancode, unsigned int keycode)
int error = -ENODEV;
list_for_each_entry(handle, &kbd_handler.h_list, h_node) {
- error = input_set_keycode(handle->dev, scancode, keycode);
+ error = handle->dev->setkeycode(handle->dev, scancode, keycode);
if (!error)
break;
}
diff --git a/trunk/drivers/char/pcmcia/Kconfig b/trunk/drivers/char/pcmcia/Kconfig
index 00b8a84b0319..f25facd97bb4 100644
--- a/trunk/drivers/char/pcmcia/Kconfig
+++ b/trunk/drivers/char/pcmcia/Kconfig
@@ -43,14 +43,5 @@ config CARDMAN_4040
(http://www.omnikey.com/), or a current development version of OpenCT
(http://www.opensc.org/).
-config IPWIRELESS
- tristate "IPWireless 3G UMTS PCMCIA card support"
- depends on PCMCIA
- select PPP
- help
- This is a driver for 3G UMTS PCMCIA card from IPWireless company. In
- some countries (for example Czech Republic, T-Mobile ISP) this card
- is shipped for service called UMTS 4G.
-
endmenu
diff --git a/trunk/drivers/char/pcmcia/Makefile b/trunk/drivers/char/pcmcia/Makefile
index be8f287aa398..0aae20985d57 100644
--- a/trunk/drivers/char/pcmcia/Makefile
+++ b/trunk/drivers/char/pcmcia/Makefile
@@ -4,8 +4,6 @@
# Makefile for the Linux PCMCIA char device drivers.
#
-obj-y += ipwireless/
-
obj-$(CONFIG_SYNCLINK_CS) += synclink_cs.o
obj-$(CONFIG_CARDMAN_4000) += cm4000_cs.o
obj-$(CONFIG_CARDMAN_4040) += cm4040_cs.o
diff --git a/trunk/drivers/char/pcmcia/ipwireless/Makefile b/trunk/drivers/char/pcmcia/ipwireless/Makefile
deleted file mode 100644
index b71eb593643d..000000000000
--- a/trunk/drivers/char/pcmcia/ipwireless/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-#
-# drivers/char/pcmcia/ipwireless/Makefile
-#
-# Makefile for the IPWireless driver
-#
-
-obj-$(CONFIG_IPWIRELESS) += ipwireless.o
-
-ipwireless-objs := hardware.o main.o network.o tty.o
-
diff --git a/trunk/drivers/char/pcmcia/ipwireless/hardware.c b/trunk/drivers/char/pcmcia/ipwireless/hardware.c
deleted file mode 100644
index 1f978ff87fa8..000000000000
--- a/trunk/drivers/char/pcmcia/ipwireless/hardware.c
+++ /dev/null
@@ -1,1787 +0,0 @@
-/*
- * IPWireless 3G PCMCIA Network Driver
- *
- * Original code
- * by Stephen Blackheath ,
- * Ben Martel
- *
- * Copyrighted as follows:
- * Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
- *
- * Various driver changes and rewrites, port to new kernels
- * Copyright (C) 2006-2007 Jiri Kosina
- *
- * Misc code cleanups and updates
- * Copyright (C) 2007 David Sterba
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "hardware.h"
-#include "setup_protocol.h"
-#include "network.h"
-#include "main.h"
-
-static void ipw_send_setup_packet(struct ipw_hardware *hw);
-static void handle_received_SETUP_packet(struct ipw_hardware *ipw,
- unsigned int address,
- unsigned char *data, int len,
- int is_last);
-static void ipwireless_setup_timer(unsigned long data);
-static void handle_received_CTRL_packet(struct ipw_hardware *hw,
- unsigned int channel_idx, unsigned char *data, int len);
-
-/*#define TIMING_DIAGNOSTICS*/
-
-#ifdef TIMING_DIAGNOSTICS
-
-static struct timing_stats {
- unsigned long last_report_time;
- unsigned long read_time;
- unsigned long write_time;
- unsigned long read_bytes;
- unsigned long write_bytes;
- unsigned long start_time;
-};
-
-static void start_timing(void)
-{
- timing_stats.start_time = jiffies;
-}
-
-static void end_read_timing(unsigned length)
-{
- timing_stats.read_time += (jiffies - start_time);
- timing_stats.read_bytes += length + 2;
- report_timing();
-}
-
-static void end_write_timing(unsigned length)
-{
- timing_stats.write_time += (jiffies - start_time);
- timing_stats.write_bytes += length + 2;
- report_timing();
-}
-
-static void report_timing(void)
-{
- unsigned long since = jiffies - timing_stats.last_report_time;
-
- /* If it's been more than one second... */
- if (since >= HZ) {
- int first = (timing_stats.last_report_time == 0);
-
- timing_stats.last_report_time = jiffies;
- if (!first)
- printk(KERN_INFO IPWIRELESS_PCCARD_NAME
- ": %u us elapsed - read %lu bytes in %u us, "
- "wrote %lu bytes in %u us\n",
- jiffies_to_usecs(since),
- timing_stats.read_bytes,
- jiffies_to_usecs(timing_stats.read_time),
- timing_stats.write_bytes,
- jiffies_to_usecs(timing_stats.write_time));
-
- timing_stats.read_time = 0;
- timing_stats.write_time = 0;
- timing_stats.read_bytes = 0;
- timing_stats.write_bytes = 0;
- }
-}
-#else
-static void start_timing(void) { }
-static void end_read_timing(unsigned length) { }
-static void end_write_timing(unsigned length) { }
-#endif
-
-/* Imported IPW definitions */
-
-#define LL_MTU_V1 318
-#define LL_MTU_V2 250
-#define LL_MTU_MAX (LL_MTU_V1 > LL_MTU_V2 ? LL_MTU_V1 : LL_MTU_V2)
-
-#define PRIO_DATA 2
-#define PRIO_CTRL 1
-#define PRIO_SETUP 0
-
-/* Addresses */
-#define ADDR_SETUP_PROT 0
-
-/* Protocol ids */
-enum {
- /* Identifier for the Com Data protocol */
- TL_PROTOCOLID_COM_DATA = 0,
-
- /* Identifier for the Com Control protocol */
- TL_PROTOCOLID_COM_CTRL = 1,
-
- /* Identifier for the Setup protocol */
- TL_PROTOCOLID_SETUP = 2
-};
-
-/* Number of bytes in NL packet header (cannot do
- * sizeof(nl_packet_header) since it's a bitfield) */
-#define NL_FIRST_PACKET_HEADER_SIZE 3
-
-/* Number of bytes in NL packet header (cannot do
- * sizeof(nl_packet_header) since it's a bitfield) */
-#define NL_FOLLOWING_PACKET_HEADER_SIZE 1
-
-struct nl_first_packet_header {
-#if defined(__BIG_ENDIAN_BITFIELD)
- unsigned char packet_rank:2;
- unsigned char address:3;
- unsigned char protocol:3;
-#else
- unsigned char protocol:3;
- unsigned char address:3;
- unsigned char packet_rank:2;
-#endif
- unsigned char length_lsb;
- unsigned char length_msb;
-};
-
-struct nl_packet_header {
-#if defined(__BIG_ENDIAN_BITFIELD)
- unsigned char packet_rank:2;
- unsigned char address:3;
- unsigned char protocol:3;
-#else
- unsigned char protocol:3;
- unsigned char address:3;
- unsigned char packet_rank:2;
-#endif
-};
-
-/* Value of 'packet_rank' above */
-#define NL_INTERMEDIATE_PACKET 0x0
-#define NL_LAST_PACKET 0x1
-#define NL_FIRST_PACKET 0x2
-
-union nl_packet {
- /* Network packet header of the first packet (a special case) */
- struct nl_first_packet_header hdr_first;
- /* Network packet header of the following packets (if any) */
- struct nl_packet_header hdr;
- /* Complete network packet (header + data) */
- unsigned char rawpkt[LL_MTU_MAX];
-} __attribute__ ((__packed__));
-
-#define HW_VERSION_UNKNOWN -1
-#define HW_VERSION_1 1
-#define HW_VERSION_2 2
-
-/* IPW I/O ports */
-#define IOIER 0x00 /* Interrupt Enable Register */
-#define IOIR 0x02 /* Interrupt Source/ACK register */
-#define IODCR 0x04 /* Data Control Register */
-#define IODRR 0x06 /* Data Read Register */
-#define IODWR 0x08 /* Data Write Register */
-#define IOESR 0x0A /* Embedded Driver Status Register */
-#define IORXR 0x0C /* Rx Fifo Register (Host to Embedded) */
-#define IOTXR 0x0E /* Tx Fifo Register (Embedded to Host) */
-
-/* I/O ports and bit definitions for version 1 of the hardware */
-
-/* IER bits*/
-#define IER_RXENABLED 0x1
-#define IER_TXENABLED 0x2
-
-/* ISR bits */
-#define IR_RXINTR 0x1
-#define IR_TXINTR 0x2
-
-/* DCR bits */
-#define DCR_RXDONE 0x1
-#define DCR_TXDONE 0x2
-#define DCR_RXRESET 0x4
-#define DCR_TXRESET 0x8
-
-/* I/O ports and bit definitions for version 2 of the hardware */
-
-struct MEMCCR {
- unsigned short reg_config_option; /* PCCOR: Configuration Option Register */
- unsigned short reg_config_and_status; /* PCCSR: Configuration and Status Register */
- unsigned short reg_pin_replacement; /* PCPRR: Pin Replacemant Register */
- unsigned short reg_socket_and_copy; /* PCSCR: Socket and Copy Register */
- unsigned short reg_ext_status; /* PCESR: Extendend Status Register */
- unsigned short reg_io_base; /* PCIOB: I/O Base Register */
-};
-
-struct MEMINFREG {
- unsigned short memreg_tx_old; /* TX Register (R/W) */
- unsigned short pad1;
- unsigned short memreg_rx_done; /* RXDone Register (R/W) */
- unsigned short pad2;
- unsigned short memreg_rx; /* RX Register (R/W) */
- unsigned short pad3;
- unsigned short memreg_pc_interrupt_ack; /* PC intr Ack Register (W) */
- unsigned short pad4;
- unsigned long memreg_card_present;/* Mask for Host to check (R) for
- * CARD_PRESENT_VALUE */
- unsigned short memreg_tx_new; /* TX2 (new) Register (R/W) */
-};
-
-#define IODMADPR 0x00 /* DMA Data Port Register (R/W) */
-
-#define CARD_PRESENT_VALUE (0xBEEFCAFEUL)
-
-#define MEMTX_TX 0x0001
-#define MEMRX_RX 0x0001
-#define MEMRX_RX_DONE 0x0001
-#define MEMRX_PCINTACKK 0x0001
-#define MEMRX_MEMSPURIOUSINT 0x0001
-
-#define NL_NUM_OF_PRIORITIES 3
-#define NL_NUM_OF_PROTOCOLS 3
-#define NL_NUM_OF_ADDRESSES NO_OF_IPW_CHANNELS
-
-struct ipw_hardware {
- unsigned int base_port;
- short hw_version;
- unsigned short ll_mtu;
- spinlock_t spinlock;
-
- int initializing;
- int init_loops;
- struct timer_list setup_timer;
-
- int tx_ready;
- struct list_head tx_queue[NL_NUM_OF_PRIORITIES];
- /* True if any packets are queued for transmission */
- int tx_queued;
-
- int rx_bytes_queued;
- struct list_head rx_queue;
- /* Pool of rx_packet structures that are not currently used. */
- struct list_head rx_pool;
- int rx_pool_size;
- /* True if reception of data is blocked while userspace processes it. */
- int blocking_rx;
- /* True if there is RX data ready on the hardware. */
- int rx_ready;
- unsigned short last_memtx_serial;
- /*
- * Newer versions of the V2 card firmware send serial numbers in the
- * MemTX register. 'serial_number_detected' is set true when we detect
- * a non-zero serial number (indicating the new firmware). Thereafter,
- * the driver can safely ignore the Timer Recovery re-sends to avoid
- * out-of-sync problems.
- */
- int serial_number_detected;
- struct work_struct work_rx;
-
- /* True if we are to send the set-up data to the hardware. */
- int to_setup;
-
- /* Card has been removed */
- int removed;
- /* Saved irq value when we disable the interrupt. */
- int irq;
- /* True if this driver is shutting down. */
- int shutting_down;
- /* Modem control lines */
- unsigned int control_lines[NL_NUM_OF_ADDRESSES];
- struct ipw_rx_packet *packet_assembler[NL_NUM_OF_ADDRESSES];
-
- struct tasklet_struct tasklet;
-
- /* The handle for the network layer, for the sending of events to it. */
- struct ipw_network *network;
- struct MEMINFREG __iomem *memory_info_regs;
- struct MEMCCR __iomem *memregs_CCR;
- void (*reboot_callback) (void *data);
- void *reboot_callback_data;
-
- unsigned short __iomem *memreg_tx;
-};
-
-/*
- * Packet info structure for tx packets.
- * Note: not all the fields defined here are required for all protocols
- */
-struct ipw_tx_packet {
- struct list_head queue;
- /* channel idx + 1 */
- unsigned char dest_addr;
- /* SETUP, CTRL or DATA */
- unsigned char protocol;
- /* Length of data block, which starts at the end of this structure */
- unsigned short length;
- /* Sending state */
- /* Offset of where we've sent up to so far */
- unsigned long offset;
- /* Count of packet fragments, starting at 0 */
- int fragment_count;
-
- /* Called after packet is sent and before is freed */
- void (*packet_callback) (void *cb_data, unsigned int packet_length);
- void *callback_data;
-};
-
-/* Signals from DTE */
-#define COMCTRL_RTS 0
-#define COMCTRL_DTR 1
-
-/* Signals from DCE */
-#define COMCTRL_CTS 2
-#define COMCTRL_DCD 3
-#define COMCTRL_DSR 4
-#define COMCTRL_RI 5
-
-struct ipw_control_packet_body {
- /* DTE signal or DCE signal */
- unsigned char sig_no;
- /* 0: set signal, 1: clear signal */
- unsigned char value;
-} __attribute__ ((__packed__));
-
-struct ipw_control_packet {
- struct ipw_tx_packet header;
- struct ipw_control_packet_body body;
-};
-
-struct ipw_rx_packet {
- struct list_head queue;
- unsigned int capacity;
- unsigned int length;
- unsigned int protocol;
- unsigned int channel_idx;
-};
-
-#ifdef IPWIRELESS_STATE_DEBUG
-int ipwireless_dump_hardware_state(char *p, size_t limit,
- struct ipw_hardware *hw)
-{
- return snprintf(p, limit,
- "debug: initializing=%d\n"
- "debug: tx_ready=%d\n"
- "debug: tx_queued=%d\n"
- "debug: rx_ready=%d\n"
- "debug: rx_bytes_queued=%d\n"
- "debug: blocking_rx=%d\n"
- "debug: removed=%d\n"
- "debug: hardware.shutting_down=%d\n"
- "debug: to_setup=%d\n",
- hw->initializing,
- hw->tx_ready,
- hw->tx_queued,
- hw->rx_ready,
- hw->rx_bytes_queued,
- hw->blocking_rx,
- hw->removed,
- hw->shutting_down,
- hw->to_setup);
-}
-#endif
-
-static char *data_type(const unsigned char *buf, unsigned length)
-{
- struct nl_packet_header *hdr = (struct nl_packet_header *) buf;
-
- if (length == 0)
- return " ";
-
- if (hdr->packet_rank & NL_FIRST_PACKET) {
- switch (hdr->protocol) {
- case TL_PROTOCOLID_COM_DATA: return "DATA ";
- case TL_PROTOCOLID_COM_CTRL: return "CTRL ";
- case TL_PROTOCOLID_SETUP: return "SETUP";
- default: return "???? ";
- }
- } else
- return " ";
-}
-
-#define DUMP_MAX_BYTES 64
-
-static void dump_data_bytes(const char *type, const unsigned char *data,
- unsigned length)
-{
- char prefix[56];
-
- sprintf(prefix, IPWIRELESS_PCCARD_NAME ": %s %s ",
- type, data_type(data, length));
- print_hex_dump_bytes(prefix, 0, (void *)data,
- length < DUMP_MAX_BYTES ? length : DUMP_MAX_BYTES);
-}
-
-static int do_send_fragment(struct ipw_hardware *hw, const unsigned char *data,
- unsigned length)
-{
- int i;
- unsigned long flags;
-
- start_timing();
-
- if (length == 0)
- return 0;
-
- if (length > hw->ll_mtu)
- return -1;
-
- if (ipwireless_debug)
- dump_data_bytes("send", data, length);
-
- spin_lock_irqsave(&hw->spinlock, flags);
-
- if (hw->hw_version == HW_VERSION_1) {
- outw((unsigned short) length, hw->base_port + IODWR);
-
- for (i = 0; i < length; i += 2) {
- unsigned short d = data[i];
- __le16 raw_data;
-
- if (likely(i + 1 < length))
- d |= data[i + 1] << 8;
- raw_data = cpu_to_le16(d);
- outw(raw_data, hw->base_port + IODWR);
- }
-
- outw(DCR_TXDONE, hw->base_port + IODCR);
- } else if (hw->hw_version == HW_VERSION_2) {
- outw((unsigned short) length, hw->base_port + IODMADPR);
-
- for (i = 0; i < length; i += 2) {
- unsigned short d = data[i];
- __le16 raw_data;
-
- if ((i + 1 < length))
- d |= data[i + 1] << 8;
- raw_data = cpu_to_le16(d);
- outw(raw_data, hw->base_port + IODMADPR);
- }
- while ((i & 3) != 2) {
- outw((unsigned short) 0xDEAD, hw->base_port + IODMADPR);
- i += 2;
- }
- writew(MEMRX_RX, &hw->memory_info_regs->memreg_rx);
- }
-
- spin_unlock_irqrestore(&hw->spinlock, flags);
-
- end_write_timing(length);
-
- return 0;
-}
-
-static int do_send_packet(struct ipw_hardware *hw, struct ipw_tx_packet *packet)
-{
- unsigned short fragment_data_len;
- unsigned short data_left = packet->length - packet->offset;
- unsigned short header_size;
- union nl_packet pkt;
-
- header_size =
- (packet->fragment_count == 0)
- ? NL_FIRST_PACKET_HEADER_SIZE
- : NL_FOLLOWING_PACKET_HEADER_SIZE;
- fragment_data_len = hw->ll_mtu - header_size;
- if (data_left < fragment_data_len)
- fragment_data_len = data_left;
-
- pkt.hdr_first.protocol = packet->protocol;
- pkt.hdr_first.address = packet->dest_addr;
- pkt.hdr_first.packet_rank = 0;
-
- /* First packet? */
- if (packet->fragment_count == 0) {
- pkt.hdr_first.packet_rank |= NL_FIRST_PACKET;
- pkt.hdr_first.length_lsb = (unsigned char) packet->length;
- pkt.hdr_first.length_msb =
- (unsigned char) (packet->length >> 8);
- }
-
- memcpy(pkt.rawpkt + header_size,
- ((unsigned char *) packet) + sizeof(struct ipw_tx_packet) +
- packet->offset, fragment_data_len);
- packet->offset += fragment_data_len;
- packet->fragment_count++;
-
- /* Last packet? (May also be first packet.) */
- if (packet->offset == packet->length)
- pkt.hdr_first.packet_rank |= NL_LAST_PACKET;
- do_send_fragment(hw, pkt.rawpkt, header_size + fragment_data_len);
-
- /* If this packet has unsent data, then re-queue it. */
- if (packet->offset < packet->length) {
- /*
- * Re-queue it at the head of the highest priority queue so
- * it goes before all other packets
- */
- unsigned long flags;
-
- spin_lock_irqsave(&hw->spinlock, flags);
- list_add(&packet->queue, &hw->tx_queue[0]);
- spin_unlock_irqrestore(&hw->spinlock, flags);
- } else {
- if (packet->packet_callback)
- packet->packet_callback(packet->callback_data,
- packet->length);
- kfree(packet);
- }
-
- return 0;
-}
-
-static void ipw_setup_hardware(struct ipw_hardware *hw)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&hw->spinlock, flags);
- if (hw->hw_version == HW_VERSION_1) {
- /* Reset RX FIFO */
- outw(DCR_RXRESET, hw->base_port + IODCR);
- /* SB: Reset TX FIFO */
- outw(DCR_TXRESET, hw->base_port + IODCR);
-
- /* Enable TX and RX interrupts. */
- outw(IER_TXENABLED | IER_RXENABLED, hw->base_port + IOIER);
- } else {
- /*
- * Set INTRACK bit (bit 0), which means we must explicitly
- * acknowledge interrupts by clearing bit 2 of reg_config_and_status.
- */
- unsigned short csr = readw(&hw->memregs_CCR->reg_config_and_status);
-
- csr |= 1;
- writew(csr, &hw->memregs_CCR->reg_config_and_status);
- }
- spin_unlock_irqrestore(&hw->spinlock, flags);
-}
-
-/*
- * If 'packet' is NULL, then this function allocates a new packet, setting its
- * length to 0 and ensuring it has the specified minimum amount of free space.
- *
- * If 'packet' is not NULL, then this function enlarges it if it doesn't
- * have the specified minimum amount of free space.
- *
- */
-static struct ipw_rx_packet *pool_allocate(struct ipw_hardware *hw,
- struct ipw_rx_packet *packet,
- int minimum_free_space)
-{
-
- if (!packet) {
- unsigned long flags;
-
- /*
- * If this is the first fragment, then we will need to fetch a
- * packet to put it in.
- */
- spin_lock_irqsave(&hw->spinlock, flags);
- /* If we have one in our pool, then pull it out. */
- if (!list_empty(&hw->rx_pool)) {
- packet = list_first_entry(&hw->rx_pool,
- struct ipw_rx_packet, queue);
- list_del(&packet->queue);
- hw->rx_pool_size--;
- spin_unlock_irqrestore(&hw->spinlock, flags);
- } else {
- /* Otherwise allocate a new one. */
- static int min_capacity = 256;
- int new_capacity;
-
- spin_unlock_irqrestore(&hw->spinlock, flags);
- new_capacity =
- minimum_free_space > min_capacity
- ? minimum_free_space
- : min_capacity;
- packet = kmalloc(sizeof(struct ipw_rx_packet)
- + new_capacity, GFP_ATOMIC);
- if (!packet)
- return NULL;
- packet->capacity = new_capacity;
- }
- packet->length = 0;
- }
-
- /*
- * If this packet does not have sufficient capacity for the data we
- * want to add, then make it bigger.
- */
- if (packet->length + minimum_free_space > packet->capacity) {
- struct ipw_rx_packet *old_packet = packet;
-
- packet = kmalloc(sizeof(struct ipw_rx_packet) +
- old_packet->length + minimum_free_space,
- GFP_ATOMIC);
- if (!packet)
- return NULL;
- memcpy(packet, old_packet,
- sizeof(struct ipw_rx_packet)
- + old_packet->length);
- packet->capacity = old_packet->length + minimum_free_space;
- kfree(old_packet);
- }
-
- return packet;
-}
-
-static void pool_free(struct ipw_hardware *hw, struct ipw_rx_packet *packet)
-{
- if (hw->rx_pool_size > 6)
- kfree(packet);
- else {
- hw->rx_pool_size++;
- list_add_tail(&packet->queue, &hw->rx_pool);
- }
-}
-
-static void queue_received_packet(struct ipw_hardware *hw,
- unsigned int protocol, unsigned int address,
- unsigned char *data, int length, int is_last)
-{
- unsigned int channel_idx = address - 1;
- struct ipw_rx_packet *packet = NULL;
- unsigned long flags;
-
- /* Discard packet if channel index is out of range. */
- if (channel_idx >= NL_NUM_OF_ADDRESSES) {
- printk(KERN_INFO IPWIRELESS_PCCARD_NAME
- ": data packet has bad address %u\n", address);
- return;
- }
-
- /*
- * ->packet_assembler is safe to touch unlocked, this is the only place
- */
- if (protocol == TL_PROTOCOLID_COM_DATA) {
- struct ipw_rx_packet **assem =
- &hw->packet_assembler[channel_idx];
-
- /*
- * Create a new packet, or assembler already contains one
- * enlarge it by 'length' bytes.
- */
- (*assem) = pool_allocate(hw, *assem, length);
- if (!(*assem)) {
- printk(KERN_ERR IPWIRELESS_PCCARD_NAME
- ": no memory for incomming data packet, dropped!\n");
- return;
- }
- (*assem)->protocol = protocol;
- (*assem)->channel_idx = channel_idx;
-
- /* Append this packet data onto existing data. */
- memcpy((unsigned char *)(*assem) +
- sizeof(struct ipw_rx_packet)
- + (*assem)->length, data, length);
- (*assem)->length += length;
- if (is_last) {
- packet = *assem;
- *assem = NULL;
- /* Count queued DATA bytes only */
- spin_lock_irqsave(&hw->spinlock, flags);
- hw->rx_bytes_queued += packet->length;
- spin_unlock_irqrestore(&hw->spinlock, flags);
- }
- } else {
- /* If it's a CTRL packet, don't assemble, just queue it. */
- packet = pool_allocate(hw, NULL, length);
- if (!packet) {
- printk(KERN_ERR IPWIRELESS_PCCARD_NAME
- ": no memory for incomming ctrl packet, dropped!\n");
- return;
- }
- packet->protocol = protocol;
- packet->channel_idx = channel_idx;
- memcpy((unsigned char *)packet + sizeof(struct ipw_rx_packet),
- data, length);
- packet->length = length;
- }
-
- /*
- * If this is the last packet, then send the assembled packet on to the
- * network layer.
- */
- if (packet) {
- spin_lock_irqsave(&hw->spinlock, flags);
- list_add_tail(&packet->queue, &hw->rx_queue);
- /* Block reception of incoming packets if queue is full. */
- hw->blocking_rx =
- hw->rx_bytes_queued >= IPWIRELESS_RX_QUEUE_SIZE;
-
- spin_unlock_irqrestore(&hw->spinlock, flags);
- schedule_work(&hw->work_rx);
- }
-}
-
-/*
- * Workqueue callback
- */
-static void ipw_receive_data_work(struct work_struct *work_rx)
-{
- struct ipw_hardware *hw =
- container_of(work_rx, struct ipw_hardware, work_rx);
- unsigned long flags;
-
- spin_lock_irqsave(&hw->spinlock, flags);
- while (!list_empty(&hw->rx_queue)) {
- struct ipw_rx_packet *packet =
- list_first_entry(&hw->rx_queue,
- struct ipw_rx_packet, queue);
-
- if (hw->shutting_down)
- break;
- list_del(&packet->queue);
-
- /*
- * Note: ipwireless_network_packet_received must be called in a
- * process context (i.e. via schedule_work) because the tty
- * output code can sleep in the tty_flip_buffer_push call.
- */
- if (packet->protocol == TL_PROTOCOLID_COM_DATA) {
- if (hw->network != NULL) {
- /* If the network hasn't been disconnected. */
- spin_unlock_irqrestore(&hw->spinlock, flags);
- /*
- * This must run unlocked due to tty processing
- * and mutex locking
- */
- ipwireless_network_packet_received(
- hw->network,
- packet->channel_idx,
- (unsigned char *)packet
- + sizeof(struct ipw_rx_packet),
- packet->length);
- spin_lock_irqsave(&hw->spinlock, flags);
- }
- /* Count queued DATA bytes only */
- hw->rx_bytes_queued -= packet->length;
- } else {
- /*
- * This is safe to be called locked, callchain does
- * not block
- */
- handle_received_CTRL_packet(hw, packet->channel_idx,
- (unsigned char *)packet
- + sizeof(struct ipw_rx_packet),
- packet->length);
- }
- pool_free(hw, packet);
- /*
- * Unblock reception of incoming packets if queue is no longer
- * full.
- */
- hw->blocking_rx =
- hw->rx_bytes_queued >= IPWIRELESS_RX_QUEUE_SIZE;
- if (hw->shutting_down)
- break;
- }
- spin_unlock_irqrestore(&hw->spinlock, flags);
-}
-
-static void handle_received_CTRL_packet(struct ipw_hardware *hw,
- unsigned int channel_idx,
- unsigned char *data, int len)
-{
- struct ipw_control_packet_body *body =
- (struct ipw_control_packet_body *) data;
- unsigned int changed_mask;
-
- if (len != sizeof(struct ipw_control_packet_body)) {
- printk(KERN_INFO IPWIRELESS_PCCARD_NAME
- ": control packet was %d bytes - wrong size!\n",
- len);
- return;
- }
-
- switch (body->sig_no) {
- case COMCTRL_CTS:
- changed_mask = IPW_CONTROL_LINE_CTS;
- break;
- case COMCTRL_DCD:
- changed_mask = IPW_CONTROL_LINE_DCD;
- break;
- case COMCTRL_DSR:
- changed_mask = IPW_CONTROL_LINE_DSR;
- break;
- case COMCTRL_RI:
- changed_mask = IPW_CONTROL_LINE_RI;
- break;
- default:
- changed_mask = 0;
- }
-
- if (changed_mask != 0) {
- if (body->value)
- hw->control_lines[channel_idx] |= changed_mask;
- else
- hw->control_lines[channel_idx] &= ~changed_mask;
- if (hw->network)
- ipwireless_network_notify_control_line_change(
- hw->network,
- channel_idx,
- hw->control_lines[channel_idx],
- changed_mask);
- }
-}
-
-static void handle_received_packet(struct ipw_hardware *hw,
- union nl_packet *packet,
- unsigned short len)
-{
- unsigned int protocol = packet->hdr.protocol;
- unsigned int address = packet->hdr.address;
- unsigned int header_length;
- unsigned char *data;
- unsigned int data_len;
- int is_last = packet->hdr.packet_rank & NL_LAST_PACKET;
-
- if (packet->hdr.packet_rank & NL_FIRST_PACKET)
- header_length = NL_FIRST_PACKET_HEADER_SIZE;
- else
- header_length = NL_FOLLOWING_PACKET_HEADER_SIZE;
-
- data = packet->rawpkt + header_length;
- data_len = len - header_length;
- switch (protocol) {
- case TL_PROTOCOLID_COM_DATA:
- case TL_PROTOCOLID_COM_CTRL:
- queue_received_packet(hw, protocol, address, data, data_len,
- is_last);
- break;
- case TL_PROTOCOLID_SETUP:
- handle_received_SETUP_packet(hw, address, data, data_len,
- is_last);
- break;
- }
-}
-
-static void acknowledge_data_read(struct ipw_hardware *hw)
-{
- if (hw->hw_version == HW_VERSION_1)
- outw(DCR_RXDONE, hw->base_port + IODCR);
- else
- writew(MEMRX_PCINTACKK,
- &hw->memory_info_regs->memreg_pc_interrupt_ack);
-}
-
-/*
- * Retrieve a packet from the IPW hardware.
- */
-static void do_receive_packet(struct ipw_hardware *hw)
-{
- unsigned len;
- unsigned int i;
- unsigned char pkt[LL_MTU_MAX];
-
- start_timing();
-
- if (hw->hw_version == HW_VERSION_1) {
- len = inw(hw->base_port + IODRR);
- if (len > hw->ll_mtu) {
- printk(KERN_INFO IPWIRELESS_PCCARD_NAME
- ": received a packet of %u bytes - "
- "longer than the MTU!\n", len);
- outw(DCR_RXDONE | DCR_RXRESET, hw->base_port + IODCR);
- return;
- }
-
- for (i = 0; i < len; i += 2) {
- __le16 raw_data = inw(hw->base_port + IODRR);
- unsigned short data = le16_to_cpu(raw_data);
-
- pkt[i] = (unsigned char) data;
- pkt[i + 1] = (unsigned char) (data >> 8);
- }
- } else {
- len = inw(hw->base_port + IODMADPR);
- if (len > hw->ll_mtu) {
- printk(KERN_INFO IPWIRELESS_PCCARD_NAME
- ": received a packet of %u bytes - "
- "longer than the MTU!\n", len);
- writew(MEMRX_PCINTACKK,
- &hw->memory_info_regs->memreg_pc_interrupt_ack);
- return;
- }
-
- for (i = 0; i < len; i += 2) {
- __le16 raw_data = inw(hw->base_port + IODMADPR);
- unsigned short data = le16_to_cpu(raw_data);
-
- pkt[i] = (unsigned char) data;
- pkt[i + 1] = (unsigned char) (data >> 8);
- }
-
- while ((i & 3) != 2) {
- inw(hw->base_port + IODMADPR);
- i += 2;
- }
- }
-
- acknowledge_data_read(hw);
-
- if (ipwireless_debug)
- dump_data_bytes("recv", pkt, len);
-
- handle_received_packet(hw, (union nl_packet *) pkt, len);
-
- end_read_timing(len);
-}
-
-static int get_current_packet_priority(struct ipw_hardware *hw)
-{
- /*
- * If we're initializing, don't send anything of higher priority than
- * PRIO_SETUP. The network layer therefore need not care about
- * hardware initialization - any of its stuff will simply be queued
- * until setup is complete.
- */
- return (hw->to_setup || hw->initializing
- ? PRIO_SETUP + 1 :
- NL_NUM_OF_PRIORITIES);
-}
-
-/*
- * return 1 if something has been received from hw
- */
-static int get_packets_from_hw(struct ipw_hardware *hw)
-{
- int received = 0;
- unsigned long flags;
-
- spin_lock_irqsave(&hw->spinlock, flags);
- while (hw->rx_ready && !hw->blocking_rx) {
- received = 1;
- hw->rx_ready--;
- spin_unlock_irqrestore(&hw->spinlock, flags);
-
- do_receive_packet(hw);
-
- spin_lock_irqsave(&hw->spinlock, flags);
- }
- spin_unlock_irqrestore(&hw->spinlock, flags);
-
- return received;
-}
-
-/*
- * Send pending packet up to given priority, prioritize SETUP data until
- * hardware is fully setup.
- *
- * return 1 if more packets can be sent
- */
-static int send_pending_packet(struct ipw_hardware *hw, int priority_limit)
-{
- int more_to_send = 0;
- unsigned long flags;
-
- spin_lock_irqsave(&hw->spinlock, flags);
- if (hw->tx_queued && hw->tx_ready != 0) {
- int priority;
- struct ipw_tx_packet *packet = NULL;
-
- hw->tx_ready--;
-
- /* Pick a packet */
- for (priority = 0; priority < priority_limit; priority++) {
- if (!list_empty(&hw->tx_queue[priority])) {
- packet = list_first_entry(
- &hw->tx_queue[priority],
- struct ipw_tx_packet,
- queue);
-
- list_del(&packet->queue);
-
- break;
- }
- }
- if (!packet) {
- hw->tx_queued = 0;
- spin_unlock_irqrestore(&hw->spinlock, flags);
- return 0;
- }
- spin_unlock_irqrestore(&hw->spinlock, flags);
-
- /* Send */
- do_send_packet(hw, packet);
-
- /* Check if more to send */
- spin_lock_irqsave(&hw->spinlock, flags);
- for (priority = 0; priority < priority_limit; priority++)
- if (!list_empty(&hw->tx_queue[priority])) {
- more_to_send = 1;
- break;
- }
-
- if (!more_to_send)
- hw->tx_queued = 0;
- }
- spin_unlock_irqrestore(&hw->spinlock, flags);
-
- return more_to_send;
-}
-
-/*
- * Send and receive all queued packets.
- */
-static void ipwireless_do_tasklet(unsigned long hw_)
-{
- struct ipw_hardware *hw = (struct ipw_hardware *) hw_;
- unsigned long flags;
-
- spin_lock_irqsave(&hw->spinlock, flags);
- if (hw->shutting_down) {
- spin_unlock_irqrestore(&hw->spinlock, flags);
- return;
- }
-
- if (hw->to_setup == 1) {
- /*
- * Initial setup data sent to hardware
- */
- hw->to_setup = 2;
- spin_unlock_irqrestore(&hw->spinlock, flags);
-
- ipw_setup_hardware(hw);
- ipw_send_setup_packet(hw);
-
- send_pending_packet(hw, PRIO_SETUP + 1);
- get_packets_from_hw(hw);
- } else {
- int priority_limit = get_current_packet_priority(hw);
- int again;
-
- spin_unlock_irqrestore(&hw->spinlock, flags);
-
- do {
- again = send_pending_packet(hw, priority_limit);
- again |= get_packets_from_hw(hw);
- } while (again);
- }
-}
-
-/*
- * return true if the card is physically present.
- */
-static int is_card_present(struct ipw_hardware *hw)
-{
- if (hw->hw_version == HW_VERSION_1)
- return inw(hw->base_port + IOIR) != 0xFFFF;
- else
- return readl(&hw->memory_info_regs->memreg_card_present) ==
- CARD_PRESENT_VALUE;
-}
-
-static irqreturn_t ipwireless_handle_v1_interrupt(int irq,
- struct ipw_hardware *hw)
-{
- unsigned short irqn;
-
- irqn = inw(hw->base_port + IOIR);
-
- /* Check if card is present */
- if (irqn == 0xFFFF)
- return IRQ_NONE;
- else if (irqn != 0) {
- unsigned short ack = 0;
- unsigned long flags;
-
- /* Transmit complete. */
- if (irqn & IR_TXINTR) {
- ack |= IR_TXINTR;
- spin_lock_irqsave(&hw->spinlock, flags);
- hw->tx_ready++;
- spin_unlock_irqrestore(&hw->spinlock, flags);
- }
- /* Received data */
- if (irqn & IR_RXINTR) {
- ack |= IR_RXINTR;
- spin_lock_irqsave(&hw->spinlock, flags);
- hw->rx_ready++;
- spin_unlock_irqrestore(&hw->spinlock, flags);
- }
- if (ack != 0) {
- outw(ack, hw->base_port + IOIR);
- tasklet_schedule(&hw->tasklet);
- }
- return IRQ_HANDLED;
- }
- return IRQ_NONE;
-}
-
-static void acknowledge_pcmcia_interrupt(struct ipw_hardware *hw)
-{
- unsigned short csr = readw(&hw->memregs_CCR->reg_config_and_status);
-
- csr &= 0xfffd;
- writew(csr, &hw->memregs_CCR->reg_config_and_status);
-}
-
-static irqreturn_t ipwireless_handle_v2_v3_interrupt(int irq,
- struct ipw_hardware *hw)
-{
- int tx = 0;
- int rx = 0;
- int rx_repeat = 0;
- int try_mem_tx_old;
- unsigned long flags;
-
- do {
-
- unsigned short memtx = readw(hw->memreg_tx);
- unsigned short memtx_serial;
- unsigned short memrxdone =
- readw(&hw->memory_info_regs->memreg_rx_done);
-
- try_mem_tx_old = 0;
-
- /* check whether the interrupt was generated by ipwireless card */
- if (!(memtx & MEMTX_TX) && !(memrxdone & MEMRX_RX_DONE)) {
-
- /* check if the card uses memreg_tx_old register */
- if (hw->memreg_tx == &hw->memory_info_regs->memreg_tx_new) {
- memtx = readw(&hw->memory_info_regs->memreg_tx_old);
- if (memtx & MEMTX_TX) {
- printk(KERN_INFO IPWIRELESS_PCCARD_NAME
- ": Using memreg_tx_old\n");
- hw->memreg_tx =
- &hw->memory_info_regs->memreg_tx_old;
- } else {
- return IRQ_NONE;
- }
- } else {
- return IRQ_NONE;
- }
- }
-
- /*
- * See if the card is physically present. Note that while it is
- * powering up, it appears not to be present.
- */
- if (!is_card_present(hw)) {
- acknowledge_pcmcia_interrupt(hw);
- return IRQ_HANDLED;
- }
-
- memtx_serial = memtx & (unsigned short) 0xff00;
- if (memtx & MEMTX_TX) {
- writew(memtx_serial, hw->memreg_tx);
-
- if (hw->serial_number_detected) {
- if (memtx_serial != hw->last_memtx_serial) {
- hw->last_memtx_serial = memtx_serial;
- spin_lock_irqsave(&hw->spinlock, flags);
- hw->rx_ready++;
- spin_unlock_irqrestore(&hw->spinlock, flags);
- rx = 1;
- } else
- /* Ignore 'Timer Recovery' duplicates. */
- rx_repeat = 1;
- } else {
- /*
- * If a non-zero serial number is seen, then enable
- * serial number checking.
- */
- if (memtx_serial != 0) {
- hw->serial_number_detected = 1;
- printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME
- ": memreg_tx serial num detected\n");
-
- spin_lock_irqsave(&hw->spinlock, flags);
- hw->rx_ready++;
- spin_unlock_irqrestore(&hw->spinlock, flags);
- }
- rx = 1;
- }
- }
- if (memrxdone & MEMRX_RX_DONE) {
- writew(0, &hw->memory_info_regs->memreg_rx_done);
- spin_lock_irqsave(&hw->spinlock, flags);
- hw->tx_ready++;
- spin_unlock_irqrestore(&hw->spinlock, flags);
- tx = 1;
- }
- if (tx)
- writew(MEMRX_PCINTACKK,
- &hw->memory_info_regs->memreg_pc_interrupt_ack);
-
- acknowledge_pcmcia_interrupt(hw);
-
- if (tx || rx)
- tasklet_schedule(&hw->tasklet);
- else if (!rx_repeat) {
- if (hw->memreg_tx == &hw->memory_info_regs->memreg_tx_new) {
- if (hw->serial_number_detected)
- printk(KERN_WARNING IPWIRELESS_PCCARD_NAME
- ": spurious interrupt - new_tx mode\n");
- else {
- printk(KERN_WARNING IPWIRELESS_PCCARD_NAME
- ": no valid memreg_tx value - "
- "switching to the old memreg_tx\n");
- hw->memreg_tx =
- &hw->memory_info_regs->memreg_tx_old;
- try_mem_tx_old = 1;
- }
- } else
- printk(KERN_WARNING IPWIRELESS_PCCARD_NAME
- ": spurious interrupt - old_tx mode\n");
- }
-
- } while (try_mem_tx_old == 1);
-
- return IRQ_HANDLED;
-}
-
-irqreturn_t ipwireless_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
- struct ipw_hardware *hw = dev_id;
-
- if (hw->hw_version == HW_VERSION_1)
- return ipwireless_handle_v1_interrupt(irq, hw);
- else
- return ipwireless_handle_v2_v3_interrupt(irq, hw);
-}
-
-static void flush_packets_to_hw(struct ipw_hardware *hw)
-{
- int priority_limit;
- unsigned long flags;
-
- spin_lock_irqsave(&hw->spinlock, flags);
- priority_limit = get_current_packet_priority(hw);
- spin_unlock_irqrestore(&hw->spinlock, flags);
-
- while (send_pending_packet(hw, priority_limit));
-}
-
-static void send_packet(struct ipw_hardware *hw, int priority,
- struct ipw_tx_packet *packet)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&hw->spinlock, flags);
- list_add_tail(&packet->queue, &hw->tx_queue[priority]);
- hw->tx_queued = 1;
- spin_unlock_irqrestore(&hw->spinlock, flags);
-
- flush_packets_to_hw(hw);
-}
-
-/* Create data packet, non-atomic allocation */
-static void *alloc_data_packet(int data_size,
- unsigned char dest_addr,
- unsigned char protocol)
-{
- struct ipw_tx_packet *packet = kzalloc(
- sizeof(struct ipw_tx_packet) + data_size,
- GFP_ATOMIC);
-
- if (!packet)
- return NULL;
-
- INIT_LIST_HEAD(&packet->queue);
- packet->dest_addr = dest_addr;
- packet->protocol = protocol;
- packet->length = data_size;
-
- return packet;
-}
-
-static void *alloc_ctrl_packet(int header_size,
- unsigned char dest_addr,
- unsigned char protocol,
- unsigned char sig_no)
-{
- /*
- * sig_no is located right after ipw_tx_packet struct in every
- * CTRL or SETUP packets, we can use ipw_control_packet as a
- * common struct
- */
- struct ipw_control_packet *packet = kzalloc(header_size, GFP_ATOMIC);
-
- if (!packet)
- return NULL;
-
- INIT_LIST_HEAD(&packet->header.queue);
- packet->header.dest_addr = dest_addr;
- packet->header.protocol = protocol;
- packet->header.length = header_size - sizeof(struct ipw_tx_packet);
- packet->body.sig_no = sig_no;
-
- return packet;
-}
-
-int ipwireless_send_packet(struct ipw_hardware *hw, unsigned int channel_idx,
- unsigned char *data, unsigned int length,
- void (*callback) (void *cb, unsigned int length),
- void *callback_data)
-{
- struct ipw_tx_packet *packet;
-
- packet = alloc_data_packet(length,
- (unsigned char) (channel_idx + 1),
- TL_PROTOCOLID_COM_DATA);
- if (!packet)
- return -ENOMEM;
- packet->packet_callback = callback;
- packet->callback_data = callback_data;
- memcpy((unsigned char *) packet +
- sizeof(struct ipw_tx_packet), data, length);
-
- send_packet(hw, PRIO_DATA, packet);
- return 0;
-}
-
-static int set_control_line(struct ipw_hardware *hw, int prio,
- unsigned int channel_idx, int line, int state)
-{
- struct ipw_control_packet *packet;
- int protocolid = TL_PROTOCOLID_COM_CTRL;
-
- if (prio == PRIO_SETUP)
- protocolid = TL_PROTOCOLID_SETUP;
-
- packet = alloc_ctrl_packet(sizeof(struct ipw_control_packet),
- (unsigned char) (channel_idx + 1),
- protocolid, line);
- if (!packet)
- return -ENOMEM;
- packet->header.length = sizeof(struct ipw_control_packet_body);
- packet->body.value = (unsigned char) (state == 0 ? 0 : 1);
- send_packet(hw, prio, &packet->header);
- return 0;
-}
-
-
-static int set_DTR(struct ipw_hardware *hw, int priority,
- unsigned int channel_idx, int state)
-{
- if (state != 0)
- hw->control_lines[channel_idx] |= IPW_CONTROL_LINE_DTR;
- else
- hw->control_lines[channel_idx] &= ~IPW_CONTROL_LINE_DTR;
-
- return set_control_line(hw, priority, channel_idx, COMCTRL_DTR, state);
-}
-
-static int set_RTS(struct ipw_hardware *hw, int priority,
- unsigned int channel_idx, int state)
-{
- if (state != 0)
- hw->control_lines[channel_idx] |= IPW_CONTROL_LINE_RTS;
- else
- hw->control_lines[channel_idx] &= ~IPW_CONTROL_LINE_RTS;
-
- return set_control_line(hw, priority, channel_idx, COMCTRL_RTS, state);
-}
-
-int ipwireless_set_DTR(struct ipw_hardware *hw, unsigned int channel_idx,
- int state)
-{
- return set_DTR(hw, PRIO_CTRL, channel_idx, state);
-}
-
-int ipwireless_set_RTS(struct ipw_hardware *hw, unsigned int channel_idx,
- int state)
-{
- return set_RTS(hw, PRIO_CTRL, channel_idx, state);
-}
-
-struct ipw_setup_get_version_query_packet {
- struct ipw_tx_packet header;
- struct tl_setup_get_version_qry body;
-};
-
-struct ipw_setup_config_packet {
- struct ipw_tx_packet header;
- struct tl_setup_config_msg body;
-};
-
-struct ipw_setup_config_done_packet {
- struct ipw_tx_packet header;
- struct tl_setup_config_done_msg body;
-};
-
-struct ipw_setup_open_packet {
- struct ipw_tx_packet header;
- struct tl_setup_open_msg body;
-};
-
-struct ipw_setup_info_packet {
- struct ipw_tx_packet header;
- struct tl_setup_info_msg body;
-};
-
-struct ipw_setup_reboot_msg_ack {
- struct ipw_tx_packet header;
- struct TlSetupRebootMsgAck body;
-};
-
-/* This handles the actual initialization of the card */
-static void __handle_setup_get_version_rsp(struct ipw_hardware *hw)
-{
- struct ipw_setup_config_packet *config_packet;
- struct ipw_setup_config_done_packet *config_done_packet;
- struct ipw_setup_open_packet *open_packet;
- struct ipw_setup_info_packet *info_packet;
- int port;
- unsigned int channel_idx;
-
- /* generate config packet */
- for (port = 1; port <= NL_NUM_OF_ADDRESSES; port++) {
- config_packet = alloc_ctrl_packet(
- sizeof(struct ipw_setup_config_packet),
- ADDR_SETUP_PROT,
- TL_PROTOCOLID_SETUP,
- TL_SETUP_SIGNO_CONFIG_MSG);
- if (!config_packet)
- goto exit_nomem;
- config_packet->header.length = sizeof(struct tl_setup_config_msg);
- config_packet->body.port_no = port;
- config_packet->body.prio_data = PRIO_DATA;
- config_packet->body.prio_ctrl = PRIO_CTRL;
- send_packet(hw, PRIO_SETUP, &config_packet->header);
- }
- config_done_packet = alloc_ctrl_packet(
- sizeof(struct ipw_setup_config_done_packet),
- ADDR_SETUP_PROT,
- TL_PROTOCOLID_SETUP,
- TL_SETUP_SIGNO_CONFIG_DONE_MSG);
- if (!config_done_packet)
- goto exit_nomem;
- config_done_packet->header.length = sizeof(struct tl_setup_config_done_msg);
- send_packet(hw, PRIO_SETUP, &config_done_packet->header);
-
- /* generate open packet */
- for (port = 1; port <= NL_NUM_OF_ADDRESSES; port++) {
- open_packet = alloc_ctrl_packet(
- sizeof(struct ipw_setup_open_packet),
- ADDR_SETUP_PROT,
- TL_PROTOCOLID_SETUP,
- TL_SETUP_SIGNO_OPEN_MSG);
- if (!open_packet)
- goto exit_nomem;
- open_packet->header.length = sizeof(struct tl_setup_open_msg);
- open_packet->body.port_no = port;
- send_packet(hw, PRIO_SETUP, &open_packet->header);
- }
- for (channel_idx = 0;
- channel_idx < NL_NUM_OF_ADDRESSES; channel_idx++) {
- int ret;
-
- ret = set_DTR(hw, PRIO_SETUP, channel_idx,
- (hw->control_lines[channel_idx] &
- IPW_CONTROL_LINE_DTR) != 0);
- if (ret) {
- printk(KERN_ERR IPWIRELESS_PCCARD_NAME
- ": error setting DTR (%d)\n", ret);
- return;
- }
-
- set_RTS(hw, PRIO_SETUP, channel_idx,
- (hw->control_lines [channel_idx] &
- IPW_CONTROL_LINE_RTS) != 0);
- if (ret) {
- printk(KERN_ERR IPWIRELESS_PCCARD_NAME
- ": error setting RTS (%d)\n", ret);
- return;
- }
- }
- /*
- * For NDIS we assume that we are using sync PPP frames, for COM async.
- * This driver uses NDIS mode too. We don't bother with translation
- * from async -> sync PPP.
- */
- info_packet = alloc_ctrl_packet(sizeof(struct ipw_setup_info_packet),
- ADDR_SETUP_PROT,
- TL_PROTOCOLID_SETUP,
- TL_SETUP_SIGNO_INFO_MSG);
- if (!info_packet)
- goto exit_nomem;
- info_packet->header.length = sizeof(struct tl_setup_info_msg);
- info_packet->body.driver_type = NDISWAN_DRIVER;
- info_packet->body.major_version = NDISWAN_DRIVER_MAJOR_VERSION;
- info_packet->body.minor_version = NDISWAN_DRIVER_MINOR_VERSION;
- send_packet(hw, PRIO_SETUP, &info_packet->header);
-
- /* Initialization is now complete, so we clear the 'to_setup' flag */
- hw->to_setup = 0;
-
- return;
-
-exit_nomem:
- printk(KERN_ERR IPWIRELESS_PCCARD_NAME
- ": not enough memory to alloc control packet\n");
- hw->to_setup = -1;
-}
-
-static void handle_setup_get_version_rsp(struct ipw_hardware *hw,
- unsigned char vers_no)
-{
- del_timer(&hw->setup_timer);
- hw->initializing = 0;
- printk(KERN_INFO IPWIRELESS_PCCARD_NAME ": card is ready.\n");
-
- if (vers_no == TL_SETUP_VERSION)
- __handle_setup_get_version_rsp(hw);
- else
- printk(KERN_ERR
- IPWIRELESS_PCCARD_NAME
- ": invalid hardware version no %u\n",
- (unsigned int) vers_no);
-}
-
-static void ipw_send_setup_packet(struct ipw_hardware *hw)
-{
- struct ipw_setup_get_version_query_packet *ver_packet;
-
- ver_packet = alloc_ctrl_packet(
- sizeof(struct ipw_setup_get_version_query_packet),
- ADDR_SETUP_PROT, TL_PROTOCOLID_SETUP,
- TL_SETUP_SIGNO_GET_VERSION_QRY);
- ver_packet->header.length = sizeof(struct tl_setup_get_version_qry);
-
- /*
- * Response is handled in handle_received_SETUP_packet
- */
- send_packet(hw, PRIO_SETUP, &ver_packet->header);
-}
-
-static void handle_received_SETUP_packet(struct ipw_hardware *hw,
- unsigned int address,
- unsigned char *data, int len,
- int is_last)
-{
- union ipw_setup_rx_msg *rx_msg = (union ipw_setup_rx_msg *) data;
-
- if (address != ADDR_SETUP_PROT) {
- printk(KERN_INFO IPWIRELESS_PCCARD_NAME
- ": setup packet has bad address %d\n", address);
- return;
- }
-
- switch (rx_msg->sig_no) {
- case TL_SETUP_SIGNO_GET_VERSION_RSP:
- if (hw->to_setup)
- handle_setup_get_version_rsp(hw,
- rx_msg->version_rsp_msg.version);
- break;
-
- case TL_SETUP_SIGNO_OPEN_MSG:
- if (ipwireless_debug) {
- unsigned int channel_idx = rx_msg->open_msg.port_no - 1;
-
- printk(KERN_INFO IPWIRELESS_PCCARD_NAME
- ": OPEN_MSG [channel %u] reply received\n",
- channel_idx);
- }
- break;
-
- case TL_SETUP_SIGNO_INFO_MSG_ACK:
- if (ipwireless_debug)
- printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME
- ": card successfully configured as NDISWAN\n");
- break;
-
- case TL_SETUP_SIGNO_REBOOT_MSG:
- if (hw->to_setup)
- printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME
- ": Setup not completed - ignoring reboot msg\n");
- else {
- struct ipw_setup_reboot_msg_ack *packet;
-
- printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME
- ": Acknowledging REBOOT message\n");
- packet = alloc_ctrl_packet(
- sizeof(struct ipw_setup_reboot_msg_ack),
- ADDR_SETUP_PROT, TL_PROTOCOLID_SETUP,
- TL_SETUP_SIGNO_REBOOT_MSG_ACK);
- packet->header.length =
- sizeof(struct TlSetupRebootMsgAck);
- send_packet(hw, PRIO_SETUP, &packet->header);
- if (hw->reboot_callback)
- hw->reboot_callback(hw->reboot_callback_data);
- }
- break;
-
- default:
- printk(KERN_INFO IPWIRELESS_PCCARD_NAME
- ": unknown setup message %u received\n",
- (unsigned int) rx_msg->sig_no);
- }
-}
-
-static void do_close_hardware(struct ipw_hardware *hw)
-{
- unsigned int irqn;
-
- if (hw->hw_version == HW_VERSION_1) {
- /* Disable TX and RX interrupts. */
- outw(0, hw->base_port + IOIER);
-
- /* Acknowledge any outstanding interrupt requests */
- irqn = inw(hw->base_port + IOIR);
- if (irqn & IR_TXINTR)
- outw(IR_TXINTR, hw->base_port + IOIR);
- if (irqn & IR_RXINTR)
- outw(IR_RXINTR, hw->base_port + IOIR);
-
- synchronize_irq(hw->irq);
- }
-}
-
-struct ipw_hardware *ipwireless_hardware_create(void)
-{
- int i;
- struct ipw_hardware *hw =
- kzalloc(sizeof(struct ipw_hardware), GFP_KERNEL);
-
- if (!hw)
- return NULL;
-
- hw->irq = -1;
- hw->initializing = 1;
- hw->tx_ready = 1;
- hw->rx_bytes_queued = 0;
- hw->rx_pool_size = 0;
- hw->last_memtx_serial = (unsigned short) 0xffff;
- for (i = 0; i < NL_NUM_OF_PRIORITIES; i++)
- INIT_LIST_HEAD(&hw->tx_queue[i]);
-
- INIT_LIST_HEAD(&hw->rx_queue);
- INIT_LIST_HEAD(&hw->rx_pool);
- spin_lock_init(&hw->spinlock);
- tasklet_init(&hw->tasklet, ipwireless_do_tasklet, (unsigned long) hw);
- INIT_WORK(&hw->work_rx, ipw_receive_data_work);
- setup_timer(&hw->setup_timer, ipwireless_setup_timer,
- (unsigned long) hw);
-
- return hw;
-}
-
-void ipwireless_init_hardware_v1(struct ipw_hardware *hw,
- unsigned int base_port,
- void __iomem *attr_memory,
- void __iomem *common_memory,
- int is_v2_card,
- void (*reboot_callback) (void *data),
- void *reboot_callback_data)
-{
- if (hw->removed) {
- hw->removed = 0;
- enable_irq(hw->irq);
- }
- hw->base_port = base_port;
- hw->hw_version = is_v2_card ? HW_VERSION_2 : HW_VERSION_1;
- hw->ll_mtu = hw->hw_version == HW_VERSION_1 ? LL_MTU_V1 : LL_MTU_V2;
- hw->memregs_CCR = (struct MEMCCR __iomem *)
- ((unsigned short __iomem *) attr_memory + 0x200);
- hw->memory_info_regs = (struct MEMINFREG __iomem *) common_memory;
- hw->memreg_tx = &hw->memory_info_regs->memreg_tx_new;
- hw->reboot_callback = reboot_callback;
- hw->reboot_callback_data = reboot_callback_data;
-}
-
-void ipwireless_init_hardware_v2_v3(struct ipw_hardware *hw)
-{
- hw->initializing = 1;
- hw->init_loops = 0;
- printk(KERN_INFO IPWIRELESS_PCCARD_NAME
- ": waiting for card to start up...\n");
- ipwireless_setup_timer((unsigned long) hw);
-}
-
-static void ipwireless_setup_timer(unsigned long data)
-{
- struct ipw_hardware *hw = (struct ipw_hardware *) data;
-
- hw->init_loops++;
-
- if (hw->init_loops == TL_SETUP_MAX_VERSION_QRY &&
- hw->hw_version == HW_VERSION_2 &&
- hw->memreg_tx == &hw->memory_info_regs->memreg_tx_new) {
- printk(KERN_INFO IPWIRELESS_PCCARD_NAME
- ": failed to startup using TX2, trying TX\n");
-
- hw->memreg_tx = &hw->memory_info_regs->memreg_tx_old;
- hw->init_loops = 0;
- }
- /* Give up after a certain number of retries */
- if (hw->init_loops == TL_SETUP_MAX_VERSION_QRY) {
- printk(KERN_INFO IPWIRELESS_PCCARD_NAME
- ": card failed to start up!\n");
- hw->initializing = 0;
- } else {
- /* Do not attempt to write to the board if it is not present. */
- if (is_card_present(hw)) {
- unsigned long flags;
-
- spin_lock_irqsave(&hw->spinlock, flags);
- hw->to_setup = 1;
- hw->tx_ready = 1;
- spin_unlock_irqrestore(&hw->spinlock, flags);
- tasklet_schedule(&hw->tasklet);
- }
-
- mod_timer(&hw->setup_timer,
- jiffies + msecs_to_jiffies(TL_SETUP_VERSION_QRY_TMO));
- }
-}
-
-/*
- * Stop any interrupts from executing so that, once this function returns,
- * other layers of the driver can be sure they won't get any more callbacks.
- * Thus must be called on a proper process context.
- */
-void ipwireless_stop_interrupts(struct ipw_hardware *hw)
-{
- if (!hw->shutting_down) {
- /* Tell everyone we are going down. */
- hw->shutting_down = 1;
- del_timer(&hw->setup_timer);
-
- /* Prevent the hardware from sending any more interrupts */
- do_close_hardware(hw);
- }
-}
-
-void ipwireless_hardware_free(struct ipw_hardware *hw)
-{
- int i;
- struct ipw_rx_packet *rp, *rq;
- struct ipw_tx_packet *tp, *tq;
-
- ipwireless_stop_interrupts(hw);
-
- flush_scheduled_work();
-
- for (i = 0; i < NL_NUM_OF_ADDRESSES; i++)
- if (hw->packet_assembler[i] != NULL)
- kfree(hw->packet_assembler[i]);
-
- for (i = 0; i < NL_NUM_OF_PRIORITIES; i++)
- list_for_each_entry_safe(tp, tq, &hw->tx_queue[i], queue) {
- list_del(&tp->queue);
- kfree(tp);
- }
-
- list_for_each_entry_safe(rp, rq, &hw->rx_queue, queue) {
- list_del(&rp->queue);
- kfree(rp);
- }
-
- list_for_each_entry_safe(rp, rq, &hw->rx_pool, queue) {
- list_del(&rp->queue);
- kfree(rp);
- }
- kfree(hw);
-}
-
-/*
- * Associate the specified network with this hardware, so it will receive events
- * from it.
- */
-void ipwireless_associate_network(struct ipw_hardware *hw,
- struct ipw_network *network)
-{
- hw->network = network;
-}
diff --git a/trunk/drivers/char/pcmcia/ipwireless/hardware.h b/trunk/drivers/char/pcmcia/ipwireless/hardware.h
deleted file mode 100644
index c83190ffb0e7..000000000000
--- a/trunk/drivers/char/pcmcia/ipwireless/hardware.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * IPWireless 3G PCMCIA Network Driver
- *
- * Original code
- * by Stephen Blackheath ,
- * Ben Martel
- *
- * Copyrighted as follows:
- * Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
- *
- * Various driver changes and rewrites, port to new kernels
- * Copyright (C) 2006-2007 Jiri Kosina
- *
- * Misc code cleanups and updates
- * Copyright (C) 2007 David Sterba
- */
-
-#ifndef _IPWIRELESS_CS_HARDWARE_H_
-#define _IPWIRELESS_CS_HARDWARE_H_
-
-#include
-#include
-#include
-
-#define IPW_CONTROL_LINE_CTS 0x0001
-#define IPW_CONTROL_LINE_DCD 0x0002
-#define IPW_CONTROL_LINE_DSR 0x0004
-#define IPW_CONTROL_LINE_RI 0x0008
-#define IPW_CONTROL_LINE_DTR 0x0010
-#define IPW_CONTROL_LINE_RTS 0x0020
-
-struct ipw_hardware;
-struct ipw_network;
-
-struct ipw_hardware *ipwireless_hardware_create(void);
-void ipwireless_hardware_free(struct ipw_hardware *hw);
-irqreturn_t ipwireless_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-int ipwireless_set_DTR(struct ipw_hardware *hw, unsigned int channel_idx,
- int state);
-int ipwireless_set_RTS(struct ipw_hardware *hw, unsigned int channel_idx,
- int state);
-int ipwireless_send_packet(struct ipw_hardware *hw,
- unsigned int channel_idx,
- unsigned char *data,
- unsigned int length,
- void (*packet_sent_callback) (void *cb,
- unsigned int length),
- void *sent_cb_data);
-void ipwireless_associate_network(struct ipw_hardware *hw,
- struct ipw_network *net);
-void ipwireless_stop_interrupts(struct ipw_hardware *hw);
-void ipwireless_init_hardware_v1(struct ipw_hardware *hw,
- unsigned int base_port,
- void __iomem *attr_memory,
- void __iomem *common_memory,
- int is_v2_card,
- void (*reboot_cb) (void *data),
- void *reboot_cb_data);
-void ipwireless_init_hardware_v2_v3(struct ipw_hardware *hw);
-void ipwireless_sleep(unsigned int tenths);
-int ipwireless_dump_hardware_state(char *p, size_t limit,
- struct ipw_hardware *hw);
-
-#endif
diff --git a/trunk/drivers/char/pcmcia/ipwireless/main.c b/trunk/drivers/char/pcmcia/ipwireless/main.c
deleted file mode 100644
index 00c7f8407e3e..000000000000
--- a/trunk/drivers/char/pcmcia/ipwireless/main.c
+++ /dev/null
@@ -1,501 +0,0 @@
-/*
- * IPWireless 3G PCMCIA Network Driver
- *
- * Original code
- * by Stephen Blackheath ,
- * Ben Martel
- *
- * Copyrighted as follows:
- * Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
- *
- * Various driver changes and rewrites, port to new kernels
- * Copyright (C) 2006-2007 Jiri Kosina
- *
- * Misc code cleanups and updates
- * Copyright (C) 2007 David Sterba
- */
-
-#include "hardware.h"
-#include "network.h"
-#include "main.h"
-#include "tty.h"
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-static struct pcmcia_device_id ipw_ids[] = {
- PCMCIA_DEVICE_MANF_CARD(0x02f2, 0x0100),
- PCMCIA_DEVICE_MANF_CARD(0x02f2, 0x0200),
- PCMCIA_DEVICE_NULL
-};
-MODULE_DEVICE_TABLE(pcmcia, ipw_ids);
-
-static void ipwireless_detach(struct pcmcia_device *link);
-
-/*
- * Module params
- */
-/* Debug mode: more verbose, print sent/recv bytes */
-int ipwireless_debug;
-int ipwireless_loopback;
-int ipwireless_out_queue = 1;
-
-module_param_named(debug, ipwireless_debug, int, 0);
-module_param_named(loopback, ipwireless_loopback, int, 0);
-module_param_named(out_queue, ipwireless_out_queue, int, 0);
-MODULE_PARM_DESC(debug, "switch on debug messages [0]");
-MODULE_PARM_DESC(loopback,
- "debug: enable ras_raw channel [0]");
-MODULE_PARM_DESC(out_queue, "debug: set size of outgoing queue [1]");
-
-/* Executes in process context. */
-static void signalled_reboot_work(struct work_struct *work_reboot)
-{
- struct ipw_dev *ipw = container_of(work_reboot, struct ipw_dev,
- work_reboot);
- struct pcmcia_device *link = ipw->link;
- int ret = pccard_reset_card(link->socket);
-
- if (ret != CS_SUCCESS)
- cs_error(link, ResetCard, ret);
-}
-
-static void signalled_reboot_callback(void *callback_data)
-{
- struct ipw_dev *ipw = (struct ipw_dev *) callback_data;
-
- /* Delegate to process context. */
- schedule_work(&ipw->work_reboot);
-}
-
-static int config_ipwireless(struct ipw_dev *ipw)
-{
- struct pcmcia_device *link = ipw->link;
- int ret;
- config_info_t conf;
- tuple_t tuple;
- unsigned short buf[64];
- cisparse_t parse;
- unsigned short cor_value;
- win_req_t request_attr_memory;
- win_req_t request_common_memory;
- memreq_t memreq_attr_memory;
- memreq_t memreq_common_memory;
-
- ipw->is_v2_card = 0;
-
- tuple.Attributes = 0;
- tuple.TupleData = (cisdata_t *) buf;
- tuple.TupleDataMax = sizeof(buf);
- tuple.TupleOffset = 0;
-
- tuple.DesiredTuple = RETURN_FIRST_TUPLE;
-
- ret = pcmcia_get_first_tuple(link, &tuple);
-
- while (ret == 0) {
- ret = pcmcia_get_tuple_data(link, &tuple);
-
- if (ret != CS_SUCCESS) {
- cs_error(link, GetTupleData, ret);
- goto exit0;
- }
- ret = pcmcia_get_next_tuple(link, &tuple);
- }
-
- tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-
- ret = pcmcia_get_first_tuple(link, &tuple);
-
- if (ret != CS_SUCCESS) {
- cs_error(link, GetFirstTuple, ret);
- goto exit0;
- }
-
- ret = pcmcia_get_tuple_data(link, &tuple);
-
- if (ret != CS_SUCCESS) {
- cs_error(link, GetTupleData, ret);
- goto exit0;
- }
-
- ret = pcmcia_parse_tuple(link, &tuple, &parse);
-
- if (ret != CS_SUCCESS) {
- cs_error(link, ParseTuple, ret);
- goto exit0;
- }
-
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
- link->io.BasePort1 = parse.cftable_entry.io.win[0].base;
- link->io.NumPorts1 = parse.cftable_entry.io.win[0].len;
- link->io.IOAddrLines = 16;
-
- link->irq.IRQInfo1 = parse.cftable_entry.irq.IRQInfo1;
-
- /* 0x40 causes it to generate level mode interrupts. */
- /* 0x04 enables IREQ pin. */
- cor_value = parse.cftable_entry.index | 0x44;
- link->conf.ConfigIndex = cor_value;
-
- /* IRQ and I/O settings */
- tuple.DesiredTuple = CISTPL_CONFIG;
-
- ret = pcmcia_get_first_tuple(link, &tuple);
-
- if (ret != CS_SUCCESS) {
- cs_error(link, GetFirstTuple, ret);
- goto exit0;
- }
-
- ret = pcmcia_get_tuple_data(link, &tuple);
-
- if (ret != CS_SUCCESS) {
- cs_error(link, GetTupleData, ret);
- goto exit0;
- }
-
- ret = pcmcia_parse_tuple(link, &tuple, &parse);
-
- if (ret != CS_SUCCESS) {
- cs_error(link, GetTupleData, ret);
- goto exit0;
- }
- link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.ConfigBase = parse.config.base;
- link->conf.Present = parse.config.rmask[0];
- link->conf.IntType = INT_MEMORY_AND_IO;
-
- link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT;
- link->irq.Handler = ipwireless_interrupt;
- link->irq.Instance = ipw->hardware;
-
- ret = pcmcia_request_io(link, &link->io);
-
- if (ret != CS_SUCCESS) {
- cs_error(link, RequestIO, ret);
- goto exit0;
- }
-
- /* memory settings */
-
- tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-
- ret = pcmcia_get_first_tuple(link, &tuple);
-
- if (ret != CS_SUCCESS) {
- cs_error(link, GetFirstTuple, ret);
- goto exit1;
- }
-
- ret = pcmcia_get_tuple_data(link, &tuple);
-
- if (ret != CS_SUCCESS) {
- cs_error(link, GetTupleData, ret);
- goto exit1;
- }
-
- ret = pcmcia_parse_tuple(link, &tuple, &parse);
-
- if (ret != CS_SUCCESS) {
- cs_error(link, ParseTuple, ret);
- goto exit1;
- }
-
- if (parse.cftable_entry.mem.nwin > 0) {
- request_common_memory.Attributes =
- WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM | WIN_ENABLE;
- request_common_memory.Base =
- parse.cftable_entry.mem.win[0].host_addr;
- request_common_memory.Size = parse.cftable_entry.mem.win[0].len;
- if (request_common_memory.Size < 0x1000)
- request_common_memory.Size = 0x1000;
- request_common_memory.AccessSpeed = 0;
-
- ret = pcmcia_request_window(&link, &request_common_memory,
- &ipw->handle_common_memory);
-
- if (ret != CS_SUCCESS) {
- cs_error(link, RequestWindow, ret);
- goto exit1;
- }
-
- memreq_common_memory.CardOffset =
- parse.cftable_entry.mem.win[0].card_addr;
- memreq_common_memory.Page = 0;
-
- ret = pcmcia_map_mem_page(ipw->handle_common_memory,
- &memreq_common_memory);
-
- if (ret != CS_SUCCESS) {
- cs_error(link, MapMemPage, ret);
- goto exit1;
- }
-
- ipw->is_v2_card =
- parse.cftable_entry.mem.win[0].len == 0x100;
-
- ipw->common_memory = ioremap(request_common_memory.Base,
- request_common_memory.Size);
-
- request_attr_memory.Attributes =
- WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_AM | WIN_ENABLE;
- request_attr_memory.Base = 0;
- request_attr_memory.Size = 0; /* this used to be 0x1000 */
- request_attr_memory.AccessSpeed = 0;
-
- ret = pcmcia_request_window(&link, &request_attr_memory,
- &ipw->handle_attr_memory);
-
- if (ret != CS_SUCCESS) {
- cs_error(link, RequestWindow, ret);
- goto exit2;
- }
-
- memreq_attr_memory.CardOffset = 0;
- memreq_attr_memory.Page = 0;
-
- ret = pcmcia_map_mem_page(ipw->handle_attr_memory,
- &memreq_attr_memory);
-
- if (ret != CS_SUCCESS) {
- cs_error(link, MapMemPage, ret);
- goto exit2;
- }
-
- ipw->attr_memory = ioremap(request_attr_memory.Base,
- request_attr_memory.Size);
- }
-
- INIT_WORK(&ipw->work_reboot, signalled_reboot_work);
-
- ipwireless_init_hardware_v1(ipw->hardware, link->io.BasePort1,
- ipw->attr_memory, ipw->common_memory,
- ipw->is_v2_card, signalled_reboot_callback,
- ipw);
-
- ret = pcmcia_request_irq(link, &link->irq);
-
- if (ret != CS_SUCCESS) {
- cs_error(link, RequestIRQ, ret);
- goto exit3;
- }
-
- /* Look up current Vcc */
-
- ret = pcmcia_get_configuration_info(link, &conf);
-
- if (ret != CS_SUCCESS) {
- cs_error(link, GetConfigurationInfo, ret);
- goto exit4;
- }
-
- printk(KERN_INFO IPWIRELESS_PCCARD_NAME ": Card type %s\n",
- ipw->is_v2_card ? "V2/V3" : "V1");
- printk(KERN_INFO IPWIRELESS_PCCARD_NAME
- ": I/O ports 0x%04x-0x%04x, irq %d\n",
- (unsigned int) link->io.BasePort1,
- (unsigned int) (link->io.BasePort1 +
- link->io.NumPorts1 - 1),
- (unsigned int) link->irq.AssignedIRQ);
- if (ipw->attr_memory && ipw->common_memory)
- printk(KERN_INFO IPWIRELESS_PCCARD_NAME
- ": attr memory 0x%08lx-0x%08lx, "
- "common memory 0x%08lx-0x%08lx\n",
- request_attr_memory.Base,
- request_attr_memory.Base
- + request_attr_memory.Size - 1,
- request_common_memory.Base,
- request_common_memory.Base
- + request_common_memory.Size - 1);
-
- ipw->network = ipwireless_network_create(ipw->hardware);
- if (!ipw->network)
- goto exit3;
-
- ipw->tty = ipwireless_tty_create(ipw->hardware, ipw->network,
- ipw->nodes);
- if (!ipw->tty)
- goto exit3;
-
- ipwireless_init_hardware_v2_v3(ipw->hardware);
-
- /*
- * Do the RequestConfiguration last, because it enables interrupts.
- * Then we don't get any interrupts before we're ready for them.
- */
- ret = pcmcia_request_configuration(link, &link->conf);
-
- if (ret != CS_SUCCESS) {
- cs_error(link, RequestConfiguration, ret);
- goto exit4;
- }
-
- link->dev_node = &ipw->nodes[0];
-
- return 0;
-
-exit4:
- pcmcia_disable_device(link);
-exit3:
- if (ipw->attr_memory) {
- iounmap(ipw->attr_memory);
- pcmcia_release_window(ipw->handle_attr_memory);
- pcmcia_disable_device(link);
- }
-exit2:
- if (ipw->common_memory) {
- iounmap(ipw->common_memory);
- pcmcia_release_window(ipw->handle_common_memory);
- }
-exit1:
- pcmcia_disable_device(link);
-exit0:
- return -1;
-}
-
-static void release_ipwireless(struct ipw_dev *ipw)
-{
- struct pcmcia_device *link = ipw->link;
-
- pcmcia_disable_device(link);
-
- if (ipw->common_memory)
- iounmap(ipw->common_memory);
- if (ipw->attr_memory)
- iounmap(ipw->attr_memory);
- if (ipw->common_memory)
- pcmcia_release_window(ipw->handle_common_memory);
- if (ipw->attr_memory)
- pcmcia_release_window(ipw->handle_attr_memory);
- pcmcia_disable_device(link);
-}
-
-/*
- * ipwireless_attach() creates an "instance" of the driver, allocating
- * local data structures for one device (one interface). The device
- * is registered with Card Services.
- *
- * The pcmcia_device structure is initialized, but we don't actually
- * configure the card at this point -- we wait until we receive a
- * card insertion event.
- */
-static int ipwireless_attach(struct pcmcia_device *link)
-{
- struct ipw_dev *ipw;
- int ret;
-
- ipw = kzalloc(sizeof(struct ipw_dev), GFP_KERNEL);
- if (!ipw)
- return -ENOMEM;
-
- ipw->link = link;
- link->priv = ipw;
- link->irq.Instance = ipw;
-
- /* Link this device into our device list. */
- link->dev_node = &ipw->nodes[0];
-
- ipw->hardware = ipwireless_hardware_create();
- if (!ipw->hardware) {
- kfree(ipw);
- return -ENOMEM;
- }
- /* RegisterClient will call config_ipwireless */
-
- ret = config_ipwireless(ipw);
-
- if (ret != 0) {
- cs_error(link, RegisterClient, ret);
- ipwireless_detach(link);
- return ret;
- }
-
- return 0;
-}
-
-/*
- * This deletes a driver "instance". The device is de-registered with
- * Card Services. If it has been released, all local data structures
- * are freed. Otherwise, the structures will be freed when the device
- * is released.
- */
-static void ipwireless_detach(struct pcmcia_device *link)
-{
- struct ipw_dev *ipw = link->priv;
-
- release_ipwireless(ipw);
-
- /* Break the link with Card Services */
- if (link)
- pcmcia_disable_device(link);
-
- if (ipw->tty != NULL)
- ipwireless_tty_free(ipw->tty);
- if (ipw->network != NULL)
- ipwireless_network_free(ipw->network);
- if (ipw->hardware != NULL)
- ipwireless_hardware_free(ipw->hardware);
- kfree(ipw);
-}
-
-static struct pcmcia_driver me = {
- .owner = THIS_MODULE,
- .probe = ipwireless_attach,
- .remove = ipwireless_detach,
- .drv = { .name = IPWIRELESS_PCCARD_NAME },
- .id_table = ipw_ids
-};
-
-/*
- * Module insertion : initialisation of the module.
- * Register the card with cardmgr...
- */
-static int __init init_ipwireless(void)
-{
- int ret;
-
- printk(KERN_INFO IPWIRELESS_PCCARD_NAME " "
- IPWIRELESS_PCMCIA_VERSION " by " IPWIRELESS_PCMCIA_AUTHOR "\n");
-
- ret = ipwireless_tty_init();
- if (ret != 0)
- return ret;
-
- ret = pcmcia_register_driver(&me);
- if (ret != 0)
- ipwireless_tty_release();
-
- return ret;
-}
-
-/*
- * Module removal
- */
-static void __exit exit_ipwireless(void)
-{
- printk(KERN_INFO IPWIRELESS_PCCARD_NAME " "
- IPWIRELESS_PCMCIA_VERSION " removed\n");
-
- pcmcia_unregister_driver(&me);
- ipwireless_tty_release();
-}
-
-module_init(init_ipwireless);
-module_exit(exit_ipwireless);
-
-MODULE_AUTHOR(IPWIRELESS_PCMCIA_AUTHOR);
-MODULE_DESCRIPTION(IPWIRELESS_PCCARD_NAME " " IPWIRELESS_PCMCIA_VERSION);
-MODULE_LICENSE("GPL");
diff --git a/trunk/drivers/char/pcmcia/ipwireless/main.h b/trunk/drivers/char/pcmcia/ipwireless/main.h
deleted file mode 100644
index 1bfdcc8d47d6..000000000000
--- a/trunk/drivers/char/pcmcia/ipwireless/main.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * IPWireless 3G PCMCIA Network Driver
- *
- * Original code
- * by Stephen Blackheath ,
- * Ben Martel
- *
- * Copyrighted as follows:
- * Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
- *
- * Various driver changes and rewrites, port to new kernels
- * Copyright (C) 2006-2007 Jiri Kosina
- *
- * Misc code cleanups and updates
- * Copyright (C) 2007 David Sterba
- */
-
-#ifndef _IPWIRELESS_CS_H_
-#define _IPWIRELESS_CS_H_
-
-#include
-#include
-
-#include
-#include
-#include
-#include
-
-#include "hardware.h"
-
-#define IPWIRELESS_PCCARD_NAME "ipwireless"
-#define IPWIRELESS_PCMCIA_VERSION "1.1"
-#define IPWIRELESS_PCMCIA_AUTHOR \
- "Stephen Blackheath, Ben Martel, Jiri Kosina and David Sterba"
-
-#define IPWIRELESS_TX_QUEUE_SIZE 262144
-#define IPWIRELESS_RX_QUEUE_SIZE 262144
-
-#define IPWIRELESS_STATE_DEBUG
-
-struct ipw_hardware;
-struct ipw_network;
-struct ipw_tty;
-
-struct ipw_dev {
- struct pcmcia_device *link;
- int is_v2_card;
- window_handle_t handle_attr_memory;
- void __iomem *attr_memory;
- window_handle_t handle_common_memory;
- void __iomem *common_memory;
- dev_node_t nodes[2];
- /* Reference to attribute memory, containing CIS data */
- void *attribute_memory;
-
- /* Hardware context */
- struct ipw_hardware *hardware;
- /* Network layer context */
- struct ipw_network *network;
- /* TTY device context */
- struct ipw_tty *tty;
- struct work_struct work_reboot;
-};
-
-/* Module parametres */
-extern int ipwireless_debug;
-extern int ipwireless_loopback;
-extern int ipwireless_out_queue;
-
-#endif
diff --git a/trunk/drivers/char/pcmcia/ipwireless/network.c b/trunk/drivers/char/pcmcia/ipwireless/network.c
deleted file mode 100644
index ff35230058d3..000000000000
--- a/trunk/drivers/char/pcmcia/ipwireless/network.c
+++ /dev/null
@@ -1,512 +0,0 @@
-/*
- * IPWireless 3G PCMCIA Network Driver
- *
- * Original code
- * by Stephen Blackheath ,
- * Ben Martel
- *
- * Copyrighted as follows:
- * Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
- *
- * Various driver changes and rewrites, port to new kernels
- * Copyright (C) 2006-2007 Jiri Kosina
- *
- * Misc code cleanups and updates
- * Copyright (C) 2007 David Sterba
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "network.h"
-#include "hardware.h"
-#include "main.h"
-#include "tty.h"
-
-#define MAX_OUTGOING_PACKETS_QUEUED ipwireless_out_queue
-#define MAX_ASSOCIATED_TTYS 2
-
-#define SC_RCV_BITS (SC_RCV_B7_1|SC_RCV_B7_0|SC_RCV_ODDP|SC_RCV_EVNP)
-
-struct ipw_network {
- /* Hardware context, used for calls to hardware layer. */
- struct ipw_hardware *hardware;
- /* Context for kernel 'generic_ppp' functionality */
- struct ppp_channel *ppp_channel;
- /* tty context connected with IPW console */
- struct ipw_tty *associated_ttys[NO_OF_IPW_CHANNELS][MAX_ASSOCIATED_TTYS];
- /* True if ppp needs waking up once we're ready to xmit */
- int ppp_blocked;
- /* Number of packets queued up in hardware module. */
- int outgoing_packets_queued;
- /* Spinlock to avoid interrupts during shutdown */
- spinlock_t spinlock;
- struct mutex close_lock;
-
- /* PPP ioctl data, not actually used anywere */
- unsigned int flags;
- unsigned int rbits;
- u32 xaccm[8];
- u32 raccm;
- int mru;
-
- int shutting_down;
- unsigned int ras_control_lines;
-
- struct work_struct work_go_online;
- struct work_struct work_go_offline;
-};
-
-
-#ifdef IPWIRELESS_STATE_DEBUG
-int ipwireless_dump_network_state(char *p, size_t limit,
- struct ipw_network *network)
-{
- return snprintf(p, limit,
- "debug: ppp_blocked=%d\n"
- "debug: outgoing_packets_queued=%d\n"
- "debug: network.shutting_down=%d\n",
- network->ppp_blocked,
- network->outgoing_packets_queued,
- network->shutting_down);
-}
-#endif
-
-static void notify_packet_sent(void *callback_data, unsigned int packet_length)
-{
- struct ipw_network *network = callback_data;
- unsigned long flags;
-
- spin_lock_irqsave(&network->spinlock, flags);
- network->outgoing_packets_queued--;
- if (network->ppp_channel != NULL) {
- if (network->ppp_blocked) {
- network->ppp_blocked = 0;
- spin_unlock_irqrestore(&network->spinlock, flags);
- ppp_output_wakeup(network->ppp_channel);
- if (ipwireless_debug)
- printk(KERN_INFO IPWIRELESS_PCCARD_NAME
- ": ppp unblocked\n");
- } else
- spin_unlock_irqrestore(&network->spinlock, flags);
- } else
- spin_unlock_irqrestore(&network->spinlock, flags);
-}
-
-/*
- * Called by the ppp system when it has a packet to send to the hardware.
- */
-static int ipwireless_ppp_start_xmit(struct ppp_channel *ppp_channel,
- struct sk_buff *skb)
-{
- struct ipw_network *network = ppp_channel->private;
- unsigned long flags;
-
- spin_lock_irqsave(&network->spinlock, flags);
- if (network->outgoing_packets_queued < MAX_OUTGOING_PACKETS_QUEUED) {
- unsigned char *buf;
- static unsigned char header[] = {
- PPP_ALLSTATIONS, /* 0xff */
- PPP_UI, /* 0x03 */
- };
- int ret;
-
- network->outgoing_packets_queued++;
- spin_unlock_irqrestore(&network->spinlock, flags);
-
- /*
- * If we have the requested amount of headroom in the skb we
- * were handed, then we can add the header efficiently.
- */
- if (skb_headroom(skb) >= 2) {
- memcpy(skb_push(skb, 2), header, 2);
- ret = ipwireless_send_packet(network->hardware,
- IPW_CHANNEL_RAS, skb->data,
- skb->len,
- notify_packet_sent,
- network);
- if (ret == -1) {
- skb_pull(skb, 2);
- return 0;
- }
- } else {
- /* Otherwise (rarely) we do it inefficiently. */
- buf = kmalloc(skb->len + 2, GFP_ATOMIC);
- if (!buf)
- return 0;
- memcpy(buf + 2, skb->data, skb->len);
- memcpy(buf, header, 2);
- ret = ipwireless_send_packet(network->hardware,
- IPW_CHANNEL_RAS, buf,
- skb->len + 2,
- notify_packet_sent,
- network);
- kfree(buf);
- if (ret == -1)
- return 0;
- }
- kfree_skb(skb);
- return 1;
- } else {
- /*
- * Otherwise reject the packet, and flag that the ppp system
- * needs to be unblocked once we are ready to send.
- */
- network->ppp_blocked = 1;
- spin_unlock_irqrestore(&network->spinlock, flags);
- return 0;
- }
-}
-
-/* Handle an ioctl call that has come in via ppp. (copy of ppp_async_ioctl() */
-static int ipwireless_ppp_ioctl(struct ppp_channel *ppp_channel,
- unsigned int cmd, unsigned long arg)
-{
- struct ipw_network *network = ppp_channel->private;
- int err, val;
- u32 accm[8];
- int __user *user_arg = (int __user *) arg;
-
- err = -EFAULT;
- switch (cmd) {
- case PPPIOCGFLAGS:
- val = network->flags | network->rbits;
- if (put_user(val, user_arg))
- break;
- err = 0;
- break;
-
- case PPPIOCSFLAGS:
- if (get_user(val, user_arg))
- break;
- network->flags = val & ~SC_RCV_BITS;
- network->rbits = val & SC_RCV_BITS;
- err = 0;
- break;
-
- case PPPIOCGASYNCMAP:
- if (put_user(network->xaccm[0], user_arg))
- break;
- err = 0;
- break;
-
- case PPPIOCSASYNCMAP:
- if (get_user(network->xaccm[0], user_arg))
- break;
- err = 0;
- break;
-
- case PPPIOCGRASYNCMAP:
- if (put_user(network->raccm, user_arg))
- break;
- err = 0;
- break;
-
- case PPPIOCSRASYNCMAP:
- if (get_user(network->raccm, user_arg))
- break;
- err = 0;
- break;
-
- case PPPIOCGXASYNCMAP:
- if (copy_to_user((void __user *) arg, network->xaccm,
- sizeof(network->xaccm)))
- break;
- err = 0;
- break;
-
- case PPPIOCSXASYNCMAP:
- if (copy_from_user(accm, (void __user *) arg, sizeof(accm)))
- break;
- accm[2] &= ~0x40000000U; /* can't escape 0x5e */
- accm[3] |= 0x60000000U; /* must escape 0x7d, 0x7e */
- memcpy(network->xaccm, accm, sizeof(network->xaccm));
- err = 0;
- break;
-
- case PPPIOCGMRU:
- if (put_user(network->mru, user_arg))
- break;
- err = 0;
- break;
-
- case PPPIOCSMRU:
- if (get_user(val, user_arg))
- break;
- if (val < PPP_MRU)
- val = PPP_MRU;
- network->mru = val;
- err = 0;
- break;
-
- default:
- err = -ENOTTY;
- }
-
- return err;
-}
-
-static struct ppp_channel_ops ipwireless_ppp_channel_ops = {
- .start_xmit = ipwireless_ppp_start_xmit,
- .ioctl = ipwireless_ppp_ioctl
-};
-
-static void do_go_online(struct work_struct *work_go_online)
-{
- struct ipw_network *network =
- container_of(work_go_online, struct ipw_network,
- work_go_online);
- unsigned long flags;
-
- spin_lock_irqsave(&network->spinlock, flags);
- if (!network->ppp_channel) {
- struct ppp_channel *channel;
-
- spin_unlock_irqrestore(&network->spinlock, flags);
- channel = kzalloc(sizeof(struct ppp_channel), GFP_KERNEL);
- if (!channel) {
- printk(KERN_ERR IPWIRELESS_PCCARD_NAME
- ": unable to allocate PPP channel\n");
- return;
- }
- channel->private = network;
- channel->mtu = 16384; /* Wild guess */
- channel->hdrlen = 2;
- channel->ops = &ipwireless_ppp_channel_ops;
-
- network->flags = 0;
- network->rbits = 0;
- network->mru = PPP_MRU;
- memset(network->xaccm, 0, sizeof(network->xaccm));
- network->xaccm[0] = ~0U;
- network->xaccm[3] = 0x60000000U;
- network->raccm = ~0U;
- ppp_register_channel(channel);
- spin_lock_irqsave(&network->spinlock, flags);
- network->ppp_channel = channel;
- }
- spin_unlock_irqrestore(&network->spinlock, flags);
-}
-
-static void do_go_offline(struct work_struct *work_go_offline)
-{
- struct ipw_network *network =
- container_of(work_go_offline, struct ipw_network,
- work_go_offline);
- unsigned long flags;
-
- mutex_lock(&network->close_lock);
- spin_lock_irqsave(&network->spinlock, flags);
- if (network->ppp_channel != NULL) {
- struct ppp_channel *channel = network->ppp_channel;
-
- network->ppp_channel = NULL;
- spin_unlock_irqrestore(&network->spinlock, flags);
- mutex_unlock(&network->close_lock);
- ppp_unregister_channel(channel);
- } else {
- spin_unlock_irqrestore(&network->spinlock, flags);
- mutex_unlock(&network->close_lock);
- }
-}
-
-void ipwireless_network_notify_control_line_change(struct ipw_network *network,
- unsigned int channel_idx,
- unsigned int control_lines,
- unsigned int changed_mask)
-{
- int i;
-
- if (channel_idx == IPW_CHANNEL_RAS)
- network->ras_control_lines = control_lines;
-
- for (i = 0; i < MAX_ASSOCIATED_TTYS; i++) {
- struct ipw_tty *tty =
- network->associated_ttys[channel_idx][i];
-
- /*
- * If it's associated with a tty (other than the RAS channel
- * when we're online), then send the data to that tty. The RAS
- * channel's data is handled above - it always goes through
- * ppp_generic.
- */
- if (tty)
- ipwireless_tty_notify_control_line_change(tty,
- channel_idx,
- control_lines,
- changed_mask);
- }
-}
-
-/*
- * Some versions of firmware stuff packets with 0xff 0x03 (PPP: ALLSTATIONS, UI)
- * bytes, which are required on sent packet, but not always present on received
- * packets
- */
-static struct sk_buff *ipw_packet_received_skb(unsigned char *data,
- unsigned int length)
-{
- struct sk_buff *skb;
-
- if (length > 2 && data[0] == PPP_ALLSTATIONS && data[1] == PPP_UI) {
- length -= 2;
- data += 2;
- }
-
- skb = dev_alloc_skb(length + 4);
- skb_reserve(skb, 2);
- memcpy(skb_put(skb, length), data, length);
-
- return skb;
-}
-
-void ipwireless_network_packet_received(struct ipw_network *network,
- unsigned int channel_idx,
- unsigned char *data,
- unsigned int length)
-{
- int i;
- unsigned long flags;
-
- for (i = 0; i < MAX_ASSOCIATED_TTYS; i++) {
- struct ipw_tty *tty = network->associated_ttys[channel_idx][i];
-
- /*
- * If it's associated with a tty (other than the RAS channel
- * when we're online), then send the data to that tty. The RAS
- * channel's data is handled above - it always goes through
- * ppp_generic.
- */
- if (tty && channel_idx == IPW_CHANNEL_RAS
- && (network->ras_control_lines &
- IPW_CONTROL_LINE_DCD) != 0
- && ipwireless_tty_is_modem(tty)) {
- /*
- * If data came in on the RAS channel and this tty is
- * the modem tty, and we are online, then we send it to
- * the PPP layer.
- */
- mutex_lock(&network->close_lock);
- spin_lock_irqsave(&network->spinlock, flags);
- if (network->ppp_channel != NULL) {
- struct sk_buff *skb;
-
- spin_unlock_irqrestore(&network->spinlock,
- flags);
-
- /* Send the data to the ppp_generic module. */
- skb = ipw_packet_received_skb(data, length);
- ppp_input(network->ppp_channel, skb);
- } else
- spin_unlock_irqrestore(&network->spinlock,
- flags);
- mutex_unlock(&network->close_lock);
- }
- /* Otherwise we send it out the tty. */
- else
- ipwireless_tty_received(tty, data, length);
- }
-}
-
-struct ipw_network *ipwireless_network_create(struct ipw_hardware *hw)
-{
- struct ipw_network *network =
- kzalloc(sizeof(struct ipw_network), GFP_ATOMIC);
-
- if (!network)
- return NULL;
-
- spin_lock_init(&network->spinlock);
- mutex_init(&network->close_lock);
-
- network->hardware = hw;
-
- INIT_WORK(&network->work_go_online, do_go_online);
- INIT_WORK(&network->work_go_offline, do_go_offline);
-
- ipwireless_associate_network(hw, network);
-
- return network;
-}
-
-void ipwireless_network_free(struct ipw_network *network)
-{
- network->shutting_down = 1;
-
- ipwireless_ppp_close(network);
- flush_scheduled_work();
-
- ipwireless_stop_interrupts(network->hardware);
- ipwireless_associate_network(network->hardware, NULL);
-
- kfree(network);
-}
-
-void ipwireless_associate_network_tty(struct ipw_network *network,
- unsigned int channel_idx,
- struct ipw_tty *tty)
-{
- int i;
-
- for (i = 0; i < MAX_ASSOCIATED_TTYS; i++)
- if (network->associated_ttys[channel_idx][i] == NULL) {
- network->associated_ttys[channel_idx][i] = tty;
- break;
- }
-}
-
-void ipwireless_disassociate_network_ttys(struct ipw_network *network,
- unsigned int channel_idx)
-{
- int i;
-
- for (i = 0; i < MAX_ASSOCIATED_TTYS; i++)
- network->associated_ttys[channel_idx][i] = NULL;
-}
-
-void ipwireless_ppp_open(struct ipw_network *network)
-{
- if (ipwireless_debug)
- printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME ": online\n");
- schedule_work(&network->work_go_online);
-}
-
-void ipwireless_ppp_close(struct ipw_network *network)
-{
- /* Disconnect from the wireless network. */
- if (ipwireless_debug)
- printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME ": offline\n");
- schedule_work(&network->work_go_offline);
-}
-
-int ipwireless_ppp_channel_index(struct ipw_network *network)
-{
- int ret = -1;
- unsigned long flags;
-
- spin_lock_irqsave(&network->spinlock, flags);
- if (network->ppp_channel != NULL)
- ret = ppp_channel_index(network->ppp_channel);
- spin_unlock_irqrestore(&network->spinlock, flags);
-
- return ret;
-}
-
-int ipwireless_ppp_unit_number(struct ipw_network *network)
-{
- int ret = -1;
- unsigned long flags;
-
- spin_lock_irqsave(&network->spinlock, flags);
- if (network->ppp_channel != NULL)
- ret = ppp_unit_number(network->ppp_channel);
- spin_unlock_irqrestore(&network->spinlock, flags);
-
- return ret;
-}
diff --git a/trunk/drivers/char/pcmcia/ipwireless/network.h b/trunk/drivers/char/pcmcia/ipwireless/network.h
deleted file mode 100644
index b0e1e952fd14..000000000000
--- a/trunk/drivers/char/pcmcia/ipwireless/network.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * IPWireless 3G PCMCIA Network Driver
- *
- * Original code
- * by Stephen Blackheath ,
- * Ben Martel
- *
- * Copyrighted as follows:
- * Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
- *
- * Various driver changes and rewrites, port to new kernels
- * Copyright (C) 2006-2007 Jiri Kosina
- *
- * Misc code cleanups and updates
- * Copyright (C) 2007 David Sterba
- */
-
-#ifndef _IPWIRELESS_CS_NETWORK_H_
-#define _IPWIRELESS_CS_NETWORK_H_
-
-#include
-
-struct ipw_network;
-struct ipw_tty;
-struct ipw_hardware;
-
-/* Definitions of the different channels on the PCMCIA UE */
-#define IPW_CHANNEL_RAS 0
-#define IPW_CHANNEL_DIALLER 1
-#define IPW_CHANNEL_CONSOLE 2
-#define NO_OF_IPW_CHANNELS 5
-
-void ipwireless_network_notify_control_line_change(struct ipw_network *net,
- unsigned int channel_idx, unsigned int control_lines,
- unsigned int control_mask);
-void ipwireless_network_packet_received(struct ipw_network *net,
- unsigned int channel_idx, unsigned char *data,
- unsigned int length);
-struct ipw_network *ipwireless_network_create(struct ipw_hardware *hw);
-void ipwireless_network_free(struct ipw_network *net);
-void ipwireless_associate_network_tty(struct ipw_network *net,
- unsigned int channel_idx, struct ipw_tty *tty);
-void ipwireless_disassociate_network_ttys(struct ipw_network *net,
- unsigned int channel_idx);
-
-void ipwireless_ppp_open(struct ipw_network *net);
-
-void ipwireless_ppp_close(struct ipw_network *net);
-int ipwireless_ppp_channel_index(struct ipw_network *net);
-int ipwireless_ppp_unit_number(struct ipw_network *net);
-
-int ipwireless_dump_network_state(char *p, size_t limit,
- struct ipw_network *net);
-
-#endif
diff --git a/trunk/drivers/char/pcmcia/ipwireless/setup_protocol.h b/trunk/drivers/char/pcmcia/ipwireless/setup_protocol.h
deleted file mode 100644
index 9d6bcc77c73c..000000000000
--- a/trunk/drivers/char/pcmcia/ipwireless/setup_protocol.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * IPWireless 3G PCMCIA Network Driver
- *
- * Original code
- * by Stephen Blackheath ,
- * Ben Martel
- *
- * Copyrighted as follows:
- * Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
- *
- * Various driver changes and rewrites, port to new kernels
- * Copyright (C) 2006-2007 Jiri Kosina
- *
- * Misc code cleanups and updates
- * Copyright (C) 2007 David Sterba
- */
-
-#ifndef _IPWIRELESS_CS_SETUP_PROTOCOL_H_
-#define _IPWIRELESS_CS_SETUP_PROTOCOL_H_
-
-/* Version of the setup protocol and transport protocols */
-#define TL_SETUP_VERSION 1
-
-#define TL_SETUP_VERSION_QRY_TMO 1000
-#define TL_SETUP_MAX_VERSION_QRY 30
-
-/* Message numbers 0-9 are obsoleted and must not be reused! */
-#define TL_SETUP_SIGNO_GET_VERSION_QRY 10
-#define TL_SETUP_SIGNO_GET_VERSION_RSP 11
-#define TL_SETUP_SIGNO_CONFIG_MSG 12
-#define TL_SETUP_SIGNO_CONFIG_DONE_MSG 13
-#define TL_SETUP_SIGNO_OPEN_MSG 14
-#define TL_SETUP_SIGNO_CLOSE_MSG 15
-
-#define TL_SETUP_SIGNO_INFO_MSG 20
-#define TL_SETUP_SIGNO_INFO_MSG_ACK 21
-
-#define TL_SETUP_SIGNO_REBOOT_MSG 22
-#define TL_SETUP_SIGNO_REBOOT_MSG_ACK 23
-
-/* Synchronous start-messages */
-struct tl_setup_get_version_qry {
- unsigned char sig_no; /* TL_SETUP_SIGNO_GET_VERSION_QRY */
-} __attribute__ ((__packed__));
-
-struct tl_setup_get_version_rsp {
- unsigned char sig_no; /* TL_SETUP_SIGNO_GET_VERSION_RSP */
- unsigned char version; /* TL_SETUP_VERSION */
-} __attribute__ ((__packed__));
-
-struct tl_setup_config_msg {
- unsigned char sig_no; /* TL_SETUP_SIGNO_CONFIG_MSG */
- unsigned char port_no;
- unsigned char prio_data;
- unsigned char prio_ctrl;
-} __attribute__ ((__packed__));
-
-struct tl_setup_config_done_msg {
- unsigned char sig_no; /* TL_SETUP_SIGNO_CONFIG_DONE_MSG */
-} __attribute__ ((__packed__));
-
-/* Asyncronous messages */
-struct tl_setup_open_msg {
- unsigned char sig_no; /* TL_SETUP_SIGNO_OPEN_MSG */
- unsigned char port_no;
-} __attribute__ ((__packed__));
-
-struct tl_setup_close_msg {
- unsigned char sig_no; /* TL_SETUP_SIGNO_CLOSE_MSG */
- unsigned char port_no;
-} __attribute__ ((__packed__));
-
-/* Driver type - for use in tl_setup_info_msg.driver_type */
-#define COMM_DRIVER 0
-#define NDISWAN_DRIVER 1
-#define NDISWAN_DRIVER_MAJOR_VERSION 2
-#define NDISWAN_DRIVER_MINOR_VERSION 0
-
-/*
- * It should not matter when this message comes over as we just store the
- * results and send the ACK.
- */
-struct tl_setup_info_msg {
- unsigned char sig_no; /* TL_SETUP_SIGNO_INFO_MSG */
- unsigned char driver_type;
- unsigned char major_version;
- unsigned char minor_version;
-} __attribute__ ((__packed__));
-
-struct tl_setup_info_msgAck {
- unsigned char sig_no; /* TL_SETUP_SIGNO_INFO_MSG_ACK */
-} __attribute__ ((__packed__));
-
-struct TlSetupRebootMsgAck {
- unsigned char sig_no; /* TL_SETUP_SIGNO_REBOOT_MSG_ACK */
-} __attribute__ ((__packed__));
-
-/* Define a union of all the msgs that the driver can receive from the card.*/
-union ipw_setup_rx_msg {
- unsigned char sig_no;
- struct tl_setup_get_version_rsp version_rsp_msg;
- struct tl_setup_open_msg open_msg;
- struct tl_setup_close_msg close_msg;
- struct tl_setup_info_msg InfoMsg;
- struct tl_setup_info_msgAck info_msg_ack;
-} __attribute__ ((__packed__));
-
-#endif /* _IPWIRELESS_CS_SETUP_PROTOCOL_H_ */
diff --git a/trunk/drivers/char/pcmcia/ipwireless/tty.c b/trunk/drivers/char/pcmcia/ipwireless/tty.c
deleted file mode 100644
index 42f3815c5ce3..000000000000
--- a/trunk/drivers/char/pcmcia/ipwireless/tty.c
+++ /dev/null
@@ -1,688 +0,0 @@
-/*
- * IPWireless 3G PCMCIA Network Driver
- *
- * Original code
- * by Stephen Blackheath ,
- * Ben Martel
- *
- * Copyrighted as follows:
- * Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
- *
- * Various driver changes and rewrites, port to new kernels
- * Copyright (C) 2006-2007 Jiri Kosina
- *
- * Misc code cleanups and updates
- * Copyright (C) 2007 David Sterba
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "tty.h"
-#include "network.h"
-#include "hardware.h"
-#include "main.h"
-
-#define IPWIRELESS_PCMCIA_START (0)
-#define IPWIRELESS_PCMCIA_MINORS (24)
-#define IPWIRELESS_PCMCIA_MINOR_RANGE (8)
-
-#define TTYTYPE_MODEM (0)
-#define TTYTYPE_MONITOR (1)
-#define TTYTYPE_RAS_RAW (2)
-
-struct ipw_tty {
- int index;
- struct ipw_hardware *hardware;
- unsigned int channel_idx;
- unsigned int secondary_channel_idx;
- int tty_type;
- struct ipw_network *network;
- struct tty_struct *linux_tty;
- int open_count;
- unsigned int control_lines;
- struct mutex ipw_tty_mutex;
- int tx_bytes_queued;
- int closing;
-};
-
-static struct ipw_tty *ttys[IPWIRELESS_PCMCIA_MINORS];
-
-static struct tty_driver *ipw_tty_driver;
-
-static char *tty_type_name(int tty_type)
-{
- static char *channel_names[] = {
- "modem",
- "monitor",
- "RAS-raw"
- };
-
- return channel_names[tty_type];
-}
-
-static void report_registering(struct ipw_tty *tty)
-{
- char *iftype = tty_type_name(tty->tty_type);
-
- printk(KERN_INFO IPWIRELESS_PCCARD_NAME
- ": registering %s device ttyIPWp%d\n", iftype, tty->index);
-}
-
-static void report_deregistering(struct ipw_tty *tty)
-{
- char *iftype = tty_type_name(tty->tty_type);
-
- printk(KERN_INFO IPWIRELESS_PCCARD_NAME
- ": deregistering %s device ttyIPWp%d\n", iftype,
- tty->index);
-}
-
-static struct ipw_tty *get_tty(int minor)
-{
- if (minor < ipw_tty_driver->minor_start
- || minor >= ipw_tty_driver->minor_start +
- IPWIRELESS_PCMCIA_MINORS)
- return NULL;
- else {
- int minor_offset = minor - ipw_tty_driver->minor_start;
-
- /*
- * The 'ras_raw' channel is only available when 'loopback' mode
- * is enabled.
- * Number of minor starts with 16 (_RANGE * _RAS_RAW).
- */
- if (!ipwireless_loopback &&
- minor_offset >=
- IPWIRELESS_PCMCIA_MINOR_RANGE * TTYTYPE_RAS_RAW)
- return NULL;
-
- return ttys[minor_offset];
- }
-}
-
-static int ipw_open(struct tty_struct *linux_tty, struct file *filp)
-{
- int minor = linux_tty->index;
- struct ipw_tty *tty = get_tty(minor);
-
- if (!tty)
- return -ENODEV;
-
- mutex_lock(&tty->ipw_tty_mutex);
-
- if (tty->closing) {
- mutex_unlock(&tty->ipw_tty_mutex);
- return -ENODEV;
- }
- if (tty->open_count == 0)
- tty->tx_bytes_queued = 0;
-
- tty->open_count++;
-
- tty->linux_tty = linux_tty;
- linux_tty->driver_data = tty;
- linux_tty->low_latency = 1;
-
- if (tty->tty_type == TTYTYPE_MODEM)
- ipwireless_ppp_open(tty->network);
-
- mutex_unlock(&tty->ipw_tty_mutex);
-
- return 0;
-}
-
-static void do_ipw_close(struct ipw_tty *tty)
-{
- tty->open_count--;
-
- if (tty->open_count == 0) {
- struct tty_struct *linux_tty = tty->linux_tty;
-
- if (linux_tty != NULL) {
- tty->linux_tty = NULL;
- linux_tty->driver_data = NULL;
-
- if (tty->tty_type == TTYTYPE_MODEM)
- ipwireless_ppp_close(tty->network);
- }
- }
-}
-
-static void ipw_hangup(struct tty_struct *linux_tty)
-{
- struct ipw_tty *tty = linux_tty->driver_data;
-
- if (!tty)
- return;
-
- mutex_lock(&tty->ipw_tty_mutex);
- if (tty->open_count == 0) {
- mutex_unlock(&tty->ipw_tty_mutex);
- return;
- }
-
- do_ipw_close(tty);
-
- mutex_unlock(&tty->ipw_tty_mutex);
-}
-
-static void ipw_close(struct tty_struct *linux_tty, struct file *filp)
-{
- ipw_hangup(linux_tty);
-}
-
-/* Take data received from hardware, and send it out the tty */
-void ipwireless_tty_received(struct ipw_tty *tty, unsigned char *data,
- unsigned int length)
-{
- struct tty_struct *linux_tty;
- int work = 0;
-
- mutex_lock(&tty->ipw_tty_mutex);
- linux_tty = tty->linux_tty;
- if (linux_tty == NULL) {
- mutex_unlock(&tty->ipw_tty_mutex);
- return;
- }
-
- if (!tty->open_count) {
- mutex_unlock(&tty->ipw_tty_mutex);
- return;
- }
- mutex_unlock(&tty->ipw_tty_mutex);
-
- work = tty_insert_flip_string(linux_tty, data, length);
-
- if (work != length)
- printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME
- ": %d chars not inserted to flip buffer!\n",
- length - work);
-
- /*
- * This may sleep if ->low_latency is set
- */
- if (work)
- tty_flip_buffer_push(linux_tty);
-}
-
-static void ipw_write_packet_sent_callback(void *callback_data,
- unsigned int packet_length)
-{
- struct ipw_tty *tty = callback_data;
-
- /*
- * Packet has been sent, so we subtract the number of bytes from our
- * tally of outstanding TX bytes.
- */
- tty->tx_bytes_queued -= packet_length;
-}
-
-static int ipw_write(struct tty_struct *linux_tty,
- const unsigned char *buf, int count)
-{
- struct ipw_tty *tty = linux_tty->driver_data;
- int room, ret;
-
- if (!tty)
- return -ENODEV;
-
- mutex_lock(&tty->ipw_tty_mutex);
- if (!tty->open_count) {
- mutex_unlock(&tty->ipw_tty_mutex);
- return -EINVAL;
- }
-
- room = IPWIRELESS_TX_QUEUE_SIZE - tty->tx_bytes_queued;
- if (room < 0)
- room = 0;
- /* Don't allow caller to write any more than we have room for */
- if (count > room)
- count = room;
-
- if (count == 0) {
- mutex_unlock(&tty->ipw_tty_mutex);
- return 0;
- }
-
- ret = ipwireless_send_packet(tty->hardware, IPW_CHANNEL_RAS,
- (unsigned char *) buf, count,
- ipw_write_packet_sent_callback, tty);
- if (ret == -1) {
- mutex_unlock(&tty->ipw_tty_mutex);
- return 0;
- }
-
- tty->tx_bytes_queued += count;
- mutex_unlock(&tty->ipw_tty_mutex);
-
- return count;
-}
-
-static int ipw_write_room(struct tty_struct *linux_tty)
-{
- struct ipw_tty *tty = linux_tty->driver_data;
- int room;
-
- if (!tty)
- return -ENODEV;
-
- if (!tty->open_count)
- return -EINVAL;
-
- room = IPWIRELESS_TX_QUEUE_SIZE - tty->tx_bytes_queued;
- if (room < 0)
- room = 0;
-
- return room;
-}
-
-static int ipwireless_get_serial_info(struct ipw_tty *tty,
- struct serial_struct __user *retinfo)
-{
- struct serial_struct tmp;
-
- if (!retinfo)
- return (-EFAULT);
-
- memset(&tmp, 0, sizeof(tmp));
- tmp.type = PORT_UNKNOWN;
- tmp.line = tty->index;
- tmp.port = 0;
- tmp.irq = 0;
- tmp.flags = 0;
- tmp.baud_base = 115200;
- tmp.close_delay = 0;
- tmp.closing_wait = 0;
- tmp.custom_divisor = 0;
- tmp.hub6 = 0;
- if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
- return -EFAULT;
-
- return 0;
-}
-
-static int ipw_chars_in_buffer(struct tty_struct *linux_tty)
-{
- struct ipw_tty *tty = linux_tty->driver_data;
-
- if (!tty)
- return -ENODEV;
-
- if (!tty->open_count)
- return -EINVAL;
-
- return tty->tx_bytes_queued;
-}
-
-static int get_control_lines(struct ipw_tty *tty)
-{
- unsigned int my = tty->control_lines;
- unsigned int out = 0;
-
- if (my & IPW_CONTROL_LINE_RTS)
- out |= TIOCM_RTS;
- if (my & IPW_CONTROL_LINE_DTR)
- out |= TIOCM_DTR;
- if (my & IPW_CONTROL_LINE_CTS)
- out |= TIOCM_CTS;
- if (my & IPW_CONTROL_LINE_DSR)
- out |= TIOCM_DSR;
- if (my & IPW_CONTROL_LINE_DCD)
- out |= TIOCM_CD;
-
- return out;
-}
-
-static int set_control_lines(struct ipw_tty *tty, unsigned int set,
- unsigned int clear)
-{
- int ret;
-
- if (set & TIOCM_RTS) {
- ret = ipwireless_set_RTS(tty->hardware, tty->channel_idx, 1);
- if (ret)
- return ret;
- if (tty->secondary_channel_idx != -1) {
- ret = ipwireless_set_RTS(tty->hardware,
- tty->secondary_channel_idx, 1);
- if (ret)
- return ret;
- }
- }
- if (set & TIOCM_DTR) {
- ret = ipwireless_set_DTR(tty->hardware, tty->channel_idx, 1);
- if (ret)
- return ret;
- if (tty->secondary_channel_idx != -1) {
- ret = ipwireless_set_DTR(tty->hardware,
- tty->secondary_channel_idx, 1);
- if (ret)
- return ret;
- }
- }
- if (clear & TIOCM_RTS) {
- ret = ipwireless_set_RTS(tty->hardware, tty->channel_idx, 0);
- if (tty->secondary_channel_idx != -1) {
- ret = ipwireless_set_RTS(tty->hardware,
- tty->secondary_channel_idx, 0);
- if (ret)
- return ret;
- }
- }
- if (clear & TIOCM_DTR) {
- ret = ipwireless_set_DTR(tty->hardware, tty->channel_idx, 0);
- if (tty->secondary_channel_idx != -1) {
- ret = ipwireless_set_DTR(tty->hardware,
- tty->secondary_channel_idx, 0);
- if (ret)
- return ret;
- }
- }
- return 0;
-}
-
-static int ipw_tiocmget(struct tty_struct *linux_tty, struct file *file)
-{
- struct ipw_tty *tty = linux_tty->driver_data;
-
- if (!tty)
- return -ENODEV;
-
- if (!tty->open_count)
- return -EINVAL;
-
- return get_control_lines(tty);
-}
-
-static int
-ipw_tiocmset(struct tty_struct *linux_tty, struct file *file,
- unsigned int set, unsigned int clear)
-{
- struct ipw_tty *tty = linux_tty->driver_data;
-
- if (!tty)
- return -ENODEV;
-
- if (!tty->open_count)
- return -EINVAL;
-
- return set_control_lines(tty, set, clear);
-}
-
-static int ipw_ioctl(struct tty_struct *linux_tty, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- struct ipw_tty *tty = linux_tty->driver_data;
-
- if (!tty)
- return -ENODEV;
-
- if (!tty->open_count)
- return -EINVAL;
-
- switch (cmd) {
- case TIOCGSERIAL:
- return ipwireless_get_serial_info(tty, (void __user *) arg);
-
- case TIOCSSERIAL:
- return 0; /* Keeps the PCMCIA scripts happy. */
- }
-
- if (tty->tty_type == TTYTYPE_MODEM) {
- switch (cmd) {
- case PPPIOCGCHAN:
- {
- int chan = ipwireless_ppp_channel_index(
- tty->network);
-
- if (chan < 0)
- return -ENODEV;
- if (put_user(chan, (int __user *) arg))
- return -EFAULT;
- }
- return 0;
-
- case PPPIOCGUNIT:
- {
- int unit = ipwireless_ppp_unit_number(
- tty->network);
-
- if (unit < 0)
- return -ENODEV;
- if (put_user(unit, (int __user *) arg))
- return -EFAULT;
- }
- return 0;
-
- case TCGETS:
- case TCGETA:
- return n_tty_ioctl(linux_tty, file, cmd, arg);
-
- case TCFLSH:
- return n_tty_ioctl(linux_tty, file, cmd, arg);
-
- case FIONREAD:
- {
- int val = 0;
-
- if (put_user(val, (int __user *) arg))
- return -EFAULT;
- }
- return 0;
- }
- }
-
- return -ENOIOCTLCMD;
-}
-
-static int add_tty(dev_node_t *nodesp, int j,
- struct ipw_hardware *hardware,
- struct ipw_network *network, int channel_idx,
- int secondary_channel_idx, int tty_type)
-{
- ttys[j] = kzalloc(sizeof(struct ipw_tty), GFP_KERNEL);
- if (!ttys[j])
- return -ENOMEM;
- ttys[j]->index = j;
- ttys[j]->hardware = hardware;
- ttys[j]->channel_idx = channel_idx;
- ttys[j]->secondary_channel_idx = secondary_channel_idx;
- ttys[j]->network = network;
- ttys[j]->tty_type = tty_type;
- mutex_init(&ttys[j]->ipw_tty_mutex);
-
- tty_register_device(ipw_tty_driver, j, NULL);
- ipwireless_associate_network_tty(network, channel_idx, ttys[j]);
-
- if (secondary_channel_idx != -1)
- ipwireless_associate_network_tty(network,
- secondary_channel_idx,
- ttys[j]);
- if (nodesp != NULL) {
- sprintf(nodesp->dev_name, "ttyIPWp%d", j);
- nodesp->major = ipw_tty_driver->major;
- nodesp->minor = j + ipw_tty_driver->minor_start;
- }
- if (get_tty(j + ipw_tty_driver->minor_start) == ttys[j])
- report_registering(ttys[j]);
- return 0;
-}
-
-struct ipw_tty *ipwireless_tty_create(struct ipw_hardware *hardware,
- struct ipw_network *network,
- dev_node_t *nodes)
-{
- int i, j;
-
- for (i = 0; i < IPWIRELESS_PCMCIA_MINOR_RANGE; i++) {
- int allfree = 1;
-
- for (j = i; j < IPWIRELESS_PCMCIA_MINORS;
- j += IPWIRELESS_PCMCIA_MINOR_RANGE)
- if (ttys[j] != NULL) {
- allfree = 0;
- break;
- }
-
- if (allfree) {
- j = i;
-
- if (add_tty(&nodes[0], j, hardware, network,
- IPW_CHANNEL_DIALLER, IPW_CHANNEL_RAS,
- TTYTYPE_MODEM))
- return NULL;
-
- j += IPWIRELESS_PCMCIA_MINOR_RANGE;
- if (add_tty(&nodes[1], j, hardware, network,
- IPW_CHANNEL_DIALLER, -1,
- TTYTYPE_MONITOR))
- return NULL;
-
- j += IPWIRELESS_PCMCIA_MINOR_RANGE;
- if (add_tty(NULL, j, hardware, network,
- IPW_CHANNEL_RAS, -1,
- TTYTYPE_RAS_RAW))
- return NULL;
-
- nodes[0].next = &nodes[1];
- nodes[1].next = NULL;
-
- return ttys[i];
- }
- }
- return NULL;
-}
-
-/*
- * Must be called before ipwireless_network_free().
- */
-void ipwireless_tty_free(struct ipw_tty *tty)
-{
- int j;
- struct ipw_network *network = ttys[tty->index]->network;
-
- for (j = tty->index; j < IPWIRELESS_PCMCIA_MINORS;
- j += IPWIRELESS_PCMCIA_MINOR_RANGE) {
- struct ipw_tty *ttyj = ttys[j];
-
- if (ttyj) {
- mutex_lock(&ttyj->ipw_tty_mutex);
- if (get_tty(j + ipw_tty_driver->minor_start) == ttyj)
- report_deregistering(ttyj);
- ttyj->closing = 1;
- if (ttyj->linux_tty != NULL) {
- mutex_unlock(&ttyj->ipw_tty_mutex);
- tty_hangup(ttyj->linux_tty);
- /* Wait till the tty_hangup has completed */
- flush_scheduled_work();
- mutex_lock(&ttyj->ipw_tty_mutex);
- }
- while (ttyj->open_count)
- do_ipw_close(ttyj);
- ipwireless_disassociate_network_ttys(network,
- ttyj->channel_idx);
- tty_unregister_device(ipw_tty_driver, j);
- ttys[j] = NULL;
- mutex_unlock(&ttyj->ipw_tty_mutex);
- kfree(ttyj);
- }
- }
-}
-
-static struct tty_operations tty_ops = {
- .open = ipw_open,
- .close = ipw_close,
- .hangup = ipw_hangup,
- .write = ipw_write,
- .write_room = ipw_write_room,
- .ioctl = ipw_ioctl,
- .chars_in_buffer = ipw_chars_in_buffer,
- .tiocmget = ipw_tiocmget,
- .tiocmset = ipw_tiocmset,
-};
-
-int ipwireless_tty_init(void)
-{
- int result;
-
- ipw_tty_driver = alloc_tty_driver(IPWIRELESS_PCMCIA_MINORS);
- if (!ipw_tty_driver)
- return -ENOMEM;
-
- ipw_tty_driver->owner = THIS_MODULE;
- ipw_tty_driver->driver_name = IPWIRELESS_PCCARD_NAME;
- ipw_tty_driver->name = "ttyIPWp";
- ipw_tty_driver->major = 0;
- ipw_tty_driver->minor_start = IPWIRELESS_PCMCIA_START;
- ipw_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
- ipw_tty_driver->subtype = SERIAL_TYPE_NORMAL;
- ipw_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
- ipw_tty_driver->init_termios = tty_std_termios;
- ipw_tty_driver->init_termios.c_cflag =
- B9600 | CS8 | CREAD | HUPCL | CLOCAL;
- ipw_tty_driver->init_termios.c_ispeed = 9600;
- ipw_tty_driver->init_termios.c_ospeed = 9600;
- tty_set_operations(ipw_tty_driver, &tty_ops);
- result = tty_register_driver(ipw_tty_driver);
- if (result) {
- printk(KERN_ERR IPWIRELESS_PCCARD_NAME
- ": failed to register tty driver\n");
- put_tty_driver(ipw_tty_driver);
- return result;
- }
-
- return 0;
-}
-
-void ipwireless_tty_release(void)
-{
- int ret;
-
- ret = tty_unregister_driver(ipw_tty_driver);
- put_tty_driver(ipw_tty_driver);
- if (ret != 0)
- printk(KERN_ERR IPWIRELESS_PCCARD_NAME
- ": tty_unregister_driver failed with code %d\n", ret);
-}
-
-int ipwireless_tty_is_modem(struct ipw_tty *tty)
-{
- return tty->tty_type == TTYTYPE_MODEM;
-}
-
-void
-ipwireless_tty_notify_control_line_change(struct ipw_tty *tty,
- unsigned int channel_idx,
- unsigned int control_lines,
- unsigned int changed_mask)
-{
- unsigned int old_control_lines = tty->control_lines;
-
- tty->control_lines = (tty->control_lines & ~changed_mask)
- | (control_lines & changed_mask);
-
- /*
- * If DCD is de-asserted, we close the tty so pppd can tell that we
- * have gone offline.
- */
- if ((old_control_lines & IPW_CONTROL_LINE_DCD)
- && !(tty->control_lines & IPW_CONTROL_LINE_DCD)
- && tty->linux_tty) {
- tty_hangup(tty->linux_tty);
- }
-}
-
diff --git a/trunk/drivers/char/pcmcia/ipwireless/tty.h b/trunk/drivers/char/pcmcia/ipwireless/tty.h
deleted file mode 100644
index b0deb9168b6b..000000000000
--- a/trunk/drivers/char/pcmcia/ipwireless/tty.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * IPWireless 3G PCMCIA Network Driver
- *
- * Original code
- * by Stephen Blackheath ,
- * Ben Martel
- *
- * Copyrighted as follows:
- * Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
- *
- * Various driver changes and rewrites, port to new kernels
- * Copyright (C) 2006-2007 Jiri Kosina
- *
- * Misc code cleanups and updates
- * Copyright (C) 2007 David Sterba
- */
-
-#ifndef _IPWIRELESS_CS_TTY_H_
-#define _IPWIRELESS_CS_TTY_H_
-
-#include
-#include
-
-#include
-#include
-#include
-#include
-
-struct ipw_tty;
-struct ipw_network;
-struct ipw_hardware;
-
-int ipwireless_tty_init(void);
-void ipwireless_tty_release(void);
-
-struct ipw_tty *ipwireless_tty_create(struct ipw_hardware *hw,
- struct ipw_network *net,
- dev_node_t *nodes);
-void ipwireless_tty_free(struct ipw_tty *tty);
-void ipwireless_tty_received(struct ipw_tty *tty, unsigned char *data,
- unsigned int length);
-int ipwireless_tty_is_modem(struct ipw_tty *tty);
-void ipwireless_tty_notify_control_line_change(struct ipw_tty *tty,
- unsigned int channel_idx,
- unsigned int control_lines,
- unsigned int changed_mask);
-
-#endif
diff --git a/trunk/drivers/input/Kconfig b/trunk/drivers/input/Kconfig
index 9dea14db724c..63512d906f02 100644
--- a/trunk/drivers/input/Kconfig
+++ b/trunk/drivers/input/Kconfig
@@ -137,18 +137,6 @@ config INPUT_EVBUG
To compile this driver as a module, choose M here: the
module will be called evbug.
-config INPUT_APMPOWER
- tristate "Input Power Event -> APM Bridge" if EMBEDDED
- depends on INPUT && APM_EMULATION
- ---help---
- Say Y here if you want suspend key events to trigger a user
- requested suspend through APM. This is useful on embedded
- systems where such behviour is desired without userspace
- interaction. If unsure, say N.
-
- To compile this driver as a module, choose M here: the
- module will be called apm-power.
-
comment "Input Device Drivers"
source "drivers/input/keyboard/Kconfig"
diff --git a/trunk/drivers/input/Makefile b/trunk/drivers/input/Makefile
index 2ae87b19caa8..99af903bd3ce 100644
--- a/trunk/drivers/input/Makefile
+++ b/trunk/drivers/input/Makefile
@@ -22,4 +22,3 @@ obj-$(CONFIG_INPUT_TABLET) += tablet/
obj-$(CONFIG_INPUT_TOUCHSCREEN) += touchscreen/
obj-$(CONFIG_INPUT_MISC) += misc/
-obj-$(CONFIG_INPUT_APMPOWER) += apm-power.o
diff --git a/trunk/drivers/input/apm-power.c b/trunk/drivers/input/apm-power.c
deleted file mode 100644
index c36d110b349a..000000000000
--- a/trunk/drivers/input/apm-power.c
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Input Power Event -> APM Bridge
- *
- * Copyright (c) 2007 Richard Purdie
- *
- * 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
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-static void system_power_event(unsigned int keycode)
-{
- switch (keycode) {
- case KEY_SUSPEND:
- apm_queue_event(APM_USER_SUSPEND);
-
- printk(KERN_INFO "apm-power: Requesting system suspend...\n");
- break;
- default:
- break;
- }
-}
-
-static void apmpower_event(struct input_handle *handle, unsigned int type,
- unsigned int code, int value)
-{
- /* only react on key down events */
- if (value != 1)
- return;
-
- switch (type) {
- case EV_PWR:
- system_power_event(code);
- break;
-
- default:
- break;
- }
-}
-
-static int apmpower_connect(struct input_handler *handler,
- struct input_dev *dev,
- const struct input_device_id *id)
-{
- struct input_handle *handle;
- int error;
-
- handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
- if (!handle)
- return -ENOMEM;
-
- handle->dev = dev;
- handle->handler = handler;
- handle->name = "apm-power";
-
- handler->private = handle;
-
- error = input_register_handle(handle);
- if (error) {
- printk(KERN_ERR
- "apm-power: Failed to register input power handler, "
- "error %d\n", error);
- kfree(handle);
- return error;
- }
-
- error = input_open_device(handle);
- if (error) {
- printk(KERN_ERR
- "apm-power: Failed to open input power device, "
- "error %d\n", error);
- input_unregister_handle(handle);
- kfree(handle);
- return error;
- }
-
- return 0;
-}
-
-static void apmpower_disconnect(struct input_handle *handler)
-{
- struct input_handle *handle = handler->private;
-
- input_close_device(handle);
- kfree(handle);
-}
-
-static const struct input_device_id apmpower_ids[] = {
- {
- .flags = INPUT_DEVICE_ID_MATCH_EVBIT,
- .evbit = { BIT_MASK(EV_PWR) },
- },
- { },
-};
-
-MODULE_DEVICE_TABLE(input, apmpower_ids);
-
-static struct input_handler apmpower_handler = {
- .event = apmpower_event,
- .connect = apmpower_connect,
- .disconnect = apmpower_disconnect,
- .name = "apm-power",
- .id_table = apmpower_ids,
-};
-
-static int __init apmpower_init(void)
-{
- return input_register_handler(&apmpower_handler);
-}
-
-static void __exit apmpower_exit(void)
-{
- input_unregister_handler(&apmpower_handler);
-}
-
-module_init(apmpower_init);
-module_exit(apmpower_exit);
-
-MODULE_AUTHOR("Richard Purdie ");
-MODULE_DESCRIPTION("Input Power Event -> APM Bridge");
-MODULE_LICENSE("GPL");
diff --git a/trunk/drivers/input/evdev.c b/trunk/drivers/input/evdev.c
index 0727b0a12557..e5b4e9bfbdc5 100644
--- a/trunk/drivers/input/evdev.c
+++ b/trunk/drivers/input/evdev.c
@@ -617,7 +617,7 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
if (get_user(t, ip))
return -EFAULT;
- error = input_get_keycode(dev, t, &v);
+ error = dev->getkeycode(dev, t, &v);
if (error)
return error;
@@ -630,7 +630,7 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
if (get_user(t, ip) || get_user(v, ip + 1))
return -EFAULT;
- return input_set_keycode(dev, t, v);
+ return dev->setkeycode(dev, t, v);
case EVIOCSFF:
if (copy_from_user(&effect, p, sizeof(effect)))
@@ -683,7 +683,7 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
case EV_FF: bits = dev->ffbit; len = FF_MAX; break;
case EV_SW: bits = dev->swbit; len = SW_MAX; break;
default: return -EINVAL;
- }
+ }
return bits_to_user(bits, len, _IOC_SIZE(cmd), p, compat_mode);
}
diff --git a/trunk/drivers/input/input-polldev.c b/trunk/drivers/input/input-polldev.c
index 490918a5d192..92b359894e81 100644
--- a/trunk/drivers/input/input-polldev.c
+++ b/trunk/drivers/input/input-polldev.c
@@ -60,21 +60,17 @@ static void input_polled_device_work(struct work_struct *work)
{
struct input_polled_dev *dev =
container_of(work, struct input_polled_dev, work.work);
- unsigned long delay;
dev->poll(dev);
-
- delay = msecs_to_jiffies(dev->poll_interval);
- if (delay >= HZ)
- delay = round_jiffies_relative(delay);
-
- queue_delayed_work(polldev_wq, &dev->work, delay);
+ queue_delayed_work(polldev_wq, &dev->work,
+ msecs_to_jiffies(dev->poll_interval));
}
static int input_open_polled_device(struct input_dev *input)
{
struct input_polled_dev *dev = input->private;
int error;
+ unsigned long ticks;
error = input_polldev_start_workqueue();
if (error)
@@ -83,8 +79,10 @@ static int input_open_polled_device(struct input_dev *input)
if (dev->flush)
dev->flush(dev);
- queue_delayed_work(polldev_wq, &dev->work,
- msecs_to_jiffies(dev->poll_interval));
+ ticks = msecs_to_jiffies(dev->poll_interval);
+ if (ticks >= HZ)
+ ticks = round_jiffies(ticks);
+ queue_delayed_work(polldev_wq, &dev->work, ticks);
return 0;
}
@@ -93,7 +91,7 @@ static void input_close_polled_device(struct input_dev *input)
{
struct input_polled_dev *dev = input->private;
- cancel_delayed_work_sync(&dev->work);
+ cancel_rearming_delayed_workqueue(polldev_wq, &dev->work);
input_polldev_stop_workqueue();
}
diff --git a/trunk/drivers/input/input.c b/trunk/drivers/input/input.c
index f02c242c3114..a0be978501ff 100644
--- a/trunk/drivers/input/input.c
+++ b/trunk/drivers/input/input.c
@@ -493,7 +493,7 @@ static void input_disconnect_device(struct input_dev *dev)
if (is_event_supported(EV_KEY, dev->evbit, EV_MAX)) {
for (code = 0; code <= KEY_MAX; code++) {
if (is_event_supported(code, dev->keybit, KEY_MAX) &&
- __test_and_clear_bit(code, dev->key)) {
+ test_bit(code, dev->key)) {
input_pass_event(dev, EV_KEY, code, 0);
}
}
@@ -526,7 +526,7 @@ static int input_default_getkeycode(struct input_dev *dev,
if (!dev->keycodesize)
return -EINVAL;
- if (scancode >= dev->keycodemax)
+ if (scancode < 0 || scancode >= dev->keycodemax)
return -EINVAL;
*keycode = input_fetch_keycode(dev, scancode);
@@ -540,7 +540,10 @@ static int input_default_setkeycode(struct input_dev *dev,
int old_keycode;
int i;
- if (scancode >= dev->keycodemax)
+ if (scancode < 0 || scancode >= dev->keycodemax)
+ return -EINVAL;
+
+ if (keycode < 0 || keycode > KEY_MAX)
return -EINVAL;
if (!dev->keycodesize)
@@ -583,75 +586,6 @@ static int input_default_setkeycode(struct input_dev *dev,
return 0;
}
-/**
- * input_get_keycode - retrieve keycode currently mapped to a given scancode
- * @dev: input device which keymap is being queried
- * @scancode: scancode (or its equivalent for device in question) for which
- * keycode is needed
- * @keycode: result
- *
- * This function should be called by anyone interested in retrieving current
- * keymap. Presently keyboard and evdev handlers use it.
- */
-int input_get_keycode(struct input_dev *dev, int scancode, int *keycode)
-{
- if (scancode < 0)
- return -EINVAL;
-
- return dev->getkeycode(dev, scancode, keycode);
-}
-EXPORT_SYMBOL(input_get_keycode);
-
-/**
- * input_get_keycode - assign new keycode to a given scancode
- * @dev: input device which keymap is being updated
- * @scancode: scancode (or its equivalent for device in question)
- * @keycode: new keycode to be assigned to the scancode
- *
- * This function should be called by anyone needing to update current
- * keymap. Presently keyboard and evdev handlers use it.
- */
-int input_set_keycode(struct input_dev *dev, int scancode, int keycode)
-{
- unsigned long flags;
- int old_keycode;
- int retval;
-
- if (scancode < 0)
- return -EINVAL;
-
- if (keycode < 0 || keycode > KEY_MAX)
- return -EINVAL;
-
- spin_lock_irqsave(&dev->event_lock, flags);
-
- retval = dev->getkeycode(dev, scancode, &old_keycode);
- if (retval)
- goto out;
-
- retval = dev->setkeycode(dev, scancode, keycode);
- if (retval)
- goto out;
-
- /*
- * Simulate keyup event if keycode is not present
- * in the keymap anymore
- */
- if (test_bit(EV_KEY, dev->evbit) &&
- !is_event_supported(old_keycode, dev->keybit, KEY_MAX) &&
- __test_and_clear_bit(old_keycode, dev->key)) {
-
- input_pass_event(dev, EV_KEY, old_keycode, 0);
- if (dev->sync)
- input_pass_event(dev, EV_SYN, SYN_REPORT, 1);
- }
-
- out:
- spin_unlock_irqrestore(&dev->event_lock, flags);
-
- return retval;
-}
-EXPORT_SYMBOL(input_set_keycode);
#define MATCH_BIT(bit, max) \
for (i = 0; i < BITS_TO_LONGS(max); i++) \
@@ -821,7 +755,7 @@ static int input_devices_seq_show(struct seq_file *seq, void *v)
return 0;
}
-static const struct seq_operations input_devices_seq_ops = {
+static struct seq_operations input_devices_seq_ops = {
.start = input_devices_seq_start,
.next = input_devices_seq_next,
.stop = input_devices_seq_stop,
@@ -874,7 +808,7 @@ static int input_handlers_seq_show(struct seq_file *seq, void *v)
return 0;
}
-static const struct seq_operations input_handlers_seq_ops = {
+static struct seq_operations input_handlers_seq_ops = {
.start = input_handlers_seq_start,
.next = input_handlers_seq_next,
.stop = input_handlers_seq_stop,
@@ -1395,6 +1329,9 @@ int input_register_device(struct input_dev *dev)
snprintf(dev->dev.bus_id, sizeof(dev->dev.bus_id),
"input%ld", (unsigned long) atomic_inc_return(&input_no) - 1);
+ if (dev->cdev.dev)
+ dev->dev.parent = dev->cdev.dev;
+
error = device_add(&dev->dev);
if (error)
return error;
diff --git a/trunk/drivers/input/joystick/amijoy.c b/trunk/drivers/input/joystick/amijoy.c
index deb9f825f92c..5cf9f3610e67 100644
--- a/trunk/drivers/input/joystick/amijoy.c
+++ b/trunk/drivers/input/joystick/amijoy.c
@@ -32,6 +32,7 @@
#include
#include
#include
+#include
#include
#include
#include
diff --git a/trunk/drivers/input/joystick/analog.c b/trunk/drivers/input/joystick/analog.c
index f32e031dcb27..15739880afc6 100644
--- a/trunk/drivers/input/joystick/analog.c
+++ b/trunk/drivers/input/joystick/analog.c
@@ -31,6 +31,7 @@
#include
#include
#include
+#include
#include
#include
#include
diff --git a/trunk/drivers/input/joystick/db9.c b/trunk/drivers/input/joystick/db9.c
index 960e501c60c8..a6ca9d5e252f 100644
--- a/trunk/drivers/input/joystick/db9.c
+++ b/trunk/drivers/input/joystick/db9.c
@@ -33,6 +33,7 @@
#include
#include
+#include
#include
#include
#include
diff --git a/trunk/drivers/input/joystick/gamecon.c b/trunk/drivers/input/joystick/gamecon.c
index 07a32aff5a31..df2a9d02ca6c 100644
--- a/trunk/drivers/input/joystick/gamecon.c
+++ b/trunk/drivers/input/joystick/gamecon.c
@@ -33,6 +33,7 @@
#include
#include
#include
+#include
#include
#include
#include
diff --git a/trunk/drivers/input/joystick/iforce/iforce-main.c b/trunk/drivers/input/joystick/iforce/iforce-main.c
index a2517fa72eb8..6f826b37d9aa 100644
--- a/trunk/drivers/input/joystick/iforce/iforce-main.c
+++ b/trunk/drivers/input/joystick/iforce/iforce-main.c
@@ -85,7 +85,7 @@ static struct iforce_device iforce_device[] = {
static int iforce_playback(struct input_dev *dev, int effect_id, int value)
{
- struct iforce *iforce = input_get_drvdata(dev);
+ struct iforce* iforce = dev->private;
struct iforce_core_effect *core_effect = &iforce->core_effects[effect_id];
if (value > 0)
@@ -99,7 +99,7 @@ static int iforce_playback(struct input_dev *dev, int effect_id, int value)
static void iforce_set_gain(struct input_dev *dev, u16 gain)
{
- struct iforce *iforce = input_get_drvdata(dev);
+ struct iforce* iforce = dev->private;
unsigned char data[3];
data[0] = gain >> 9;
@@ -108,7 +108,7 @@ static void iforce_set_gain(struct input_dev *dev, u16 gain)
static void iforce_set_autocenter(struct input_dev *dev, u16 magnitude)
{
- struct iforce *iforce = input_get_drvdata(dev);
+ struct iforce* iforce = dev->private;
unsigned char data[3];
data[0] = 0x03;
@@ -126,7 +126,7 @@ static void iforce_set_autocenter(struct input_dev *dev, u16 magnitude)
*/
static int iforce_upload_effect(struct input_dev *dev, struct ff_effect *effect, struct ff_effect *old)
{
- struct iforce *iforce = input_get_drvdata(dev);
+ struct iforce* iforce = dev->private;
struct iforce_core_effect *core_effect = &iforce->core_effects[effect->id];
int ret;
@@ -173,7 +173,7 @@ static int iforce_upload_effect(struct input_dev *dev, struct ff_effect *effect,
*/
static int iforce_erase_effect(struct input_dev *dev, int effect_id)
{
- struct iforce *iforce = input_get_drvdata(dev);
+ struct iforce *iforce = dev->private;
struct iforce_core_effect *core_effect = &iforce->core_effects[effect_id];
int err = 0;
@@ -191,7 +191,7 @@ static int iforce_erase_effect(struct input_dev *dev, int effect_id)
static int iforce_open(struct input_dev *dev)
{
- struct iforce *iforce = input_get_drvdata(dev);
+ struct iforce *iforce = dev->private;
switch (iforce->bus) {
#ifdef CONFIG_JOYSTICK_IFORCE_USB
@@ -213,7 +213,7 @@ static int iforce_open(struct input_dev *dev)
static void iforce_release(struct input_dev *dev)
{
- struct iforce *iforce = input_get_drvdata(dev);
+ struct iforce *iforce = dev->private;
int i;
if (test_bit(EV_FF, dev->evbit)) {
@@ -298,8 +298,7 @@ int iforce_init_device(struct iforce *iforce)
#endif
}
- input_set_drvdata(input_dev, iforce);
-
+ input_dev->private = iforce;
input_dev->name = "Unknown I-Force device";
input_dev->open = iforce_open;
input_dev->close = iforce_release;
diff --git a/trunk/drivers/input/joystick/turbografx.c b/trunk/drivers/input/joystick/turbografx.c
index 989483f53160..bbebd4e2ad7f 100644
--- a/trunk/drivers/input/joystick/turbografx.c
+++ b/trunk/drivers/input/joystick/turbografx.c
@@ -35,6 +35,7 @@
#include
#include
#include
+#include
#include
#include
diff --git a/trunk/drivers/input/joystick/xpad.c b/trunk/drivers/input/joystick/xpad.c
index 0380597249bb..6e9d75bd2b15 100644
--- a/trunk/drivers/input/joystick/xpad.c
+++ b/trunk/drivers/input/joystick/xpad.c
@@ -75,6 +75,7 @@
#include
#include
#include
+#include
#include
#define DRIVER_VERSION "v0.0.6"
diff --git a/trunk/drivers/input/keyboard/Kconfig b/trunk/drivers/input/keyboard/Kconfig
index 8ea709be3306..086d58c0ccbe 100644
--- a/trunk/drivers/input/keyboard/Kconfig
+++ b/trunk/drivers/input/keyboard/Kconfig
@@ -154,27 +154,6 @@ config KEYBOARD_SPITZ
To compile this driver as a module, choose M here: the
module will be called spitzkbd.
-config KEYBOARD_TOSA
- tristate "Tosa keyboard"
- depends on MACH_TOSA
- default y
- help
- Say Y here to enable the keyboard on the Sharp Zaurus SL-6000x (Tosa)
-
- To compile this driver as a module, choose M here: the
- module will be called tosakbd.
-
-config KEYBOARD_TOSA_USE_EXT_KEYCODES
- bool "Tosa keyboard: use extended keycodes"
- depends on KEYBOARD_TOSA
- default n
- help
- Say Y here to enable the tosa keyboard driver to generate extended
- (>= 127) keycodes. Be aware, that they can't be correctly interpreted
- by either console keyboard driver or by Kdrive keybd driver.
-
- Say Y only if you know, what you are doing!
-
config KEYBOARD_AMIGA
tristate "Amiga keyboard"
depends on AMIGA
@@ -260,13 +239,13 @@ config KEYBOARD_OMAP
module will be called omap-keypad.
config KEYBOARD_PXA27x
- tristate "PXA27x/PXA3xx keypad support"
- depends on PXA27x || PXA3xx
+ tristate "PXA27x keyboard support"
+ depends on PXA27x
help
- Enable support for PXA27x/PXA3xx keypad controller
+ Enable support for PXA27x matrix keyboard controller
To compile this driver as a module, choose M here: the
- module will be called pxa27x_keypad.
+ module will be called pxa27x_keyboard.
config KEYBOARD_AAED2000
tristate "AAED-2000 keyboard"
diff --git a/trunk/drivers/input/keyboard/Makefile b/trunk/drivers/input/keyboard/Makefile
index e741f4031012..e97455fdcc83 100644
--- a/trunk/drivers/input/keyboard/Makefile
+++ b/trunk/drivers/input/keyboard/Makefile
@@ -15,11 +15,10 @@ obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o
obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o
obj-$(CONFIG_KEYBOARD_CORGI) += corgikbd.o
obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o
-obj-$(CONFIG_KEYBOARD_TOSA) += tosakbd.o
obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o
obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o
obj-$(CONFIG_KEYBOARD_OMAP) += omap-keypad.o
-obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keypad.o
+obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keyboard.o
obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o
obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o
obj-$(CONFIG_KEYBOARD_HP6XX) += jornada680_kbd.o
diff --git a/trunk/drivers/input/keyboard/atkbd.c b/trunk/drivers/input/keyboard/atkbd.c
index 4a95adc4cc78..b39c5b31e620 100644
--- a/trunk/drivers/input/keyboard/atkbd.c
+++ b/trunk/drivers/input/keyboard/atkbd.c
@@ -19,6 +19,7 @@
#include
#include
+#include
#include
#include
#include
@@ -27,7 +28,6 @@
#include
#include
#include
-#include
#define DRIVER_DESC "AT and PS/2 keyboard driver"
@@ -201,7 +201,6 @@ struct atkbd {
unsigned short id;
unsigned char keycode[512];
- DECLARE_BITMAP(force_release_mask, 512);
unsigned char set;
unsigned char translated;
unsigned char extra;
@@ -226,11 +225,6 @@ struct atkbd {
unsigned long event_mask;
};
-/*
- * System-specific ketymap fixup routine
- */
-static void (*atkbd_platform_fixup)(struct atkbd *);
-
static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf,
ssize_t (*handler)(struct atkbd *, char *));
static ssize_t atkbd_attr_set_helper(struct device *dev, const char *buf, size_t count,
@@ -355,7 +349,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
struct atkbd *atkbd = serio_get_drvdata(serio);
struct input_dev *dev = atkbd->dev;
unsigned int code = data;
- int scroll = 0, hscroll = 0, click = -1;
+ int scroll = 0, hscroll = 0, click = -1, add_release_event = 0;
int value;
unsigned char keycode;
@@ -420,6 +414,14 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
"Some program might be trying access hardware directly.\n",
data == ATKBD_RET_ACK ? "ACK" : "NAK", serio->phys);
goto out;
+ case ATKBD_RET_HANGEUL:
+ case ATKBD_RET_HANJA:
+ /*
+ * These keys do not report release and thus need to be
+ * flagged properly
+ */
+ add_release_event = 1;
+ break;
case ATKBD_RET_ERR:
atkbd->err_count++;
#ifdef ATKBD_DEBUG
@@ -489,7 +491,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
input_event(dev, EV_KEY, keycode, value);
input_sync(dev);
- if (value && test_bit(code, atkbd->force_release_mask)) {
+ if (value && add_release_event) {
input_report_key(dev, keycode, 0);
input_sync(dev);
}
@@ -822,6 +824,7 @@ static void atkbd_disconnect(struct serio *serio)
atkbd_disable(atkbd);
/* make sure we don't have a command in flight */
+ synchronize_sched(); /* Allow atkbd_interrupt()s to complete. */
flush_scheduled_work();
sysfs_remove_group(&serio->dev.kobj, &atkbd_attribute_group);
@@ -831,22 +834,6 @@ static void atkbd_disconnect(struct serio *serio)
kfree(atkbd);
}
-/*
- * Most special keys (Fn+F?) on Dell Latitudes do not generate release
- * events so we have to do it ourselves.
- */
-static void atkbd_latitude_keymap_fixup(struct atkbd *atkbd)
-{
- const unsigned int forced_release_keys[] = {
- 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8f, 0x93,
- };
- int i;
-
- if (atkbd->set == 2)
- for (i = 0; i < ARRAY_SIZE(forced_release_keys); i++)
- __set_bit(forced_release_keys[i],
- atkbd->force_release_mask);
-}
/*
* atkbd_set_keycode_table() initializes keyboard's keycode table
@@ -855,20 +842,17 @@ static void atkbd_latitude_keymap_fixup(struct atkbd *atkbd)
static void atkbd_set_keycode_table(struct atkbd *atkbd)
{
- unsigned int scancode;
int i, j;
memset(atkbd->keycode, 0, sizeof(atkbd->keycode));
- bitmap_zero(atkbd->force_release_mask, 512);
if (atkbd->translated) {
for (i = 0; i < 128; i++) {
- scancode = atkbd_unxlate_table[i];
- atkbd->keycode[i] = atkbd_set2_keycode[scancode];
- atkbd->keycode[i | 0x80] = atkbd_set2_keycode[scancode | 0x80];
+ atkbd->keycode[i] = atkbd_set2_keycode[atkbd_unxlate_table[i]];
+ atkbd->keycode[i | 0x80] = atkbd_set2_keycode[atkbd_unxlate_table[i] | 0x80];
if (atkbd->scroll)
for (j = 0; j < ARRAY_SIZE(atkbd_scroll_keys); j++)
- if ((scancode | 0x80) == atkbd_scroll_keys[j].set2)
+ if ((atkbd_unxlate_table[i] | 0x80) == atkbd_scroll_keys[j].set2)
atkbd->keycode[i | 0x80] = atkbd_scroll_keys[j].keycode;
}
} else if (atkbd->set == 3) {
@@ -877,29 +861,12 @@ static void atkbd_set_keycode_table(struct atkbd *atkbd)
memcpy(atkbd->keycode, atkbd_set2_keycode, sizeof(atkbd->keycode));
if (atkbd->scroll)
- for (i = 0; i < ARRAY_SIZE(atkbd_scroll_keys); i++) {
- scancode = atkbd_scroll_keys[i].set2;
- atkbd->keycode[scancode] = atkbd_scroll_keys[i].keycode;
- }
+ for (i = 0; i < ARRAY_SIZE(atkbd_scroll_keys); i++)
+ atkbd->keycode[atkbd_scroll_keys[i].set2] = atkbd_scroll_keys[i].keycode;
}
-/*
- * HANGEUL and HANJA keys do not send release events so we need to
- * generate such events ourselves
- */
- scancode = atkbd_compat_scancode(atkbd, ATKBD_RET_HANGEUL);
- atkbd->keycode[scancode] = KEY_HANGEUL;
- __set_bit(scancode, atkbd->force_release_mask);
-
- scancode = atkbd_compat_scancode(atkbd, ATKBD_RET_HANJA);
- atkbd->keycode[scancode] = KEY_HANJA;
- __set_bit(scancode, atkbd->force_release_mask);
-
-/*
- * Perform additional fixups
- */
- if (atkbd_platform_fixup)
- atkbd_platform_fixup(atkbd);
+ atkbd->keycode[atkbd_compat_scancode(atkbd, ATKBD_RET_HANGEUL)] = KEY_HANGUEL;
+ atkbd->keycode[atkbd_compat_scancode(atkbd, ATKBD_RET_HANJA)] = KEY_HANJA;
}
/*
@@ -1434,29 +1401,9 @@ static ssize_t atkbd_show_err_count(struct atkbd *atkbd, char *buf)
return sprintf(buf, "%lu\n", atkbd->err_count);
}
-static int __init atkbd_setup_fixup(const struct dmi_system_id *id)
-{
- atkbd_platform_fixup = id->driver_data;
- return 0;
-}
-
-static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
- {
- .ident = "Dell Latitude series",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "Latitude"),
- },
- .callback = atkbd_setup_fixup,
- .driver_data = atkbd_latitude_keymap_fixup,
- },
- { }
-};
static int __init atkbd_init(void)
{
- dmi_check_system(atkbd_dmi_quirk_table);
-
return serio_register_driver(&atkbd_drv);
}
diff --git a/trunk/drivers/input/keyboard/lkkbd.c b/trunk/drivers/input/keyboard/lkkbd.c
index 32e2c2605d95..1b08f4e79dd2 100644
--- a/trunk/drivers/input/keyboard/lkkbd.c
+++ b/trunk/drivers/input/keyboard/lkkbd.c
@@ -64,6 +64,7 @@
#include
#include
#include
+#include
#include
#include
#include
diff --git a/trunk/drivers/input/keyboard/pxa27x_keyboard.c b/trunk/drivers/input/keyboard/pxa27x_keyboard.c
new file mode 100644
index 000000000000..bdd64ee4c5c8
--- /dev/null
+++ b/trunk/drivers/input/keyboard/pxa27x_keyboard.c
@@ -0,0 +1,274 @@
+/*
+ * linux/drivers/input/keyboard/pxa27x_keyboard.c
+ *
+ * Driver for the pxa27x matrix keyboard controller.
+ *
+ * Created: Feb 22, 2007
+ * Author: Rodolfo Giometti
+ *
+ * Based on a previous implementations by Kevin O'Connor
+ * and Alex Osborne and
+ * on some suggestions by Nicolas Pitre .
+ *
+ * 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
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#define DRIVER_NAME "pxa27x-keyboard"
+
+#define KPASMKP(col) (col/2 == 0 ? KPASMKP0 : \
+ col/2 == 1 ? KPASMKP1 : \
+ col/2 == 2 ? KPASMKP2 : KPASMKP3)
+#define KPASMKPx_MKC(row, col) (1 << (row + 16 * (col % 2)))
+
+static struct clk *pxakbd_clk;
+
+static irqreturn_t pxakbd_irq_handler(int irq, void *dev_id)
+{
+ struct platform_device *pdev = dev_id;
+ struct pxa27x_keyboard_platform_data *pdata = pdev->dev.platform_data;
+ struct input_dev *input_dev = platform_get_drvdata(pdev);
+ unsigned long kpc = KPC;
+ int p, row, col, rel;
+
+ if (kpc & KPC_DI) {
+ unsigned long kpdk = KPDK;
+
+ if (!(kpdk & KPDK_DKP)) {
+ /* better luck next time */
+ } else if (kpc & KPC_REE0) {
+ unsigned long kprec = KPREC;
+ KPREC = 0x7f;
+
+ if (kprec & KPREC_OF0)
+ rel = (kprec & 0xff) + 0x7f;
+ else if (kprec & KPREC_UF0)
+ rel = (kprec & 0xff) - 0x7f - 0xff;
+ else
+ rel = (kprec & 0xff) - 0x7f;
+
+ if (rel) {
+ input_report_rel(input_dev, REL_WHEEL, rel);
+ input_sync(input_dev);
+ }
+ }
+ }
+
+ if (kpc & KPC_MI) {
+ /* report the status of every button */
+ for (row = 0; row < pdata->nr_rows; row++) {
+ for (col = 0; col < pdata->nr_cols; col++) {
+ p = KPASMKP(col) & KPASMKPx_MKC(row, col) ?
+ 1 : 0;
+ pr_debug("keycode %x - pressed %x\n",
+ pdata->keycodes[row][col], p);
+ input_report_key(input_dev,
+ pdata->keycodes[row][col], p);
+ }
+ }
+ input_sync(input_dev);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int pxakbd_open(struct input_dev *dev)
+{
+ /* Set keypad control register */
+ KPC |= (KPC_ASACT |
+ KPC_MS_ALL |
+ (2 << 6) | KPC_REE0 | KPC_DK_DEB_SEL |
+ KPC_ME | KPC_MIE | KPC_DE | KPC_DIE);
+
+ KPC &= ~KPC_AS; /* disable automatic scan */
+ KPC &= ~KPC_IMKP; /* do not ignore multiple keypresses */
+
+ /* Set rotary count to mid-point value */
+ KPREC = 0x7F;
+
+ /* Enable unit clock */
+ clk_enable(pxakbd_clk);
+
+ return 0;
+}
+
+static void pxakbd_close(struct input_dev *dev)
+{
+ /* Disable clock unit */
+ clk_disable(pxakbd_clk);
+}
+
+#ifdef CONFIG_PM
+static int pxakbd_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct pxa27x_keyboard_platform_data *pdata = pdev->dev.platform_data;
+
+ /* Save controller status */
+ pdata->reg_kpc = KPC;
+ pdata->reg_kprec = KPREC;
+
+ return 0;
+}
+
+static int pxakbd_resume(struct platform_device *pdev)
+{
+ struct pxa27x_keyboard_platform_data *pdata = pdev->dev.platform_data;
+ struct input_dev *input_dev = platform_get_drvdata(pdev);
+
+ mutex_lock(&input_dev->mutex);
+
+ if (input_dev->users) {
+ /* Restore controller status */
+ KPC = pdata->reg_kpc;
+ KPREC = pdata->reg_kprec;
+
+ /* Enable unit clock */
+ clk_disable(pxakbd_clk);
+ clk_enable(pxakbd_clk);
+ }
+
+ mutex_unlock(&input_dev->mutex);
+
+ return 0;
+}
+#else
+#define pxakbd_suspend NULL
+#define pxakbd_resume NULL
+#endif
+
+static int __devinit pxakbd_probe(struct platform_device *pdev)
+{
+ struct pxa27x_keyboard_platform_data *pdata = pdev->dev.platform_data;
+ struct input_dev *input_dev;
+ int i, row, col, error;
+
+ pxakbd_clk = clk_get(&pdev->dev, "KBDCLK");
+ if (IS_ERR(pxakbd_clk)) {
+ error = PTR_ERR(pxakbd_clk);
+ goto err_clk;
+ }
+
+ /* Create and register the input driver. */
+ input_dev = input_allocate_device();
+ if (!input_dev) {
+ printk(KERN_ERR "Cannot request keypad device\n");
+ error = -ENOMEM;
+ goto err_alloc;
+ }
+
+ input_dev->name = DRIVER_NAME;
+ input_dev->id.bustype = BUS_HOST;
+ input_dev->open = pxakbd_open;
+ input_dev->close = pxakbd_close;
+ input_dev->dev.parent = &pdev->dev;
+
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) |
+ BIT_MASK(EV_REL);
+ input_dev->relbit[BIT_WORD(REL_WHEEL)] = BIT_MASK(REL_WHEEL);
+ for (row = 0; row < pdata->nr_rows; row++) {
+ for (col = 0; col < pdata->nr_cols; col++) {
+ int code = pdata->keycodes[row][col];
+ if (code > 0)
+ set_bit(code, input_dev->keybit);
+ }
+ }
+
+ error = request_irq(IRQ_KEYPAD, pxakbd_irq_handler, IRQF_DISABLED,
+ DRIVER_NAME, pdev);
+ if (error) {
+ printk(KERN_ERR "Cannot request keypad IRQ\n");
+ goto err_free_dev;
+ }
+
+ platform_set_drvdata(pdev, input_dev);
+
+ /* Register the input device */
+ error = input_register_device(input_dev);
+ if (error)
+ goto err_free_irq;
+
+ /* Setup GPIOs. */
+ for (i = 0; i < pdata->nr_rows + pdata->nr_cols; i++)
+ pxa_gpio_mode(pdata->gpio_modes[i]);
+
+ /*
+ * Store rows/cols info into keyboard registers.
+ */
+
+ KPC |= (pdata->nr_rows - 1) << 26;
+ KPC |= (pdata->nr_cols - 1) << 23;
+
+ for (col = 0; col < pdata->nr_cols; col++)
+ KPC |= KPC_MS0 << col;
+
+ return 0;
+
+ err_free_irq:
+ platform_set_drvdata(pdev, NULL);
+ free_irq(IRQ_KEYPAD, pdev);
+ err_free_dev:
+ input_free_device(input_dev);
+ err_alloc:
+ clk_put(pxakbd_clk);
+ err_clk:
+ return error;
+}
+
+static int __devexit pxakbd_remove(struct platform_device *pdev)
+{
+ struct input_dev *input_dev = platform_get_drvdata(pdev);
+
+ input_unregister_device(input_dev);
+ free_irq(IRQ_KEYPAD, pdev);
+ clk_put(pxakbd_clk);
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
+}
+
+static struct platform_driver pxakbd_driver = {
+ .probe = pxakbd_probe,
+ .remove = __devexit_p(pxakbd_remove),
+ .suspend = pxakbd_suspend,
+ .resume = pxakbd_resume,
+ .driver = {
+ .name = DRIVER_NAME,
+ },
+};
+
+static int __init pxakbd_init(void)
+{
+ return platform_driver_register(&pxakbd_driver);
+}
+
+static void __exit pxakbd_exit(void)
+{
+ platform_driver_unregister(&pxakbd_driver);
+}
+
+module_init(pxakbd_init);
+module_exit(pxakbd_exit);
+
+MODULE_DESCRIPTION("PXA27x Matrix Keyboard Driver");
+MODULE_LICENSE("GPL");
diff --git a/trunk/drivers/input/keyboard/pxa27x_keypad.c b/trunk/drivers/input/keyboard/pxa27x_keypad.c
deleted file mode 100644
index 6224c2fb3b65..000000000000
--- a/trunk/drivers/input/keyboard/pxa27x_keypad.c
+++ /dev/null
@@ -1,572 +0,0 @@
-/*
- * linux/drivers/input/keyboard/pxa27x_keypad.c
- *
- * Driver for the pxa27x matrix keyboard controller.
- *
- * Created: Feb 22, 2007
- * Author: Rodolfo Giometti
- *
- * Based on a previous implementations by Kevin O'Connor
- * and Alex Osborne and
- * on some suggestions by Nicolas Pitre .
- *
- * 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
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-
-#include
-#include
-
-/*
- * Keypad Controller registers
- */
-#define KPC 0x0000 /* Keypad Control register */
-#define KPDK 0x0008 /* Keypad Direct Key register */
-#define KPREC 0x0010 /* Keypad Rotary Encoder register */
-#define KPMK 0x0018 /* Keypad Matrix Key register */
-#define KPAS 0x0020 /* Keypad Automatic Scan register */
-
-/* Keypad Automatic Scan Multiple Key Presser register 0-3 */
-#define KPASMKP0 0x0028
-#define KPASMKP1 0x0030
-#define KPASMKP2 0x0038
-#define KPASMKP3 0x0040
-#define KPKDI 0x0048
-
-/* bit definitions */
-#define KPC_MKRN(n) ((((n) & 0x7) - 1) << 26) /* matrix key row number */
-#define KPC_MKCN(n) ((((n) & 0x7) - 1) << 23) /* matrix key column number */
-#define KPC_DKN(n) ((((n) & 0x7) - 1) << 6) /* direct key number */
-
-#define KPC_AS (0x1 << 30) /* Automatic Scan bit */
-#define KPC_ASACT (0x1 << 29) /* Automatic Scan on Activity */
-#define KPC_MI (0x1 << 22) /* Matrix interrupt bit */
-#define KPC_IMKP (0x1 << 21) /* Ignore Multiple Key Press */
-
-#define KPC_MS(n) (0x1 << (13 + (n))) /* Matrix scan line 'n' */
-#define KPC_MS_ALL (0xff << 13)
-
-#define KPC_ME (0x1 << 12) /* Matrix Keypad Enable */
-#define KPC_MIE (0x1 << 11) /* Matrix Interrupt Enable */
-#define KPC_DK_DEB_SEL (0x1 << 9) /* Direct Keypad Debounce Select */
-#define KPC_DI (0x1 << 5) /* Direct key interrupt bit */
-#define KPC_RE_ZERO_DEB (0x1 << 4) /* Rotary Encoder Zero Debounce */
-#define KPC_REE1 (0x1 << 3) /* Rotary Encoder1 Enable */
-#define KPC_REE0 (0x1 << 2) /* Rotary Encoder0 Enable */
-#define KPC_DE (0x1 << 1) /* Direct Keypad Enable */
-#define KPC_DIE (0x1 << 0) /* Direct Keypad interrupt Enable */
-
-#define KPDK_DKP (0x1 << 31)
-#define KPDK_DK(n) ((n) & 0xff)
-
-#define KPREC_OF1 (0x1 << 31)
-#define kPREC_UF1 (0x1 << 30)
-#define KPREC_OF0 (0x1 << 15)
-#define KPREC_UF0 (0x1 << 14)
-
-#define KPREC_RECOUNT0(n) ((n) & 0xff)
-#define KPREC_RECOUNT1(n) (((n) >> 16) & 0xff)
-
-#define KPMK_MKP (0x1 << 31)
-#define KPAS_SO (0x1 << 31)
-#define KPASMKPx_SO (0x1 << 31)
-
-#define KPAS_MUKP(n) (((n) >> 26) & 0x1f)
-#define KPAS_RP(n) (((n) >> 4) & 0xf)
-#define KPAS_CP(n) ((n) & 0xf)
-
-#define KPASMKP_MKC_MASK (0xff)
-
-#define keypad_readl(off) __raw_readl(keypad->mmio_base + (off))
-#define keypad_writel(off, v) __raw_writel((v), keypad->mmio_base + (off))
-
-#define MAX_MATRIX_KEY_NUM (8 * 8)
-
-struct pxa27x_keypad {
- struct pxa27x_keypad_platform_data *pdata;
-
- struct clk *clk;
- struct input_dev *input_dev;
- void __iomem *mmio_base;
-
- /* matrix key code map */
- unsigned int matrix_keycodes[MAX_MATRIX_KEY_NUM];
-
- /* state row bits of each column scan */
- uint32_t matrix_key_state[MAX_MATRIX_KEY_COLS];
- uint32_t direct_key_state;
-
- unsigned int direct_key_mask;
-
- int rotary_rel_code[2];
- int rotary_up_key[2];
- int rotary_down_key[2];
-};
-
-static void pxa27x_keypad_build_keycode(struct pxa27x_keypad *keypad)
-{
- struct pxa27x_keypad_platform_data *pdata = keypad->pdata;
- struct input_dev *input_dev = keypad->input_dev;
- unsigned int *key;
- int i;
-
- key = &pdata->matrix_key_map[0];
- for (i = 0; i < pdata->matrix_key_map_size; i++, key++) {
- int row = ((*key) >> 28) & 0xf;
- int col = ((*key) >> 24) & 0xf;
- int code = (*key) & 0xffffff;
-
- keypad->matrix_keycodes[(row << 3) + col] = code;
- set_bit(code, input_dev->keybit);
- }
-
- keypad->rotary_up_key[0] = pdata->rotary0_up_key;
- keypad->rotary_up_key[1] = pdata->rotary1_up_key;
- keypad->rotary_down_key[0] = pdata->rotary0_down_key;
- keypad->rotary_down_key[1] = pdata->rotary1_down_key;
- keypad->rotary_rel_code[0] = pdata->rotary0_rel_code;
- keypad->rotary_rel_code[1] = pdata->rotary1_rel_code;
-
- if (pdata->rotary0_up_key && pdata->rotary0_down_key) {
- set_bit(pdata->rotary0_up_key, input_dev->keybit);
- set_bit(pdata->rotary0_down_key, input_dev->keybit);
- } else
- set_bit(pdata->rotary0_rel_code, input_dev->relbit);
-
- if (pdata->rotary1_up_key && pdata->rotary1_down_key) {
- set_bit(pdata->rotary1_up_key, input_dev->keybit);
- set_bit(pdata->rotary1_down_key, input_dev->keybit);
- } else
- set_bit(pdata->rotary1_rel_code, input_dev->relbit);
-}
-
-static inline unsigned int lookup_matrix_keycode(
- struct pxa27x_keypad *keypad, int row, int col)
-{
- return keypad->matrix_keycodes[(row << 3) + col];
-}
-
-static void pxa27x_keypad_scan_matrix(struct pxa27x_keypad *keypad)
-{
- struct pxa27x_keypad_platform_data *pdata = keypad->pdata;
- int row, col, num_keys_pressed = 0;
- uint32_t new_state[MAX_MATRIX_KEY_COLS];
- uint32_t kpas = keypad_readl(KPAS);
-
- num_keys_pressed = KPAS_MUKP(kpas);
-
- memset(new_state, 0, sizeof(new_state));
-
- if (num_keys_pressed == 0)
- goto scan;
-
- if (num_keys_pressed == 1) {
- col = KPAS_CP(kpas);
- row = KPAS_RP(kpas);
-
- /* if invalid row/col, treat as no key pressed */
- if (col >= pdata->matrix_key_cols ||
- row >= pdata->matrix_key_rows)
- goto scan;
-
- new_state[col] = (1 << row);
- goto scan;
- }
-
- if (num_keys_pressed > 1) {
- uint32_t kpasmkp0 = keypad_readl(KPASMKP0);
- uint32_t kpasmkp1 = keypad_readl(KPASMKP1);
- uint32_t kpasmkp2 = keypad_readl(KPASMKP2);
- uint32_t kpasmkp3 = keypad_readl(KPASMKP3);
-
- new_state[0] = kpasmkp0 & KPASMKP_MKC_MASK;
- new_state[1] = (kpasmkp0 >> 16) & KPASMKP_MKC_MASK;
- new_state[2] = kpasmkp1 & KPASMKP_MKC_MASK;
- new_state[3] = (kpasmkp1 >> 16) & KPASMKP_MKC_MASK;
- new_state[4] = kpasmkp2 & KPASMKP_MKC_MASK;
- new_state[5] = (kpasmkp2 >> 16) & KPASMKP_MKC_MASK;
- new_state[6] = kpasmkp3 & KPASMKP_MKC_MASK;
- new_state[7] = (kpasmkp3 >> 16) & KPASMKP_MKC_MASK;
- }
-scan:
- for (col = 0; col < pdata->matrix_key_cols; col++) {
- uint32_t bits_changed;
-
- bits_changed = keypad->matrix_key_state[col] ^ new_state[col];
- if (bits_changed == 0)
- continue;
-
- for (row = 0; row < pdata->matrix_key_rows; row++) {
- if ((bits_changed & (1 << row)) == 0)
- continue;
-
- input_report_key(keypad->input_dev,
- lookup_matrix_keycode(keypad, row, col),
- new_state[col] & (1 << row));
- }
- }
- input_sync(keypad->input_dev);
- memcpy(keypad->matrix_key_state, new_state, sizeof(new_state));
-}
-
-#define DEFAULT_KPREC (0x007f007f)
-
-static inline int rotary_delta(uint32_t kprec)
-{
- if (kprec & KPREC_OF0)
- return (kprec & 0xff) + 0x7f;
- else if (kprec & KPREC_UF0)
- return (kprec & 0xff) - 0x7f - 0xff;
- else
- return (kprec & 0xff) - 0x7f;
-}
-
-static void report_rotary_event(struct pxa27x_keypad *keypad, int r, int delta)
-{
- struct input_dev *dev = keypad->input_dev;
-
- if (delta == 0)
- return;
-
- if (keypad->rotary_up_key[r] && keypad->rotary_down_key[r]) {
- int keycode = (delta > 0) ? keypad->rotary_up_key[r] :
- keypad->rotary_down_key[r];
-
- /* simulate a press-n-release */
- input_report_key(dev, keycode, 1);
- input_sync(dev);
- input_report_key(dev, keycode, 0);
- input_sync(dev);
- } else {
- input_report_rel(dev, keypad->rotary_rel_code[r], delta);
- input_sync(dev);
- }
-}
-
-static void pxa27x_keypad_scan_rotary(struct pxa27x_keypad *keypad)
-{
- struct pxa27x_keypad_platform_data *pdata = keypad->pdata;
- uint32_t kprec;
-
- /* read and reset to default count value */
- kprec = keypad_readl(KPREC);
- keypad_writel(KPREC, DEFAULT_KPREC);
-
- if (pdata->enable_rotary0)
- report_rotary_event(keypad, 0, rotary_delta(kprec));
-
- if (pdata->enable_rotary1)
- report_rotary_event(keypad, 1, rotary_delta(kprec >> 16));
-}
-
-static void pxa27x_keypad_scan_direct(struct pxa27x_keypad *keypad)
-{
- struct pxa27x_keypad_platform_data *pdata = keypad->pdata;
- unsigned int new_state;
- uint32_t kpdk, bits_changed;
- int i;
-
- kpdk = keypad_readl(KPDK);
-
- if (pdata->enable_rotary0 || pdata->enable_rotary1)
- pxa27x_keypad_scan_rotary(keypad);
-
- if (pdata->direct_key_map == NULL)
- return;
-
- new_state = KPDK_DK(kpdk) & keypad->direct_key_mask;
- bits_changed = keypad->direct_key_state ^ new_state;
-
- if (bits_changed == 0)
- return;
-
- for (i = 0; i < pdata->direct_key_num; i++) {
- if (bits_changed & (1 << i))
- input_report_key(keypad->input_dev,
- pdata->direct_key_map[i],
- (new_state & (1 << i)));
- }
- input_sync(keypad->input_dev);
- keypad->direct_key_state = new_state;
-}
-
-static irqreturn_t pxa27x_keypad_irq_handler(int irq, void *dev_id)
-{
- struct pxa27x_keypad *keypad = dev_id;
- unsigned long kpc = keypad_readl(KPC);
-
- if (kpc & KPC_DI)
- pxa27x_keypad_scan_direct(keypad);
-
- if (kpc & KPC_MI)
- pxa27x_keypad_scan_matrix(keypad);
-
- return IRQ_HANDLED;
-}
-
-static void pxa27x_keypad_config(struct pxa27x_keypad *keypad)
-{
- struct pxa27x_keypad_platform_data *pdata = keypad->pdata;
- unsigned int mask = 0, direct_key_num = 0;
- unsigned long kpc = 0;
-
- /* enable matrix keys with automatic scan */
- if (pdata->matrix_key_rows && pdata->matrix_key_cols) {
- kpc |= KPC_ASACT | KPC_MIE | KPC_ME | KPC_MS_ALL;
- kpc |= KPC_MKRN(pdata->matrix_key_rows) |
- KPC_MKCN(pdata->matrix_key_cols);
- }
-
- /* enable rotary key, debounce interval same as direct keys */
- if (pdata->enable_rotary0) {
- mask |= 0x03;
- direct_key_num = 2;
- kpc |= KPC_REE0;
- }
-
- if (pdata->enable_rotary1) {
- mask |= 0x0c;
- direct_key_num = 4;
- kpc |= KPC_REE1;
- }
-
- if (pdata->direct_key_num > direct_key_num)
- direct_key_num = pdata->direct_key_num;
-
- keypad->direct_key_mask = ((2 << direct_key_num) - 1) & ~mask;
-
- /* enable direct key */
- if (direct_key_num)
- kpc |= KPC_DE | KPC_DIE | KPC_DKN(direct_key_num);
-
- keypad_writel(KPC, kpc | KPC_RE_ZERO_DEB);
- keypad_writel(KPREC, DEFAULT_KPREC);
- keypad_writel(KPKDI, pdata->debounce_interval);
-}
-
-static int pxa27x_keypad_open(struct input_dev *dev)
-{
- struct pxa27x_keypad *keypad = input_get_drvdata(dev);
-
- /* Enable unit clock */
- clk_enable(keypad->clk);
- pxa27x_keypad_config(keypad);
-
- return 0;
-}
-
-static void pxa27x_keypad_close(struct input_dev *dev)
-{
- struct pxa27x_keypad *keypad = input_get_drvdata(dev);
-
- /* Disable clock unit */
- clk_disable(keypad->clk);
-}
-
-#ifdef CONFIG_PM
-static int pxa27x_keypad_suspend(struct platform_device *pdev, pm_message_t state)
-{
- struct pxa27x_keypad *keypad = platform_get_drvdata(pdev);
-
- clk_disable(keypad->clk);
- return 0;
-}
-
-static int pxa27x_keypad_resume(struct platform_device *pdev)
-{
- struct pxa27x_keypad *keypad = platform_get_drvdata(pdev);
- struct input_dev *input_dev = keypad->input_dev;
-
- mutex_lock(&input_dev->mutex);
-
- if (input_dev->users) {
- /* Enable unit clock */
- clk_enable(keypad->clk);
- pxa27x_keypad_config(keypad);
- }
-
- mutex_unlock(&input_dev->mutex);
-
- return 0;
-}
-#else
-#define pxa27x_keypad_suspend NULL
-#define pxa27x_keypad_resume NULL
-#endif
-
-#define res_size(res) ((res)->end - (res)->start + 1)
-
-static int __devinit pxa27x_keypad_probe(struct platform_device *pdev)
-{
- struct pxa27x_keypad *keypad;
- struct input_dev *input_dev;
- struct resource *res;
- int irq, error;
-
- keypad = kzalloc(sizeof(struct pxa27x_keypad), GFP_KERNEL);
- if (keypad == NULL) {
- dev_err(&pdev->dev, "failed to allocate driver data\n");
- return -ENOMEM;
- }
-
- keypad->pdata = pdev->dev.platform_data;
- if (keypad->pdata == NULL) {
- dev_err(&pdev->dev, "no platform data defined\n");
- error = -EINVAL;
- goto failed_free;
- }
-
- irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_err(&pdev->dev, "failed to get keypad irq\n");
- error = -ENXIO;
- goto failed_free;
- }
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (res == NULL) {
- dev_err(&pdev->dev, "failed to get I/O memory\n");
- error = -ENXIO;
- goto failed_free;
- }
-
- res = request_mem_region(res->start, res_size(res), pdev->name);
- if (res == NULL) {
- dev_err(&pdev->dev, "failed to request I/O memory\n");
- error = -EBUSY;
- goto failed_free;
- }
-
- keypad->mmio_base = ioremap(res->start, res_size(res));
- if (keypad->mmio_base == NULL) {
- dev_err(&pdev->dev, "failed to remap I/O memory\n");
- error = -ENXIO;
- goto failed_free_mem;
- }
-
- keypad->clk = clk_get(&pdev->dev, "KBDCLK");
- if (IS_ERR(keypad->clk)) {
- dev_err(&pdev->dev, "failed to get keypad clock\n");
- error = PTR_ERR(keypad->clk);
- goto failed_free_io;
- }
-
- /* Create and register the input driver. */
- input_dev = input_allocate_device();
- if (!input_dev) {
- dev_err(&pdev->dev, "failed to allocate input device\n");
- error = -ENOMEM;
- goto failed_put_clk;
- }
-
- input_dev->name = pdev->name;
- input_dev->id.bustype = BUS_HOST;
- input_dev->open = pxa27x_keypad_open;
- input_dev->close = pxa27x_keypad_close;
- input_dev->dev.parent = &pdev->dev;
-
- keypad->input_dev = input_dev;
- input_set_drvdata(input_dev, keypad);
-
- input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) |
- BIT_MASK(EV_REL);
-
- pxa27x_keypad_build_keycode(keypad);
- platform_set_drvdata(pdev, keypad);
-
- error = request_irq(irq, pxa27x_keypad_irq_handler, IRQF_DISABLED,
- pdev->name, keypad);
- if (error) {
- dev_err(&pdev->dev, "failed to request IRQ\n");
- goto failed_free_dev;
- }
-
- /* Register the input device */
- error = input_register_device(input_dev);
- if (error) {
- dev_err(&pdev->dev, "failed to register input device\n");
- goto failed_free_irq;
- }
-
- return 0;
-
-failed_free_irq:
- free_irq(irq, pdev);
- platform_set_drvdata(pdev, NULL);
-failed_free_dev:
- input_free_device(input_dev);
-failed_put_clk:
- clk_put(keypad->clk);
-failed_free_io:
- iounmap(keypad->mmio_base);
-failed_free_mem:
- release_mem_region(res->start, res_size(res));
-failed_free:
- kfree(keypad);
- return error;
-}
-
-static int __devexit pxa27x_keypad_remove(struct platform_device *pdev)
-{
- struct pxa27x_keypad *keypad = platform_get_drvdata(pdev);
- struct resource *res;
-
- free_irq(platform_get_irq(pdev, 0), pdev);
-
- clk_disable(keypad->clk);
- clk_put(keypad->clk);
-
- input_unregister_device(keypad->input_dev);
- input_free_device(keypad->input_dev);
-
- iounmap(keypad->mmio_base);
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- release_mem_region(res->start, res_size(res));
-
- platform_set_drvdata(pdev, NULL);
- kfree(keypad);
- return 0;
-}
-
-static struct platform_driver pxa27x_keypad_driver = {
- .probe = pxa27x_keypad_probe,
- .remove = __devexit_p(pxa27x_keypad_remove),
- .suspend = pxa27x_keypad_suspend,
- .resume = pxa27x_keypad_resume,
- .driver = {
- .name = "pxa27x-keypad",
- },
-};
-
-static int __init pxa27x_keypad_init(void)
-{
- return platform_driver_register(&pxa27x_keypad_driver);
-}
-
-static void __exit pxa27x_keypad_exit(void)
-{
- platform_driver_unregister(&pxa27x_keypad_driver);
-}
-
-module_init(pxa27x_keypad_init);
-module_exit(pxa27x_keypad_exit);
-
-MODULE_DESCRIPTION("PXA27x Keypad Controller Driver");
-MODULE_LICENSE("GPL");
diff --git a/trunk/drivers/input/keyboard/tosakbd.c b/trunk/drivers/input/keyboard/tosakbd.c
deleted file mode 100644
index 3884d1e3f070..000000000000
--- a/trunk/drivers/input/keyboard/tosakbd.c
+++ /dev/null
@@ -1,415 +0,0 @@
-/*
- * Keyboard driver for Sharp Tosa models (SL-6000x)
- *
- * Copyright (c) 2005 Dirk Opfer
- * Copyright (c) 2007 Dmitry Baryshkov
- *
- * Based on xtkbd.c/locomkbd.c/corgikbd.c
- *
- * 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
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-
-#define KB_ROWMASK(r) (1 << (r))
-#define SCANCODE(r, c) (((r)<<4) + (c) + 1)
-#define NR_SCANCODES SCANCODE(TOSA_KEY_SENSE_NUM - 1, TOSA_KEY_STROBE_NUM - 1) + 1
-
-#define SCAN_INTERVAL (HZ/10)
-
-#define KB_DISCHARGE_DELAY 10
-#define KB_ACTIVATE_DELAY 10
-
-static unsigned int tosakbd_keycode[NR_SCANCODES] = {
-0,
-0, KEY_W, 0, 0, 0, KEY_K, KEY_BACKSPACE, KEY_P,
-0, 0, 0, 0, 0, 0, 0, 0,
-KEY_Q, KEY_E, KEY_T, KEY_Y, 0, KEY_O, KEY_I, KEY_COMMA,
-0, 0, 0, 0, 0, 0, 0, 0,
-KEY_A, KEY_D, KEY_G, KEY_U, 0, KEY_L, KEY_ENTER, KEY_DOT,
-0, 0, 0, 0, 0, 0, 0, 0,
-KEY_Z, KEY_C, KEY_V, KEY_J, TOSA_KEY_ADDRESSBOOK, TOSA_KEY_CANCEL, TOSA_KEY_CENTER, TOSA_KEY_OK,
-KEY_LEFTSHIFT, 0, 0, 0, 0, 0, 0, 0,
-KEY_S, KEY_R, KEY_B, KEY_N, TOSA_KEY_CALENDAR, TOSA_KEY_HOMEPAGE, KEY_LEFTCTRL, TOSA_KEY_LIGHT,
-0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0,
-KEY_TAB, KEY_SLASH, KEY_H, KEY_M, TOSA_KEY_MENU, 0, KEY_UP, 0,
-0, 0, TOSA_KEY_FN, 0, 0, 0, 0, 0,
-KEY_X, KEY_F, KEY_SPACE, KEY_APOSTROPHE, TOSA_KEY_MAIL, KEY_LEFT, KEY_DOWN, KEY_RIGHT,
-0, 0, 0,
-};
-
-struct tosakbd {
- unsigned int keycode[ARRAY_SIZE(tosakbd_keycode)];
- struct input_dev *input;
-
- spinlock_t lock; /* protect kbd scanning */
- struct timer_list timer;
-};
-
-
-/* Helper functions for reading the keyboard matrix
- * Note: We should really be using pxa_gpio_mode to alter GPDR but it
- * requires a function call per GPIO bit which is excessive
- * when we need to access 12 bits at once, multiple times.
- * These functions must be called within local_irq_save()/local_irq_restore()
- * or similar.
- */
-#define GET_ROWS_STATUS(c) ((GPLR2 & TOSA_GPIO_ALL_SENSE_BIT) >> TOSA_GPIO_ALL_SENSE_RSHIFT)
-
-static inline void tosakbd_discharge_all(void)
-{
- /* STROBE All HiZ */
- GPCR1 = TOSA_GPIO_HIGH_STROBE_BIT;
- GPDR1 &= ~TOSA_GPIO_HIGH_STROBE_BIT;
- GPCR2 = TOSA_GPIO_LOW_STROBE_BIT;
- GPDR2 &= ~TOSA_GPIO_LOW_STROBE_BIT;
-}
-
-static inline void tosakbd_activate_all(void)
-{
- /* STROBE ALL -> High */
- GPSR1 = TOSA_GPIO_HIGH_STROBE_BIT;
- GPDR1 |= TOSA_GPIO_HIGH_STROBE_BIT;
- GPSR2 = TOSA_GPIO_LOW_STROBE_BIT;
- GPDR2 |= TOSA_GPIO_LOW_STROBE_BIT;
-
- udelay(KB_DISCHARGE_DELAY);
-
- /* STATE CLEAR */
- GEDR2 |= TOSA_GPIO_ALL_SENSE_BIT;
-}
-
-static inline void tosakbd_activate_col(int col)
-{
- if (col <= 5) {
- /* STROBE col -> High, not col -> HiZ */
- GPSR1 = TOSA_GPIO_STROBE_BIT(col);
- GPDR1 = (GPDR1 & ~TOSA_GPIO_HIGH_STROBE_BIT) | TOSA_GPIO_STROBE_BIT(col);
- } else {
- /* STROBE col -> High, not col -> HiZ */
- GPSR2 = TOSA_GPIO_STROBE_BIT(col);
- GPDR2 = (GPDR2 & ~TOSA_GPIO_LOW_STROBE_BIT) | TOSA_GPIO_STROBE_BIT(col);
- }
-}
-
-static inline void tosakbd_reset_col(int col)
-{
- if (col <= 5) {
- /* STROBE col -> Low */
- GPCR1 = TOSA_GPIO_STROBE_BIT(col);
- /* STROBE col -> out, not col -> HiZ */
- GPDR1 = (GPDR1 & ~TOSA_GPIO_HIGH_STROBE_BIT) | TOSA_GPIO_STROBE_BIT(col);
- } else {
- /* STROBE col -> Low */
- GPCR2 = TOSA_GPIO_STROBE_BIT(col);
- /* STROBE col -> out, not col -> HiZ */
- GPDR2 = (GPDR2 & ~TOSA_GPIO_LOW_STROBE_BIT) | TOSA_GPIO_STROBE_BIT(col);
- }
-}
-/*
- * The tosa keyboard only generates interrupts when a key is pressed.
- * So when a key is pressed, we enable a timer. This timer scans the
- * keyboard, and this is how we detect when the key is released.
- */
-
-/* Scan the hardware keyboard and push any changes up through the input layer */
-static void tosakbd_scankeyboard(struct platform_device *dev)
-{
- struct tosakbd *tosakbd = platform_get_drvdata(dev);
- unsigned int row, col, rowd;
- unsigned long flags;
- unsigned int num_pressed = 0;
-
- spin_lock_irqsave(&tosakbd->lock, flags);
-
- for (col = 0; col < TOSA_KEY_STROBE_NUM; col++) {
- /*
- * Discharge the output driver capacitatance
- * in the keyboard matrix. (Yes it is significant..)
- */
- tosakbd_discharge_all();
- udelay(KB_DISCHARGE_DELAY);
-
- tosakbd_activate_col(col);
- udelay(KB_ACTIVATE_DELAY);
-
- rowd = GET_ROWS_STATUS(col);
-
- for (row = 0; row < TOSA_KEY_SENSE_NUM; row++) {
- unsigned int scancode, pressed;
- scancode = SCANCODE(row, col);
- pressed = rowd & KB_ROWMASK(row);
-
- if (pressed && !tosakbd->keycode[scancode])
- dev_warn(&dev->dev,
- "unhandled scancode: 0x%02x\n",
- scancode);
-
- input_report_key(tosakbd->input,
- tosakbd->keycode[scancode],
- pressed);
- if (pressed)
- num_pressed++;
- }
-
- tosakbd_reset_col(col);
- }
-
- tosakbd_activate_all();
-
- input_sync(tosakbd->input);
-
- /* if any keys are pressed, enable the timer */
- if (num_pressed)
- mod_timer(&tosakbd->timer, jiffies + SCAN_INTERVAL);
-
- spin_unlock_irqrestore(&tosakbd->lock, flags);
-}
-
-/*
- * tosa keyboard interrupt handler.
- */
-static irqreturn_t tosakbd_interrupt(int irq, void *__dev)
-{
- struct platform_device *dev = __dev;
- struct tosakbd *tosakbd = platform_get_drvdata(dev);
-
- if (!timer_pending(&tosakbd->timer)) {
- /** wait chattering delay **/
- udelay(20);
- tosakbd_scankeyboard(dev);
- }
-
- return IRQ_HANDLED;
-}
-
-/*
- * tosa timer checking for released keys
- */
-static void tosakbd_timer_callback(unsigned long __dev)
-{
- struct platform_device *dev = (struct platform_device *)__dev;
- tosakbd_scankeyboard(dev);
-}
-
-#ifdef CONFIG_PM
-static int tosakbd_suspend(struct platform_device *dev, pm_message_t state)
-{
- struct tosakbd *tosakbd = platform_get_drvdata(dev);
-
- del_timer_sync(&tosakbd->timer);
-
- return 0;
-}
-
-static int tosakbd_resume(struct platform_device *dev)
-{
- tosakbd_scankeyboard(dev);
-
- return 0;
-}
-#else
-#define tosakbd_suspend NULL
-#define tosakbd_resume NULL
-#endif
-
-static int __devinit tosakbd_probe(struct platform_device *pdev) {
-
- int i;
- struct tosakbd *tosakbd;
- struct input_dev *input_dev;
- int error;
-
- tosakbd = kzalloc(sizeof(struct tosakbd), GFP_KERNEL);
- if (!tosakbd)
- return -ENOMEM;
-
- input_dev = input_allocate_device();
- if (!input_dev) {
- kfree(tosakbd);
- return -ENOMEM;
- }
-
- platform_set_drvdata(pdev, tosakbd);
-
- spin_lock_init(&tosakbd->lock);
-
- /* Init Keyboard rescan timer */
- init_timer(&tosakbd->timer);
- tosakbd->timer.function = tosakbd_timer_callback;
- tosakbd->timer.data = (unsigned long) pdev;
-
- tosakbd->input = input_dev;
-
- input_set_drvdata(input_dev, tosakbd);
- input_dev->name = "Tosa Keyboard";
- input_dev->phys = "tosakbd/input0";
- input_dev->dev.parent = &pdev->dev;
-
- input_dev->id.bustype = BUS_HOST;
- input_dev->id.vendor = 0x0001;
- input_dev->id.product = 0x0001;
- input_dev->id.version = 0x0100;
-
- input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
- input_dev->keycode = tosakbd->keycode;
- input_dev->keycodesize = sizeof(unsigned int);
- input_dev->keycodemax = ARRAY_SIZE(tosakbd_keycode);
-
- memcpy(tosakbd->keycode, tosakbd_keycode, sizeof(tosakbd_keycode));
-
- for (i = 0; i < ARRAY_SIZE(tosakbd_keycode); i++)
- __set_bit(tosakbd->keycode[i], input_dev->keybit);
- clear_bit(0, input_dev->keybit);
-
- /* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */
- for (i = 0; i < TOSA_KEY_SENSE_NUM; i++) {
- int gpio = TOSA_GPIO_KEY_SENSE(i);
- int irq;
- error = gpio_request(gpio, "tosakbd");
- if (error < 0) {
- printk(KERN_ERR "tosakbd: failed to request GPIO %d, "
- " error %d\n", gpio, error);
- goto fail;
- }
-
- error = gpio_direction_input(TOSA_GPIO_KEY_SENSE(i));
- if (error < 0) {
- printk(KERN_ERR "tosakbd: failed to configure input"
- " direction for GPIO %d, error %d\n",
- gpio, error);
- gpio_free(gpio);
- goto fail;
- }
-
- irq = gpio_to_irq(gpio);
- if (irq < 0) {
- error = irq;
- printk(KERN_ERR "gpio-keys: Unable to get irq number"
- " for GPIO %d, error %d\n",
- gpio, error);
- gpio_free(gpio);
- goto fail;
- }
-
- error = request_irq(irq, tosakbd_interrupt,
- IRQF_DISABLED | IRQF_TRIGGER_RISING,
- "tosakbd", pdev);
-
- if (error) {
- printk("tosakbd: Can't get IRQ: %d: error %d!\n",
- irq, error);
- gpio_free(gpio);
- goto fail;
- }
- }
-
- /* Set Strobe lines as outputs - set high */
- for (i = 0; i < TOSA_KEY_STROBE_NUM; i++) {
- int gpio = TOSA_GPIO_KEY_STROBE(i);
- error = gpio_request(gpio, "tosakbd");
- if (error < 0) {
- printk(KERN_ERR "tosakbd: failed to request GPIO %d, "
- " error %d\n", gpio, error);
- goto fail2;
- }
-
- error = gpio_direction_output(gpio, 1);
- if (error < 0) {
- printk(KERN_ERR "tosakbd: failed to configure input"
- " direction for GPIO %d, error %d\n",
- gpio, error);
- gpio_free(gpio);
- goto fail;
- }
-
- }
-
- error = input_register_device(input_dev);
- if (error) {
- printk(KERN_ERR "tosakbd: Unable to register input device, "
- "error: %d\n", error);
- goto fail;
- }
-
- printk(KERN_INFO "input: Tosa Keyboard Registered\n");
-
- return 0;
-
-fail2:
- while (--i >= 0)
- gpio_free(TOSA_GPIO_KEY_STROBE(i));
-
- i = TOSA_KEY_SENSE_NUM;
-fail:
- while (--i >= 0) {
- free_irq(gpio_to_irq(TOSA_GPIO_KEY_SENSE(i)), pdev);
- gpio_free(TOSA_GPIO_KEY_SENSE(i));
- }
-
- platform_set_drvdata(pdev, NULL);
- input_free_device(input_dev);
- kfree(tosakbd);
-
- return error;
-}
-
-static int __devexit tosakbd_remove(struct platform_device *dev) {
-
- int i;
- struct tosakbd *tosakbd = platform_get_drvdata(dev);
-
- for (i = 0; i < TOSA_KEY_STROBE_NUM; i++)
- gpio_free(TOSA_GPIO_KEY_STROBE(i));
-
- for (i = 0; i < TOSA_KEY_SENSE_NUM; i++) {
- free_irq(gpio_to_irq(TOSA_GPIO_KEY_SENSE(i)), dev);
- gpio_free(TOSA_GPIO_KEY_SENSE(i));
- }
-
- del_timer_sync(&tosakbd->timer);
-
- input_unregister_device(tosakbd->input);
-
- kfree(tosakbd);
-
- return 0;
-}
-
-static struct platform_driver tosakbd_driver = {
- .probe = tosakbd_probe,
- .remove = __devexit_p(tosakbd_remove),
- .suspend = tosakbd_suspend,
- .resume = tosakbd_resume,
- .driver = {
- .name = "tosa-keyboard",
- },
-};
-
-static int __devinit tosakbd_init(void)
-{
- return platform_driver_register(&tosakbd_driver);
-}
-
-static void __exit tosakbd_exit(void)
-{
- platform_driver_unregister(&tosakbd_driver);
-}
-
-module_init(tosakbd_init);
-module_exit(tosakbd_exit);
-
-MODULE_AUTHOR("Dirk Opfer ");
-MODULE_DESCRIPTION("Tosa Keyboard Driver");
-MODULE_LICENSE("GPL v2");
diff --git a/trunk/drivers/input/misc/Kconfig b/trunk/drivers/input/misc/Kconfig
index 8b10d9f23bef..8f5c7b90187d 100644
--- a/trunk/drivers/input/misc/Kconfig
+++ b/trunk/drivers/input/misc/Kconfig
@@ -40,20 +40,6 @@ config INPUT_M68K_BEEP
tristate "M68k Beeper support"
depends on M68K
-config INPUT_APANEL
- tristate "Fujitsu Lifebook Application Panel buttons"
- depends on X86
- select I2C_I801
- select INPUT_POLLDEV
- select CHECK_SIGNATURE
- help
- Say Y here for support of the Application Panel buttons, used on
- Fujitsu Lifebook. These are attached to the mainboard through
- an SMBus interface managed by the I2C Intel ICH (i801) driver.
-
- To compile this driver as a module, choose M here: the module will
- be called apanel.
-
config INPUT_IXP4XX_BEEPER
tristate "IXP4XX Beeper support"
depends on ARCH_IXP4XX
diff --git a/trunk/drivers/input/misc/Makefile b/trunk/drivers/input/misc/Makefile
index ebd39f291d25..3585b5038418 100644
--- a/trunk/drivers/input/misc/Makefile
+++ b/trunk/drivers/input/misc/Makefile
@@ -18,4 +18,3 @@ obj-$(CONFIG_INPUT_POWERMATE) += powermate.o
obj-$(CONFIG_INPUT_YEALINK) += yealink.o
obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o
obj-$(CONFIG_INPUT_UINPUT) += uinput.o
-obj-$(CONFIG_INPUT_APANEL) += apanel.o
diff --git a/trunk/drivers/input/misc/apanel.c b/trunk/drivers/input/misc/apanel.c
deleted file mode 100644
index 9531d8c7444f..000000000000
--- a/trunk/drivers/input/misc/apanel.c
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
- * Fujitsu Lifebook Application Panel button drive
- *
- * Copyright (C) 2007 Stephen Hemminger
- * Copyright (C) 2001-2003 Jochen Eisinger
- *
- * 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.
- *
- * Many Fujitsu Lifebook laptops have a small panel of buttons that are
- * accessible via the i2c/smbus interface. This driver polls those
- * buttons and generates input events.
- *
- * For more details see:
- * http://apanel.sourceforge.net/tech.php
- */
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#define APANEL_NAME "Fujitsu Application Panel"
-#define APANEL_VERSION "1.3.1"
-#define APANEL "apanel"
-
-/* How often we poll keys - msecs */
-#define POLL_INTERVAL_DEFAULT 1000
-
-/* Magic constants in BIOS that tell about buttons */
-enum apanel_devid {
- APANEL_DEV_NONE = 0,
- APANEL_DEV_APPBTN = 1,
- APANEL_DEV_CDBTN = 2,
- APANEL_DEV_LCD = 3,
- APANEL_DEV_LED = 4,
-
- APANEL_DEV_MAX,
-};
-
-enum apanel_chip {
- CHIP_NONE = 0,
- CHIP_OZ992C = 1,
- CHIP_OZ163T = 2,
- CHIP_OZ711M3 = 4,
-};
-
-/* Result of BIOS snooping/probing -- what features are supported */
-static enum apanel_chip device_chip[APANEL_DEV_MAX];
-
-#define MAX_PANEL_KEYS 12
-
-struct apanel {
- struct input_polled_dev *ipdev;
- struct i2c_client client;
- unsigned short keymap[MAX_PANEL_KEYS];
- u16 nkeys;
- u16 led_bits;
- struct work_struct led_work;
- struct led_classdev mail_led;
-};
-
-
-static int apanel_probe(struct i2c_adapter *, int, int);
-
-/* for now, we only support one address */
-static unsigned short normal_i2c[] = {0, I2C_CLIENT_END};
-static unsigned short ignore = I2C_CLIENT_END;
-static struct i2c_client_address_data addr_data = {
- .normal_i2c = normal_i2c,
- .probe = &ignore,
- .ignore = &ignore,
-};
-
-static void report_key(struct input_dev *input, unsigned keycode)
-{
- pr_debug(APANEL ": report key %#x\n", keycode);
- input_report_key(input, keycode, 1);
- input_sync(input);
-
- input_report_key(input, keycode, 0);
- input_sync(input);
-}
-
-/* Poll for key changes
- *
- * Read Application keys via SMI
- * A (0x4), B (0x8), Internet (0x2), Email (0x1).
- *
- * CD keys:
- * Forward (0x100), Rewind (0x200), Stop (0x400), Pause (0x800)
- */
-static void apanel_poll(struct input_polled_dev *ipdev)
-{
- struct apanel *ap = ipdev->private;
- struct input_dev *idev = ipdev->input;
- u8 cmd = device_chip[APANEL_DEV_APPBTN] == CHIP_OZ992C ? 0 : 8;
- s32 data;
- int i;
-
- data = i2c_smbus_read_word_data(&ap->client, cmd);
- if (data < 0)
- return; /* ignore errors (due to ACPI??) */
-
- /* write back to clear latch */
- i2c_smbus_write_word_data(&ap->client, cmd, 0);
-
- if (!data)
- return;
-
- dev_dbg(&idev->dev, APANEL ": data %#x\n", data);
- for (i = 0; i < idev->keycodemax; i++)
- if ((1u << i) & data)
- report_key(idev, ap->keymap[i]);
-}
-
-/* Track state changes of LED */
-static void led_update(struct work_struct *work)
-{
- struct apanel *ap = container_of(work, struct apanel, led_work);
-
- i2c_smbus_write_word_data(&ap->client, 0x10, ap->led_bits);
-}
-
-static void mail_led_set(struct led_classdev *led,
- enum led_brightness value)
-{
- struct apanel *ap = container_of(led, struct apanel, mail_led);
-
- if (value != LED_OFF)
- ap->led_bits |= 0x8000;
- else
- ap->led_bits &= ~0x8000;
-
- schedule_work(&ap->led_work);
-}
-
-static int apanel_detach_client(struct i2c_client *client)
-{
- struct apanel *ap = i2c_get_clientdata(client);
-
- if (device_chip[APANEL_DEV_LED] != CHIP_NONE)
- led_classdev_unregister(&ap->mail_led);
-
- input_unregister_polled_device(ap->ipdev);
- i2c_detach_client(&ap->client);
- input_free_polled_device(ap->ipdev);
-
- return 0;
-}
-
-/* Function is invoked for every i2c adapter. */
-static int apanel_attach_adapter(struct i2c_adapter *adap)
-{
- dev_dbg(&adap->dev, APANEL ": attach adapter id=%d\n", adap->id);
-
- /* Our device is connected only to i801 on laptop */
- if (adap->id != I2C_HW_SMBUS_I801)
- return -ENODEV;
-
- return i2c_probe(adap, &addr_data, apanel_probe);
-}
-
-static void apanel_shutdown(struct i2c_client *client)
-{
- apanel_detach_client(client);
-}
-
-static struct i2c_driver apanel_driver = {
- .driver = {
- .name = APANEL,
- },
- .attach_adapter = &apanel_attach_adapter,
- .detach_client = &apanel_detach_client,
- .shutdown = &apanel_shutdown,
-};
-
-static struct apanel apanel = {
- .client = {
- .driver = &apanel_driver,
- .name = APANEL,
- },
- .keymap = {
- [0] = KEY_MAIL,
- [1] = KEY_WWW,
- [2] = KEY_PROG2,
- [3] = KEY_PROG1,
-
- [8] = KEY_FORWARD,
- [9] = KEY_REWIND,
- [10] = KEY_STOPCD,
- [11] = KEY_PLAYPAUSE,
-
- },
- .mail_led = {
- .name = "mail:blue",
- .brightness_set = mail_led_set,
- },
-};
-
-/* NB: Only one panel on the i2c. */
-static int apanel_probe(struct i2c_adapter *bus, int address, int kind)
-{
- struct apanel *ap;
- struct input_polled_dev *ipdev;
- struct input_dev *idev;
- u8 cmd = device_chip[APANEL_DEV_APPBTN] == CHIP_OZ992C ? 0 : 8;
- int i, err = -ENOMEM;
-
- dev_dbg(&bus->dev, APANEL ": probe adapter %p addr %d kind %d\n",
- bus, address, kind);
-
- ap = &apanel;
-
- ipdev = input_allocate_polled_device();
- if (!ipdev)
- goto out1;
-
- ap->ipdev = ipdev;
- ap->client.adapter = bus;
- ap->client.addr = address;
-
- i2c_set_clientdata(&ap->client, ap);
-
- err = i2c_attach_client(&ap->client);
- if (err)
- goto out2;
-
- err = i2c_smbus_write_word_data(&ap->client, cmd, 0);
- if (err) {
- dev_warn(&ap->client.dev, APANEL ": smbus write error %d\n",
- err);
- goto out3;
- }
-
- ipdev->poll = apanel_poll;
- ipdev->poll_interval = POLL_INTERVAL_DEFAULT;
- ipdev->private = ap;
-
- idev = ipdev->input;
- idev->name = APANEL_NAME " buttons";
- idev->phys = "apanel/input0";
- idev->id.bustype = BUS_HOST;
- idev->dev.parent = &ap->client.dev;
-
- set_bit(EV_KEY, idev->evbit);
-
- idev->keycode = ap->keymap;
- idev->keycodesize = sizeof(ap->keymap[0]);
- idev->keycodemax = (device_chip[APANEL_DEV_CDBTN] != CHIP_NONE) ? 12 : 4;
-
- for (i = 0; i < idev->keycodemax; i++)
- if (ap->keymap[i])
- set_bit(ap->keymap[i], idev->keybit);
-
- err = input_register_polled_device(ipdev);
- if (err)
- goto out3;
-
- INIT_WORK(&ap->led_work, led_update);
- if (device_chip[APANEL_DEV_LED] != CHIP_NONE) {
- err = led_classdev_register(&ap->client.dev, &ap->mail_led);
- if (err)
- goto out4;
- }
-
- return 0;
-out4:
- input_unregister_polled_device(ipdev);
-out3:
- i2c_detach_client(&ap->client);
-out2:
- input_free_polled_device(ipdev);
-out1:
- return err;
-}
-
-/* Scan the system ROM for the signature "FJKEYINF" */
-static __init const void __iomem *bios_signature(const void __iomem *bios)
-{
- ssize_t offset;
- const unsigned char signature[] = "FJKEYINF";
-
- for (offset = 0; offset < 0x10000; offset += 0x10) {
- if (check_signature(bios + offset, signature,
- sizeof(signature)-1))
- return bios + offset;
- }
- pr_notice(APANEL ": Fujitsu BIOS signature '%s' not found...\n",
- signature);
- return NULL;
-}
-
-static int __init apanel_init(void)
-{
- void __iomem *bios;
- const void __iomem *p;
- u8 devno;
- int found = 0;
-
- bios = ioremap(0xF0000, 0x10000); /* Can't fail */
-
- p = bios_signature(bios);
- if (!p) {
- iounmap(bios);
- return -ENODEV;
- }
-
- /* just use the first address */
- p += 8;
- normal_i2c[0] = readb(p+3) >> 1;
-
- for ( ; (devno = readb(p)) & 0x7f; p += 4) {
- unsigned char method, slave, chip;
-
- method = readb(p + 1);
- chip = readb(p + 2);
- slave = readb(p + 3) >> 1;
-
- if (slave != normal_i2c[0]) {
- pr_notice(APANEL ": only one SMBus slave "
- "address supported, skiping device...\n");
- continue;
- }
-
- /* translate alternative device numbers */
- switch (devno) {
- case 6:
- devno = APANEL_DEV_APPBTN;
- break;
- case 7:
- devno = APANEL_DEV_LED;
- break;
- }
-
- if (devno >= APANEL_DEV_MAX)
- pr_notice(APANEL ": unknown device %u found\n", devno);
- else if (device_chip[devno] != CHIP_NONE)
- pr_warning(APANEL ": duplicate entry for devno %u\n", devno);
-
- else if (method != 1 && method != 2 && method != 4) {
- pr_notice(APANEL ": unknown method %u for devno %u\n",
- method, devno);
- } else {
- device_chip[devno] = (enum apanel_chip) chip;
- ++found;
- }
- }
- iounmap(bios);
-
- if (found == 0) {
- pr_info(APANEL ": no input devices reported by BIOS\n");
- return -EIO;
- }
-
- return i2c_add_driver(&apanel_driver);
-}
-module_init(apanel_init);
-
-static void __exit apanel_cleanup(void)
-{
- i2c_del_driver(&apanel_driver);
-}
-module_exit(apanel_cleanup);
-
-MODULE_AUTHOR("Stephen Hemminger ");
-MODULE_DESCRIPTION(APANEL_NAME " driver");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(APANEL_VERSION);
-
-MODULE_ALIAS("dmi:*:svnFUJITSU:pnLifeBook*:pvr*:rvnFUJITSU:*");
-MODULE_ALIAS("dmi:*:svnFUJITSU:pnLifebook*:pvr*:rvnFUJITSU:*");
diff --git a/trunk/drivers/input/misc/ati_remote.c b/trunk/drivers/input/misc/ati_remote.c
index f3b86c2b0797..3a7937481ad8 100644
--- a/trunk/drivers/input/misc/ati_remote.c
+++ b/trunk/drivers/input/misc/ati_remote.c
@@ -90,6 +90,7 @@
#include
#include
#include
+#include
#include
#include
#include
diff --git a/trunk/drivers/input/misc/atlas_btns.c b/trunk/drivers/input/misc/atlas_btns.c
index 1b871917340a..4e3ad657ed80 100644
--- a/trunk/drivers/input/misc/atlas_btns.c
+++ b/trunk/drivers/input/misc/atlas_btns.c
@@ -29,10 +29,9 @@
#include
#include
-#define ACPI_ATLAS_NAME "Atlas ACPI"
-#define ACPI_ATLAS_CLASS "Atlas"
+#define ACPI_ATLAS_NAME "Atlas ACPI"
+#define ACPI_ATLAS_CLASS "Atlas"
-static unsigned short atlas_keymap[16];
static struct input_dev *input_dev;
/* button handling code */
@@ -51,15 +50,12 @@ static acpi_status acpi_atlas_button_handler(u32 function,
void *handler_context, void *region_context)
{
acpi_status status;
+ int keycode;
if (function == ACPI_WRITE) {
- int code = address & 0x0f;
- int key_down = !(address & 0x10);
-
- input_event(input_dev, EV_MSC, MSC_SCAN, code);
- input_report_key(input_dev, atlas_keymap[code], key_down);
+ keycode = KEY_F1 + (address & 0x0F);
+ input_report_key(input_dev, keycode, !(address & 0x10));
input_sync(input_dev);
-
status = 0;
} else {
printk(KERN_WARNING "atlas: shrugged on unexpected function"
@@ -74,7 +70,6 @@ static acpi_status acpi_atlas_button_handler(u32 function,
static int atlas_acpi_button_add(struct acpi_device *device)
{
acpi_status status;
- int i;
int err;
input_dev = input_allocate_device();
@@ -86,19 +81,17 @@ static int atlas_acpi_button_add(struct acpi_device *device)
input_dev->name = "Atlas ACPI button driver";
input_dev->phys = "ASIM0000/atlas/input0";
input_dev->id.bustype = BUS_HOST;
- input_dev->keycode = atlas_keymap;
- input_dev->keycodesize = sizeof(unsigned short);
- input_dev->keycodemax = ARRAY_SIZE(atlas_keymap);
-
- input_set_capability(input_dev, EV_MSC, MSC_SCAN);
- __set_bit(EV_KEY, input_dev->evbit);
- for (i = 0; i < ARRAY_SIZE(atlas_keymap); i++) {
- if (i < 9) {
- atlas_keymap[i] = KEY_F1 + i;
- __set_bit(KEY_F1 + i, input_dev->keybit);
- } else
- atlas_keymap[i] = KEY_RESERVED;
- }
+ input_dev->evbit[BIT_WORD(EV_KEY)] = BIT_MASK(EV_KEY);
+
+ set_bit(KEY_F1, input_dev->keybit);
+ set_bit(KEY_F2, input_dev->keybit);
+ set_bit(KEY_F3, input_dev->keybit);
+ set_bit(KEY_F4, input_dev->keybit);
+ set_bit(KEY_F5, input_dev->keybit);
+ set_bit(KEY_F6, input_dev->keybit);
+ set_bit(KEY_F7, input_dev->keybit);
+ set_bit(KEY_F8, input_dev->keybit);
+ set_bit(KEY_F9, input_dev->keybit);
err = input_register_device(input_dev);
if (err) {
diff --git a/trunk/drivers/input/misc/cobalt_btns.c b/trunk/drivers/input/misc/cobalt_btns.c
index 4833b1a82623..1aef97ed5e84 100644
--- a/trunk/drivers/input/misc/cobalt_btns.c
+++ b/trunk/drivers/input/misc/cobalt_btns.c
@@ -27,48 +27,55 @@
#define BUTTONS_COUNT_THRESHOLD 3
#define BUTTONS_STATUS_MASK 0xfe000000
-static const unsigned short cobalt_map[] = {
- KEY_RESERVED,
- KEY_RESTART,
- KEY_LEFT,
- KEY_UP,
- KEY_DOWN,
- KEY_RIGHT,
- KEY_ENTER,
- KEY_SELECT
-};
-
struct buttons_dev {
struct input_polled_dev *poll_dev;
- unsigned short keymap[ARRAY_SIZE(cobalt_map)];
- int count[ARRAY_SIZE(cobalt_map)];
void __iomem *reg;
};
+struct buttons_map {
+ uint32_t mask;
+ int keycode;
+ int count;
+};
+
+static struct buttons_map buttons_map[] = {
+ { 0x02000000, KEY_RESTART, },
+ { 0x04000000, KEY_LEFT, },
+ { 0x08000000, KEY_UP, },
+ { 0x10000000, KEY_DOWN, },
+ { 0x20000000, KEY_RIGHT, },
+ { 0x40000000, KEY_ENTER, },
+ { 0x80000000, KEY_SELECT, },
+};
+
static void handle_buttons(struct input_polled_dev *dev)
{
+ struct buttons_map *button = buttons_map;
struct buttons_dev *bdev = dev->private;
struct input_dev *input = dev->input;
uint32_t status;
int i;
- status = ~readl(bdev->reg) >> 24;
+ status = readl(bdev->reg);
+ status = ~status & BUTTONS_STATUS_MASK;
- for (i = 0; i < ARRAY_SIZE(bdev->keymap); i++) {
- if (status & (1UL << i)) {
- if (++bdev->count[i] == BUTTONS_COUNT_THRESHOLD) {
- input_event(input, EV_MSC, MSC_SCAN, i);
- input_report_key(input, bdev->keymap[i], 1);
- input_sync(input);
- }
+ for (i = 0; i < ARRAY_SIZE(buttons_map); i++) {
+ if (status & button->mask) {
+ button->count++;
} else {
- if (bdev->count[i] >= BUTTONS_COUNT_THRESHOLD) {
- input_event(input, EV_MSC, MSC_SCAN, i);
- input_report_key(input, bdev->keymap[i], 0);
+ if (button->count >= BUTTONS_COUNT_THRESHOLD) {
+ input_report_key(input, button->keycode, 0);
input_sync(input);
}
- bdev->count[i] = 0;
+ button->count = 0;
+ }
+
+ if (button->count == BUTTONS_COUNT_THRESHOLD) {
+ input_report_key(input, button->keycode, 1);
+ input_sync(input);
}
+
+ button++;
}
}
@@ -87,8 +94,6 @@ static int __devinit cobalt_buttons_probe(struct platform_device *pdev)
goto err_free_mem;
}
- memcpy(bdev->keymap, cobalt_map, sizeof(bdev->keymap));
-
poll_dev->private = bdev;
poll_dev->poll = handle_buttons;
poll_dev->poll_interval = BUTTONS_POLL_INTERVAL;
@@ -99,15 +104,11 @@ static int __devinit cobalt_buttons_probe(struct platform_device *pdev)
input->id.bustype = BUS_HOST;
input->cdev.dev = &pdev->dev;
- input->keycode = pdev->keymap;
- input->keycodemax = ARRAY_SIZE(pdev->keymap);
- input->keycodesize = sizeof(unsigned short);
-
- input_set_capability(input, EV_MSC, MSC_SCAN);
- __set_bit(EV_KEY, input->evbit);
- for (i = 0; i < ARRAY_SIZE(buttons_map); i++)
- __set_bit(input->keycode[i], input->keybit);
- __clear_bit(KEY_RESERVED, input->keybit);
+ input->evbit[0] = BIT_MASK(EV_KEY);
+ for (i = 0; i < ARRAY_SIZE(buttons_map); i++) {
+ set_bit(buttons_map[i].keycode, input->keybit);
+ buttons_map[i].count = 0;
+ }
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
diff --git a/trunk/drivers/input/misc/keyspan_remote.c b/trunk/drivers/input/misc/keyspan_remote.c
index 952938a8e991..fd74347047dd 100644
--- a/trunk/drivers/input/misc/keyspan_remote.c
+++ b/trunk/drivers/input/misc/keyspan_remote.c
@@ -16,6 +16,7 @@
#include
#include
#include
+#include
#include
#define DRIVER_VERSION "v0.1"
@@ -45,12 +46,53 @@ MODULE_PARM_DESC(debug, "Enable extra debug messages and information");
#define RECV_SIZE 8 /* The UIA-11 type have a 8 byte limit. */
+/* table of devices that work with this driver */
+static struct usb_device_id keyspan_table[] = {
+ { USB_DEVICE(USB_KEYSPAN_VENDOR_ID, USB_KEYSPAN_PRODUCT_UIA11) },
+ { } /* Terminating entry */
+};
+
+/* Structure to store all the real stuff that a remote sends to us. */
+struct keyspan_message {
+ u16 system;
+ u8 button;
+ u8 toggle;
+};
+
+/* Structure used for all the bit testing magic needed to be done. */
+struct bit_tester {
+ u32 tester;
+ int len;
+ int pos;
+ int bits_left;
+ u8 buffer[32];
+};
+
+/* Structure to hold all of our driver specific stuff */
+struct usb_keyspan {
+ char name[128];
+ char phys[64];
+ struct usb_device* udev;
+ struct input_dev *input;
+ struct usb_interface* interface;
+ struct usb_endpoint_descriptor* in_endpoint;
+ struct urb* irq_urb;
+ int open;
+ dma_addr_t in_dma;
+ unsigned char* in_buffer;
+
+ /* variables used to parse messages from remote. */
+ struct bit_tester data;
+ int stage;
+ int toggle;
+};
+
/*
* Table that maps the 31 possible keycodes to input keys.
* Currently there are 15 and 17 button models so RESERVED codes
* are blank areas in the mapping.
*/
-static const unsigned short keyspan_key_table[] = {
+static const int keyspan_key_table[] = {
KEY_RESERVED, /* 0 is just a place holder. */
KEY_RESERVED,
KEY_STOP,
@@ -85,48 +127,6 @@ static const unsigned short keyspan_key_table[] = {
KEY_MENU
};
-/* table of devices that work with this driver */
-static struct usb_device_id keyspan_table[] = {
- { USB_DEVICE(USB_KEYSPAN_VENDOR_ID, USB_KEYSPAN_PRODUCT_UIA11) },
- { } /* Terminating entry */
-};
-
-/* Structure to store all the real stuff that a remote sends to us. */
-struct keyspan_message {
- u16 system;
- u8 button;
- u8 toggle;
-};
-
-/* Structure used for all the bit testing magic needed to be done. */
-struct bit_tester {
- u32 tester;
- int len;
- int pos;
- int bits_left;
- u8 buffer[32];
-};
-
-/* Structure to hold all of our driver specific stuff */
-struct usb_keyspan {
- char name[128];
- char phys[64];
- unsigned short keymap[ARRAY_SIZE(keyspan_key_table)];
- struct usb_device *udev;
- struct input_dev *input;
- struct usb_interface *interface;
- struct usb_endpoint_descriptor *in_endpoint;
- struct urb* irq_urb;
- int open;
- dma_addr_t in_dma;
- unsigned char *in_buffer;
-
- /* variables used to parse messages from remote. */
- struct bit_tester data;
- int stage;
- int toggle;
-};
-
static struct usb_driver keyspan_driver;
/*
@@ -173,15 +173,6 @@ static int keyspan_load_tester(struct usb_keyspan* dev, int bits_needed)
return 0;
}
-static void keyspan_report_button(struct usb_keyspan *remote, int button, int press)
-{
- struct input_dev *input = remote->input;
-
- input_event(input, EV_MSC, MSC_SCAN, button);
- input_report_key(input, remote->keymap[button], press);
- input_sync(input);
-}
-
/*
* Routine that handles all the logic needed to parse out the message from the remote.
*/
@@ -320,8 +311,9 @@ static void keyspan_check_data(struct usb_keyspan *remote)
__FUNCTION__, message.system, message.button, message.toggle);
if (message.toggle != remote->toggle) {
- keyspan_report_button(remote, message.button, 1);
- keyspan_report_button(remote, message.button, 0);
+ input_report_key(remote->input, keyspan_key_table[message.button], 1);
+ input_report_key(remote->input, keyspan_key_table[message.button], 0);
+ input_sync(remote->input);
remote->toggle = message.toggle;
}
@@ -499,21 +491,16 @@ static int keyspan_probe(struct usb_interface *interface, const struct usb_devic
usb_make_path(udev, remote->phys, sizeof(remote->phys));
strlcat(remote->phys, "/input0", sizeof(remote->phys));
- memcpy(remote->keymap, keyspan_key_table, sizeof(remote->keymap));
input_dev->name = remote->name;
input_dev->phys = remote->phys;
usb_to_input_id(udev, &input_dev->id);
input_dev->dev.parent = &interface->dev;
- input_dev->keycode = remote->keymap;
- input_dev->keycodesize = sizeof(unsigned short);
- input_dev->keycodemax = ARRAY_SIZE(remote->keymap);
- input_set_capability(input_dev, EV_MSC, MSC_SCAN);
- __set_bit(EV_KEY, input_dev->evbit);
+ input_dev->evbit[0] = BIT_MASK(EV_KEY); /* We will only report KEY events. */
for (i = 0; i < ARRAY_SIZE(keyspan_key_table); i++)
- __set_bit(keyspan_key_table[i], input_dev->keybit);
- __clear_bit(KEY_RESERVED, input_dev->keybit);
+ if (keyspan_key_table[i] != KEY_RESERVED)
+ set_bit(keyspan_key_table[i], input_dev->keybit);
input_set_drvdata(input_dev, remote);
@@ -521,14 +508,12 @@ static int keyspan_probe(struct usb_interface *interface, const struct usb_devic
input_dev->close = keyspan_close;
/*
- * Initialize the URB to access the device.
- * The urb gets sent to the device in keyspan_open()
+ * Initialize the URB to access the device. The urb gets sent to the device in keyspan_open()
*/
usb_fill_int_urb(remote->irq_urb,
- remote->udev,
- usb_rcvintpipe(remote->udev, endpoint->bEndpointAddress),
+ remote->udev, usb_rcvintpipe(remote->udev, remote->in_endpoint->bEndpointAddress),
remote->in_buffer, RECV_SIZE, keyspan_irq_recv, remote,
- endpoint->bInterval);
+ remote->in_endpoint->bInterval);
remote->irq_urb->transfer_dma = remote->in_dma;
remote->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
diff --git a/trunk/drivers/input/mouse/inport.c b/trunk/drivers/input/mouse/inport.c
index 06c35fc553c0..26ec09529b51 100644
--- a/trunk/drivers/input/mouse/inport.c
+++ b/trunk/drivers/input/mouse/inport.c
@@ -35,6 +35,7 @@
*/
#include
+#include
#include
#include
#include
diff --git a/trunk/drivers/input/mouse/logibm.c b/trunk/drivers/input/mouse/logibm.c
index 9ea895593b27..37e7c75b43bd 100644
--- a/trunk/drivers/input/mouse/logibm.c
+++ b/trunk/drivers/input/mouse/logibm.c
@@ -36,6 +36,7 @@
*/
#include
+#include
#include
#include
#include
diff --git a/trunk/drivers/input/mouse/psmouse-base.c b/trunk/drivers/input/mouse/psmouse-base.c
index f5a6be1d3c46..b8628252e10c 100644
--- a/trunk/drivers/input/mouse/psmouse-base.c
+++ b/trunk/drivers/input/mouse/psmouse-base.c
@@ -13,6 +13,7 @@
#include
#include
+#include
#include
#include
#include
diff --git a/trunk/drivers/input/mouse/trackpoint.c b/trunk/drivers/input/mouse/trackpoint.c
index 26b845fc186a..9ab5b5ea809d 100644
--- a/trunk/drivers/input/mouse/trackpoint.c
+++ b/trunk/drivers/input/mouse/trackpoint.c
@@ -11,6 +11,7 @@
#include
#include
#include
+#include
#include