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