aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/irda
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/irda')
-rw-r--r--drivers/net/irda/Kconfig20
-rw-r--r--drivers/net/irda/Makefile2
-rw-r--r--drivers/net/irda/irda-usb.c8
-rw-r--r--drivers/net/irda/sir-dev.h13
-rw-r--r--drivers/net/irda/sir_dev.c315
-rw-r--r--drivers/net/irda/sir_kthread.c508
-rw-r--r--drivers/net/irda/smsc-ircc2.c330
7 files changed, 606 insertions, 590 deletions
diff --git a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig
index 5e6d00752990..cff8598aa800 100644
--- a/drivers/net/irda/Kconfig
+++ b/drivers/net/irda/Kconfig
@@ -33,7 +33,7 @@ config DONGLE
33 33
34config ESI_DONGLE 34config ESI_DONGLE
35 tristate "ESI JetEye PC dongle" 35 tristate "ESI JetEye PC dongle"
36 depends on DONGLE && IRDA 36 depends on IRTTY_SIR && DONGLE && IRDA
37 help 37 help
38 Say Y here if you want to build support for the Extended Systems 38 Say Y here if you want to build support for the Extended Systems
39 JetEye PC dongle. To compile it as a module, choose M here. The ESI 39 JetEye PC dongle. To compile it as a module, choose M here. The ESI
@@ -44,7 +44,7 @@ config ESI_DONGLE
44 44
45config ACTISYS_DONGLE 45config ACTISYS_DONGLE
46 tristate "ACTiSYS IR-220L and IR220L+ dongle" 46 tristate "ACTiSYS IR-220L and IR220L+ dongle"
47 depends on DONGLE && IRDA 47 depends on IRTTY_SIR && DONGLE && IRDA
48 help 48 help
49 Say Y here if you want to build support for the ACTiSYS IR-220L and 49 Say Y here if you want to build support for the ACTiSYS IR-220L and
50 IR220L+ dongles. To compile it as a module, choose M here. The 50 IR220L+ dongles. To compile it as a module, choose M here. The
@@ -55,7 +55,7 @@ config ACTISYS_DONGLE
55 55
56config TEKRAM_DONGLE 56config TEKRAM_DONGLE
57 tristate "Tekram IrMate 210B dongle" 57 tristate "Tekram IrMate 210B dongle"
58 depends on DONGLE && IRDA 58 depends on IRTTY_SIR && DONGLE && IRDA
59 help 59 help
60 Say Y here if you want to build support for the Tekram IrMate 210B 60 Say Y here if you want to build support for the Tekram IrMate 210B
61 dongle. To compile it as a module, choose M here. The Tekram dongle 61 dongle. To compile it as a module, choose M here. The Tekram dongle
@@ -66,7 +66,7 @@ config TEKRAM_DONGLE
66 66
67config TOIM3232_DONGLE 67config TOIM3232_DONGLE
68 tristate "TOIM3232 IrDa dongle" 68 tristate "TOIM3232 IrDa dongle"
69 depends on DONGLE && IRDA 69 depends on IRTTY_SIR && DONGLE && IRDA
70 help 70 help
71 Say Y here if you want to build support for the Vishay/Temic 71 Say Y here if you want to build support for the Vishay/Temic
72 TOIM3232 and TOIM4232 based dongles. 72 TOIM3232 and TOIM4232 based dongles.
@@ -74,7 +74,7 @@ config TOIM3232_DONGLE
74 74
75config LITELINK_DONGLE 75config LITELINK_DONGLE
76 tristate "Parallax LiteLink dongle" 76 tristate "Parallax LiteLink dongle"
77 depends on DONGLE && IRDA 77 depends on IRTTY_SIR && DONGLE && IRDA
78 help 78 help
79 Say Y here if you want to build support for the Parallax Litelink 79 Say Y here if you want to build support for the Parallax Litelink
80 dongle. To compile it as a module, choose M here. The Parallax 80 dongle. To compile it as a module, choose M here. The Parallax
@@ -85,7 +85,7 @@ config LITELINK_DONGLE
85 85
86config MA600_DONGLE 86config MA600_DONGLE
87 tristate "Mobile Action MA600 dongle" 87 tristate "Mobile Action MA600 dongle"
88 depends on DONGLE && IRDA && EXPERIMENTAL 88 depends on IRTTY_SIR && DONGLE && IRDA && EXPERIMENTAL
89 help 89 help
90 Say Y here if you want to build support for the Mobile Action MA600 90 Say Y here if you want to build support for the Mobile Action MA600
91 dongle. To compile it as a module, choose M here. The MA600 dongle 91 dongle. To compile it as a module, choose M here. The MA600 dongle
@@ -98,7 +98,7 @@ config MA600_DONGLE
98 98
99config GIRBIL_DONGLE 99config GIRBIL_DONGLE
100 tristate "Greenwich GIrBIL dongle" 100 tristate "Greenwich GIrBIL dongle"
101 depends on DONGLE && IRDA && EXPERIMENTAL 101 depends on IRTTY_SIR && DONGLE && IRDA && EXPERIMENTAL
102 help 102 help
103 Say Y here if you want to build support for the Greenwich GIrBIL 103 Say Y here if you want to build support for the Greenwich GIrBIL
104 dongle. If you want to compile it as a module, choose M here. 104 dongle. If you want to compile it as a module, choose M here.
@@ -109,7 +109,7 @@ config GIRBIL_DONGLE
109 109
110config MCP2120_DONGLE 110config MCP2120_DONGLE
111 tristate "Microchip MCP2120" 111 tristate "Microchip MCP2120"
112 depends on DONGLE && IRDA && EXPERIMENTAL 112 depends on IRTTY_SIR && DONGLE && IRDA && EXPERIMENTAL
113 help 113 help
114 Say Y here if you want to build support for the Microchip MCP2120 114 Say Y here if you want to build support for the Microchip MCP2120
115 dongle. If you want to compile it as a module, choose M here. 115 dongle. If you want to compile it as a module, choose M here.
@@ -123,7 +123,7 @@ config MCP2120_DONGLE
123 123
124config OLD_BELKIN_DONGLE 124config OLD_BELKIN_DONGLE
125 tristate "Old Belkin dongle" 125 tristate "Old Belkin dongle"
126 depends on DONGLE && IRDA && EXPERIMENTAL 126 depends on IRTTY_SIR && DONGLE && IRDA && EXPERIMENTAL
127 help 127 help
128 Say Y here if you want to build support for the Adaptec Airport 1000 128 Say Y here if you want to build support for the Adaptec Airport 1000
129 and 2000 dongles. If you want to compile it as a module, choose 129 and 2000 dongles. If you want to compile it as a module, choose
@@ -132,7 +132,7 @@ config OLD_BELKIN_DONGLE
132 132
133config ACT200L_DONGLE 133config ACT200L_DONGLE
134 tristate "ACTiSYS IR-200L dongle" 134 tristate "ACTiSYS IR-200L dongle"
135 depends on DONGLE && IRDA && EXPERIMENTAL 135 depends on IRTTY_SIR && DONGLE && IRDA && EXPERIMENTAL
136 help 136 help
137 Say Y here if you want to build support for the ACTiSYS IR-200L 137 Say Y here if you want to build support for the ACTiSYS IR-200L
138 dongle. If you want to compile it as a module, choose M here. 138 dongle. If you want to compile it as a module, choose M here.
diff --git a/drivers/net/irda/Makefile b/drivers/net/irda/Makefile
index 27ab75f20799..c1ce2398efea 100644
--- a/drivers/net/irda/Makefile
+++ b/drivers/net/irda/Makefile
@@ -46,4 +46,4 @@ obj-$(CONFIG_MA600_DONGLE) += ma600-sir.o
46obj-$(CONFIG_TOIM3232_DONGLE) += toim3232-sir.o 46obj-$(CONFIG_TOIM3232_DONGLE) += toim3232-sir.o
47 47
48# The SIR helper module 48# The SIR helper module
49sir-dev-objs := sir_dev.o sir_dongle.o sir_kthread.o 49sir-dev-objs := sir_dev.o sir_dongle.o
diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
index 606243d11793..cd87593e4e8a 100644
--- a/drivers/net/irda/irda-usb.c
+++ b/drivers/net/irda/irda-usb.c
@@ -1778,7 +1778,7 @@ static int irda_usb_probe(struct usb_interface *intf,
1778 1778
1779 if (self->needspatch) { 1779 if (self->needspatch) {
1780 ret = usb_control_msg (self->usbdev, usb_sndctrlpipe (self->usbdev, 0), 1780 ret = usb_control_msg (self->usbdev, usb_sndctrlpipe (self->usbdev, 0),
1781 0x02, 0x40, 0, 0, 0, 0, msecs_to_jiffies(500)); 1781 0x02, 0x40, 0, 0, NULL, 0, 500);
1782 if (ret < 0) { 1782 if (ret < 0) {
1783 IRDA_DEBUG (0, "usb_control_msg failed %d\n", ret); 1783 IRDA_DEBUG (0, "usb_control_msg failed %d\n", ret);
1784 goto err_out_3; 1784 goto err_out_3;
@@ -1815,14 +1815,14 @@ static int irda_usb_probe(struct usb_interface *intf,
1815 self->needspatch = (ret < 0); 1815 self->needspatch = (ret < 0);
1816 if (ret < 0) { 1816 if (ret < 0) {
1817 printk("patch_device failed\n"); 1817 printk("patch_device failed\n");
1818 goto err_out_4; 1818 goto err_out_5;
1819 } 1819 }
1820 1820
1821 /* replace IrDA class descriptor with what patched device is now reporting */ 1821 /* replace IrDA class descriptor with what patched device is now reporting */
1822 irda_desc = irda_usb_find_class_desc (self->usbintf); 1822 irda_desc = irda_usb_find_class_desc (self->usbintf);
1823 if (irda_desc == NULL) { 1823 if (irda_desc == NULL) {
1824 ret = -ENODEV; 1824 ret = -ENODEV;
1825 goto err_out_4; 1825 goto err_out_5;
1826 } 1826 }
1827 if (self->irda_desc) 1827 if (self->irda_desc)
1828 kfree (self->irda_desc); 1828 kfree (self->irda_desc);
@@ -1832,6 +1832,8 @@ static int irda_usb_probe(struct usb_interface *intf,
1832 1832
1833 return 0; 1833 return 0;
1834 1834
1835err_out_5:
1836 unregister_netdev(self->netdev);
1835err_out_4: 1837err_out_4:
1836 kfree(self->speed_buff); 1838 kfree(self->speed_buff);
1837err_out_3: 1839err_out_3:
diff --git a/drivers/net/irda/sir-dev.h b/drivers/net/irda/sir-dev.h
index f69fb4cec76f..9fa294a546d6 100644
--- a/drivers/net/irda/sir-dev.h
+++ b/drivers/net/irda/sir-dev.h
@@ -15,23 +15,14 @@
15#define IRDA_SIR_H 15#define IRDA_SIR_H
16 16
17#include <linux/netdevice.h> 17#include <linux/netdevice.h>
18#include <linux/workqueue.h>
18 19
19#include <net/irda/irda.h> 20#include <net/irda/irda.h>
20#include <net/irda/irda_device.h> // iobuff_t 21#include <net/irda/irda_device.h> // iobuff_t
21 22
22/* FIXME: unify irda_request with sir_fsm! */
23
24struct irda_request {
25 struct list_head lh_request;
26 unsigned long pending;
27 void (*func)(void *);
28 void *data;
29 struct timer_list timer;
30};
31
32struct sir_fsm { 23struct sir_fsm {
33 struct semaphore sem; 24 struct semaphore sem;
34 struct irda_request rq; 25 struct work_struct work;
35 unsigned state, substate; 26 unsigned state, substate;
36 int param; 27 int param;
37 int result; 28 int result;
diff --git a/drivers/net/irda/sir_dev.c b/drivers/net/irda/sir_dev.c
index ea7c9464d46a..3b5854d10c17 100644
--- a/drivers/net/irda/sir_dev.c
+++ b/drivers/net/irda/sir_dev.c
@@ -23,6 +23,298 @@
23 23
24#include "sir-dev.h" 24#include "sir-dev.h"
25 25
26
27static struct workqueue_struct *irda_sir_wq;
28
29/* STATE MACHINE */
30
31/* substate handler of the config-fsm to handle the cases where we want
32 * to wait for transmit completion before changing the port configuration
33 */
34
35static int sirdev_tx_complete_fsm(struct sir_dev *dev)
36{
37 struct sir_fsm *fsm = &dev->fsm;
38 unsigned next_state, delay;
39 unsigned bytes_left;
40
41 do {
42 next_state = fsm->substate; /* default: stay in current substate */
43 delay = 0;
44
45 switch(fsm->substate) {
46
47 case SIRDEV_STATE_WAIT_XMIT:
48 if (dev->drv->chars_in_buffer)
49 bytes_left = dev->drv->chars_in_buffer(dev);
50 else
51 bytes_left = 0;
52 if (!bytes_left) {
53 next_state = SIRDEV_STATE_WAIT_UNTIL_SENT;
54 break;
55 }
56
57 if (dev->speed > 115200)
58 delay = (bytes_left*8*10000) / (dev->speed/100);
59 else if (dev->speed > 0)
60 delay = (bytes_left*10*10000) / (dev->speed/100);
61 else
62 delay = 0;
63 /* expected delay (usec) until remaining bytes are sent */
64 if (delay < 100) {
65 udelay(delay);
66 delay = 0;
67 break;
68 }
69 /* sleep some longer delay (msec) */
70 delay = (delay+999) / 1000;
71 break;
72
73 case SIRDEV_STATE_WAIT_UNTIL_SENT:
74 /* block until underlaying hardware buffer are empty */
75 if (dev->drv->wait_until_sent)
76 dev->drv->wait_until_sent(dev);
77 next_state = SIRDEV_STATE_TX_DONE;
78 break;
79
80 case SIRDEV_STATE_TX_DONE:
81 return 0;
82
83 default:
84 IRDA_ERROR("%s - undefined state\n", __FUNCTION__);
85 return -EINVAL;
86 }
87 fsm->substate = next_state;
88 } while (delay == 0);
89 return delay;
90}
91
92/*
93 * Function sirdev_config_fsm
94 *
95 * State machine to handle the configuration of the device (and attached dongle, if any).
96 * This handler is scheduled for execution in kIrDAd context, so we can sleep.
97 * however, kIrDAd is shared by all sir_dev devices so we better don't sleep there too
98 * long. Instead, for longer delays we start a timer to reschedule us later.
99 * On entry, fsm->sem is always locked and the netdev xmit queue stopped.
100 * Both must be unlocked/restarted on completion - but only on final exit.
101 */
102
103static void sirdev_config_fsm(void *data)
104{
105 struct sir_dev *dev = data;
106 struct sir_fsm *fsm = &dev->fsm;
107 int next_state;
108 int ret = -1;
109 unsigned delay;
110
111 IRDA_DEBUG(2, "%s(), <%ld>\n", __FUNCTION__, jiffies);
112
113 do {
114 IRDA_DEBUG(3, "%s - state=0x%04x / substate=0x%04x\n",
115 __FUNCTION__, fsm->state, fsm->substate);
116
117 next_state = fsm->state;
118 delay = 0;
119
120 switch(fsm->state) {
121
122 case SIRDEV_STATE_DONGLE_OPEN:
123 if (dev->dongle_drv != NULL) {
124 ret = sirdev_put_dongle(dev);
125 if (ret) {
126 fsm->result = -EINVAL;
127 next_state = SIRDEV_STATE_ERROR;
128 break;
129 }
130 }
131
132 /* Initialize dongle */
133 ret = sirdev_get_dongle(dev, fsm->param);
134 if (ret) {
135 fsm->result = ret;
136 next_state = SIRDEV_STATE_ERROR;
137 break;
138 }
139
140 /* Dongles are powered through the modem control lines which
141 * were just set during open. Before resetting, let's wait for
142 * the power to stabilize. This is what some dongle drivers did
143 * in open before, while others didn't - should be safe anyway.
144 */
145
146 delay = 50;
147 fsm->substate = SIRDEV_STATE_DONGLE_RESET;
148 next_state = SIRDEV_STATE_DONGLE_RESET;
149
150 fsm->param = 9600;
151
152 break;
153
154 case SIRDEV_STATE_DONGLE_CLOSE:
155 /* shouldn't we just treat this as success=? */
156 if (dev->dongle_drv == NULL) {
157 fsm->result = -EINVAL;
158 next_state = SIRDEV_STATE_ERROR;
159 break;
160 }
161
162 ret = sirdev_put_dongle(dev);
163 if (ret) {
164 fsm->result = ret;
165 next_state = SIRDEV_STATE_ERROR;
166 break;
167 }
168 next_state = SIRDEV_STATE_DONE;
169 break;
170
171 case SIRDEV_STATE_SET_DTR_RTS:
172 ret = sirdev_set_dtr_rts(dev,
173 (fsm->param&0x02) ? TRUE : FALSE,
174 (fsm->param&0x01) ? TRUE : FALSE);
175 next_state = SIRDEV_STATE_DONE;
176 break;
177
178 case SIRDEV_STATE_SET_SPEED:
179 fsm->substate = SIRDEV_STATE_WAIT_XMIT;
180 next_state = SIRDEV_STATE_DONGLE_CHECK;
181 break;
182
183 case SIRDEV_STATE_DONGLE_CHECK:
184 ret = sirdev_tx_complete_fsm(dev);
185 if (ret < 0) {
186 fsm->result = ret;
187 next_state = SIRDEV_STATE_ERROR;
188 break;
189 }
190 if ((delay=ret) != 0)
191 break;
192
193 if (dev->dongle_drv) {
194 fsm->substate = SIRDEV_STATE_DONGLE_RESET;
195 next_state = SIRDEV_STATE_DONGLE_RESET;
196 }
197 else {
198 dev->speed = fsm->param;
199 next_state = SIRDEV_STATE_PORT_SPEED;
200 }
201 break;
202
203 case SIRDEV_STATE_DONGLE_RESET:
204 if (dev->dongle_drv->reset) {
205 ret = dev->dongle_drv->reset(dev);
206 if (ret < 0) {
207 fsm->result = ret;
208 next_state = SIRDEV_STATE_ERROR;
209 break;
210 }
211 }
212 else
213 ret = 0;
214 if ((delay=ret) == 0) {
215 /* set serial port according to dongle default speed */
216 if (dev->drv->set_speed)
217 dev->drv->set_speed(dev, dev->speed);
218 fsm->substate = SIRDEV_STATE_DONGLE_SPEED;
219 next_state = SIRDEV_STATE_DONGLE_SPEED;
220 }
221 break;
222
223 case SIRDEV_STATE_DONGLE_SPEED:
224 if (dev->dongle_drv->reset) {
225 ret = dev->dongle_drv->set_speed(dev, fsm->param);
226 if (ret < 0) {
227 fsm->result = ret;
228 next_state = SIRDEV_STATE_ERROR;
229 break;
230 }
231 }
232 else
233 ret = 0;
234 if ((delay=ret) == 0)
235 next_state = SIRDEV_STATE_PORT_SPEED;
236 break;
237
238 case SIRDEV_STATE_PORT_SPEED:
239 /* Finally we are ready to change the serial port speed */
240 if (dev->drv->set_speed)
241 dev->drv->set_speed(dev, dev->speed);
242 dev->new_speed = 0;
243 next_state = SIRDEV_STATE_DONE;
244 break;
245
246 case SIRDEV_STATE_DONE:
247 /* Signal network layer so it can send more frames */
248 netif_wake_queue(dev->netdev);
249 next_state = SIRDEV_STATE_COMPLETE;
250 break;
251
252 default:
253 IRDA_ERROR("%s - undefined state\n", __FUNCTION__);
254 fsm->result = -EINVAL;
255 /* fall thru */
256
257 case SIRDEV_STATE_ERROR:
258 IRDA_ERROR("%s - error: %d\n", __FUNCTION__, fsm->result);
259
260#if 0 /* don't enable this before we have netdev->tx_timeout to recover */
261 netif_stop_queue(dev->netdev);
262#else
263 netif_wake_queue(dev->netdev);
264#endif
265 /* fall thru */
266
267 case SIRDEV_STATE_COMPLETE:
268 /* config change finished, so we are not busy any longer */
269 sirdev_enable_rx(dev);
270 up(&fsm->sem);
271 return;
272 }
273 fsm->state = next_state;
274 } while(!delay);
275
276 queue_delayed_work(irda_sir_wq, &fsm->work, msecs_to_jiffies(delay));
277}
278
279/* schedule some device configuration task for execution by kIrDAd
280 * on behalf of the above state machine.
281 * can be called from process or interrupt/tasklet context.
282 */
283
284int sirdev_schedule_request(struct sir_dev *dev, int initial_state, unsigned param)
285{
286 struct sir_fsm *fsm = &dev->fsm;
287
288 IRDA_DEBUG(2, "%s - state=0x%04x / param=%u\n", __FUNCTION__, initial_state, param);
289
290 if (down_trylock(&fsm->sem)) {
291 if (in_interrupt() || in_atomic() || irqs_disabled()) {
292 IRDA_DEBUG(1, "%s(), state machine busy!\n", __FUNCTION__);
293 return -EWOULDBLOCK;
294 } else
295 down(&fsm->sem);
296 }
297
298 if (fsm->state == SIRDEV_STATE_DEAD) {
299 /* race with sirdev_close should never happen */
300 IRDA_ERROR("%s(), instance staled!\n", __FUNCTION__);
301 up(&fsm->sem);
302 return -ESTALE; /* or better EPIPE? */
303 }
304
305 netif_stop_queue(dev->netdev);
306 atomic_set(&dev->enable_rx, 0);
307
308 fsm->state = initial_state;
309 fsm->param = param;
310 fsm->result = 0;
311
312 INIT_WORK(&fsm->work, sirdev_config_fsm, dev);
313 queue_work(irda_sir_wq, &fsm->work);
314 return 0;
315}
316
317
26/***************************************************************************/ 318/***************************************************************************/
27 319
28void sirdev_enable_rx(struct sir_dev *dev) 320void sirdev_enable_rx(struct sir_dev *dev)
@@ -619,10 +911,6 @@ struct sir_dev * sirdev_get_instance(const struct sir_driver *drv, const char *n
619 spin_lock_init(&dev->tx_lock); 911 spin_lock_init(&dev->tx_lock);
620 init_MUTEX(&dev->fsm.sem); 912 init_MUTEX(&dev->fsm.sem);
621 913
622 INIT_LIST_HEAD(&dev->fsm.rq.lh_request);
623 dev->fsm.rq.pending = 0;
624 init_timer(&dev->fsm.rq.timer);
625
626 dev->drv = drv; 914 dev->drv = drv;
627 dev->netdev = ndev; 915 dev->netdev = ndev;
628 916
@@ -682,3 +970,22 @@ int sirdev_put_instance(struct sir_dev *dev)
682} 970}
683EXPORT_SYMBOL(sirdev_put_instance); 971EXPORT_SYMBOL(sirdev_put_instance);
684 972
973static int __init sir_wq_init(void)
974{
975 irda_sir_wq = create_singlethread_workqueue("irda_sir_wq");
976 if (!irda_sir_wq)
977 return -ENOMEM;
978 return 0;
979}
980
981static void __exit sir_wq_exit(void)
982{
983 destroy_workqueue(irda_sir_wq);
984}
985
986module_init(sir_wq_init);
987module_exit(sir_wq_exit);
988
989MODULE_AUTHOR("Martin Diehl <info@mdiehl.de>");
990MODULE_DESCRIPTION("IrDA SIR core");
991MODULE_LICENSE("GPL");
diff --git a/drivers/net/irda/sir_kthread.c b/drivers/net/irda/sir_kthread.c
deleted file mode 100644
index e3904d6bfecd..000000000000
--- a/drivers/net/irda/sir_kthread.c
+++ /dev/null
@@ -1,508 +0,0 @@
1/*********************************************************************
2 *
3 * sir_kthread.c: dedicated thread to process scheduled
4 * sir device setup requests
5 *
6 * Copyright (c) 2002 Martin Diehl
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
12 *
13 ********************************************************************/
14
15#include <linux/module.h>
16#include <linux/kernel.h>
17#include <linux/version.h>
18#include <linux/init.h>
19#include <linux/smp_lock.h>
20#include <linux/completion.h>
21#include <linux/delay.h>
22
23#include <net/irda/irda.h>
24
25#include "sir-dev.h"
26
27/**************************************************************************
28 *
29 * kIrDAd kernel thread and config state machine
30 *
31 */
32
33struct irda_request_queue {
34 struct list_head request_list;
35 spinlock_t lock;
36 task_t *thread;
37 struct completion exit;
38 wait_queue_head_t kick, done;
39 atomic_t num_pending;
40};
41
42static struct irda_request_queue irda_rq_queue;
43
44static int irda_queue_request(struct irda_request *rq)
45{
46 int ret = 0;
47 unsigned long flags;
48
49 if (!test_and_set_bit(0, &rq->pending)) {
50 spin_lock_irqsave(&irda_rq_queue.lock, flags);
51 list_add_tail(&rq->lh_request, &irda_rq_queue.request_list);
52 wake_up(&irda_rq_queue.kick);
53 atomic_inc(&irda_rq_queue.num_pending);
54 spin_unlock_irqrestore(&irda_rq_queue.lock, flags);
55 ret = 1;
56 }
57 return ret;
58}
59
60static void irda_request_timer(unsigned long data)
61{
62 struct irda_request *rq = (struct irda_request *)data;
63 unsigned long flags;
64
65 spin_lock_irqsave(&irda_rq_queue.lock, flags);
66 list_add_tail(&rq->lh_request, &irda_rq_queue.request_list);
67 wake_up(&irda_rq_queue.kick);
68 spin_unlock_irqrestore(&irda_rq_queue.lock, flags);
69}
70
71static int irda_queue_delayed_request(struct irda_request *rq, unsigned long delay)
72{
73 int ret = 0;
74 struct timer_list *timer = &rq->timer;
75
76 if (!test_and_set_bit(0, &rq->pending)) {
77 timer->expires = jiffies + delay;
78 timer->function = irda_request_timer;
79 timer->data = (unsigned long)rq;
80 atomic_inc(&irda_rq_queue.num_pending);
81 add_timer(timer);
82 ret = 1;
83 }
84 return ret;
85}
86
87static void run_irda_queue(void)
88{
89 unsigned long flags;
90 struct list_head *entry, *tmp;
91 struct irda_request *rq;
92
93 spin_lock_irqsave(&irda_rq_queue.lock, flags);
94 list_for_each_safe(entry, tmp, &irda_rq_queue.request_list) {
95 rq = list_entry(entry, struct irda_request, lh_request);
96 list_del_init(entry);
97 spin_unlock_irqrestore(&irda_rq_queue.lock, flags);
98
99 clear_bit(0, &rq->pending);
100 rq->func(rq->data);
101
102 if (atomic_dec_and_test(&irda_rq_queue.num_pending))
103 wake_up(&irda_rq_queue.done);
104
105 spin_lock_irqsave(&irda_rq_queue.lock, flags);
106 }
107 spin_unlock_irqrestore(&irda_rq_queue.lock, flags);
108}
109
110static int irda_thread(void *startup)
111{
112 DECLARE_WAITQUEUE(wait, current);
113
114 daemonize("kIrDAd");
115
116 irda_rq_queue.thread = current;
117
118 complete((struct completion *)startup);
119
120 while (irda_rq_queue.thread != NULL) {
121
122 /* We use TASK_INTERRUPTIBLE, rather than
123 * TASK_UNINTERRUPTIBLE. Andrew Morton made this
124 * change ; he told me that it is safe, because "signal
125 * blocking is now handled in daemonize()", he added
126 * that the problem is that "uninterruptible sleep
127 * contributes to load average", making user worry.
128 * Jean II */
129 set_task_state(current, TASK_INTERRUPTIBLE);
130 add_wait_queue(&irda_rq_queue.kick, &wait);
131 if (list_empty(&irda_rq_queue.request_list))
132 schedule();
133 else
134 __set_task_state(current, TASK_RUNNING);
135 remove_wait_queue(&irda_rq_queue.kick, &wait);
136
137 /* make swsusp happy with our thread */
138 try_to_freeze();
139
140 run_irda_queue();
141 }
142
143#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,35)
144 reparent_to_init();
145#endif
146 complete_and_exit(&irda_rq_queue.exit, 0);
147 /* never reached */
148 return 0;
149}
150
151
152static void flush_irda_queue(void)
153{
154 if (atomic_read(&irda_rq_queue.num_pending)) {
155
156 DECLARE_WAITQUEUE(wait, current);
157
158 if (!list_empty(&irda_rq_queue.request_list))
159 run_irda_queue();
160
161 set_task_state(current, TASK_UNINTERRUPTIBLE);
162 add_wait_queue(&irda_rq_queue.done, &wait);
163 if (atomic_read(&irda_rq_queue.num_pending))
164 schedule();
165 else
166 __set_task_state(current, TASK_RUNNING);
167 remove_wait_queue(&irda_rq_queue.done, &wait);
168 }
169}
170
171/* substate handler of the config-fsm to handle the cases where we want
172 * to wait for transmit completion before changing the port configuration
173 */
174
175static int irda_tx_complete_fsm(struct sir_dev *dev)
176{
177 struct sir_fsm *fsm = &dev->fsm;
178 unsigned next_state, delay;
179 unsigned bytes_left;
180
181 do {
182 next_state = fsm->substate; /* default: stay in current substate */
183 delay = 0;
184
185 switch(fsm->substate) {
186
187 case SIRDEV_STATE_WAIT_XMIT:
188 if (dev->drv->chars_in_buffer)
189 bytes_left = dev->drv->chars_in_buffer(dev);
190 else
191 bytes_left = 0;
192 if (!bytes_left) {
193 next_state = SIRDEV_STATE_WAIT_UNTIL_SENT;
194 break;
195 }
196
197 if (dev->speed > 115200)
198 delay = (bytes_left*8*10000) / (dev->speed/100);
199 else if (dev->speed > 0)
200 delay = (bytes_left*10*10000) / (dev->speed/100);
201 else
202 delay = 0;
203 /* expected delay (usec) until remaining bytes are sent */
204 if (delay < 100) {
205 udelay(delay);
206 delay = 0;
207 break;
208 }
209 /* sleep some longer delay (msec) */
210 delay = (delay+999) / 1000;
211 break;
212
213 case SIRDEV_STATE_WAIT_UNTIL_SENT:
214 /* block until underlaying hardware buffer are empty */
215 if (dev->drv->wait_until_sent)
216 dev->drv->wait_until_sent(dev);
217 next_state = SIRDEV_STATE_TX_DONE;
218 break;
219
220 case SIRDEV_STATE_TX_DONE:
221 return 0;
222
223 default:
224 IRDA_ERROR("%s - undefined state\n", __FUNCTION__);
225 return -EINVAL;
226 }
227 fsm->substate = next_state;
228 } while (delay == 0);
229 return delay;
230}
231
232/*
233 * Function irda_config_fsm
234 *
235 * State machine to handle the configuration of the device (and attached dongle, if any).
236 * This handler is scheduled for execution in kIrDAd context, so we can sleep.
237 * however, kIrDAd is shared by all sir_dev devices so we better don't sleep there too
238 * long. Instead, for longer delays we start a timer to reschedule us later.
239 * On entry, fsm->sem is always locked and the netdev xmit queue stopped.
240 * Both must be unlocked/restarted on completion - but only on final exit.
241 */
242
243static void irda_config_fsm(void *data)
244{
245 struct sir_dev *dev = data;
246 struct sir_fsm *fsm = &dev->fsm;
247 int next_state;
248 int ret = -1;
249 unsigned delay;
250
251 IRDA_DEBUG(2, "%s(), <%ld>\n", __FUNCTION__, jiffies);
252
253 do {
254 IRDA_DEBUG(3, "%s - state=0x%04x / substate=0x%04x\n",
255 __FUNCTION__, fsm->state, fsm->substate);
256
257 next_state = fsm->state;
258 delay = 0;
259
260 switch(fsm->state) {
261
262 case SIRDEV_STATE_DONGLE_OPEN:
263 if (dev->dongle_drv != NULL) {
264 ret = sirdev_put_dongle(dev);
265 if (ret) {
266 fsm->result = -EINVAL;
267 next_state = SIRDEV_STATE_ERROR;
268 break;
269 }
270 }
271
272 /* Initialize dongle */
273 ret = sirdev_get_dongle(dev, fsm->param);
274 if (ret) {
275 fsm->result = ret;
276 next_state = SIRDEV_STATE_ERROR;
277 break;
278 }
279
280 /* Dongles are powered through the modem control lines which
281 * were just set during open. Before resetting, let's wait for
282 * the power to stabilize. This is what some dongle drivers did
283 * in open before, while others didn't - should be safe anyway.
284 */
285
286 delay = 50;
287 fsm->substate = SIRDEV_STATE_DONGLE_RESET;
288 next_state = SIRDEV_STATE_DONGLE_RESET;
289
290 fsm->param = 9600;
291
292 break;
293
294 case SIRDEV_STATE_DONGLE_CLOSE:
295 /* shouldn't we just treat this as success=? */
296 if (dev->dongle_drv == NULL) {
297 fsm->result = -EINVAL;
298 next_state = SIRDEV_STATE_ERROR;
299 break;
300 }
301
302 ret = sirdev_put_dongle(dev);
303 if (ret) {
304 fsm->result = ret;
305 next_state = SIRDEV_STATE_ERROR;
306 break;
307 }
308 next_state = SIRDEV_STATE_DONE;
309 break;
310
311 case SIRDEV_STATE_SET_DTR_RTS:
312 ret = sirdev_set_dtr_rts(dev,
313 (fsm->param&0x02) ? TRUE : FALSE,
314 (fsm->param&0x01) ? TRUE : FALSE);
315 next_state = SIRDEV_STATE_DONE;
316 break;
317
318 case SIRDEV_STATE_SET_SPEED:
319 fsm->substate = SIRDEV_STATE_WAIT_XMIT;
320 next_state = SIRDEV_STATE_DONGLE_CHECK;
321 break;
322
323 case SIRDEV_STATE_DONGLE_CHECK:
324 ret = irda_tx_complete_fsm(dev);
325 if (ret < 0) {
326 fsm->result = ret;
327 next_state = SIRDEV_STATE_ERROR;
328 break;
329 }
330 if ((delay=ret) != 0)
331 break;
332
333 if (dev->dongle_drv) {
334 fsm->substate = SIRDEV_STATE_DONGLE_RESET;
335 next_state = SIRDEV_STATE_DONGLE_RESET;
336 }
337 else {
338 dev->speed = fsm->param;
339 next_state = SIRDEV_STATE_PORT_SPEED;
340 }
341 break;
342
343 case SIRDEV_STATE_DONGLE_RESET:
344 if (dev->dongle_drv->reset) {
345 ret = dev->dongle_drv->reset(dev);
346 if (ret < 0) {
347 fsm->result = ret;
348 next_state = SIRDEV_STATE_ERROR;
349 break;
350 }
351 }
352 else
353 ret = 0;
354 if ((delay=ret) == 0) {
355 /* set serial port according to dongle default speed */
356 if (dev->drv->set_speed)
357 dev->drv->set_speed(dev, dev->speed);
358 fsm->substate = SIRDEV_STATE_DONGLE_SPEED;
359 next_state = SIRDEV_STATE_DONGLE_SPEED;
360 }
361 break;
362
363 case SIRDEV_STATE_DONGLE_SPEED:
364 if (dev->dongle_drv->reset) {
365 ret = dev->dongle_drv->set_speed(dev, fsm->param);
366 if (ret < 0) {
367 fsm->result = ret;
368 next_state = SIRDEV_STATE_ERROR;
369 break;
370 }
371 }
372 else
373 ret = 0;
374 if ((delay=ret) == 0)
375 next_state = SIRDEV_STATE_PORT_SPEED;
376 break;
377
378 case SIRDEV_STATE_PORT_SPEED:
379 /* Finally we are ready to change the serial port speed */
380 if (dev->drv->set_speed)
381 dev->drv->set_speed(dev, dev->speed);
382 dev->new_speed = 0;
383 next_state = SIRDEV_STATE_DONE;
384 break;
385
386 case SIRDEV_STATE_DONE:
387 /* Signal network layer so it can send more frames */
388 netif_wake_queue(dev->netdev);
389 next_state = SIRDEV_STATE_COMPLETE;
390 break;
391
392 default:
393 IRDA_ERROR("%s - undefined state\n", __FUNCTION__);
394 fsm->result = -EINVAL;
395 /* fall thru */
396
397 case SIRDEV_STATE_ERROR:
398 IRDA_ERROR("%s - error: %d\n", __FUNCTION__, fsm->result);
399
400#if 0 /* don't enable this before we have netdev->tx_timeout to recover */
401 netif_stop_queue(dev->netdev);
402#else
403 netif_wake_queue(dev->netdev);
404#endif
405 /* fall thru */
406
407 case SIRDEV_STATE_COMPLETE:
408 /* config change finished, so we are not busy any longer */
409 sirdev_enable_rx(dev);
410 up(&fsm->sem);
411 return;
412 }
413 fsm->state = next_state;
414 } while(!delay);
415
416 irda_queue_delayed_request(&fsm->rq, msecs_to_jiffies(delay));
417}
418
419/* schedule some device configuration task for execution by kIrDAd
420 * on behalf of the above state machine.
421 * can be called from process or interrupt/tasklet context.
422 */
423
424int sirdev_schedule_request(struct sir_dev *dev, int initial_state, unsigned param)
425{
426 struct sir_fsm *fsm = &dev->fsm;
427 int xmit_was_down;
428
429 IRDA_DEBUG(2, "%s - state=0x%04x / param=%u\n", __FUNCTION__, initial_state, param);
430
431 if (down_trylock(&fsm->sem)) {
432 if (in_interrupt() || in_atomic() || irqs_disabled()) {
433 IRDA_DEBUG(1, "%s(), state machine busy!\n", __FUNCTION__);
434 return -EWOULDBLOCK;
435 } else
436 down(&fsm->sem);
437 }
438
439 if (fsm->state == SIRDEV_STATE_DEAD) {
440 /* race with sirdev_close should never happen */
441 IRDA_ERROR("%s(), instance staled!\n", __FUNCTION__);
442 up(&fsm->sem);
443 return -ESTALE; /* or better EPIPE? */
444 }
445
446 xmit_was_down = netif_queue_stopped(dev->netdev);
447 netif_stop_queue(dev->netdev);
448 atomic_set(&dev->enable_rx, 0);
449
450 fsm->state = initial_state;
451 fsm->param = param;
452 fsm->result = 0;
453
454 INIT_LIST_HEAD(&fsm->rq.lh_request);
455 fsm->rq.pending = 0;
456 fsm->rq.func = irda_config_fsm;
457 fsm->rq.data = dev;
458
459 if (!irda_queue_request(&fsm->rq)) { /* returns 0 on error! */
460 atomic_set(&dev->enable_rx, 1);
461 if (!xmit_was_down)
462 netif_wake_queue(dev->netdev);
463 up(&fsm->sem);
464 return -EAGAIN;
465 }
466 return 0;
467}
468
469static int __init irda_thread_create(void)
470{
471 struct completion startup;
472 int pid;
473
474 spin_lock_init(&irda_rq_queue.lock);
475 irda_rq_queue.thread = NULL;
476 INIT_LIST_HEAD(&irda_rq_queue.request_list);
477 init_waitqueue_head(&irda_rq_queue.kick);
478 init_waitqueue_head(&irda_rq_queue.done);
479 atomic_set(&irda_rq_queue.num_pending, 0);
480
481 init_completion(&startup);
482 pid = kernel_thread(irda_thread, &startup, CLONE_FS|CLONE_FILES);
483 if (pid <= 0)
484 return -EAGAIN;
485 else
486 wait_for_completion(&startup);
487
488 return 0;
489}
490
491static void __exit irda_thread_join(void)
492{
493 if (irda_rq_queue.thread) {
494 flush_irda_queue();
495 init_completion(&irda_rq_queue.exit);
496 irda_rq_queue.thread = NULL;
497 wake_up(&irda_rq_queue.kick);
498 wait_for_completion(&irda_rq_queue.exit);
499 }
500}
501
502module_init(irda_thread_create);
503module_exit(irda_thread_join);
504
505MODULE_AUTHOR("Martin Diehl <info@mdiehl.de>");
506MODULE_DESCRIPTION("IrDA SIR core");
507MODULE_LICENSE("GPL");
508
diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c
index bbcfc8ec35a1..a4674044bd6f 100644
--- a/drivers/net/irda/smsc-ircc2.c
+++ b/drivers/net/irda/smsc-ircc2.c
@@ -54,6 +54,7 @@
54#include <linux/rtnetlink.h> 54#include <linux/rtnetlink.h>
55#include <linux/serial_reg.h> 55#include <linux/serial_reg.h>
56#include <linux/dma-mapping.h> 56#include <linux/dma-mapping.h>
57#include <linux/pnp.h>
57#include <linux/platform_device.h> 58#include <linux/platform_device.h>
58 59
59#include <asm/io.h> 60#include <asm/io.h>
@@ -225,6 +226,8 @@ static int __init smsc_superio_lpc(unsigned short cfg_base);
225#ifdef CONFIG_PCI 226#ifdef CONFIG_PCI
226static int __init preconfigure_smsc_chip(struct smsc_ircc_subsystem_configuration *conf); 227static int __init preconfigure_smsc_chip(struct smsc_ircc_subsystem_configuration *conf);
227static int __init preconfigure_through_82801(struct pci_dev *dev, struct smsc_ircc_subsystem_configuration *conf); 228static int __init preconfigure_through_82801(struct pci_dev *dev, struct smsc_ircc_subsystem_configuration *conf);
229static void __init preconfigure_ali_port(struct pci_dev *dev,
230 unsigned short port);
228static int __init preconfigure_through_ali(struct pci_dev *dev, struct smsc_ircc_subsystem_configuration *conf); 231static int __init preconfigure_through_ali(struct pci_dev *dev, struct smsc_ircc_subsystem_configuration *conf);
229static int __init smsc_ircc_preconfigure_subsystems(unsigned short ircc_cfg, 232static int __init smsc_ircc_preconfigure_subsystems(unsigned short ircc_cfg,
230 unsigned short ircc_fir, 233 unsigned short ircc_fir,
@@ -356,6 +359,16 @@ static inline void register_bank(int iobase, int bank)
356 iobase + IRCC_MASTER); 359 iobase + IRCC_MASTER);
357} 360}
358 361
362#ifdef CONFIG_PNP
363/* PNP hotplug support */
364static const struct pnp_device_id smsc_ircc_pnp_table[] = {
365 { .id = "SMCf010", .driver_data = 0 },
366 /* and presumably others */
367 { }
368};
369MODULE_DEVICE_TABLE(pnp, smsc_ircc_pnp_table);
370#endif
371
359 372
360/******************************************************************************* 373/*******************************************************************************
361 * 374 *
@@ -2070,7 +2083,8 @@ static void smsc_ircc_sir_wait_hw_transmitter_finish(struct smsc_ircc_cb *self)
2070 2083
2071/* PROBING 2084/* PROBING
2072 * 2085 *
2073 * 2086 * REVISIT we can be told about the device by PNP, and should use that info
2087 * instead of probing hardware and creating a platform_device ...
2074 */ 2088 */
2075 2089
2076static int __init smsc_ircc_look_for_chips(void) 2090static int __init smsc_ircc_look_for_chips(void)
@@ -2327,9 +2341,14 @@ static int __init smsc_superio_lpc(unsigned short cfg_base)
2327 * pre-configuration not properly done by the BIOS (especially laptops) 2341 * pre-configuration not properly done by the BIOS (especially laptops)
2328 * This code is based in part on smcinit.c, tosh1800-smcinit.c 2342 * This code is based in part on smcinit.c, tosh1800-smcinit.c
2329 * and tosh2450-smcinit.c. The table lists the device entries 2343 * and tosh2450-smcinit.c. The table lists the device entries
2330 * for ISA bridges with an LPC (Local Peripheral Configurator) 2344 * for ISA bridges with an LPC (Low Pin Count) controller which
2331 * that are in turn used to configure the SMSC device with default 2345 * handles the communication with the SMSC device. After the LPC
2332 * SIR and FIR I/O ports, DMA and IRQ. 2346 * controller is initialized through PCI, the SMSC device is initialized
2347 * through a dedicated port in the ISA port-mapped I/O area, this latter
2348 * area is used to configure the SMSC device with default
2349 * SIR and FIR I/O ports, DMA and IRQ. Different vendors have
2350 * used different sets of parameters and different control port
2351 * addresses making a subsystem device table necessary.
2333 */ 2352 */
2334#ifdef CONFIG_PCI 2353#ifdef CONFIG_PCI
2335#define PCIID_VENDOR_INTEL 0x8086 2354#define PCIID_VENDOR_INTEL 0x8086
@@ -2340,9 +2359,10 @@ static struct smsc_ircc_subsystem_configuration subsystem_configurations[] __dev
2340 .device = 0x24cc, 2359 .device = 0x24cc,
2341 .subvendor = 0x103c, 2360 .subvendor = 0x103c,
2342 .subdevice = 0x088c, 2361 .subdevice = 0x088c,
2343 .sir_io = 0x02f8, /* Quite certain these are the same for nc8000 as for nc6000 */ 2362 /* Quite certain these are the same for nc8000 as for nc6000 */
2363 .sir_io = 0x02f8,
2344 .fir_io = 0x0130, 2364 .fir_io = 0x0130,
2345 .fir_irq = 0x09, 2365 .fir_irq = 0x05,
2346 .fir_dma = 0x03, 2366 .fir_dma = 0x03,
2347 .cfg_base = 0x004e, 2367 .cfg_base = 0x004e,
2348 .preconfigure = preconfigure_through_82801, 2368 .preconfigure = preconfigure_through_82801,
@@ -2355,60 +2375,79 @@ static struct smsc_ircc_subsystem_configuration subsystem_configurations[] __dev
2355 .subdevice = 0x0890, 2375 .subdevice = 0x0890,
2356 .sir_io = 0x02f8, 2376 .sir_io = 0x02f8,
2357 .fir_io = 0x0130, 2377 .fir_io = 0x0130,
2358 .fir_irq = 0x09, 2378 .fir_irq = 0x05,
2359 .fir_dma = 0x03, 2379 .fir_dma = 0x03,
2360 .cfg_base = 0x004e, 2380 .cfg_base = 0x004e,
2361 .preconfigure = preconfigure_through_82801, 2381 .preconfigure = preconfigure_through_82801,
2362 .name = "HP nc6000", 2382 .name = "HP nc6000",
2363 }, 2383 },
2364 { 2384 {
2365 .vendor = PCIID_VENDOR_INTEL, /* Intel 82801DB/DBL (ICH4/ICH4-L) LPC Interface Bridge */ 2385 /* Intel 82801DB/DBL (ICH4/ICH4-L) LPC Interface Bridge */
2386 .vendor = PCIID_VENDOR_INTEL,
2366 .device = 0x24c0, 2387 .device = 0x24c0,
2367 .subvendor = 0x1179, 2388 .subvendor = 0x1179,
2368 .subdevice = 0xffff, /* 0xffff is "any", Not sure, 0x0001 or 0x0002 */ 2389 .subdevice = 0xffff, /* 0xffff is "any" */
2369 .sir_io = 0x03f8, 2390 .sir_io = 0x03f8,
2370 .fir_io = 0x0130, 2391 .fir_io = 0x0130,
2371 .fir_irq = 0x07, 2392 .fir_irq = 0x07,
2372 .fir_dma = 0x01, 2393 .fir_dma = 0x01,
2373 .cfg_base = 0x002e, 2394 .cfg_base = 0x002e,
2374 .preconfigure = preconfigure_through_82801, 2395 .preconfigure = preconfigure_through_82801,
2375 .name = "Toshiba Satellite 2450", 2396 .name = "Toshiba laptop with Intel 82801DB/DBL LPC bridge",
2376 }, 2397 },
2377 { 2398 {
2378 .vendor = PCIID_VENDOR_INTEL, /* Intel 82801CAM ISA bridge */ 2399 .vendor = PCIID_VENDOR_INTEL, /* Intel 82801CAM ISA bridge */
2379 .device = 0x248c, /* Some use 24cc? */ 2400 .device = 0x248c,
2401 .subvendor = 0x1179,
2402 .subdevice = 0xffff, /* 0xffff is "any" */
2403 .sir_io = 0x03f8,
2404 .fir_io = 0x0130,
2405 .fir_irq = 0x03,
2406 .fir_dma = 0x03,
2407 .cfg_base = 0x002e,
2408 .preconfigure = preconfigure_through_82801,
2409 .name = "Toshiba laptop with Intel 82801CAM ISA bridge",
2410 },
2411 {
2412 /* 82801DBM (ICH4-M) LPC Interface Bridge */
2413 .vendor = PCIID_VENDOR_INTEL,
2414 .device = 0x24cc,
2380 .subvendor = 0x1179, 2415 .subvendor = 0x1179,
2381 .subdevice = 0xffff, /* 0xffff is "any", Not sure, 0x0001 or 0x0002 */ 2416 .subdevice = 0xffff, /* 0xffff is "any" */
2382 .sir_io = 0x03f8, 2417 .sir_io = 0x03f8,
2383 .fir_io = 0x0130, 2418 .fir_io = 0x0130,
2384 .fir_irq = 0x03, 2419 .fir_irq = 0x03,
2385 .fir_dma = 0x03, 2420 .fir_dma = 0x03,
2386 .cfg_base = 0x002e, 2421 .cfg_base = 0x002e,
2387 .preconfigure = preconfigure_through_82801, 2422 .preconfigure = preconfigure_through_82801,
2388 .name = "Toshiba Satellite 5100/5200, Tecra 9100", 2423 .name = "Toshiba laptop with Intel 8281DBM LPC bridge",
2389 }, 2424 },
2390 { 2425 {
2391 .vendor = PCIID_VENDOR_ALI, /* ALi M1533/M1535 PCI to ISA Bridge [Aladdin IV/V/V+] */ 2426 /* ALi M1533/M1535 PCI to ISA Bridge [Aladdin IV/V/V+] */
2427 .vendor = PCIID_VENDOR_ALI,
2392 .device = 0x1533, 2428 .device = 0x1533,
2393 .subvendor = 0x1179, 2429 .subvendor = 0x1179,
2394 .subdevice = 0xffff, /* 0xffff is "any", Not sure, 0x0001 or 0x0002 */ 2430 .subdevice = 0xffff, /* 0xffff is "any" */
2395 .sir_io = 0x02e8, 2431 .sir_io = 0x02e8,
2396 .fir_io = 0x02f8, 2432 .fir_io = 0x02f8,
2397 .fir_irq = 0x07, 2433 .fir_irq = 0x07,
2398 .fir_dma = 0x03, 2434 .fir_dma = 0x03,
2399 .cfg_base = 0x002e, 2435 .cfg_base = 0x002e,
2400 .preconfigure = preconfigure_through_ali, 2436 .preconfigure = preconfigure_through_ali,
2401 .name = "Toshiba Satellite 1800", 2437 .name = "Toshiba laptop with ALi ISA bridge",
2402 }, 2438 },
2403 { } // Terminator 2439 { } // Terminator
2404}; 2440};
2405 2441
2406 2442
2407/* 2443/*
2408 * This sets up the basic SMSC parameters (FIR port, SIR port, FIR DMA, FIR IRQ) 2444 * This sets up the basic SMSC parameters
2445 * (FIR port, SIR port, FIR DMA, FIR IRQ)
2409 * through the chip configuration port. 2446 * through the chip configuration port.
2410 */ 2447 */
2411static int __init preconfigure_smsc_chip(struct smsc_ircc_subsystem_configuration *conf) 2448static int __init preconfigure_smsc_chip(struct
2449 smsc_ircc_subsystem_configuration
2450 *conf)
2412{ 2451{
2413 unsigned short iobase = conf->cfg_base; 2452 unsigned short iobase = conf->cfg_base;
2414 unsigned char tmpbyte; 2453 unsigned char tmpbyte;
@@ -2416,7 +2455,9 @@ static int __init preconfigure_smsc_chip(struct smsc_ircc_subsystem_configuratio
2416 outb(LPC47N227_CFGACCESSKEY, iobase); // enter configuration state 2455 outb(LPC47N227_CFGACCESSKEY, iobase); // enter configuration state
2417 outb(SMSCSIOFLAT_DEVICEID_REG, iobase); // set for device ID 2456 outb(SMSCSIOFLAT_DEVICEID_REG, iobase); // set for device ID
2418 tmpbyte = inb(iobase +1); // Read device ID 2457 tmpbyte = inb(iobase +1); // Read device ID
2419 IRDA_DEBUG(0, "Detected Chip id: 0x%02x, setting up registers...\n",tmpbyte); 2458 IRDA_DEBUG(0,
2459 "Detected Chip id: 0x%02x, setting up registers...\n",
2460 tmpbyte);
2420 2461
2421 /* Disable UART1 and set up SIR I/O port */ 2462 /* Disable UART1 and set up SIR I/O port */
2422 outb(0x24, iobase); // select CR24 - UART1 base addr 2463 outb(0x24, iobase); // select CR24 - UART1 base addr
@@ -2426,6 +2467,7 @@ static int __init preconfigure_smsc_chip(struct smsc_ircc_subsystem_configuratio
2426 tmpbyte = inb(iobase + 1); 2467 tmpbyte = inb(iobase + 1);
2427 if (tmpbyte != (conf->sir_io >> 2) ) { 2468 if (tmpbyte != (conf->sir_io >> 2) ) {
2428 IRDA_WARNING("ERROR: could not configure SIR ioport.\n"); 2469 IRDA_WARNING("ERROR: could not configure SIR ioport.\n");
2470 IRDA_WARNING("Try to supply ircc_cfg argument.\n");
2429 return -ENXIO; 2471 return -ENXIO;
2430 } 2472 }
2431 2473
@@ -2461,7 +2503,8 @@ static int __init preconfigure_smsc_chip(struct smsc_ircc_subsystem_configuratio
2461 2503
2462 outb(SMSCSIOFLAT_UARTMODE0C_REG, iobase); // CR0C - UART mode 2504 outb(SMSCSIOFLAT_UARTMODE0C_REG, iobase); // CR0C - UART mode
2463 tmpbyte = inb(iobase + 1); 2505 tmpbyte = inb(iobase + 1);
2464 tmpbyte &= ~SMSCSIOFLAT_UART2MODE_MASK | SMSCSIOFLAT_UART2MODE_VAL_IRDA; 2506 tmpbyte &= ~SMSCSIOFLAT_UART2MODE_MASK |
2507 SMSCSIOFLAT_UART2MODE_VAL_IRDA;
2465 outb(tmpbyte, iobase + 1); // enable IrDA (HPSIR) mode, high speed 2508 outb(tmpbyte, iobase + 1); // enable IrDA (HPSIR) mode, high speed
2466 2509
2467 outb(LPC47N227_APMBOOTDRIVE_REG, iobase); // CR07 - Auto Pwr Mgt/boot drive sel 2510 outb(LPC47N227_APMBOOTDRIVE_REG, iobase); // CR07 - Auto Pwr Mgt/boot drive sel
@@ -2486,53 +2529,226 @@ static int __init preconfigure_smsc_chip(struct smsc_ircc_subsystem_configuratio
2486 return 0; 2529 return 0;
2487} 2530}
2488 2531
2489/* 82801CAM registers */ 2532/* 82801CAM generic registers */
2490#define VID 0x00 2533#define VID 0x00
2491#define DID 0x02 2534#define DID 0x02
2492#define PIRQA_ROUT 0x60 2535#define PIRQ_A_D_ROUT 0x60
2536#define SIRQ_CNTL 0x64
2537#define PIRQ_E_H_ROUT 0x68
2493#define PCI_DMA_C 0x90 2538#define PCI_DMA_C 0x90
2539/* LPC-specific registers */
2494#define COM_DEC 0xe0 2540#define COM_DEC 0xe0
2541#define GEN1_DEC 0xe4
2495#define LPC_EN 0xe6 2542#define LPC_EN 0xe6
2496#define GEN2_DEC 0xec 2543#define GEN2_DEC 0xec
2497/* 2544/*
2498 * Sets up the I/O range using the 82801CAM ISA bridge, 82801DBM LPC bridge or 2545 * Sets up the I/O range using the 82801CAM ISA bridge, 82801DBM LPC bridge
2499 * Intel 82801DB/DBL (ICH4/ICH4-L) LPC Interface Bridge. They all work the same way! 2546 * or Intel 82801DB/DBL (ICH4/ICH4-L) LPC Interface Bridge.
2547 * They all work the same way!
2500 */ 2548 */
2501static int __init preconfigure_through_82801(struct pci_dev *dev, 2549static int __init preconfigure_through_82801(struct pci_dev *dev,
2502 struct smsc_ircc_subsystem_configuration *conf) 2550 struct
2551 smsc_ircc_subsystem_configuration
2552 *conf)
2503{ 2553{
2504 unsigned short tmpword; 2554 unsigned short tmpword;
2505 int ret; 2555 unsigned char tmpbyte;
2506 2556
2507 IRDA_MESSAGE("Setting up the SMSC device via the 82801 controller.\n"); 2557 IRDA_MESSAGE("Setting up Intel 82801 controller and SMSC device\n");
2508 pci_write_config_byte(dev, COM_DEC, 0x10); 2558 /*
2559 * Select the range for the COMA COM port (SIR)
2560 * Register COM_DEC:
2561 * Bit 7: reserved
2562 * Bit 6-4, COMB decode range
2563 * Bit 3: reserved
2564 * Bit 2-0, COMA decode range
2565 *
2566 * Decode ranges:
2567 * 000 = 0x3f8-0x3ff (COM1)
2568 * 001 = 0x2f8-0x2ff (COM2)
2569 * 010 = 0x220-0x227
2570 * 011 = 0x228-0x22f
2571 * 100 = 0x238-0x23f
2572 * 101 = 0x2e8-0x2ef (COM4)
2573 * 110 = 0x338-0x33f
2574 * 111 = 0x3e8-0x3ef (COM3)
2575 */
2576 pci_read_config_byte(dev, COM_DEC, &tmpbyte);
2577 tmpbyte &= 0xf8; /* mask COMA bits */
2578 switch(conf->sir_io) {
2579 case 0x3f8:
2580 tmpbyte |= 0x00;
2581 break;
2582 case 0x2f8:
2583 tmpbyte |= 0x01;
2584 break;
2585 case 0x220:
2586 tmpbyte |= 0x02;
2587 break;
2588 case 0x228:
2589 tmpbyte |= 0x03;
2590 break;
2591 case 0x238:
2592 tmpbyte |= 0x04;
2593 break;
2594 case 0x2e8:
2595 tmpbyte |= 0x05;
2596 break;
2597 case 0x338:
2598 tmpbyte |= 0x06;
2599 break;
2600 case 0x3e8:
2601 tmpbyte |= 0x07;
2602 break;
2603 default:
2604 tmpbyte |= 0x01; /* COM2 default */
2605 }
2606 IRDA_DEBUG(1, "COM_DEC (write): 0x%02x\n", tmpbyte);
2607 pci_write_config_byte(dev, COM_DEC, tmpbyte);
2509 2608
2510 /* Enable LPC */ 2609 /* Enable Low Pin Count interface */
2511 pci_read_config_word(dev, LPC_EN, &tmpword); /* LPC_EN register */ 2610 pci_read_config_word(dev, LPC_EN, &tmpword);
2512 tmpword &= 0xfffd; /* mask bit 1 */ 2611 /* These seem to be set up at all times,
2513 tmpword |= 0x0001; /* set bit 0 : COMA addr range enable */ 2612 * just make sure it is properly set.
2613 */
2614 switch(conf->cfg_base) {
2615 case 0x04e:
2616 tmpword |= 0x2000;
2617 break;
2618 case 0x02e:
2619 tmpword |= 0x1000;
2620 break;
2621 case 0x062:
2622 tmpword |= 0x0800;
2623 break;
2624 case 0x060:
2625 tmpword |= 0x0400;
2626 break;
2627 default:
2628 IRDA_WARNING("Uncommon I/O base address: 0x%04x\n",
2629 conf->cfg_base);
2630 break;
2631 }
2632 tmpword &= 0xfffd; /* disable LPC COMB */
2633 tmpword |= 0x0001; /* set bit 0 : enable LPC COMA addr range (GEN2) */
2634 IRDA_DEBUG(1, "LPC_EN (write): 0x%04x\n", tmpword);
2514 pci_write_config_word(dev, LPC_EN, tmpword); 2635 pci_write_config_word(dev, LPC_EN, tmpword);
2515 2636
2516 /* Setup DMA */ 2637 /*
2517 pci_write_config_word(dev, PCI_DMA_C, 0xc0c0); /* LPC I/F DMA on, channel 3 -- rtm (?? PCI DMA ?) */ 2638 * Configure LPC DMA channel
2518 pci_write_config_word(dev, GEN2_DEC, 0x131); /* LPC I/F 2nd decode range */ 2639 * PCI_DMA_C bits:
2640 * Bit 15-14: DMA channel 7 select
2641 * Bit 13-12: DMA channel 6 select
2642 * Bit 11-10: DMA channel 5 select
2643 * Bit 9-8: Reserved
2644 * Bit 7-6: DMA channel 3 select
2645 * Bit 5-4: DMA channel 2 select
2646 * Bit 3-2: DMA channel 1 select
2647 * Bit 1-0: DMA channel 0 select
2648 * 00 = Reserved value
2649 * 01 = PC/PCI DMA
2650 * 10 = Reserved value
2651 * 11 = LPC I/F DMA
2652 */
2653 pci_read_config_word(dev, PCI_DMA_C, &tmpword);
2654 switch(conf->fir_dma) {
2655 case 0x07:
2656 tmpword |= 0xc000;
2657 break;
2658 case 0x06:
2659 tmpword |= 0x3000;
2660 break;
2661 case 0x05:
2662 tmpword |= 0x0c00;
2663 break;
2664 case 0x03:
2665 tmpword |= 0x00c0;
2666 break;
2667 case 0x02:
2668 tmpword |= 0x0030;
2669 break;
2670 case 0x01:
2671 tmpword |= 0x000c;
2672 break;
2673 case 0x00:
2674 tmpword |= 0x0003;
2675 break;
2676 default:
2677 break; /* do not change settings */
2678 }
2679 IRDA_DEBUG(1, "PCI_DMA_C (write): 0x%04x\n", tmpword);
2680 pci_write_config_word(dev, PCI_DMA_C, tmpword);
2681
2682 /*
2683 * GEN2_DEC bits:
2684 * Bit 15-4: Generic I/O range
2685 * Bit 3-1: reserved (read as 0)
2686 * Bit 0: enable GEN2 range on LPC I/F
2687 */
2688 tmpword = conf->fir_io & 0xfff8;
2689 tmpword |= 0x0001;
2690 IRDA_DEBUG(1, "GEN2_DEC (write): 0x%04x\n", tmpword);
2691 pci_write_config_word(dev, GEN2_DEC, tmpword);
2519 2692
2520 /* Pre-configure chip */ 2693 /* Pre-configure chip */
2521 ret = preconfigure_smsc_chip(conf); 2694 return preconfigure_smsc_chip(conf);
2695}
2522 2696
2523 /* Disable LPC */ 2697/*
2524 pci_read_config_word(dev, LPC_EN, &tmpword); /* LPC_EN register */ 2698 * Pre-configure a certain port on the ALi 1533 bridge.
2525 tmpword &= 0xfffc; /* mask bit 1 and bit 0, COMA addr range disable */ 2699 * This is based on reverse-engineering since ALi does not
2526 pci_write_config_word(dev, LPC_EN, tmpword); 2700 * provide any data sheet for the 1533 chip.
2527 return ret; 2701 */
2702static void __init preconfigure_ali_port(struct pci_dev *dev,
2703 unsigned short port)
2704{
2705 unsigned char reg;
2706 /* These bits obviously control the different ports */
2707 unsigned char mask;
2708 unsigned char tmpbyte;
2709
2710 switch(port) {
2711 case 0x0130:
2712 case 0x0178:
2713 reg = 0xb0;
2714 mask = 0x80;
2715 break;
2716 case 0x03f8:
2717 reg = 0xb4;
2718 mask = 0x80;
2719 break;
2720 case 0x02f8:
2721 reg = 0xb4;
2722 mask = 0x30;
2723 break;
2724 case 0x02e8:
2725 reg = 0xb4;
2726 mask = 0x08;
2727 break;
2728 default:
2729 IRDA_ERROR("Failed to configure unsupported port on ALi 1533 bridge: 0x%04x\n", port);
2730 return;
2731 }
2732
2733 pci_read_config_byte(dev, reg, &tmpbyte);
2734 /* Turn on the right bits */
2735 tmpbyte |= mask;
2736 pci_write_config_byte(dev, reg, tmpbyte);
2737 IRDA_MESSAGE("Activated ALi 1533 ISA bridge port 0x%04x.\n", port);
2738 return;
2528} 2739}
2529 2740
2530static int __init preconfigure_through_ali(struct pci_dev *dev, 2741static int __init preconfigure_through_ali(struct pci_dev *dev,
2531 struct smsc_ircc_subsystem_configuration *conf) 2742 struct
2743 smsc_ircc_subsystem_configuration
2744 *conf)
2532{ 2745{
2533 /* TODO: put in ALi 1533 configuration here. */ 2746 /* Configure the two ports on the ALi 1533 */
2534 IRDA_MESSAGE("SORRY: %s has an unsupported bridge controller (ALi): not pre-configured.\n", conf->name); 2747 preconfigure_ali_port(dev, conf->sir_io);
2535 return -ENODEV; 2748 preconfigure_ali_port(dev, conf->fir_io);
2749
2750 /* Pre-configure chip */
2751 return preconfigure_smsc_chip(conf);
2536} 2752}
2537 2753
2538static int __init smsc_ircc_preconfigure_subsystems(unsigned short ircc_cfg, 2754static int __init smsc_ircc_preconfigure_subsystems(unsigned short ircc_cfg,
@@ -2552,9 +2768,10 @@ static int __init smsc_ircc_preconfigure_subsystems(unsigned short ircc_cfg,
2552 struct smsc_ircc_subsystem_configuration *conf; 2768 struct smsc_ircc_subsystem_configuration *conf;
2553 2769
2554 /* 2770 /*
2555 * Cache the subsystem vendor/device: some manufacturers fail to set 2771 * Cache the subsystem vendor/device:
2556 * this for all components, so we save it in case there is just 2772 * some manufacturers fail to set this for all components,
2557 * 0x0000 0x0000 on the device we want to check. 2773 * so we save it in case there is just 0x0000 0x0000 on the
2774 * device we want to check.
2558 */ 2775 */
2559 if (dev->subsystem_vendor != 0x0000U) { 2776 if (dev->subsystem_vendor != 0x0000U) {
2560 ss_vendor = dev->subsystem_vendor; 2777 ss_vendor = dev->subsystem_vendor;
@@ -2564,13 +2781,20 @@ static int __init smsc_ircc_preconfigure_subsystems(unsigned short ircc_cfg,
2564 for( ; conf->subvendor; conf++) { 2781 for( ; conf->subvendor; conf++) {
2565 if(conf->vendor == dev->vendor && 2782 if(conf->vendor == dev->vendor &&
2566 conf->device == dev->device && 2783 conf->device == dev->device &&
2567 conf->subvendor == ss_vendor && /* Sometimes these are cached values */ 2784 conf->subvendor == ss_vendor &&
2568 (conf->subdevice == ss_device || conf->subdevice == 0xffff)) { 2785 /* Sometimes these are cached values */
2569 struct smsc_ircc_subsystem_configuration tmpconf; 2786 (conf->subdevice == ss_device ||
2787 conf->subdevice == 0xffff)) {
2788 struct smsc_ircc_subsystem_configuration
2789 tmpconf;
2570 2790
2571 memcpy(&tmpconf, conf, sizeof(struct smsc_ircc_subsystem_configuration)); 2791 memcpy(&tmpconf, conf,
2792 sizeof(struct smsc_ircc_subsystem_configuration));
2572 2793
2573 /* Override the default values with anything passed in as parameter */ 2794 /*
2795 * Override the default values with anything
2796 * passed in as parameter
2797 */
2574 if (ircc_cfg != 0) 2798 if (ircc_cfg != 0)
2575 tmpconf.cfg_base = ircc_cfg; 2799 tmpconf.cfg_base = ircc_cfg;
2576 if (ircc_fir != 0) 2800 if (ircc_fir != 0)