diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-03-21 12:31:48 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-03-21 12:31:48 -0500 |
commit | 3d1f337b3e7378923c89f37afb573a918ef40be5 (patch) | |
tree | 386798378567a10d1c7b24f599cb50f70298694c /drivers/net/irda | |
parent | 2bf2154c6bb5599e3ec3f73c34861a0b12aa839e (diff) | |
parent | 5e35941d990123f155b02d5663e51a24f816b6f3 (diff) |
Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6: (235 commits)
[NETFILTER]: Add H.323 conntrack/NAT helper
[TG3]: Don't mark tg3_test_registers() as returning const.
[IPV6]: Cleanups for net/ipv6/addrconf.c (kzalloc, early exit) v2
[IPV6]: Nearly complete kzalloc cleanup for net/ipv6
[IPV6]: Cleanup of net/ipv6/reassambly.c
[BRIDGE]: Remove duplicate const from is_link_local() argument type.
[DECNET]: net/decnet/dn_route.c: fix inconsequent NULL checking
[TG3]: make drivers/net/tg3.c:tg3_request_irq() static
[BRIDGE]: use LLC to send STP
[LLC]: llc_mac_hdr_init const arguments
[BRIDGE]: allow show/store of group multicast address
[BRIDGE]: use llc for receiving STP packets
[BRIDGE]: stp timer to jiffies cleanup
[BRIDGE]: forwarding remove unneeded preempt and bh diasables
[BRIDGE]: netfilter inline cleanup
[BRIDGE]: netfilter VLAN macro cleanup
[BRIDGE]: netfilter dont use __constant_htons
[BRIDGE]: netfilter whitespace
[BRIDGE]: optimize frame pass up
[BRIDGE]: use kzalloc
...
Diffstat (limited to 'drivers/net/irda')
-rw-r--r-- | drivers/net/irda/Kconfig | 8 | ||||
-rw-r--r-- | drivers/net/irda/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/irda/donauboe.c | 2 | ||||
-rw-r--r-- | drivers/net/irda/ep7211_ir.c | 11 | ||||
-rw-r--r-- | drivers/net/irda/irtty-sir.c | 19 | ||||
-rw-r--r-- | drivers/net/irda/nsc-ircc.c | 320 | ||||
-rw-r--r-- | drivers/net/irda/nsc-ircc.h | 2 | ||||
-rw-r--r-- | drivers/net/irda/sir_dongle.c | 19 | ||||
-rw-r--r-- | drivers/net/irda/toim3232-sir.c | 375 | ||||
-rw-r--r-- | drivers/net/irda/vlsi_ir.c | 2 |
10 files changed, 665 insertions, 94 deletions
diff --git a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig index c81fe1c382d5..5e6d00752990 100644 --- a/drivers/net/irda/Kconfig +++ b/drivers/net/irda/Kconfig | |||
@@ -64,6 +64,14 @@ config TEKRAM_DONGLE | |||
64 | dongles you will have to start irattach like this: | 64 | dongles you will have to start irattach like this: |
65 | "irattach -d tekram". | 65 | "irattach -d tekram". |
66 | 66 | ||
67 | config TOIM3232_DONGLE | ||
68 | tristate "TOIM3232 IrDa dongle" | ||
69 | depends on DONGLE && IRDA | ||
70 | help | ||
71 | Say Y here if you want to build support for the Vishay/Temic | ||
72 | TOIM3232 and TOIM4232 based dongles. | ||
73 | To compile it as a module, choose M here. | ||
74 | |||
67 | config LITELINK_DONGLE | 75 | config LITELINK_DONGLE |
68 | tristate "Parallax LiteLink dongle" | 76 | tristate "Parallax LiteLink dongle" |
69 | depends on DONGLE && IRDA | 77 | depends on DONGLE && IRDA |
diff --git a/drivers/net/irda/Makefile b/drivers/net/irda/Makefile index 72cbfdc9cfcc..27ab75f20799 100644 --- a/drivers/net/irda/Makefile +++ b/drivers/net/irda/Makefile | |||
@@ -43,6 +43,7 @@ obj-$(CONFIG_OLD_BELKIN_DONGLE) += old_belkin-sir.o | |||
43 | obj-$(CONFIG_MCP2120_DONGLE) += mcp2120-sir.o | 43 | obj-$(CONFIG_MCP2120_DONGLE) += mcp2120-sir.o |
44 | obj-$(CONFIG_ACT200L_DONGLE) += act200l-sir.o | 44 | obj-$(CONFIG_ACT200L_DONGLE) += act200l-sir.o |
45 | obj-$(CONFIG_MA600_DONGLE) += ma600-sir.o | 45 | obj-$(CONFIG_MA600_DONGLE) += ma600-sir.o |
46 | obj-$(CONFIG_TOIM3232_DONGLE) += toim3232-sir.o | ||
46 | 47 | ||
47 | # The SIR helper module | 48 | # The SIR helper module |
48 | sir-dev-objs := sir_dev.o sir_dongle.o sir_kthread.o | 49 | sir-dev-objs := sir_dev.o sir_dongle.o sir_kthread.o |
diff --git a/drivers/net/irda/donauboe.c b/drivers/net/irda/donauboe.c index 3137592d60c0..910c0cab35b0 100644 --- a/drivers/net/irda/donauboe.c +++ b/drivers/net/irda/donauboe.c | |||
@@ -1778,7 +1778,7 @@ static struct pci_driver donauboe_pci_driver = { | |||
1778 | static int __init | 1778 | static int __init |
1779 | donauboe_init (void) | 1779 | donauboe_init (void) |
1780 | { | 1780 | { |
1781 | return pci_module_init(&donauboe_pci_driver); | 1781 | return pci_register_driver(&donauboe_pci_driver); |
1782 | } | 1782 | } |
1783 | 1783 | ||
1784 | static void __exit | 1784 | static void __exit |
diff --git a/drivers/net/irda/ep7211_ir.c b/drivers/net/irda/ep7211_ir.c index 31896262d21c..4cba38f7e4a8 100644 --- a/drivers/net/irda/ep7211_ir.c +++ b/drivers/net/irda/ep7211_ir.c | |||
@@ -8,6 +8,7 @@ | |||
8 | #include <linux/delay.h> | 8 | #include <linux/delay.h> |
9 | #include <linux/tty.h> | 9 | #include <linux/tty.h> |
10 | #include <linux/init.h> | 10 | #include <linux/init.h> |
11 | #include <linux/spinlock.h> | ||
11 | 12 | ||
12 | #include <net/irda/irda.h> | 13 | #include <net/irda/irda.h> |
13 | #include <net/irda/irda_device.h> | 14 | #include <net/irda/irda_device.h> |
@@ -23,6 +24,8 @@ static void ep7211_ir_close(dongle_t *self); | |||
23 | static int ep7211_ir_change_speed(struct irda_task *task); | 24 | static int ep7211_ir_change_speed(struct irda_task *task); |
24 | static int ep7211_ir_reset(struct irda_task *task); | 25 | static int ep7211_ir_reset(struct irda_task *task); |
25 | 26 | ||
27 | static DEFINE_SPINLOCK(ep7211_lock); | ||
28 | |||
26 | static struct dongle_reg dongle = { | 29 | static struct dongle_reg dongle = { |
27 | .type = IRDA_EP7211_IR, | 30 | .type = IRDA_EP7211_IR, |
28 | .open = ep7211_ir_open, | 31 | .open = ep7211_ir_open, |
@@ -36,7 +39,7 @@ static void ep7211_ir_open(dongle_t *self, struct qos_info *qos) | |||
36 | { | 39 | { |
37 | unsigned int syscon1, flags; | 40 | unsigned int syscon1, flags; |
38 | 41 | ||
39 | save_flags(flags); cli(); | 42 | spin_lock_irqsave(&ep7211_lock, flags); |
40 | 43 | ||
41 | /* Turn on the SIR encoder. */ | 44 | /* Turn on the SIR encoder. */ |
42 | syscon1 = clps_readl(SYSCON1); | 45 | syscon1 = clps_readl(SYSCON1); |
@@ -46,14 +49,14 @@ static void ep7211_ir_open(dongle_t *self, struct qos_info *qos) | |||
46 | /* XXX: We should disable modem status interrupts on the first | 49 | /* XXX: We should disable modem status interrupts on the first |
47 | UART (interrupt #14). */ | 50 | UART (interrupt #14). */ |
48 | 51 | ||
49 | restore_flags(flags); | 52 | spin_unlock_irqrestore(&ep7211_lock, flags); |
50 | } | 53 | } |
51 | 54 | ||
52 | static void ep7211_ir_close(dongle_t *self) | 55 | static void ep7211_ir_close(dongle_t *self) |
53 | { | 56 | { |
54 | unsigned int syscon1, flags; | 57 | unsigned int syscon1, flags; |
55 | 58 | ||
56 | save_flags(flags); cli(); | 59 | spin_lock_irqsave(&ep7211_lock, flags); |
57 | 60 | ||
58 | /* Turn off the SIR encoder. */ | 61 | /* Turn off the SIR encoder. */ |
59 | syscon1 = clps_readl(SYSCON1); | 62 | syscon1 = clps_readl(SYSCON1); |
@@ -63,7 +66,7 @@ static void ep7211_ir_close(dongle_t *self) | |||
63 | /* XXX: If we've disabled the modem status interrupts, we should | 66 | /* XXX: If we've disabled the modem status interrupts, we should |
64 | reset them back to their original state. */ | 67 | reset them back to their original state. */ |
65 | 68 | ||
66 | restore_flags(flags); | 69 | spin_unlock_irqrestore(&ep7211_lock, flags); |
67 | } | 70 | } |
68 | 71 | ||
69 | /* | 72 | /* |
diff --git a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c index 101750bf210f..6a98b7ae4975 100644 --- a/drivers/net/irda/irtty-sir.c +++ b/drivers/net/irda/irtty-sir.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <asm/uaccess.h> | 33 | #include <asm/uaccess.h> |
34 | #include <linux/smp_lock.h> | 34 | #include <linux/smp_lock.h> |
35 | #include <linux/delay.h> | 35 | #include <linux/delay.h> |
36 | #include <linux/mutex.h> | ||
36 | 37 | ||
37 | #include <net/irda/irda.h> | 38 | #include <net/irda/irda.h> |
38 | #include <net/irda/irda_device.h> | 39 | #include <net/irda/irda_device.h> |
@@ -338,7 +339,7 @@ static inline void irtty_stop_receiver(struct tty_struct *tty, int stop) | |||
338 | /*****************************************************************/ | 339 | /*****************************************************************/ |
339 | 340 | ||
340 | /* serialize ldisc open/close with sir_dev */ | 341 | /* serialize ldisc open/close with sir_dev */ |
341 | static DECLARE_MUTEX(irtty_sem); | 342 | static DEFINE_MUTEX(irtty_mutex); |
342 | 343 | ||
343 | /* notifier from sir_dev when irda% device gets opened (ifup) */ | 344 | /* notifier from sir_dev when irda% device gets opened (ifup) */ |
344 | 345 | ||
@@ -348,11 +349,11 @@ static int irtty_start_dev(struct sir_dev *dev) | |||
348 | struct tty_struct *tty; | 349 | struct tty_struct *tty; |
349 | 350 | ||
350 | /* serialize with ldisc open/close */ | 351 | /* serialize with ldisc open/close */ |
351 | down(&irtty_sem); | 352 | mutex_lock(&irtty_mutex); |
352 | 353 | ||
353 | priv = dev->priv; | 354 | priv = dev->priv; |
354 | if (unlikely(!priv || priv->magic!=IRTTY_MAGIC)) { | 355 | if (unlikely(!priv || priv->magic!=IRTTY_MAGIC)) { |
355 | up(&irtty_sem); | 356 | mutex_unlock(&irtty_mutex); |
356 | return -ESTALE; | 357 | return -ESTALE; |
357 | } | 358 | } |
358 | 359 | ||
@@ -363,7 +364,7 @@ static int irtty_start_dev(struct sir_dev *dev) | |||
363 | /* Make sure we can receive more data */ | 364 | /* Make sure we can receive more data */ |
364 | irtty_stop_receiver(tty, FALSE); | 365 | irtty_stop_receiver(tty, FALSE); |
365 | 366 | ||
366 | up(&irtty_sem); | 367 | mutex_unlock(&irtty_mutex); |
367 | return 0; | 368 | return 0; |
368 | } | 369 | } |
369 | 370 | ||
@@ -375,11 +376,11 @@ static int irtty_stop_dev(struct sir_dev *dev) | |||
375 | struct tty_struct *tty; | 376 | struct tty_struct *tty; |
376 | 377 | ||
377 | /* serialize with ldisc open/close */ | 378 | /* serialize with ldisc open/close */ |
378 | down(&irtty_sem); | 379 | mutex_lock(&irtty_mutex); |
379 | 380 | ||
380 | priv = dev->priv; | 381 | priv = dev->priv; |
381 | if (unlikely(!priv || priv->magic!=IRTTY_MAGIC)) { | 382 | if (unlikely(!priv || priv->magic!=IRTTY_MAGIC)) { |
382 | up(&irtty_sem); | 383 | mutex_unlock(&irtty_mutex); |
383 | return -ESTALE; | 384 | return -ESTALE; |
384 | } | 385 | } |
385 | 386 | ||
@@ -390,7 +391,7 @@ static int irtty_stop_dev(struct sir_dev *dev) | |||
390 | if (tty->driver->stop) | 391 | if (tty->driver->stop) |
391 | tty->driver->stop(tty); | 392 | tty->driver->stop(tty); |
392 | 393 | ||
393 | up(&irtty_sem); | 394 | mutex_unlock(&irtty_mutex); |
394 | 395 | ||
395 | return 0; | 396 | return 0; |
396 | } | 397 | } |
@@ -514,13 +515,13 @@ static int irtty_open(struct tty_struct *tty) | |||
514 | priv->dev = dev; | 515 | priv->dev = dev; |
515 | 516 | ||
516 | /* serialize with start_dev - in case we were racing with ifup */ | 517 | /* serialize with start_dev - in case we were racing with ifup */ |
517 | down(&irtty_sem); | 518 | mutex_lock(&irtty_mutex); |
518 | 519 | ||
519 | dev->priv = priv; | 520 | dev->priv = priv; |
520 | tty->disc_data = priv; | 521 | tty->disc_data = priv; |
521 | tty->receive_room = 65536; | 522 | tty->receive_room = 65536; |
522 | 523 | ||
523 | up(&irtty_sem); | 524 | mutex_unlock(&irtty_mutex); |
524 | 525 | ||
525 | IRDA_DEBUG(0, "%s - %s: irda line discipline opened\n", __FUNCTION__, tty->name); | 526 | IRDA_DEBUG(0, "%s - %s: irda line discipline opened\n", __FUNCTION__, tty->name); |
526 | 527 | ||
diff --git a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c index ee717d0e939e..83141a3ff546 100644 --- a/drivers/net/irda/nsc-ircc.c +++ b/drivers/net/irda/nsc-ircc.c | |||
@@ -12,6 +12,7 @@ | |||
12 | * Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no> | 12 | * Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no> |
13 | * Copyright (c) 1998 Lichen Wang, <lwang@actisys.com> | 13 | * Copyright (c) 1998 Lichen Wang, <lwang@actisys.com> |
14 | * Copyright (c) 1998 Actisys Corp., www.actisys.com | 14 | * Copyright (c) 1998 Actisys Corp., www.actisys.com |
15 | * Copyright (c) 2000-2004 Jean Tourrilhes <jt@hpl.hp.com> | ||
15 | * All Rights Reserved | 16 | * All Rights Reserved |
16 | * | 17 | * |
17 | * This program is free software; you can redistribute it and/or | 18 | * This program is free software; you can redistribute it and/or |
@@ -53,14 +54,13 @@ | |||
53 | #include <linux/init.h> | 54 | #include <linux/init.h> |
54 | #include <linux/rtnetlink.h> | 55 | #include <linux/rtnetlink.h> |
55 | #include <linux/dma-mapping.h> | 56 | #include <linux/dma-mapping.h> |
57 | #include <linux/pnp.h> | ||
58 | #include <linux/platform_device.h> | ||
56 | 59 | ||
57 | #include <asm/io.h> | 60 | #include <asm/io.h> |
58 | #include <asm/dma.h> | 61 | #include <asm/dma.h> |
59 | #include <asm/byteorder.h> | 62 | #include <asm/byteorder.h> |
60 | 63 | ||
61 | #include <linux/pm.h> | ||
62 | #include <linux/pm_legacy.h> | ||
63 | |||
64 | #include <net/irda/wrapper.h> | 64 | #include <net/irda/wrapper.h> |
65 | #include <net/irda/irda.h> | 65 | #include <net/irda/irda.h> |
66 | #include <net/irda/irda_device.h> | 66 | #include <net/irda/irda_device.h> |
@@ -72,14 +72,27 @@ | |||
72 | 72 | ||
73 | static char *driver_name = "nsc-ircc"; | 73 | static char *driver_name = "nsc-ircc"; |
74 | 74 | ||
75 | /* Power Management */ | ||
76 | #define NSC_IRCC_DRIVER_NAME "nsc-ircc" | ||
77 | static int nsc_ircc_suspend(struct platform_device *dev, pm_message_t state); | ||
78 | static int nsc_ircc_resume(struct platform_device *dev); | ||
79 | |||
80 | static struct platform_driver nsc_ircc_driver = { | ||
81 | .suspend = nsc_ircc_suspend, | ||
82 | .resume = nsc_ircc_resume, | ||
83 | .driver = { | ||
84 | .name = NSC_IRCC_DRIVER_NAME, | ||
85 | }, | ||
86 | }; | ||
87 | |||
75 | /* Module parameters */ | 88 | /* Module parameters */ |
76 | static int qos_mtt_bits = 0x07; /* 1 ms or more */ | 89 | static int qos_mtt_bits = 0x07; /* 1 ms or more */ |
77 | static int dongle_id; | 90 | static int dongle_id; |
78 | 91 | ||
79 | /* Use BIOS settions by default, but user may supply module parameters */ | 92 | /* Use BIOS settions by default, but user may supply module parameters */ |
80 | static unsigned int io[] = { ~0, ~0, ~0, ~0 }; | 93 | static unsigned int io[] = { ~0, ~0, ~0, ~0, ~0 }; |
81 | static unsigned int irq[] = { 0, 0, 0, 0, 0 }; | 94 | static unsigned int irq[] = { 0, 0, 0, 0, 0 }; |
82 | static unsigned int dma[] = { 0, 0, 0, 0, 0 }; | 95 | static unsigned int dma[] = { 0, 0, 0, 0, 0 }; |
83 | 96 | ||
84 | static int nsc_ircc_probe_108(nsc_chip_t *chip, chipio_t *info); | 97 | static int nsc_ircc_probe_108(nsc_chip_t *chip, chipio_t *info); |
85 | static int nsc_ircc_probe_338(nsc_chip_t *chip, chipio_t *info); | 98 | static int nsc_ircc_probe_338(nsc_chip_t *chip, chipio_t *info); |
@@ -87,6 +100,7 @@ static int nsc_ircc_probe_39x(nsc_chip_t *chip, chipio_t *info); | |||
87 | static int nsc_ircc_init_108(nsc_chip_t *chip, chipio_t *info); | 100 | static int nsc_ircc_init_108(nsc_chip_t *chip, chipio_t *info); |
88 | static int nsc_ircc_init_338(nsc_chip_t *chip, chipio_t *info); | 101 | static int nsc_ircc_init_338(nsc_chip_t *chip, chipio_t *info); |
89 | static int nsc_ircc_init_39x(nsc_chip_t *chip, chipio_t *info); | 102 | static int nsc_ircc_init_39x(nsc_chip_t *chip, chipio_t *info); |
103 | static int nsc_ircc_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *id); | ||
90 | 104 | ||
91 | /* These are the known NSC chips */ | 105 | /* These are the known NSC chips */ |
92 | static nsc_chip_t chips[] = { | 106 | static nsc_chip_t chips[] = { |
@@ -101,11 +115,12 @@ static nsc_chip_t chips[] = { | |||
101 | /* Contributed by Jan Frey - IBM A30/A31 */ | 115 | /* Contributed by Jan Frey - IBM A30/A31 */ |
102 | { "PC8739x", { 0x2e, 0x4e, 0x0 }, 0x20, 0xea, 0xff, | 116 | { "PC8739x", { 0x2e, 0x4e, 0x0 }, 0x20, 0xea, 0xff, |
103 | nsc_ircc_probe_39x, nsc_ircc_init_39x }, | 117 | nsc_ircc_probe_39x, nsc_ircc_init_39x }, |
118 | { "IBM", { 0x2e, 0x4e, 0x0 }, 0x20, 0xf4, 0xff, | ||
119 | nsc_ircc_probe_39x, nsc_ircc_init_39x }, | ||
104 | { NULL } | 120 | { NULL } |
105 | }; | 121 | }; |
106 | 122 | ||
107 | /* Max 4 instances for now */ | 123 | static struct nsc_ircc_cb *dev_self[] = { NULL, NULL, NULL, NULL, NULL }; |
108 | static struct nsc_ircc_cb *dev_self[] = { NULL, NULL, NULL, NULL }; | ||
109 | 124 | ||
110 | static char *dongle_types[] = { | 125 | static char *dongle_types[] = { |
111 | "Differential serial interface", | 126 | "Differential serial interface", |
@@ -126,8 +141,24 @@ static char *dongle_types[] = { | |||
126 | "No dongle connected", | 141 | "No dongle connected", |
127 | }; | 142 | }; |
128 | 143 | ||
144 | /* PNP probing */ | ||
145 | static chipio_t pnp_info; | ||
146 | static const struct pnp_device_id nsc_ircc_pnp_table[] = { | ||
147 | { .id = "NSC6001", .driver_data = 0 }, | ||
148 | { .id = "IBM0071", .driver_data = 0 }, | ||
149 | { } | ||
150 | }; | ||
151 | |||
152 | MODULE_DEVICE_TABLE(pnp, nsc_ircc_pnp_table); | ||
153 | |||
154 | static struct pnp_driver nsc_ircc_pnp_driver = { | ||
155 | .name = "nsc-ircc", | ||
156 | .id_table = nsc_ircc_pnp_table, | ||
157 | .probe = nsc_ircc_pnp_probe, | ||
158 | }; | ||
159 | |||
129 | /* Some prototypes */ | 160 | /* Some prototypes */ |
130 | static int nsc_ircc_open(int i, chipio_t *info); | 161 | static int nsc_ircc_open(chipio_t *info); |
131 | static int nsc_ircc_close(struct nsc_ircc_cb *self); | 162 | static int nsc_ircc_close(struct nsc_ircc_cb *self); |
132 | static int nsc_ircc_setup(chipio_t *info); | 163 | static int nsc_ircc_setup(chipio_t *info); |
133 | static void nsc_ircc_pio_receive(struct nsc_ircc_cb *self); | 164 | static void nsc_ircc_pio_receive(struct nsc_ircc_cb *self); |
@@ -146,7 +177,10 @@ static int nsc_ircc_net_open(struct net_device *dev); | |||
146 | static int nsc_ircc_net_close(struct net_device *dev); | 177 | static int nsc_ircc_net_close(struct net_device *dev); |
147 | static int nsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); | 178 | static int nsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); |
148 | static struct net_device_stats *nsc_ircc_net_get_stats(struct net_device *dev); | 179 | static struct net_device_stats *nsc_ircc_net_get_stats(struct net_device *dev); |
149 | static int nsc_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data); | 180 | |
181 | /* Globals */ | ||
182 | static int pnp_registered; | ||
183 | static int pnp_succeeded; | ||
150 | 184 | ||
151 | /* | 185 | /* |
152 | * Function nsc_ircc_init () | 186 | * Function nsc_ircc_init () |
@@ -158,28 +192,36 @@ static int __init nsc_ircc_init(void) | |||
158 | { | 192 | { |
159 | chipio_t info; | 193 | chipio_t info; |
160 | nsc_chip_t *chip; | 194 | nsc_chip_t *chip; |
161 | int ret = -ENODEV; | 195 | int ret; |
162 | int cfg_base; | 196 | int cfg_base; |
163 | int cfg, id; | 197 | int cfg, id; |
164 | int reg; | 198 | int reg; |
165 | int i = 0; | 199 | int i = 0; |
166 | 200 | ||
201 | ret = platform_driver_register(&nsc_ircc_driver); | ||
202 | if (ret) { | ||
203 | IRDA_ERROR("%s, Can't register driver!\n", driver_name); | ||
204 | return ret; | ||
205 | } | ||
206 | |||
207 | /* Register with PnP subsystem to detect disable ports */ | ||
208 | ret = pnp_register_driver(&nsc_ircc_pnp_driver); | ||
209 | |||
210 | if (ret >= 0) | ||
211 | pnp_registered = 1; | ||
212 | |||
213 | ret = -ENODEV; | ||
214 | |||
167 | /* Probe for all the NSC chipsets we know about */ | 215 | /* Probe for all the NSC chipsets we know about */ |
168 | for (chip=chips; chip->name ; chip++) { | 216 | for (chip = chips; chip->name ; chip++) { |
169 | IRDA_DEBUG(2, "%s(), Probing for %s ...\n", __FUNCTION__, | 217 | IRDA_DEBUG(2, "%s(), Probing for %s ...\n", __FUNCTION__, |
170 | chip->name); | 218 | chip->name); |
171 | 219 | ||
172 | /* Try all config registers for this chip */ | 220 | /* Try all config registers for this chip */ |
173 | for (cfg=0; cfg<3; cfg++) { | 221 | for (cfg = 0; cfg < ARRAY_SIZE(chip->cfg); cfg++) { |
174 | cfg_base = chip->cfg[cfg]; | 222 | cfg_base = chip->cfg[cfg]; |
175 | if (!cfg_base) | 223 | if (!cfg_base) |
176 | continue; | 224 | continue; |
177 | |||
178 | memset(&info, 0, sizeof(chipio_t)); | ||
179 | info.cfg_base = cfg_base; | ||
180 | info.fir_base = io[i]; | ||
181 | info.dma = dma[i]; | ||
182 | info.irq = irq[i]; | ||
183 | 225 | ||
184 | /* Read index register */ | 226 | /* Read index register */ |
185 | reg = inb(cfg_base); | 227 | reg = inb(cfg_base); |
@@ -194,24 +236,65 @@ static int __init nsc_ircc_init(void) | |||
194 | if ((id & chip->cid_mask) == chip->cid_value) { | 236 | if ((id & chip->cid_mask) == chip->cid_value) { |
195 | IRDA_DEBUG(2, "%s() Found %s chip, revision=%d\n", | 237 | IRDA_DEBUG(2, "%s() Found %s chip, revision=%d\n", |
196 | __FUNCTION__, chip->name, id & ~chip->cid_mask); | 238 | __FUNCTION__, chip->name, id & ~chip->cid_mask); |
197 | /* | ||
198 | * If the user supplies the base address, then | ||
199 | * we init the chip, if not we probe the values | ||
200 | * set by the BIOS | ||
201 | */ | ||
202 | if (io[i] < 0x2000) { | ||
203 | chip->init(chip, &info); | ||
204 | } else | ||
205 | chip->probe(chip, &info); | ||
206 | 239 | ||
207 | if (nsc_ircc_open(i, &info) == 0) | 240 | /* |
208 | ret = 0; | 241 | * If we found a correct PnP setting, |
242 | * we first try it. | ||
243 | */ | ||
244 | if (pnp_succeeded) { | ||
245 | memset(&info, 0, sizeof(chipio_t)); | ||
246 | info.cfg_base = cfg_base; | ||
247 | info.fir_base = pnp_info.fir_base; | ||
248 | info.dma = pnp_info.dma; | ||
249 | info.irq = pnp_info.irq; | ||
250 | |||
251 | if (info.fir_base < 0x2000) { | ||
252 | IRDA_MESSAGE("%s, chip->init\n", driver_name); | ||
253 | chip->init(chip, &info); | ||
254 | } else | ||
255 | chip->probe(chip, &info); | ||
256 | |||
257 | if (nsc_ircc_open(&info) >= 0) | ||
258 | ret = 0; | ||
259 | } | ||
260 | |||
261 | /* | ||
262 | * Opening based on PnP values failed. | ||
263 | * Let's fallback to user values, or probe | ||
264 | * the chip. | ||
265 | */ | ||
266 | if (ret) { | ||
267 | IRDA_DEBUG(2, "%s, PnP init failed\n", driver_name); | ||
268 | memset(&info, 0, sizeof(chipio_t)); | ||
269 | info.cfg_base = cfg_base; | ||
270 | info.fir_base = io[i]; | ||
271 | info.dma = dma[i]; | ||
272 | info.irq = irq[i]; | ||
273 | |||
274 | /* | ||
275 | * If the user supplies the base address, then | ||
276 | * we init the chip, if not we probe the values | ||
277 | * set by the BIOS | ||
278 | */ | ||
279 | if (io[i] < 0x2000) { | ||
280 | chip->init(chip, &info); | ||
281 | } else | ||
282 | chip->probe(chip, &info); | ||
283 | |||
284 | if (nsc_ircc_open(&info) >= 0) | ||
285 | ret = 0; | ||
286 | } | ||
209 | i++; | 287 | i++; |
210 | } else { | 288 | } else { |
211 | IRDA_DEBUG(2, "%s(), Wrong chip id=0x%02x\n", __FUNCTION__, id); | 289 | IRDA_DEBUG(2, "%s(), Wrong chip id=0x%02x\n", __FUNCTION__, id); |
212 | } | 290 | } |
213 | } | 291 | } |
214 | 292 | } | |
293 | |||
294 | if (ret) { | ||
295 | platform_driver_unregister(&nsc_ircc_driver); | ||
296 | pnp_unregister_driver(&nsc_ircc_pnp_driver); | ||
297 | pnp_registered = 0; | ||
215 | } | 298 | } |
216 | 299 | ||
217 | return ret; | 300 | return ret; |
@@ -227,12 +310,17 @@ static void __exit nsc_ircc_cleanup(void) | |||
227 | { | 310 | { |
228 | int i; | 311 | int i; |
229 | 312 | ||
230 | pm_unregister_all(nsc_ircc_pmproc); | 313 | for (i = 0; i < ARRAY_SIZE(dev_self); i++) { |
231 | |||
232 | for (i=0; i < 4; i++) { | ||
233 | if (dev_self[i]) | 314 | if (dev_self[i]) |
234 | nsc_ircc_close(dev_self[i]); | 315 | nsc_ircc_close(dev_self[i]); |
235 | } | 316 | } |
317 | |||
318 | platform_driver_unregister(&nsc_ircc_driver); | ||
319 | |||
320 | if (pnp_registered) | ||
321 | pnp_unregister_driver(&nsc_ircc_pnp_driver); | ||
322 | |||
323 | pnp_registered = 0; | ||
236 | } | 324 | } |
237 | 325 | ||
238 | /* | 326 | /* |
@@ -241,16 +329,26 @@ static void __exit nsc_ircc_cleanup(void) | |||
241 | * Open driver instance | 329 | * Open driver instance |
242 | * | 330 | * |
243 | */ | 331 | */ |
244 | static int __init nsc_ircc_open(int i, chipio_t *info) | 332 | static int __init nsc_ircc_open(chipio_t *info) |
245 | { | 333 | { |
246 | struct net_device *dev; | 334 | struct net_device *dev; |
247 | struct nsc_ircc_cb *self; | 335 | struct nsc_ircc_cb *self; |
248 | struct pm_dev *pmdev; | ||
249 | void *ret; | 336 | void *ret; |
250 | int err; | 337 | int err, chip_index; |
251 | 338 | ||
252 | IRDA_DEBUG(2, "%s()\n", __FUNCTION__); | 339 | IRDA_DEBUG(2, "%s()\n", __FUNCTION__); |
253 | 340 | ||
341 | |||
342 | for (chip_index = 0; chip_index < ARRAY_SIZE(dev_self); chip_index++) { | ||
343 | if (!dev_self[chip_index]) | ||
344 | break; | ||
345 | } | ||
346 | |||
347 | if (chip_index == ARRAY_SIZE(dev_self)) { | ||
348 | IRDA_ERROR("%s(), maximum number of supported chips reached!\n", __FUNCTION__); | ||
349 | return -ENOMEM; | ||
350 | } | ||
351 | |||
254 | IRDA_MESSAGE("%s, Found chip at base=0x%03x\n", driver_name, | 352 | IRDA_MESSAGE("%s, Found chip at base=0x%03x\n", driver_name, |
255 | info->cfg_base); | 353 | info->cfg_base); |
256 | 354 | ||
@@ -271,8 +369,8 @@ static int __init nsc_ircc_open(int i, chipio_t *info) | |||
271 | spin_lock_init(&self->lock); | 369 | spin_lock_init(&self->lock); |
272 | 370 | ||
273 | /* Need to store self somewhere */ | 371 | /* Need to store self somewhere */ |
274 | dev_self[i] = self; | 372 | dev_self[chip_index] = self; |
275 | self->index = i; | 373 | self->index = chip_index; |
276 | 374 | ||
277 | /* Initialize IO */ | 375 | /* Initialize IO */ |
278 | self->io.cfg_base = info->cfg_base; | 376 | self->io.cfg_base = info->cfg_base; |
@@ -351,7 +449,7 @@ static int __init nsc_ircc_open(int i, chipio_t *info) | |||
351 | 449 | ||
352 | /* Check if user has supplied a valid dongle id or not */ | 450 | /* Check if user has supplied a valid dongle id or not */ |
353 | if ((dongle_id <= 0) || | 451 | if ((dongle_id <= 0) || |
354 | (dongle_id >= (sizeof(dongle_types) / sizeof(dongle_types[0]))) ) { | 452 | (dongle_id >= ARRAY_SIZE(dongle_types))) { |
355 | dongle_id = nsc_ircc_read_dongle_id(self->io.fir_base); | 453 | dongle_id = nsc_ircc_read_dongle_id(self->io.fir_base); |
356 | 454 | ||
357 | IRDA_MESSAGE("%s, Found dongle: %s\n", driver_name, | 455 | IRDA_MESSAGE("%s, Found dongle: %s\n", driver_name, |
@@ -364,11 +462,18 @@ static int __init nsc_ircc_open(int i, chipio_t *info) | |||
364 | self->io.dongle_id = dongle_id; | 462 | self->io.dongle_id = dongle_id; |
365 | nsc_ircc_init_dongle_interface(self->io.fir_base, dongle_id); | 463 | nsc_ircc_init_dongle_interface(self->io.fir_base, dongle_id); |
366 | 464 | ||
367 | pmdev = pm_register(PM_SYS_DEV, PM_SYS_IRDA, nsc_ircc_pmproc); | 465 | self->pldev = platform_device_register_simple(NSC_IRCC_DRIVER_NAME, |
368 | if (pmdev) | 466 | self->index, NULL, 0); |
369 | pmdev->data = self; | 467 | if (IS_ERR(self->pldev)) { |
468 | err = PTR_ERR(self->pldev); | ||
469 | goto out5; | ||
470 | } | ||
471 | platform_set_drvdata(self->pldev, self); | ||
370 | 472 | ||
371 | return 0; | 473 | return chip_index; |
474 | |||
475 | out5: | ||
476 | unregister_netdev(dev); | ||
372 | out4: | 477 | out4: |
373 | dma_free_coherent(NULL, self->tx_buff.truesize, | 478 | dma_free_coherent(NULL, self->tx_buff.truesize, |
374 | self->tx_buff.head, self->tx_buff_dma); | 479 | self->tx_buff.head, self->tx_buff_dma); |
@@ -379,7 +484,7 @@ static int __init nsc_ircc_open(int i, chipio_t *info) | |||
379 | release_region(self->io.fir_base, self->io.fir_ext); | 484 | release_region(self->io.fir_base, self->io.fir_ext); |
380 | out1: | 485 | out1: |
381 | free_netdev(dev); | 486 | free_netdev(dev); |
382 | dev_self[i] = NULL; | 487 | dev_self[chip_index] = NULL; |
383 | return err; | 488 | return err; |
384 | } | 489 | } |
385 | 490 | ||
@@ -399,6 +504,8 @@ static int __exit nsc_ircc_close(struct nsc_ircc_cb *self) | |||
399 | 504 | ||
400 | iobase = self->io.fir_base; | 505 | iobase = self->io.fir_base; |
401 | 506 | ||
507 | platform_device_unregister(self->pldev); | ||
508 | |||
402 | /* Remove netdevice */ | 509 | /* Remove netdevice */ |
403 | unregister_netdev(self->netdev); | 510 | unregister_netdev(self->netdev); |
404 | 511 | ||
@@ -806,6 +913,43 @@ static int nsc_ircc_probe_39x(nsc_chip_t *chip, chipio_t *info) | |||
806 | return 0; | 913 | return 0; |
807 | } | 914 | } |
808 | 915 | ||
916 | /* PNP probing */ | ||
917 | static int nsc_ircc_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *id) | ||
918 | { | ||
919 | memset(&pnp_info, 0, sizeof(chipio_t)); | ||
920 | pnp_info.irq = -1; | ||
921 | pnp_info.dma = -1; | ||
922 | pnp_succeeded = 1; | ||
923 | |||
924 | /* There don't seem to be any way to get the cfg_base. | ||
925 | * On my box, cfg_base is in the PnP descriptor of the | ||
926 | * motherboard. Oh well... Jean II */ | ||
927 | |||
928 | if (pnp_port_valid(dev, 0) && | ||
929 | !(pnp_port_flags(dev, 0) & IORESOURCE_DISABLED)) | ||
930 | pnp_info.fir_base = pnp_port_start(dev, 0); | ||
931 | |||
932 | if (pnp_irq_valid(dev, 0) && | ||
933 | !(pnp_irq_flags(dev, 0) & IORESOURCE_DISABLED)) | ||
934 | pnp_info.irq = pnp_irq(dev, 0); | ||
935 | |||
936 | if (pnp_dma_valid(dev, 0) && | ||
937 | !(pnp_dma_flags(dev, 0) & IORESOURCE_DISABLED)) | ||
938 | pnp_info.dma = pnp_dma(dev, 0); | ||
939 | |||
940 | IRDA_DEBUG(0, "%s() : From PnP, found firbase 0x%03X ; irq %d ; dma %d.\n", | ||
941 | __FUNCTION__, pnp_info.fir_base, pnp_info.irq, pnp_info.dma); | ||
942 | |||
943 | if((pnp_info.fir_base == 0) || | ||
944 | (pnp_info.irq == -1) || (pnp_info.dma == -1)) { | ||
945 | /* Returning an error will disable the device. Yuck ! */ | ||
946 | //return -EINVAL; | ||
947 | pnp_succeeded = 0; | ||
948 | } | ||
949 | |||
950 | return 0; | ||
951 | } | ||
952 | |||
809 | /* | 953 | /* |
810 | * Function nsc_ircc_setup (info) | 954 | * Function nsc_ircc_setup (info) |
811 | * | 955 | * |
@@ -2161,45 +2305,83 @@ static struct net_device_stats *nsc_ircc_net_get_stats(struct net_device *dev) | |||
2161 | return &self->stats; | 2305 | return &self->stats; |
2162 | } | 2306 | } |
2163 | 2307 | ||
2164 | static void nsc_ircc_suspend(struct nsc_ircc_cb *self) | 2308 | static int nsc_ircc_suspend(struct platform_device *dev, pm_message_t state) |
2165 | { | 2309 | { |
2166 | IRDA_MESSAGE("%s, Suspending\n", driver_name); | 2310 | struct nsc_ircc_cb *self = platform_get_drvdata(dev); |
2311 | int bank; | ||
2312 | unsigned long flags; | ||
2313 | int iobase = self->io.fir_base; | ||
2167 | 2314 | ||
2168 | if (self->io.suspended) | 2315 | if (self->io.suspended) |
2169 | return; | 2316 | return 0; |
2170 | 2317 | ||
2171 | nsc_ircc_net_close(self->netdev); | 2318 | IRDA_DEBUG(1, "%s, Suspending\n", driver_name); |
2172 | 2319 | ||
2320 | rtnl_lock(); | ||
2321 | if (netif_running(self->netdev)) { | ||
2322 | netif_device_detach(self->netdev); | ||
2323 | spin_lock_irqsave(&self->lock, flags); | ||
2324 | /* Save current bank */ | ||
2325 | bank = inb(iobase+BSR); | ||
2326 | |||
2327 | /* Disable interrupts */ | ||
2328 | switch_bank(iobase, BANK0); | ||
2329 | outb(0, iobase+IER); | ||
2330 | |||
2331 | /* Restore bank register */ | ||
2332 | outb(bank, iobase+BSR); | ||
2333 | |||
2334 | spin_unlock_irqrestore(&self->lock, flags); | ||
2335 | free_irq(self->io.irq, self->netdev); | ||
2336 | disable_dma(self->io.dma); | ||
2337 | } | ||
2173 | self->io.suspended = 1; | 2338 | self->io.suspended = 1; |
2339 | rtnl_unlock(); | ||
2340 | |||
2341 | return 0; | ||
2174 | } | 2342 | } |
2175 | 2343 | ||
2176 | static void nsc_ircc_wakeup(struct nsc_ircc_cb *self) | 2344 | static int nsc_ircc_resume(struct platform_device *dev) |
2177 | { | 2345 | { |
2346 | struct nsc_ircc_cb *self = platform_get_drvdata(dev); | ||
2347 | unsigned long flags; | ||
2348 | |||
2178 | if (!self->io.suspended) | 2349 | if (!self->io.suspended) |
2179 | return; | 2350 | return 0; |
2180 | 2351 | ||
2352 | IRDA_DEBUG(1, "%s, Waking up\n", driver_name); | ||
2353 | |||
2354 | rtnl_lock(); | ||
2181 | nsc_ircc_setup(&self->io); | 2355 | nsc_ircc_setup(&self->io); |
2182 | nsc_ircc_net_open(self->netdev); | 2356 | nsc_ircc_init_dongle_interface(self->io.fir_base, self->io.dongle_id); |
2183 | |||
2184 | IRDA_MESSAGE("%s, Waking up\n", driver_name); | ||
2185 | 2357 | ||
2358 | if (netif_running(self->netdev)) { | ||
2359 | if (request_irq(self->io.irq, nsc_ircc_interrupt, 0, | ||
2360 | self->netdev->name, self->netdev)) { | ||
2361 | IRDA_WARNING("%s, unable to allocate irq=%d\n", | ||
2362 | driver_name, self->io.irq); | ||
2363 | |||
2364 | /* | ||
2365 | * Don't fail resume process, just kill this | ||
2366 | * network interface | ||
2367 | */ | ||
2368 | unregister_netdevice(self->netdev); | ||
2369 | } else { | ||
2370 | spin_lock_irqsave(&self->lock, flags); | ||
2371 | nsc_ircc_change_speed(self, self->io.speed); | ||
2372 | spin_unlock_irqrestore(&self->lock, flags); | ||
2373 | netif_device_attach(self->netdev); | ||
2374 | } | ||
2375 | |||
2376 | } else { | ||
2377 | spin_lock_irqsave(&self->lock, flags); | ||
2378 | nsc_ircc_change_speed(self, 9600); | ||
2379 | spin_unlock_irqrestore(&self->lock, flags); | ||
2380 | } | ||
2186 | self->io.suspended = 0; | 2381 | self->io.suspended = 0; |
2187 | } | 2382 | rtnl_unlock(); |
2188 | 2383 | ||
2189 | static int nsc_ircc_pmproc(struct pm_dev *dev, pm_request_t rqst, void *data) | 2384 | return 0; |
2190 | { | ||
2191 | struct nsc_ircc_cb *self = (struct nsc_ircc_cb*) dev->data; | ||
2192 | if (self) { | ||
2193 | switch (rqst) { | ||
2194 | case PM_SUSPEND: | ||
2195 | nsc_ircc_suspend(self); | ||
2196 | break; | ||
2197 | case PM_RESUME: | ||
2198 | nsc_ircc_wakeup(self); | ||
2199 | break; | ||
2200 | } | ||
2201 | } | ||
2202 | return 0; | ||
2203 | } | 2385 | } |
2204 | 2386 | ||
2205 | MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>"); | 2387 | MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>"); |
diff --git a/drivers/net/irda/nsc-ircc.h b/drivers/net/irda/nsc-ircc.h index 6edf7e514624..dacf671abcd6 100644 --- a/drivers/net/irda/nsc-ircc.h +++ b/drivers/net/irda/nsc-ircc.h | |||
@@ -269,7 +269,7 @@ struct nsc_ircc_cb { | |||
269 | __u32 new_speed; | 269 | __u32 new_speed; |
270 | int index; /* Instance index */ | 270 | int index; /* Instance index */ |
271 | 271 | ||
272 | struct pm_dev *dev; | 272 | struct platform_device *pldev; |
273 | }; | 273 | }; |
274 | 274 | ||
275 | static inline void switch_bank(int iobase, int bank) | 275 | static inline void switch_bank(int iobase, int bank) |
diff --git a/drivers/net/irda/sir_dongle.c b/drivers/net/irda/sir_dongle.c index 8d225921ae7b..d7e32d9554fc 100644 --- a/drivers/net/irda/sir_dongle.c +++ b/drivers/net/irda/sir_dongle.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
17 | #include <linux/smp_lock.h> | 17 | #include <linux/smp_lock.h> |
18 | #include <linux/kmod.h> | 18 | #include <linux/kmod.h> |
19 | #include <linux/mutex.h> | ||
19 | 20 | ||
20 | #include <net/irda/irda.h> | 21 | #include <net/irda/irda.h> |
21 | 22 | ||
@@ -28,7 +29,7 @@ | |||
28 | */ | 29 | */ |
29 | 30 | ||
30 | static LIST_HEAD(dongle_list); /* list of registered dongle drivers */ | 31 | static LIST_HEAD(dongle_list); /* list of registered dongle drivers */ |
31 | static DECLARE_MUTEX(dongle_list_lock); /* protects the list */ | 32 | static DEFINE_MUTEX(dongle_list_lock); /* protects the list */ |
32 | 33 | ||
33 | int irda_register_dongle(struct dongle_driver *new) | 34 | int irda_register_dongle(struct dongle_driver *new) |
34 | { | 35 | { |
@@ -38,25 +39,25 @@ int irda_register_dongle(struct dongle_driver *new) | |||
38 | IRDA_DEBUG(0, "%s : registering dongle \"%s\" (%d).\n", | 39 | IRDA_DEBUG(0, "%s : registering dongle \"%s\" (%d).\n", |
39 | __FUNCTION__, new->driver_name, new->type); | 40 | __FUNCTION__, new->driver_name, new->type); |
40 | 41 | ||
41 | down(&dongle_list_lock); | 42 | mutex_lock(&dongle_list_lock); |
42 | list_for_each(entry, &dongle_list) { | 43 | list_for_each(entry, &dongle_list) { |
43 | drv = list_entry(entry, struct dongle_driver, dongle_list); | 44 | drv = list_entry(entry, struct dongle_driver, dongle_list); |
44 | if (new->type == drv->type) { | 45 | if (new->type == drv->type) { |
45 | up(&dongle_list_lock); | 46 | mutex_unlock(&dongle_list_lock); |
46 | return -EEXIST; | 47 | return -EEXIST; |
47 | } | 48 | } |
48 | } | 49 | } |
49 | list_add(&new->dongle_list, &dongle_list); | 50 | list_add(&new->dongle_list, &dongle_list); |
50 | up(&dongle_list_lock); | 51 | mutex_unlock(&dongle_list_lock); |
51 | return 0; | 52 | return 0; |
52 | } | 53 | } |
53 | EXPORT_SYMBOL(irda_register_dongle); | 54 | EXPORT_SYMBOL(irda_register_dongle); |
54 | 55 | ||
55 | int irda_unregister_dongle(struct dongle_driver *drv) | 56 | int irda_unregister_dongle(struct dongle_driver *drv) |
56 | { | 57 | { |
57 | down(&dongle_list_lock); | 58 | mutex_lock(&dongle_list_lock); |
58 | list_del(&drv->dongle_list); | 59 | list_del(&drv->dongle_list); |
59 | up(&dongle_list_lock); | 60 | mutex_unlock(&dongle_list_lock); |
60 | return 0; | 61 | return 0; |
61 | } | 62 | } |
62 | EXPORT_SYMBOL(irda_unregister_dongle); | 63 | EXPORT_SYMBOL(irda_unregister_dongle); |
@@ -75,7 +76,7 @@ int sirdev_get_dongle(struct sir_dev *dev, IRDA_DONGLE type) | |||
75 | return -EBUSY; | 76 | return -EBUSY; |
76 | 77 | ||
77 | /* serialize access to the list of registered dongles */ | 78 | /* serialize access to the list of registered dongles */ |
78 | down(&dongle_list_lock); | 79 | mutex_lock(&dongle_list_lock); |
79 | 80 | ||
80 | list_for_each(entry, &dongle_list) { | 81 | list_for_each(entry, &dongle_list) { |
81 | drv = list_entry(entry, struct dongle_driver, dongle_list); | 82 | drv = list_entry(entry, struct dongle_driver, dongle_list); |
@@ -109,14 +110,14 @@ int sirdev_get_dongle(struct sir_dev *dev, IRDA_DONGLE type) | |||
109 | if (!drv->open || (err=drv->open(dev))!=0) | 110 | if (!drv->open || (err=drv->open(dev))!=0) |
110 | goto out_reject; /* failed to open driver */ | 111 | goto out_reject; /* failed to open driver */ |
111 | 112 | ||
112 | up(&dongle_list_lock); | 113 | mutex_unlock(&dongle_list_lock); |
113 | return 0; | 114 | return 0; |
114 | 115 | ||
115 | out_reject: | 116 | out_reject: |
116 | dev->dongle_drv = NULL; | 117 | dev->dongle_drv = NULL; |
117 | module_put(drv->owner); | 118 | module_put(drv->owner); |
118 | out_unlock: | 119 | out_unlock: |
119 | up(&dongle_list_lock); | 120 | mutex_unlock(&dongle_list_lock); |
120 | return err; | 121 | return err; |
121 | } | 122 | } |
122 | 123 | ||
diff --git a/drivers/net/irda/toim3232-sir.c b/drivers/net/irda/toim3232-sir.c new file mode 100644 index 000000000000..aa1a9b0ed83e --- /dev/null +++ b/drivers/net/irda/toim3232-sir.c | |||
@@ -0,0 +1,375 @@ | |||
1 | /********************************************************************* | ||
2 | * | ||
3 | * Filename: toim3232-sir.c | ||
4 | * Version: 1.0 | ||
5 | * Description: Implementation of dongles based on the Vishay/Temic | ||
6 | * TOIM3232 SIR Endec chipset. Currently only the | ||
7 | * IRWave IR320ST-2 is tested, although it should work | ||
8 | * with any TOIM3232 or TOIM4232 chipset based RS232 | ||
9 | * dongle with minimal modification. | ||
10 | * Based heavily on the Tekram driver (tekram.c), | ||
11 | * with thanks to Dag Brattli and Martin Diehl. | ||
12 | * Status: Experimental. | ||
13 | * Author: David Basden <davidb-irda@rcpt.to> | ||
14 | * Created at: Thu Feb 09 23:47:32 2006 | ||
15 | * | ||
16 | * Copyright (c) 2006 David Basden. | ||
17 | * Copyright (c) 1998-1999 Dag Brattli, | ||
18 | * Copyright (c) 2002 Martin Diehl, | ||
19 | * All Rights Reserved. | ||
20 | * | ||
21 | * This program is free software; you can redistribute it and/or | ||
22 | * modify it under the terms of the GNU General Public License as | ||
23 | * published by the Free Software Foundation; either version 2 of | ||
24 | * the License, or (at your option) any later version. | ||
25 | * | ||
26 | * Neither Dag Brattli nor University of Tromsø admit liability nor | ||
27 | * provide warranty for any of this software. This material is | ||
28 | * provided "AS-IS" and at no charge. | ||
29 | * | ||
30 | ********************************************************************/ | ||
31 | |||
32 | /* | ||
33 | * This driver has currently only been tested on the IRWave IR320ST-2 | ||
34 | * | ||
35 | * PROTOCOL: | ||
36 | * | ||
37 | * The protocol for talking to the TOIM3232 is quite easy, and is | ||
38 | * designed to interface with RS232 with only level convertors. The | ||
39 | * BR/~D line on the chip is brought high to signal 'command mode', | ||
40 | * where a command byte is sent to select the baudrate of the RS232 | ||
41 | * interface and the pulse length of the IRDA output. When BR/~D | ||
42 | * is brought low, the dongle then changes to the selected baudrate, | ||
43 | * and the RS232 interface is used for data until BR/~D is brought | ||
44 | * high again. The initial speed for the TOIMx323 after RESET is | ||
45 | * 9600 baud. The baudrate for command-mode is the last selected | ||
46 | * baud-rate, or 9600 after a RESET. | ||
47 | * | ||
48 | * The dongle I have (below) adds some extra hardware on the front end, | ||
49 | * but this is mostly directed towards pariasitic power from the RS232 | ||
50 | * line rather than changing very much about how to communicate with | ||
51 | * the TOIM3232. | ||
52 | * | ||
53 | * The protocol to talk to the TOIM4232 chipset seems to be almost | ||
54 | * identical to the TOIM3232 (and the 4232 datasheet is more detailed) | ||
55 | * so this code will probably work on that as well, although I haven't | ||
56 | * tested it on that hardware. | ||
57 | * | ||
58 | * Target dongle variations that might be common: | ||
59 | * | ||
60 | * DTR and RTS function: | ||
61 | * The data sheet for the 4232 has a sample implementation that hooks the | ||
62 | * DTR and RTS lines to the RESET and BaudRate/~Data lines of the | ||
63 | * chip (through line-converters). Given both DTR and RTS would have to | ||
64 | * be held low in normal operation, and the TOIMx232 requires +5V to | ||
65 | * signal ground, most dongle designers would almost certainly choose | ||
66 | * an implementation that kept at least one of DTR or RTS high in | ||
67 | * normal operation to provide power to the dongle, but will likely | ||
68 | * vary between designs. | ||
69 | * | ||
70 | * User specified command bits: | ||
71 | * There are two user-controllable output lines from the TOIMx232 that | ||
72 | * can be set low or high by setting the appropriate bits in the | ||
73 | * high-nibble of the command byte (when setting speed and pulse length). | ||
74 | * These might be used to switch on and off added hardware or extra | ||
75 | * dongle features. | ||
76 | * | ||
77 | * | ||
78 | * Target hardware: IRWave IR320ST-2 | ||
79 | * | ||
80 | * The IRWave IR320ST-2 is a simple dongle based on the Vishay/Temic | ||
81 | * TOIM3232 SIR Endec and the Vishay/Temic TFDS4500 SIR IRDA transciever. | ||
82 | * It uses a hex inverter and some discrete components to buffer and | ||
83 | * line convert the RS232 down to 5V. | ||
84 | * | ||
85 | * The dongle is powered through a voltage regulator, fed by a large | ||
86 | * capacitor. To switch the dongle on, DTR is brought high to charge | ||
87 | * the capacitor and drive the voltage regulator. DTR isn't associated | ||
88 | * with any control lines on the TOIM3232. Parisitic power is also taken | ||
89 | * from the RTS, TD and RD lines when brought high, but through resistors. | ||
90 | * When DTR is low, the circuit might lose power even with RTS high. | ||
91 | * | ||
92 | * RTS is inverted and attached to the BR/~D input pin. When RTS | ||
93 | * is high, BR/~D is low, and the TOIM3232 is in the normal 'data' mode. | ||
94 | * RTS is brought low, BR/~D is high, and the TOIM3232 is in 'command | ||
95 | * mode'. | ||
96 | * | ||
97 | * For some unknown reason, the RESET line isn't actually connected | ||
98 | * to anything. This means to reset the dongle to get it to a known | ||
99 | * state (9600 baud) you must drop DTR and RTS low, wait for the power | ||
100 | * capacitor to discharge, and then bring DTR (and RTS for data mode) | ||
101 | * high again, and wait for the capacitor to charge, the power supply | ||
102 | * to stabilise, and the oscillator clock to stabilise. | ||
103 | * | ||
104 | * Fortunately, if the current baudrate is known, the chipset can | ||
105 | * easily change speed by entering command mode without having to | ||
106 | * reset the dongle first. | ||
107 | * | ||
108 | * Major Components: | ||
109 | * | ||
110 | * - Vishay/Temic TOIM3232 SIR Endec to change RS232 pulse timings | ||
111 | * to IRDA pulse timings | ||
112 | * - 3.6864MHz crystal to drive TOIM3232 clock oscillator | ||
113 | * - DM74lS04M Inverting Hex line buffer for RS232 input buffering | ||
114 | * and level conversion | ||
115 | * - PJ2951AC 150mA voltage regulator | ||
116 | * - Vishay/Temic TFDS4500 SIR IRDA front-end transceiver | ||
117 | * | ||
118 | */ | ||
119 | |||
120 | #include <linux/module.h> | ||
121 | #include <linux/delay.h> | ||
122 | #include <linux/init.h> | ||
123 | |||
124 | #include <net/irda/irda.h> | ||
125 | |||
126 | #include "sir-dev.h" | ||
127 | |||
128 | static int toim3232delay = 150; /* default is 150 ms */ | ||
129 | module_param(toim3232delay, int, 0); | ||
130 | MODULE_PARM_DESC(toim3232delay, "toim3232 dongle write complete delay"); | ||
131 | |||
132 | #if 0 | ||
133 | static int toim3232flipdtr = 0; /* default is DTR high to reset */ | ||
134 | module_param(toim3232flipdtr, int, 0); | ||
135 | MODULE_PARM_DESC(toim3232flipdtr, "toim3232 dongle invert DTR (Reset)"); | ||
136 | |||
137 | static int toim3232fliprts = 0; /* default is RTS high for baud change */ | ||
138 | module_param(toim3232fliptrs, int, 0); | ||
139 | MODULE_PARM_DESC(toim3232fliprts, "toim3232 dongle invert RTS (BR/D)"); | ||
140 | #endif | ||
141 | |||
142 | static int toim3232_open(struct sir_dev *); | ||
143 | static int toim3232_close(struct sir_dev *); | ||
144 | static int toim3232_change_speed(struct sir_dev *, unsigned); | ||
145 | static int toim3232_reset(struct sir_dev *); | ||
146 | |||
147 | #define TOIM3232_115200 0x00 | ||
148 | #define TOIM3232_57600 0x01 | ||
149 | #define TOIM3232_38400 0x02 | ||
150 | #define TOIM3232_19200 0x03 | ||
151 | #define TOIM3232_9600 0x06 | ||
152 | #define TOIM3232_2400 0x0A | ||
153 | |||
154 | #define TOIM3232_PW 0x10 /* Pulse select bit */ | ||
155 | |||
156 | static struct dongle_driver toim3232 = { | ||
157 | .owner = THIS_MODULE, | ||
158 | .driver_name = "Vishay TOIM3232", | ||
159 | .type = IRDA_TOIM3232_DONGLE, | ||
160 | .open = toim3232_open, | ||
161 | .close = toim3232_close, | ||
162 | .reset = toim3232_reset, | ||
163 | .set_speed = toim3232_change_speed, | ||
164 | }; | ||
165 | |||
166 | static int __init toim3232_sir_init(void) | ||
167 | { | ||
168 | if (toim3232delay < 1 || toim3232delay > 500) | ||
169 | toim3232delay = 200; | ||
170 | IRDA_DEBUG(1, "%s - using %d ms delay\n", | ||
171 | toim3232.driver_name, toim3232delay); | ||
172 | return irda_register_dongle(&toim3232); | ||
173 | } | ||
174 | |||
175 | static void __exit toim3232_sir_cleanup(void) | ||
176 | { | ||
177 | irda_unregister_dongle(&toim3232); | ||
178 | } | ||
179 | |||
180 | static int toim3232_open(struct sir_dev *dev) | ||
181 | { | ||
182 | struct qos_info *qos = &dev->qos; | ||
183 | |||
184 | IRDA_DEBUG(2, "%s()\n", __FUNCTION__); | ||
185 | |||
186 | /* Pull the lines high to start with. | ||
187 | * | ||
188 | * For the IR320ST-2, we need to charge the main supply capacitor to | ||
189 | * switch the device on. We keep DTR high throughout to do this. | ||
190 | * When RTS, TD and RD are high, they will also trickle-charge the | ||
191 | * cap. RTS is high for data transmission, and low for baud rate select. | ||
192 | * -- DGB | ||
193 | */ | ||
194 | sirdev_set_dtr_rts(dev, TRUE, TRUE); | ||
195 | |||
196 | /* The TOI3232 supports many speeds between 1200bps and 115000bps. | ||
197 | * We really only care about those supported by the IRDA spec, but | ||
198 | * 38400 seems to be implemented in many places */ | ||
199 | qos->baud_rate.bits &= IR_2400|IR_9600|IR_19200|IR_38400|IR_57600|IR_115200; | ||
200 | |||
201 | /* From the tekram driver. Not sure what a reasonable value is -- DGB */ | ||
202 | qos->min_turn_time.bits = 0x01; /* Needs at least 10 ms */ | ||
203 | irda_qos_bits_to_value(qos); | ||
204 | |||
205 | /* irda thread waits 50 msec for power settling */ | ||
206 | |||
207 | return 0; | ||
208 | } | ||
209 | |||
210 | static int toim3232_close(struct sir_dev *dev) | ||
211 | { | ||
212 | IRDA_DEBUG(2, "%s()\n", __FUNCTION__); | ||
213 | |||
214 | /* Power off dongle */ | ||
215 | sirdev_set_dtr_rts(dev, FALSE, FALSE); | ||
216 | |||
217 | return 0; | ||
218 | } | ||
219 | |||
220 | /* | ||
221 | * Function toim3232change_speed (dev, state, speed) | ||
222 | * | ||
223 | * Set the speed for the TOIM3232 based dongle. Warning, this | ||
224 | * function must be called with a process context! | ||
225 | * | ||
226 | * Algorithm | ||
227 | * 1. keep DTR high but clear RTS to bring into baud programming mode | ||
228 | * 2. wait at least 7us to enter programming mode | ||
229 | * 3. send control word to set baud rate and timing | ||
230 | * 4. wait at least 1us | ||
231 | * 5. bring RTS high to enter DATA mode (RS232 is passed through to transceiver) | ||
232 | * 6. should take effect immediately (although probably worth waiting) | ||
233 | */ | ||
234 | |||
235 | #define TOIM3232_STATE_WAIT_SPEED (SIRDEV_STATE_DONGLE_SPEED + 1) | ||
236 | |||
237 | static int toim3232_change_speed(struct sir_dev *dev, unsigned speed) | ||
238 | { | ||
239 | unsigned state = dev->fsm.substate; | ||
240 | unsigned delay = 0; | ||
241 | u8 byte; | ||
242 | static int ret = 0; | ||
243 | |||
244 | IRDA_DEBUG(2, "%s()\n", __FUNCTION__); | ||
245 | |||
246 | switch(state) { | ||
247 | case SIRDEV_STATE_DONGLE_SPEED: | ||
248 | |||
249 | /* Figure out what we are going to send as a control byte */ | ||
250 | switch (speed) { | ||
251 | case 2400: | ||
252 | byte = TOIM3232_PW|TOIM3232_2400; | ||
253 | break; | ||
254 | default: | ||
255 | speed = 9600; | ||
256 | ret = -EINVAL; | ||
257 | /* fall thru */ | ||
258 | case 9600: | ||
259 | byte = TOIM3232_PW|TOIM3232_9600; | ||
260 | break; | ||
261 | case 19200: | ||
262 | byte = TOIM3232_PW|TOIM3232_19200; | ||
263 | break; | ||
264 | case 38400: | ||
265 | byte = TOIM3232_PW|TOIM3232_38400; | ||
266 | break; | ||
267 | case 57600: | ||
268 | byte = TOIM3232_PW|TOIM3232_57600; | ||
269 | break; | ||
270 | case 115200: | ||
271 | byte = TOIM3232_115200; | ||
272 | break; | ||
273 | } | ||
274 | |||
275 | /* Set DTR, Clear RTS: Go into baud programming mode */ | ||
276 | sirdev_set_dtr_rts(dev, TRUE, FALSE); | ||
277 | |||
278 | /* Wait at least 7us */ | ||
279 | udelay(14); | ||
280 | |||
281 | /* Write control byte */ | ||
282 | sirdev_raw_write(dev, &byte, 1); | ||
283 | |||
284 | dev->speed = speed; | ||
285 | |||
286 | state = TOIM3232_STATE_WAIT_SPEED; | ||
287 | delay = toim3232delay; | ||
288 | break; | ||
289 | |||
290 | case TOIM3232_STATE_WAIT_SPEED: | ||
291 | /* Have transmitted control byte * Wait for 'at least 1us' */ | ||
292 | udelay(14); | ||
293 | |||
294 | /* Set DTR, Set RTS: Go into normal data mode */ | ||
295 | sirdev_set_dtr_rts(dev, TRUE, TRUE); | ||
296 | |||
297 | /* Wait (TODO: check this is needed) */ | ||
298 | udelay(50); | ||
299 | break; | ||
300 | |||
301 | default: | ||
302 | printk(KERN_ERR "%s - undefined state %d\n", __FUNCTION__, state); | ||
303 | ret = -EINVAL; | ||
304 | break; | ||
305 | } | ||
306 | |||
307 | dev->fsm.substate = state; | ||
308 | return (delay > 0) ? delay : ret; | ||
309 | } | ||
310 | |||
311 | /* | ||
312 | * Function toim3232reset (driver) | ||
313 | * | ||
314 | * This function resets the toim3232 dongle. Warning, this function | ||
315 | * must be called with a process context!! | ||
316 | * | ||
317 | * What we should do is: | ||
318 | * 0. Pull RESET high | ||
319 | * 1. Wait for at least 7us | ||
320 | * 2. Pull RESET low | ||
321 | * 3. Wait for at least 7us | ||
322 | * 4. Pull BR/~D high | ||
323 | * 5. Wait for at least 7us | ||
324 | * 6. Send control byte to set baud rate | ||
325 | * 7. Wait at least 1us after stop bit | ||
326 | * 8. Pull BR/~D low | ||
327 | * 9. Should then be in data mode | ||
328 | * | ||
329 | * Because the IR320ST-2 doesn't have the RESET line connected for some reason, | ||
330 | * we'll have to do something else. | ||
331 | * | ||
332 | * The default speed after a RESET is 9600, so lets try just bringing it up in | ||
333 | * data mode after switching it off, waiting for the supply capacitor to | ||
334 | * discharge, and then switch it back on. This isn't actually pulling RESET | ||
335 | * high, but it seems to have the same effect. | ||
336 | * | ||
337 | * This behaviour will probably work on dongles that have the RESET line connected, | ||
338 | * but if not, add a flag for the IR320ST-2, and implment the above-listed proper | ||
339 | * behaviour. | ||
340 | * | ||
341 | * RTS is inverted and then fed to BR/~D, so to put it in programming mode, we | ||
342 | * need to have pull RTS low | ||
343 | */ | ||
344 | |||
345 | static int toim3232_reset(struct sir_dev *dev) | ||
346 | { | ||
347 | IRDA_DEBUG(2, "%s()\n", __FUNCTION__); | ||
348 | |||
349 | /* Switch off both DTR and RTS to switch off dongle */ | ||
350 | sirdev_set_dtr_rts(dev, FALSE, FALSE); | ||
351 | |||
352 | /* Should sleep a while. This might be evil doing it this way.*/ | ||
353 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
354 | schedule_timeout(msecs_to_jiffies(50)); | ||
355 | |||
356 | /* Set DTR, Set RTS (data mode) */ | ||
357 | sirdev_set_dtr_rts(dev, TRUE, TRUE); | ||
358 | |||
359 | /* Wait at least 10 ms for power to stabilize again */ | ||
360 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
361 | schedule_timeout(msecs_to_jiffies(10)); | ||
362 | |||
363 | /* Speed should now be 9600 */ | ||
364 | dev->speed = 9600; | ||
365 | |||
366 | return 0; | ||
367 | } | ||
368 | |||
369 | MODULE_AUTHOR("David Basden <davidb-linux@rcpt.to>"); | ||
370 | MODULE_DESCRIPTION("Vishay/Temic TOIM3232 based dongle driver"); | ||
371 | MODULE_LICENSE("GPL"); | ||
372 | MODULE_ALIAS("irda-dongle-12"); /* IRDA_TOIM3232_DONGLE */ | ||
373 | |||
374 | module_init(toim3232_sir_init); | ||
375 | module_exit(toim3232_sir_cleanup); | ||
diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c index a9f49f058cfb..97a49e0be76b 100644 --- a/drivers/net/irda/vlsi_ir.c +++ b/drivers/net/irda/vlsi_ir.c | |||
@@ -1887,7 +1887,7 @@ static int __init vlsi_mod_init(void) | |||
1887 | vlsi_proc_root->owner = THIS_MODULE; | 1887 | vlsi_proc_root->owner = THIS_MODULE; |
1888 | } | 1888 | } |
1889 | 1889 | ||
1890 | ret = pci_module_init(&vlsi_irda_driver); | 1890 | ret = pci_register_driver(&vlsi_irda_driver); |
1891 | 1891 | ||
1892 | if (ret && vlsi_proc_root) | 1892 | if (ret && vlsi_proc_root) |
1893 | remove_proc_entry(PROC_DIR, NULL); | 1893 | remove_proc_entry(PROC_DIR, NULL); |