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
18DECLARE_MUTEX(pnp_res_mutex);
19
20static 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
64static 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
118static 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
171static 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 */
223void 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 */
257static 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 */
297static 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
381fail:
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 */
395int 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
433fail:
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 */
445int 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_dbg("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
482int pnp_start_dev(struct pnp_dev *dev)
483{
484	if (!pnp_can_write(dev)) {
485		pnp_dbg("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
506int pnp_stop_dev(struct pnp_dev *dev)
507{
508	if (!pnp_can_disable(dev)) {
509		pnp_dbg("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 */
528int 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 */
557int 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 */
588void 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
599EXPORT_SYMBOL(pnp_manual_config_dev);
600EXPORT_SYMBOL(pnp_start_dev);
601EXPORT_SYMBOL(pnp_stop_dev);
602EXPORT_SYMBOL(pnp_activate_dev);
603EXPORT_SYMBOL(pnp_disable_dev);
604EXPORT_SYMBOL(pnp_resource_change);
605EXPORT_SYMBOL(pnp_init_resource_table);
606