[PATCH] kthread: convert loop.c to kthread
[linux-2.6] / drivers / pnp / manager.c
1 /*
2  * manager.c - Resource Management, Conflict Resolution, Activation and Disabling of Devices
3  *
4  * based on isapnp.c resource management (c) Jaroslav Kysela <perex@suse.cz>
5  * Copyright 2003 Adam Belay <ambx1@neo.rr.com>
6  *
7  */
8
9 #include <linux/errno.h>
10 #include <linux/module.h>
11 #include <linux/init.h>
12 #include <linux/kernel.h>
13 #include <linux/pnp.h>
14 #include <linux/slab.h>
15 #include <linux/bitmap.h>
16 #include "base.h"
17
18 DECLARE_MUTEX(pnp_res_mutex);
19
20 static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx)
21 {
22         resource_size_t *start, *end;
23         unsigned long *flags;
24
25         if (!dev || !rule)
26                 return -EINVAL;
27
28         if (idx >= PNP_MAX_PORT) {
29                 pnp_err("More than 4 ports is incompatible with pnp specifications.");
30                 /* pretend we were successful so at least the manager won't try again */
31                 return 1;
32         }
33
34         /* check if this resource has been manually set, if so skip */
35         if (!(dev->res.port_resource[idx].flags & IORESOURCE_AUTO))
36                 return 1;
37
38         start = &dev->res.port_resource[idx].start;
39         end = &dev->res.port_resource[idx].end;
40         flags = &dev->res.port_resource[idx].flags;
41
42         /* set the initial values */
43         *flags |= rule->flags | IORESOURCE_IO;
44         *flags &=  ~IORESOURCE_UNSET;
45
46         if (!rule->size) {
47                 *flags |= IORESOURCE_DISABLED;
48                 return 1; /* skip disabled resource requests */
49         }
50
51         *start = rule->min;
52         *end = *start + rule->size - 1;
53
54         /* run through until pnp_check_port is happy */
55         while (!pnp_check_port(dev, idx)) {
56                 *start += rule->align;
57                 *end = *start + rule->size - 1;
58                 if (*start > rule->max || !rule->align)
59                         return 0;
60         }
61         return 1;
62 }
63
64 static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx)
65 {
66         resource_size_t *start, *end;
67         unsigned long *flags;
68
69         if (!dev || !rule)
70                 return -EINVAL;
71
72         if (idx >= PNP_MAX_MEM) {
73                 pnp_err("More than 8 mems is incompatible with pnp specifications.");
74                 /* pretend we were successful so at least the manager won't try again */
75                 return 1;
76         }
77
78         /* check if this resource has been manually set, if so skip */
79         if (!(dev->res.mem_resource[idx].flags & IORESOURCE_AUTO))
80                 return 1;
81
82         start = &dev->res.mem_resource[idx].start;
83         end = &dev->res.mem_resource[idx].end;
84         flags = &dev->res.mem_resource[idx].flags;
85
86         /* set the initial values */
87         *flags |= rule->flags | IORESOURCE_MEM;
88         *flags &=  ~IORESOURCE_UNSET;
89
90         /* convert pnp flags to standard Linux flags */
91         if (!(rule->flags & IORESOURCE_MEM_WRITEABLE))
92                 *flags |= IORESOURCE_READONLY;
93         if (rule->flags & IORESOURCE_MEM_CACHEABLE)
94                 *flags |= IORESOURCE_CACHEABLE;
95         if (rule->flags & IORESOURCE_MEM_RANGELENGTH)
96                 *flags |= IORESOURCE_RANGELENGTH;
97         if (rule->flags & IORESOURCE_MEM_SHADOWABLE)
98                 *flags |= IORESOURCE_SHADOWABLE;
99
100         if (!rule->size) {
101                 *flags |= IORESOURCE_DISABLED;
102                 return 1; /* skip disabled resource requests */
103         }
104
105         *start = rule->min;
106         *end = *start + rule->size -1;
107
108         /* run through until pnp_check_mem is happy */
109         while (!pnp_check_mem(dev, idx)) {
110                 *start += rule->align;
111                 *end = *start + rule->size - 1;
112                 if (*start > rule->max || !rule->align)
113                         return 0;
114         }
115         return 1;
116 }
117
118 static int pnp_assign_irq(struct pnp_dev * dev, struct pnp_irq *rule, int idx)
119 {
120         resource_size_t *start, *end;
121         unsigned long *flags;
122         int i;
123
124         /* IRQ priority: this table is good for i386 */
125         static unsigned short xtab[16] = {
126                 5, 10, 11, 12, 9, 14, 15, 7, 3, 4, 13, 0, 1, 6, 8, 2
127         };
128
129         if (!dev || !rule)
130                 return -EINVAL;
131
132         if (idx >= PNP_MAX_IRQ) {
133                 pnp_err("More than 2 irqs is incompatible with pnp specifications.");
134                 /* pretend we were successful so at least the manager won't try again */
135                 return 1;
136         }
137
138         /* check if this resource has been manually set, if so skip */
139         if (!(dev->res.irq_resource[idx].flags & IORESOURCE_AUTO))
140                 return 1;
141
142         start = &dev->res.irq_resource[idx].start;
143         end = &dev->res.irq_resource[idx].end;
144         flags = &dev->res.irq_resource[idx].flags;
145
146         /* set the initial values */
147         *flags |= rule->flags | IORESOURCE_IRQ;
148         *flags &=  ~IORESOURCE_UNSET;
149
150         if (bitmap_empty(rule->map, PNP_IRQ_NR)) {
151                 *flags |= IORESOURCE_DISABLED;
152                 return 1; /* skip disabled resource requests */
153         }
154
155         /* TBD: need check for >16 IRQ */
156         *start = find_next_bit(rule->map, PNP_IRQ_NR, 16);
157         if (*start < PNP_IRQ_NR) {
158                 *end = *start;
159                 return 1;
160         }
161         for (i = 0; i < 16; i++) {
162                 if(test_bit(xtab[i], rule->map)) {
163                         *start = *end = xtab[i];
164                         if(pnp_check_irq(dev, idx))
165                                 return 1;
166                 }
167         }
168         return 0;
169 }
170
171 static int pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx)
172 {
173         resource_size_t *start, *end;
174         unsigned long *flags;
175         int i;
176
177         /* DMA priority: this table is good for i386 */
178         static unsigned short xtab[8] = {
179                 1, 3, 5, 6, 7, 0, 2, 4
180         };
181
182         if (!dev || !rule)
183                 return -EINVAL;
184
185         if (idx >= PNP_MAX_DMA) {
186                 pnp_err("More than 2 dmas is incompatible with pnp specifications.");
187                 /* pretend we were successful so at least the manager won't try again */
188                 return 1;
189         }
190
191         /* check if this resource has been manually set, if so skip */
192         if (!(dev->res.dma_resource[idx].flags & IORESOURCE_AUTO))
193                 return 1;
194
195         start = &dev->res.dma_resource[idx].start;
196         end = &dev->res.dma_resource[idx].end;
197         flags = &dev->res.dma_resource[idx].flags;
198
199         /* set the initial values */
200         *flags |= rule->flags | IORESOURCE_DMA;
201         *flags &=  ~IORESOURCE_UNSET;
202
203         if (!rule->map) {
204                 *flags |= IORESOURCE_DISABLED;
205                 return 1; /* skip disabled resource requests */
206         }
207
208         for (i = 0; i < 8; i++) {
209                 if(rule->map & (1<<xtab[i])) {
210                         *start = *end = xtab[i];
211                         if(pnp_check_dma(dev, idx))
212                                 return 1;
213                 }
214         }
215         return 0;
216 }
217
218 /**
219  * pnp_init_resources - Resets a resource table to default values.
220  * @table: pointer to the desired resource table
221  *
222  */
223 void pnp_init_resource_table(struct pnp_resource_table *table)
224 {
225         int idx;
226         for (idx = 0; idx < PNP_MAX_IRQ; idx++) {
227                 table->irq_resource[idx].name = NULL;
228                 table->irq_resource[idx].start = -1;
229                 table->irq_resource[idx].end = -1;
230                 table->irq_resource[idx].flags = IORESOURCE_IRQ | IORESOURCE_AUTO | IORESOURCE_UNSET;
231         }
232         for (idx = 0; idx < PNP_MAX_DMA; idx++) {
233                 table->dma_resource[idx].name = NULL;
234                 table->dma_resource[idx].start = -1;
235                 table->dma_resource[idx].end = -1;
236                 table->dma_resource[idx].flags = IORESOURCE_DMA | IORESOURCE_AUTO | IORESOURCE_UNSET;
237         }
238         for (idx = 0; idx < PNP_MAX_PORT; idx++) {
239                 table->port_resource[idx].name = NULL;
240                 table->port_resource[idx].start = 0;
241                 table->port_resource[idx].end = 0;
242                 table->port_resource[idx].flags = IORESOURCE_IO | IORESOURCE_AUTO | IORESOURCE_UNSET;
243         }
244         for (idx = 0; idx < PNP_MAX_MEM; idx++) {
245                 table->mem_resource[idx].name = NULL;
246                 table->mem_resource[idx].start = 0;
247                 table->mem_resource[idx].end = 0;
248                 table->mem_resource[idx].flags = IORESOURCE_MEM | IORESOURCE_AUTO | IORESOURCE_UNSET;
249         }
250 }
251
252 /**
253  * pnp_clean_resources - clears resources that were not manually set
254  * @res: the resources to clean
255  *
256  */
257 static void pnp_clean_resource_table(struct pnp_resource_table * res)
258 {
259         int idx;
260         for (idx = 0; idx < PNP_MAX_IRQ; idx++) {
261                 if (!(res->irq_resource[idx].flags & IORESOURCE_AUTO))
262                         continue;
263                 res->irq_resource[idx].start = -1;
264                 res->irq_resource[idx].end = -1;
265                 res->irq_resource[idx].flags = IORESOURCE_IRQ | IORESOURCE_AUTO | IORESOURCE_UNSET;
266         }
267         for (idx = 0; idx < PNP_MAX_DMA; idx++) {
268                 if (!(res->dma_resource[idx].flags & IORESOURCE_AUTO))
269                         continue;
270                 res->dma_resource[idx].start = -1;
271                 res->dma_resource[idx].end = -1;
272                 res->dma_resource[idx].flags = IORESOURCE_DMA | IORESOURCE_AUTO | IORESOURCE_UNSET;
273         }
274         for (idx = 0; idx < PNP_MAX_PORT; idx++) {
275                 if (!(res->port_resource[idx].flags & IORESOURCE_AUTO))
276                         continue;
277                 res->port_resource[idx].start = 0;
278                 res->port_resource[idx].end = 0;
279                 res->port_resource[idx].flags = IORESOURCE_IO | IORESOURCE_AUTO | IORESOURCE_UNSET;
280         }
281         for (idx = 0; idx < PNP_MAX_MEM; idx++) {
282                 if (!(res->mem_resource[idx].flags & IORESOURCE_AUTO))
283                         continue;
284                 res->mem_resource[idx].start = 0;
285                 res->mem_resource[idx].end = 0;
286                 res->mem_resource[idx].flags = IORESOURCE_MEM | IORESOURCE_AUTO | IORESOURCE_UNSET;
287         }
288 }
289
290 /**
291  * pnp_assign_resources - assigns resources to the device based on the specified dependent number
292  * @dev: pointer to the desired device
293  * @depnum: the dependent function number
294  *
295  * Only set depnum to 0 if the device does not have dependent options.
296  */
297 static int pnp_assign_resources(struct pnp_dev *dev, int depnum)
298 {
299         struct pnp_port *port;
300         struct pnp_mem *mem;
301         struct pnp_irq *irq;
302         struct pnp_dma *dma;
303         int nport = 0, nmem = 0, nirq = 0, ndma = 0;
304
305         if (!pnp_can_configure(dev))
306                 return -ENODEV;
307
308         down(&pnp_res_mutex);
309         pnp_clean_resource_table(&dev->res); /* start with a fresh slate */
310         if (dev->independent) {
311                 port = dev->independent->port;
312                 mem = dev->independent->mem;
313                 irq = dev->independent->irq;
314                 dma = dev->independent->dma;
315                 while (port) {
316                         if (!pnp_assign_port(dev, port, nport))
317                                 goto fail;
318                         nport++;
319                         port = port->next;
320                 }
321                 while (mem) {
322                         if (!pnp_assign_mem(dev, mem, nmem))
323                                 goto fail;
324                         nmem++;
325                         mem = mem->next;
326                 }
327                 while (irq) {
328                         if (!pnp_assign_irq(dev, irq, nirq))
329                                 goto fail;
330                         nirq++;
331                         irq = irq->next;
332                 }
333                 while (dma) {
334                         if (!pnp_assign_dma(dev, dma, ndma))
335                                 goto fail;
336                         ndma++;
337                         dma = dma->next;
338                 }
339         }
340
341         if (depnum) {
342                 struct pnp_option *dep;
343                 int i;
344                 for (i=1,dep=dev->dependent; i<depnum; i++, dep=dep->next)
345                         if(!dep)
346                                 goto fail;
347                 port =dep->port;
348                 mem = dep->mem;
349                 irq = dep->irq;
350                 dma = dep->dma;
351                 while (port) {
352                         if (!pnp_assign_port(dev, port, nport))
353                                 goto fail;
354                         nport++;
355                         port = port->next;
356                 }
357                 while (mem) {
358                         if (!pnp_assign_mem(dev, mem, nmem))
359                                 goto fail;
360                         nmem++;
361                         mem = mem->next;
362                 }
363                 while (irq) {
364                         if (!pnp_assign_irq(dev, irq, nirq))
365                                 goto fail;
366                         nirq++;
367                         irq = irq->next;
368                 }
369                 while (dma) {
370                         if (!pnp_assign_dma(dev, dma, ndma))
371                                 goto fail;
372                         ndma++;
373                         dma = dma->next;
374                 }
375         } else if (dev->dependent)
376                 goto fail;
377
378         up(&pnp_res_mutex);
379         return 1;
380
381 fail:
382         pnp_clean_resource_table(&dev->res);
383         up(&pnp_res_mutex);
384         return 0;
385 }
386
387 /**
388  * pnp_manual_config_dev - Disables Auto Config and Manually sets the resource table
389  * @dev: pointer to the desired device
390  * @res: pointer to the new resource config
391  * @mode: 0 or PNP_CONFIG_FORCE
392  *
393  * This function can be used by drivers that want to manually set thier resources.
394  */
395 int pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table * res, int mode)
396 {
397         int i;
398         struct pnp_resource_table * bak;
399         if (!dev || !res)
400                 return -EINVAL;
401         if (!pnp_can_configure(dev))
402                 return -ENODEV;
403         bak = pnp_alloc(sizeof(struct pnp_resource_table));
404         if (!bak)
405                 return -ENOMEM;
406         *bak = dev->res;
407
408         down(&pnp_res_mutex);
409         dev->res = *res;
410         if (!(mode & PNP_CONFIG_FORCE)) {
411                 for (i = 0; i < PNP_MAX_PORT; i++) {
412                         if(!pnp_check_port(dev,i))
413                                 goto fail;
414                 }
415                 for (i = 0; i < PNP_MAX_MEM; i++) {
416                         if(!pnp_check_mem(dev,i))
417                                 goto fail;
418                 }
419                 for (i = 0; i < PNP_MAX_IRQ; i++) {
420                         if(!pnp_check_irq(dev,i))
421                                 goto fail;
422                 }
423                 for (i = 0; i < PNP_MAX_DMA; i++) {
424                         if(!pnp_check_dma(dev,i))
425                                 goto fail;
426                 }
427         }
428         up(&pnp_res_mutex);
429
430         kfree(bak);
431         return 0;
432
433 fail:
434         dev->res = *bak;
435         up(&pnp_res_mutex);
436         kfree(bak);
437         return -EINVAL;
438 }
439
440 /**
441  * pnp_auto_config_dev - automatically assigns resources to a device
442  * @dev: pointer to the desired device
443  *
444  */
445 int pnp_auto_config_dev(struct pnp_dev *dev)
446 {
447         struct pnp_option *dep;
448         int i = 1;
449
450         if(!dev)
451                 return -EINVAL;
452
453         if(!pnp_can_configure(dev)) {
454                 pnp_info("Device %s does not support resource configuration.", dev->dev.bus_id);
455                 return -ENODEV;
456         }
457
458         if (!dev->dependent) {
459                 if (pnp_assign_resources(dev, 0))
460                         return 0;
461         } else {
462                 dep = dev->dependent;
463                 do {
464                         if (pnp_assign_resources(dev, i))
465                                 return 0;
466                         dep = dep->next;
467                         i++;
468                 } while (dep);
469         }
470
471         pnp_err("Unable to assign resources to device %s.", dev->dev.bus_id);
472         return -EBUSY;
473 }
474
475 /**
476  * pnp_start_dev - low-level start of the PnP device
477  * @dev: pointer to the desired device
478  *
479  * assumes that resources have alread been allocated
480  */
481
482 int pnp_start_dev(struct pnp_dev *dev)
483 {
484         if (!pnp_can_write(dev)) {
485                 pnp_info("Device %s does not support activation.", dev->dev.bus_id);
486                 return -EINVAL;
487         }
488
489         if (dev->protocol->set(dev, &dev->res)<0) {
490                 pnp_err("Failed to activate device %s.", dev->dev.bus_id);
491                 return -EIO;
492         }
493
494         pnp_info("Device %s activated.", dev->dev.bus_id);
495
496         return 0;
497 }
498
499 /**
500  * pnp_stop_dev - low-level disable of the PnP device
501  * @dev: pointer to the desired device
502  *
503  * does not free resources
504  */
505
506 int pnp_stop_dev(struct pnp_dev *dev)
507 {
508         if (!pnp_can_disable(dev)) {
509                 pnp_info("Device %s does not support disabling.", dev->dev.bus_id);
510                 return -EINVAL;
511         }
512         if (dev->protocol->disable(dev)<0) {
513                 pnp_err("Failed to disable device %s.", dev->dev.bus_id);
514                 return -EIO;
515         }
516
517         pnp_info("Device %s disabled.", dev->dev.bus_id);
518
519         return 0;
520 }
521
522 /**
523  * pnp_activate_dev - activates a PnP device for use
524  * @dev: pointer to the desired device
525  *
526  * does not validate or set resources so be careful.
527  */
528 int pnp_activate_dev(struct pnp_dev *dev)
529 {
530         int error;
531
532         if (!dev)
533                 return -EINVAL;
534         if (dev->active) {
535                 return 0; /* the device is already active */
536         }
537
538         /* ensure resources are allocated */
539         if (pnp_auto_config_dev(dev))
540                 return -EBUSY;
541
542         error = pnp_start_dev(dev);
543         if (error)
544                 return error;
545
546         dev->active = 1;
547
548         return 1;
549 }
550
551 /**
552  * pnp_disable_dev - disables device
553  * @dev: pointer to the desired device
554  *
555  * inform the correct pnp protocol so that resources can be used by other devices
556  */
557 int pnp_disable_dev(struct pnp_dev *dev)
558 {
559         int error;
560
561         if (!dev)
562                 return -EINVAL;
563         if (!dev->active) {
564                 return 0; /* the device is already disabled */
565         }
566
567         error = pnp_stop_dev(dev);
568         if (error)
569                 return error;
570
571         dev->active = 0;
572
573         /* release the resources so that other devices can use them */
574         down(&pnp_res_mutex);
575         pnp_clean_resource_table(&dev->res);
576         up(&pnp_res_mutex);
577
578         return 1;
579 }
580
581 /**
582  * pnp_resource_change - change one resource
583  * @resource: pointer to resource to be changed
584  * @start: start of region
585  * @size: size of region
586  *
587  */
588 void pnp_resource_change(struct resource *resource, resource_size_t start,
589                                 resource_size_t size)
590 {
591         if (resource == NULL)
592                 return;
593         resource->flags &= ~(IORESOURCE_AUTO | IORESOURCE_UNSET);
594         resource->start = start;
595         resource->end = start + size - 1;
596 }
597
598
599 EXPORT_SYMBOL(pnp_manual_config_dev);
600 #if 0
601 EXPORT_SYMBOL(pnp_auto_config_dev);
602 #endif
603 EXPORT_SYMBOL(pnp_start_dev);
604 EXPORT_SYMBOL(pnp_stop_dev);
605 EXPORT_SYMBOL(pnp_activate_dev);
606 EXPORT_SYMBOL(pnp_disable_dev);
607 EXPORT_SYMBOL(pnp_resource_change);
608 EXPORT_SYMBOL(pnp_init_resource_table);