xref: /linux/drivers/pnp/manager.c (revision 14b42963f64b98ab61fa9723c03d71aa5ef4f862)
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);
609