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