manager.c revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * manager.c - Resource Management, Conflict Resolution, Activation and Disabling of Devices 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * based on isapnp.c resource management (c) Jaroslav Kysela <perex@suse.cz> 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright 2003 Adam Belay <ambx1@neo.rr.com> 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/config.h> 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h> 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_PNP_DEBUG 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds #define DEBUG 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds #undef DEBUG 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pnp.h> 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "base.h" 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsDECLARE_MUTEX(pnp_res_mutex); 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx) 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long *start, *end, *flags; 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev || !rule) 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (idx >= PNP_MAX_PORT) { 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pnp_err("More than 4 ports is incompatible with pnp specifications."); 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* pretend we were successful so at least the manager won't try again */ 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* check if this resource has been manually set, if so skip */ 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(dev->res.port_resource[idx].flags & IORESOURCE_AUTO)) 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds start = &dev->res.port_resource[idx].start; 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds end = &dev->res.port_resource[idx].end; 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flags = &dev->res.port_resource[idx].flags; 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set the initial values */ 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *flags |= rule->flags | IORESOURCE_IO; 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *flags &= ~IORESOURCE_UNSET; 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!rule->size) { 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *flags |= IORESOURCE_DISABLED; 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; /* skip disabled resource requests */ 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *start = rule->min; 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *end = *start + rule->size - 1; 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* run through until pnp_check_port is happy */ 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (!pnp_check_port(dev, idx)) { 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *start += rule->align; 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *end = *start + rule->size - 1; 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*start > rule->max || !rule->align) 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx) 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long *start, *end, *flags; 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev || !rule) 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (idx >= PNP_MAX_MEM) { 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pnp_err("More than 8 mems is incompatible with pnp specifications."); 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* pretend we were successful so at least the manager won't try again */ 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* check if this resource has been manually set, if so skip */ 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(dev->res.mem_resource[idx].flags & IORESOURCE_AUTO)) 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds start = &dev->res.mem_resource[idx].start; 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds end = &dev->res.mem_resource[idx].end; 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flags = &dev->res.mem_resource[idx].flags; 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set the initial values */ 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *flags |= rule->flags | IORESOURCE_MEM; 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *flags &= ~IORESOURCE_UNSET; 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* convert pnp flags to standard Linux flags */ 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(rule->flags & IORESOURCE_MEM_WRITEABLE)) 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *flags |= IORESOURCE_READONLY; 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rule->flags & IORESOURCE_MEM_CACHEABLE) 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *flags |= IORESOURCE_CACHEABLE; 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rule->flags & IORESOURCE_MEM_RANGELENGTH) 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *flags |= IORESOURCE_RANGELENGTH; 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rule->flags & IORESOURCE_MEM_SHADOWABLE) 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *flags |= IORESOURCE_SHADOWABLE; 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!rule->size) { 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *flags |= IORESOURCE_DISABLED; 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; /* skip disabled resource requests */ 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *start = rule->min; 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *end = *start + rule->size -1; 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* run through until pnp_check_mem is happy */ 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (!pnp_check_mem(dev, idx)) { 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *start += rule->align; 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *end = *start + rule->size - 1; 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*start > rule->max || !rule->align) 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pnp_assign_irq(struct pnp_dev * dev, struct pnp_irq *rule, int idx) 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long *start, *end, *flags; 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* IRQ priority: this table is good for i386 */ 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds static unsigned short xtab[16] = { 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5, 10, 11, 12, 9, 14, 15, 7, 3, 4, 13, 0, 1, 6, 8, 2 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }; 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev || !rule) 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (idx >= PNP_MAX_IRQ) { 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pnp_err("More than 2 irqs is incompatible with pnp specifications."); 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* pretend we were successful so at least the manager won't try again */ 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* check if this resource has been manually set, if so skip */ 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(dev->res.irq_resource[idx].flags & IORESOURCE_AUTO)) 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds start = &dev->res.irq_resource[idx].start; 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds end = &dev->res.irq_resource[idx].end; 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flags = &dev->res.irq_resource[idx].flags; 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set the initial values */ 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *flags |= rule->flags | IORESOURCE_IRQ; 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *flags &= ~IORESOURCE_UNSET; 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bitmap_empty(rule->map, PNP_IRQ_NR)) { 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *flags |= IORESOURCE_DISABLED; 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; /* skip disabled resource requests */ 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* TBD: need check for >16 IRQ */ 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *start = find_next_bit(rule->map, PNP_IRQ_NR, 16); 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*start < PNP_IRQ_NR) { 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *end = *start; 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < 16; i++) { 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(test_bit(xtab[i], rule->map)) { 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *start = *end = xtab[i]; 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(pnp_check_irq(dev, idx)) 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx) 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long *start, *end, *flags; 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* DMA priority: this table is good for i386 */ 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds static unsigned short xtab[8] = { 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1, 3, 5, 6, 7, 0, 2, 4 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }; 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev || !rule) 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (idx >= PNP_MAX_DMA) { 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pnp_err("More than 2 dmas is incompatible with pnp specifications."); 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* pretend we were successful so at least the manager won't try again */ 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* check if this resource has been manually set, if so skip */ 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(dev->res.dma_resource[idx].flags & IORESOURCE_AUTO)) 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds start = &dev->res.dma_resource[idx].start; 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds end = &dev->res.dma_resource[idx].end; 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flags = &dev->res.dma_resource[idx].flags; 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set the initial values */ 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *flags |= rule->flags | IORESOURCE_DMA; 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *flags &= ~IORESOURCE_UNSET; 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!rule->map) { 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *flags |= IORESOURCE_DISABLED; 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; /* skip disabled resource requests */ 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < 8; i++) { 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(rule->map & (1<<xtab[i])) { 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *start = *end = xtab[i]; 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(pnp_check_dma(dev, idx)) 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pnp_init_resources - Resets a resource table to default values. 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @table: pointer to the desired resource table 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid pnp_init_resource_table(struct pnp_resource_table *table) 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int idx; 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (idx = 0; idx < PNP_MAX_IRQ; idx++) { 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds table->irq_resource[idx].name = NULL; 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds table->irq_resource[idx].start = -1; 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds table->irq_resource[idx].end = -1; 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds table->irq_resource[idx].flags = IORESOURCE_IRQ | IORESOURCE_AUTO | IORESOURCE_UNSET; 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (idx = 0; idx < PNP_MAX_DMA; idx++) { 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds table->dma_resource[idx].name = NULL; 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds table->dma_resource[idx].start = -1; 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds table->dma_resource[idx].end = -1; 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds table->dma_resource[idx].flags = IORESOURCE_DMA | IORESOURCE_AUTO | IORESOURCE_UNSET; 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (idx = 0; idx < PNP_MAX_PORT; idx++) { 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds table->port_resource[idx].name = NULL; 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds table->port_resource[idx].start = 0; 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds table->port_resource[idx].end = 0; 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds table->port_resource[idx].flags = IORESOURCE_IO | IORESOURCE_AUTO | IORESOURCE_UNSET; 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (idx = 0; idx < PNP_MAX_MEM; idx++) { 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds table->mem_resource[idx].name = NULL; 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds table->mem_resource[idx].start = 0; 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds table->mem_resource[idx].end = 0; 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds table->mem_resource[idx].flags = IORESOURCE_MEM | IORESOURCE_AUTO | IORESOURCE_UNSET; 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pnp_clean_resources - clears resources that were not manually set 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @res - the resources to clean 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void pnp_clean_resource_table(struct pnp_resource_table * res) 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int idx; 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (idx = 0; idx < PNP_MAX_IRQ; idx++) { 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(res->irq_resource[idx].flags & IORESOURCE_AUTO)) 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res->irq_resource[idx].start = -1; 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res->irq_resource[idx].end = -1; 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res->irq_resource[idx].flags = IORESOURCE_IRQ | IORESOURCE_AUTO | IORESOURCE_UNSET; 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (idx = 0; idx < PNP_MAX_DMA; idx++) { 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(res->dma_resource[idx].flags & IORESOURCE_AUTO)) 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res->dma_resource[idx].start = -1; 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res->dma_resource[idx].end = -1; 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res->dma_resource[idx].flags = IORESOURCE_DMA | IORESOURCE_AUTO | IORESOURCE_UNSET; 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (idx = 0; idx < PNP_MAX_PORT; idx++) { 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(res->port_resource[idx].flags & IORESOURCE_AUTO)) 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res->port_resource[idx].start = 0; 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res->port_resource[idx].end = 0; 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res->port_resource[idx].flags = IORESOURCE_IO | IORESOURCE_AUTO | IORESOURCE_UNSET; 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (idx = 0; idx < PNP_MAX_MEM; idx++) { 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(res->mem_resource[idx].flags & IORESOURCE_AUTO)) 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res->mem_resource[idx].start = 0; 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res->mem_resource[idx].end = 0; 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res->mem_resource[idx].flags = IORESOURCE_MEM | IORESOURCE_AUTO | IORESOURCE_UNSET; 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pnp_assign_resources - assigns resources to the device based on the specified dependent number 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: pointer to the desired device 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @depnum: the dependent function number 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Only set depnum to 0 if the device does not have dependent options. 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pnp_assign_resources(struct pnp_dev *dev, int depnum) 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pnp_port *port; 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pnp_mem *mem; 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pnp_irq *irq; 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pnp_dma *dma; 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int nport = 0, nmem = 0, nirq = 0, ndma = 0; 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!pnp_can_configure(dev)) 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds down(&pnp_res_mutex); 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pnp_clean_resource_table(&dev->res); /* start with a fresh slate */ 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->independent) { 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port = dev->independent->port; 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mem = dev->independent->mem; 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds irq = dev->independent->irq; 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dma = dev->independent->dma; 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (port) { 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!pnp_assign_port(dev, port, nport)) 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail; 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nport++; 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port = port->next; 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (mem) { 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!pnp_assign_mem(dev, mem, nmem)) 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail; 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nmem++; 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mem = mem->next; 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (irq) { 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!pnp_assign_irq(dev, irq, nirq)) 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail; 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nirq++; 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds irq = irq->next; 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (dma) { 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!pnp_assign_dma(dev, dma, ndma)) 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail; 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ndma++; 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dma = dma->next; 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (depnum) { 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pnp_option *dep; 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i=1,dep=dev->dependent; i<depnum; i++, dep=dep->next) 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(!dep) 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail; 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port =dep->port; 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mem = dep->mem; 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds irq = dep->irq; 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dma = dep->dma; 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (port) { 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!pnp_assign_port(dev, port, nport)) 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail; 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nport++; 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port = port->next; 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (mem) { 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!pnp_assign_mem(dev, mem, nmem)) 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail; 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nmem++; 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mem = mem->next; 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (irq) { 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!pnp_assign_irq(dev, irq, nirq)) 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail; 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nirq++; 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds irq = irq->next; 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (dma) { 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!pnp_assign_dma(dev, dma, ndma)) 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail; 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ndma++; 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dma = dma->next; 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (dev->dependent) 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail; 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up(&pnp_res_mutex); 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfail: 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pnp_clean_resource_table(&dev->res); 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up(&pnp_res_mutex); 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pnp_manual_config_dev - Disables Auto Config and Manually sets the resource table 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: pointer to the desired device 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @res: pointer to the new resource config 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This function can be used by drivers that want to manually set thier resources. 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table * res, int mode) 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pnp_resource_table * bak; 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev || !res) 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!pnp_can_configure(dev)) 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bak = pnp_alloc(sizeof(struct pnp_resource_table)); 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!bak) 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *bak = dev->res; 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds down(&pnp_res_mutex); 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->res = *res; 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(mode & PNP_CONFIG_FORCE)) { 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < PNP_MAX_PORT; i++) { 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(!pnp_check_port(dev,i)) 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail; 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < PNP_MAX_MEM; i++) { 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(!pnp_check_mem(dev,i)) 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail; 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < PNP_MAX_IRQ; i++) { 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(!pnp_check_irq(dev,i)) 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail; 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < PNP_MAX_DMA; i++) { 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(!pnp_check_dma(dev,i)) 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail; 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up(&pnp_res_mutex); 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(bak); 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfail: 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->res = *bak; 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up(&pnp_res_mutex); 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(bak); 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pnp_auto_config_dev - automatically assigns resources to a device 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: pointer to the desired device 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint pnp_auto_config_dev(struct pnp_dev *dev) 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pnp_option *dep; 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i = 1; 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(!dev) 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(!pnp_can_configure(dev)) { 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pnp_info("Device %s does not support resource configuration.", dev->dev.bus_id); 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev->dependent) { 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pnp_assign_resources(dev, 0)) 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dep = dev->dependent; 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do { 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pnp_assign_resources(dev, i)) 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dep = dep->next; 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i++; 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } while (dep); 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pnp_err("Unable to assign resources to device %s.", dev->dev.bus_id); 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EBUSY; 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pnp_activate_dev - activates a PnP device for use 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: pointer to the desired device 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * does not validate or set resources so be careful. 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint pnp_activate_dev(struct pnp_dev *dev) 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev) 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->active) { 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; /* the device is already active */ 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ensure resources are allocated */ 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pnp_auto_config_dev(dev)) 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EBUSY; 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!pnp_can_write(dev)) { 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pnp_info("Device %s does not supported activation.", dev->dev.bus_id); 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->protocol->set(dev, &dev->res)<0) { 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pnp_err("Failed to activate device %s.", dev->dev.bus_id); 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->active = 1; 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pnp_info("Device %s activated.", dev->dev.bus_id); 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pnp_disable_dev - disables device 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: pointer to the desired device 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * inform the correct pnp protocol so that resources can be used by other devices 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint pnp_disable_dev(struct pnp_dev *dev) 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev) 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev->active) { 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; /* the device is already disabled */ 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!pnp_can_disable(dev)) { 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pnp_info("Device %s does not supported disabling.", dev->dev.bus_id); 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->protocol->disable(dev)<0) { 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pnp_err("Failed to disable device %s.", dev->dev.bus_id); 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->active = 0; 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pnp_info("Device %s disabled.", dev->dev.bus_id); 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* release the resources so that other devices can use them */ 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds down(&pnp_res_mutex); 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pnp_clean_resource_table(&dev->res); 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up(&pnp_res_mutex); 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pnp_resource_change - change one resource 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @resource: pointer to resource to be changed 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @start: start of region 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @size: size of region 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid pnp_resource_change(struct resource *resource, unsigned long start, unsigned long size) 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (resource == NULL) 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds resource->flags &= ~(IORESOURCE_AUTO | IORESOURCE_UNSET); 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds resource->start = start; 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds resource->end = start + size - 1; 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(pnp_manual_config_dev); 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(pnp_auto_config_dev); 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(pnp_activate_dev); 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(pnp_disable_dev); 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(pnp_resource_change); 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(pnp_init_resource_table); 567