1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32#include <linux/string.h>
33#include <linux/proc_fs.h>
34#include <linux/skbuff.h>
35#include <linux/capability.h>
36#include <linux/if.h>
37#include <linux/if_ether.h>
38#include <linux/if_arp.h>
39#include <linux/netdevice.h>
40#include <linux/init.h>
41#include <linux/tty.h>
42#include <linux/kmod.h>
43#include <linux/spinlock.h>
44
45#include <asm/ioctls.h>
46#include <asm/uaccess.h>
47#include <asm/dma.h>
48#include <asm/io.h>
49
50#include <net/irda/irda_device.h>
51#include <net/irda/irlap.h>
52#include <net/irda/timer.h>
53#include <net/irda/wrapper.h>
54
55static void __irda_task_delete(struct irda_task *task);
56
57static hashbin_t *dongles = NULL;
58static hashbin_t *tasks = NULL;
59
60#ifdef CONFIG_IRDA_DEBUG
61static const char *task_state[] = {
62 "IRDA_TASK_INIT",
63 "IRDA_TASK_DONE",
64 "IRDA_TASK_WAIT",
65 "IRDA_TASK_WAIT1",
66 "IRDA_TASK_WAIT2",
67 "IRDA_TASK_WAIT3",
68 "IRDA_TASK_CHILD_INIT",
69 "IRDA_TASK_CHILD_WAIT",
70 "IRDA_TASK_CHILD_DONE",
71};
72#endif
73
74static void irda_task_timer_expired(void *data);
75
76int __init irda_device_init( void)
77{
78 dongles = hashbin_new(HB_NOLOCK);
79 if (dongles == NULL) {
80 IRDA_WARNING("IrDA: Can't allocate dongles hashbin!\n");
81 return -ENOMEM;
82 }
83 spin_lock_init(&dongles->hb_spinlock);
84
85 tasks = hashbin_new(HB_LOCK);
86 if (tasks == NULL) {
87 IRDA_WARNING("IrDA: Can't allocate tasks hashbin!\n");
88 hashbin_delete(dongles, NULL);
89 return -ENOMEM;
90 }
91
92
93
94
95 return 0;
96}
97
98static void leftover_dongle(void *arg)
99{
100 struct dongle_reg *reg = arg;
101 IRDA_WARNING("IrDA: Dongle type %x not unregistered\n",
102 reg->type);
103}
104
105void irda_device_cleanup(void)
106{
107 IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
108
109 hashbin_delete(tasks, (FREE_FUNC) __irda_task_delete);
110
111 hashbin_delete(dongles, leftover_dongle);
112}
113
114
115
116
117
118
119
120void irda_device_set_media_busy(struct net_device *dev, int status)
121{
122 struct irlap_cb *self;
123
124 IRDA_DEBUG(4, "%s(%s)\n", __FUNCTION__, status ? "TRUE" : "FALSE");
125
126 self = (struct irlap_cb *) dev->atalk_ptr;
127
128
129
130
131
132
133
134
135 if (!self || self->magic != LAP_MAGIC)
136 return;
137
138 if (status) {
139 self->media_busy = TRUE;
140 if (status == SMALL)
141 irlap_start_mbusy_timer(self, SMALLBUSY_TIMEOUT);
142 else
143 irlap_start_mbusy_timer(self, MEDIABUSY_TIMEOUT);
144 IRDA_DEBUG( 4, "Media busy!\n");
145 } else {
146 self->media_busy = FALSE;
147 irlap_stop_mbusy_timer(self);
148 }
149}
150EXPORT_SYMBOL(irda_device_set_media_busy);
151
152
153
154
155
156
157
158
159int irda_device_is_receiving(struct net_device *dev)
160{
161 struct if_irda_req req;
162 int ret;
163
164 IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
165
166 if (!dev->do_ioctl) {
167 IRDA_ERROR("%s: do_ioctl not impl. by device driver\n",
168 __FUNCTION__);
169 return -1;
170 }
171
172 ret = dev->do_ioctl(dev, (struct ifreq *) &req, SIOCGRECEIVING);
173 if (ret < 0)
174 return ret;
175
176 return req.ifr_receiving;
177}
178
179void irda_task_next_state(struct irda_task *task, IRDA_TASK_STATE state)
180{
181 IRDA_DEBUG(2, "%s(), state = %s\n", __FUNCTION__, task_state[state]);
182
183 task->state = state;
184}
185EXPORT_SYMBOL(irda_task_next_state);
186
187static void __irda_task_delete(struct irda_task *task)
188{
189 del_timer(&task->timer);
190
191 kfree(task);
192}
193
194void irda_task_delete(struct irda_task *task)
195{
196
197 hashbin_remove(tasks, (long) task, NULL);
198
199 __irda_task_delete(task);
200}
201EXPORT_SYMBOL(irda_task_delete);
202
203
204
205
206
207
208
209
210
211static int irda_task_kick(struct irda_task *task)
212{
213 int finished = TRUE;
214 int count = 0;
215 int timeout;
216
217 IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
218
219 IRDA_ASSERT(task != NULL, return -1;);
220 IRDA_ASSERT(task->magic == IRDA_TASK_MAGIC, return -1;);
221
222
223 do {
224 timeout = task->function(task);
225 if (count++ > 100) {
226 IRDA_ERROR("%s: error in task handler!\n",
227 __FUNCTION__);
228 irda_task_delete(task);
229 return TRUE;
230 }
231 } while ((timeout == 0) && (task->state != IRDA_TASK_DONE));
232
233 if (timeout < 0) {
234 IRDA_ERROR("%s: Error executing task!\n", __FUNCTION__);
235 irda_task_delete(task);
236 return TRUE;
237 }
238
239
240 if (task->state == IRDA_TASK_DONE) {
241 del_timer(&task->timer);
242
243
244 if (task->finished)
245 task->finished(task);
246
247
248 if (task->parent) {
249
250 if (task->parent->state == IRDA_TASK_CHILD_WAIT) {
251 task->parent->state = IRDA_TASK_CHILD_DONE;
252
253
254 del_timer(&task->parent->timer);
255
256
257 irda_task_kick(task->parent);
258 }
259 }
260 irda_task_delete(task);
261 } else if (timeout > 0) {
262 irda_start_timer(&task->timer, timeout, (void *) task,
263 irda_task_timer_expired);
264 finished = FALSE;
265 } else {
266 IRDA_DEBUG(0, "%s(), not finished, and no timeout!\n",
267 __FUNCTION__);
268 finished = FALSE;
269 }
270
271 return finished;
272}
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288struct irda_task *irda_task_execute(void *instance,
289 IRDA_TASK_CALLBACK function,
290 IRDA_TASK_CALLBACK finished,
291 struct irda_task *parent, void *param)
292{
293 struct irda_task *task;
294
295 IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
296
297 task = kmalloc(sizeof(struct irda_task), GFP_ATOMIC);
298 if (!task)
299 return NULL;
300
301 task->state = IRDA_TASK_INIT;
302 task->instance = instance;
303 task->function = function;
304 task->finished = finished;
305 task->parent = parent;
306 task->param = param;
307 task->magic = IRDA_TASK_MAGIC;
308
309 init_timer(&task->timer);
310
311
312 hashbin_insert(tasks, (irda_queue_t *) task, (long) task, NULL);
313
314
315 return irda_task_kick(task) ? NULL : task;
316}
317EXPORT_SYMBOL(irda_task_execute);
318
319
320
321
322
323
324
325static void irda_task_timer_expired(void *data)
326{
327 struct irda_task *task;
328
329 IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
330
331 task = (struct irda_task *) data;
332
333 irda_task_kick(task);
334}
335
336
337
338
339
340
341
342static void irda_device_setup(struct net_device *dev)
343{
344 dev->hard_header_len = 0;
345 dev->addr_len = LAP_ALEN;
346
347 dev->type = ARPHRD_IRDA;
348 dev->tx_queue_len = 8;
349
350 memset(dev->broadcast, 0xff, LAP_ALEN);
351
352 dev->mtu = 2048;
353 dev->flags = IFF_NOARP;
354}
355
356
357
358
359
360
361struct net_device *alloc_irdadev(int sizeof_priv)
362{
363 return alloc_netdev(sizeof_priv, "irda%d", irda_device_setup);
364}
365EXPORT_SYMBOL(alloc_irdadev);
366
367
368
369
370
371
372
373
374
375dongle_t *irda_device_dongle_init(struct net_device *dev, int type)
376{
377 struct dongle_reg *reg;
378 dongle_t *dongle = kzalloc(sizeof(dongle_t), GFP_KERNEL);
379
380 might_sleep();
381
382 spin_lock(&dongles->hb_spinlock);
383 reg = hashbin_find(dongles, type, NULL);
384
385#ifdef CONFIG_KMOD
386
387 if (!reg && capable(CAP_SYS_MODULE)) {
388 spin_unlock(&dongles->hb_spinlock);
389
390 request_module("irda-dongle-%d", type);
391
392 spin_lock(&dongles->hb_spinlock);
393 reg = hashbin_find(dongles, type, NULL);
394 }
395#endif
396
397 if (!reg || !try_module_get(reg->owner) ) {
398 IRDA_ERROR("IrDA: Unable to find requested dongle type %x\n",
399 type);
400 kfree(dongle);
401 dongle = NULL;
402 }
403 if (dongle) {
404
405 dongle->issue = reg;
406 dongle->dev = dev;
407 }
408 spin_unlock(&dongles->hb_spinlock);
409 return dongle;
410}
411EXPORT_SYMBOL(irda_device_dongle_init);
412
413
414
415
416int irda_device_dongle_cleanup(dongle_t *dongle)
417{
418 IRDA_ASSERT(dongle != NULL, return -1;);
419
420 dongle->issue->close(dongle);
421 module_put(dongle->issue->owner);
422 kfree(dongle);
423
424 return 0;
425}
426EXPORT_SYMBOL(irda_device_dongle_cleanup);
427
428
429
430
431int irda_device_register_dongle(struct dongle_reg *new)
432{
433 spin_lock(&dongles->hb_spinlock);
434
435 if (hashbin_find(dongles, new->type, NULL)) {
436 IRDA_MESSAGE("%s: Dongle type %x already registered\n",
437 __FUNCTION__, new->type);
438 } else {
439
440 hashbin_insert(dongles, (irda_queue_t *) new, new->type, NULL);
441 }
442 spin_unlock(&dongles->hb_spinlock);
443
444 return 0;
445}
446EXPORT_SYMBOL(irda_device_register_dongle);
447
448
449
450
451
452
453
454void irda_device_unregister_dongle(struct dongle_reg *dongle)
455{
456 struct dongle *node;
457
458 spin_lock(&dongles->hb_spinlock);
459 node = hashbin_remove(dongles, dongle->type, NULL);
460 if (!node)
461 IRDA_ERROR("%s: dongle not found!\n", __FUNCTION__);
462 spin_unlock(&dongles->hb_spinlock);
463}
464EXPORT_SYMBOL(irda_device_unregister_dongle);
465
466#ifdef CONFIG_ISA_DMA_API
467
468
469
470
471
472
473void irda_setup_dma(int channel, dma_addr_t buffer, int count, int mode)
474{
475 unsigned long flags;
476
477 flags = claim_dma_lock();
478
479 disable_dma(channel);
480 clear_dma_ff(channel);
481 set_dma_mode(channel, mode);
482 set_dma_addr(channel, buffer);
483 set_dma_count(channel, count);
484 enable_dma(channel);
485
486 release_dma_lock(flags);
487}
488EXPORT_SYMBOL(irda_setup_dma);
489#endif
490