manager.c revision 07d4e9af109221ab731c5aaf832e89776c64b013
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#include <linux/errno.h> 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pnp.h> 134e57b6817880946a3a78d5d8cad1ace363f7e449Tim Schmielau#include <linux/slab.h> 144e57b6817880946a3a78d5d8cad1ace363f7e449Tim Schmielau#include <linux/bitmap.h> 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "base.h" 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsDECLARE_MUTEX(pnp_res_mutex); 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx) 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 21b60ba8343b78b182c03cf239d4342785376c1ad1Greg Kroah-Hartman resource_size_t *start, *end; 22b60ba8343b78b182c03cf239d4342785376c1ad1Greg Kroah-Hartman unsigned long *flags; 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev || !rule) 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (idx >= PNP_MAX_PORT) { 289dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas pnp_err 299dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas ("More than 4 ports is incompatible with pnp specifications."); 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* pretend we were successful so at least the manager won't try again */ 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* check if this resource has been manually set, if so skip */ 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(dev->res.port_resource[idx].flags & IORESOURCE_AUTO)) 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds start = &dev->res.port_resource[idx].start; 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds end = &dev->res.port_resource[idx].end; 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flags = &dev->res.port_resource[idx].flags; 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set the initial values */ 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *flags |= rule->flags | IORESOURCE_IO; 449dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas *flags &= ~IORESOURCE_UNSET; 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!rule->size) { 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *flags |= IORESOURCE_DISABLED; 489dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas return 1; /* skip disabled resource requests */ 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *start = rule->min; 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *end = *start + rule->size - 1; 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* run through until pnp_check_port is happy */ 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (!pnp_check_port(dev, idx)) { 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *start += rule->align; 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *end = *start + rule->size - 1; 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*start > rule->max || !rule->align) 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx) 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 66b60ba8343b78b182c03cf239d4342785376c1ad1Greg Kroah-Hartman resource_size_t *start, *end; 67b60ba8343b78b182c03cf239d4342785376c1ad1Greg Kroah-Hartman unsigned long *flags; 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev || !rule) 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (idx >= PNP_MAX_MEM) { 739dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas pnp_err 749dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas ("More than 8 mems is incompatible with pnp specifications."); 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* pretend we were successful so at least the manager won't try again */ 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* check if this resource has been manually set, if so skip */ 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(dev->res.mem_resource[idx].flags & IORESOURCE_AUTO)) 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds start = &dev->res.mem_resource[idx].start; 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds end = &dev->res.mem_resource[idx].end; 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flags = &dev->res.mem_resource[idx].flags; 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set the initial values */ 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *flags |= rule->flags | IORESOURCE_MEM; 899dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas *flags &= ~IORESOURCE_UNSET; 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* convert pnp flags to standard Linux flags */ 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(rule->flags & IORESOURCE_MEM_WRITEABLE)) 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *flags |= IORESOURCE_READONLY; 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rule->flags & IORESOURCE_MEM_CACHEABLE) 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *flags |= IORESOURCE_CACHEABLE; 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rule->flags & IORESOURCE_MEM_RANGELENGTH) 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *flags |= IORESOURCE_RANGELENGTH; 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rule->flags & IORESOURCE_MEM_SHADOWABLE) 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *flags |= IORESOURCE_SHADOWABLE; 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!rule->size) { 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *flags |= IORESOURCE_DISABLED; 1039dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas return 1; /* skip disabled resource requests */ 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *start = rule->min; 1079dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas *end = *start + rule->size - 1; 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* run through until pnp_check_mem is happy */ 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (!pnp_check_mem(dev, idx)) { 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *start += rule->align; 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *end = *start + rule->size - 1; 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*start > rule->max || !rule->align) 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1199dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaasstatic int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx) 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 121b60ba8343b78b182c03cf239d4342785376c1ad1Greg Kroah-Hartman resource_size_t *start, *end; 122b60ba8343b78b182c03cf239d4342785376c1ad1Greg Kroah-Hartman unsigned long *flags; 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* IRQ priority: this table is good for i386 */ 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds static unsigned short xtab[16] = { 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5, 10, 11, 12, 9, 14, 15, 7, 3, 4, 13, 0, 1, 6, 8, 2 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }; 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev || !rule) 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (idx >= PNP_MAX_IRQ) { 1349dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas pnp_err 1359dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas ("More than 2 irqs is incompatible with pnp specifications."); 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* pretend we were successful so at least the manager won't try again */ 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* check if this resource has been manually set, if so skip */ 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(dev->res.irq_resource[idx].flags & IORESOURCE_AUTO)) 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds start = &dev->res.irq_resource[idx].start; 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds end = &dev->res.irq_resource[idx].end; 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flags = &dev->res.irq_resource[idx].flags; 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set the initial values */ 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *flags |= rule->flags | IORESOURCE_IRQ; 1509dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas *flags &= ~IORESOURCE_UNSET; 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bitmap_empty(rule->map, PNP_IRQ_NR)) { 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *flags |= IORESOURCE_DISABLED; 1549dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas return 1; /* skip disabled resource requests */ 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* TBD: need check for >16 IRQ */ 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *start = find_next_bit(rule->map, PNP_IRQ_NR, 16); 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (*start < PNP_IRQ_NR) { 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *end = *start; 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < 16; i++) { 1649dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas if (test_bit(xtab[i], rule->map)) { 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *start = *end = xtab[i]; 1669dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas if (pnp_check_irq(dev, idx)) 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx) 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 175b60ba8343b78b182c03cf239d4342785376c1ad1Greg Kroah-Hartman resource_size_t *start, *end; 176b60ba8343b78b182c03cf239d4342785376c1ad1Greg Kroah-Hartman unsigned long *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) { 1889dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas pnp_err 1899dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas ("More than 2 dmas is incompatible with pnp specifications."); 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* pretend we were successful so at least the manager won't try again */ 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* check if this resource has been manually set, if so skip */ 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(dev->res.dma_resource[idx].flags & IORESOURCE_AUTO)) 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds start = &dev->res.dma_resource[idx].start; 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds end = &dev->res.dma_resource[idx].end; 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flags = &dev->res.dma_resource[idx].flags; 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* set the initial values */ 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *flags |= rule->flags | IORESOURCE_DMA; 2049dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas *flags &= ~IORESOURCE_UNSET; 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!rule->map) { 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *flags |= IORESOURCE_DISABLED; 2089dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas return 1; /* skip disabled resource requests */ 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < 8; i++) { 2129dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas if (rule->map & (1 << xtab[i])) { 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *start = *end = xtab[i]; 2149dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas if (pnp_check_dma(dev, idx)) 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pnp_init_resources - Resets a resource table to default values. 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @table: pointer to the desired resource table 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid pnp_init_resource_table(struct pnp_resource_table *table) 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int idx; 22807d4e9af109221ab731c5aaf832e89776c64b013Bjorn Helgaas 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (idx = 0; idx < PNP_MAX_IRQ; idx++) { 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds table->irq_resource[idx].name = NULL; 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds table->irq_resource[idx].start = -1; 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds table->irq_resource[idx].end = -1; 2339dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas table->irq_resource[idx].flags = 2349dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas IORESOURCE_IRQ | IORESOURCE_AUTO | IORESOURCE_UNSET; 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (idx = 0; idx < PNP_MAX_DMA; idx++) { 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds table->dma_resource[idx].name = NULL; 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds table->dma_resource[idx].start = -1; 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds table->dma_resource[idx].end = -1; 2409dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas table->dma_resource[idx].flags = 2419dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas IORESOURCE_DMA | IORESOURCE_AUTO | IORESOURCE_UNSET; 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (idx = 0; idx < PNP_MAX_PORT; idx++) { 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds table->port_resource[idx].name = NULL; 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds table->port_resource[idx].start = 0; 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds table->port_resource[idx].end = 0; 2479dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas table->port_resource[idx].flags = 2489dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas IORESOURCE_IO | IORESOURCE_AUTO | IORESOURCE_UNSET; 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (idx = 0; idx < PNP_MAX_MEM; idx++) { 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds table->mem_resource[idx].name = NULL; 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds table->mem_resource[idx].start = 0; 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds table->mem_resource[idx].end = 0; 2549dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas table->mem_resource[idx].flags = 2559dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas IORESOURCE_MEM | IORESOURCE_AUTO | IORESOURCE_UNSET; 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pnp_clean_resources - clears resources that were not manually set 26167be2dd1bace0ec7ce2dbc1bba3f8df3d7be597eMartin Waitz * @res: the resources to clean 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2639dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaasstatic void pnp_clean_resource_table(struct pnp_resource_table *res) 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int idx; 26607d4e9af109221ab731c5aaf832e89776c64b013Bjorn Helgaas 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (idx = 0; idx < PNP_MAX_IRQ; idx++) { 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(res->irq_resource[idx].flags & IORESOURCE_AUTO)) 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res->irq_resource[idx].start = -1; 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res->irq_resource[idx].end = -1; 2729dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas res->irq_resource[idx].flags = 2739dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas IORESOURCE_IRQ | IORESOURCE_AUTO | IORESOURCE_UNSET; 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (idx = 0; idx < PNP_MAX_DMA; idx++) { 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(res->dma_resource[idx].flags & IORESOURCE_AUTO)) 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res->dma_resource[idx].start = -1; 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res->dma_resource[idx].end = -1; 2809dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas res->dma_resource[idx].flags = 2819dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas IORESOURCE_DMA | IORESOURCE_AUTO | IORESOURCE_UNSET; 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (idx = 0; idx < PNP_MAX_PORT; idx++) { 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(res->port_resource[idx].flags & IORESOURCE_AUTO)) 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res->port_resource[idx].start = 0; 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res->port_resource[idx].end = 0; 2889dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas res->port_resource[idx].flags = 2899dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas IORESOURCE_IO | IORESOURCE_AUTO | IORESOURCE_UNSET; 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (idx = 0; idx < PNP_MAX_MEM; idx++) { 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(res->mem_resource[idx].flags & IORESOURCE_AUTO)) 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res->mem_resource[idx].start = 0; 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds res->mem_resource[idx].end = 0; 2969dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas res->mem_resource[idx].flags = 2979dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas IORESOURCE_MEM | IORESOURCE_AUTO | IORESOURCE_UNSET; 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pnp_assign_resources - assigns resources to the device based on the specified dependent number 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: pointer to the desired device 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @depnum: the dependent function number 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Only set depnum to 0 if the device does not have dependent options. 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pnp_assign_resources(struct pnp_dev *dev, int depnum) 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pnp_port *port; 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pnp_mem *mem; 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pnp_irq *irq; 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pnp_dma *dma; 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int nport = 0, nmem = 0, nirq = 0, ndma = 0; 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!pnp_can_configure(dev)) 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds down(&pnp_res_mutex); 3209dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas pnp_clean_resource_table(&dev->res); /* start with a fresh slate */ 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->independent) { 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port = dev->independent->port; 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mem = dev->independent->mem; 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds irq = dev->independent->irq; 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dma = dev->independent->dma; 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (port) { 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!pnp_assign_port(dev, port, nport)) 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail; 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nport++; 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port = port->next; 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (mem) { 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!pnp_assign_mem(dev, mem, nmem)) 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail; 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nmem++; 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mem = mem->next; 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (irq) { 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!pnp_assign_irq(dev, irq, nirq)) 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail; 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nirq++; 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds irq = irq->next; 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (dma) { 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!pnp_assign_dma(dev, dma, ndma)) 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail; 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ndma++; 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dma = dma->next; 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (depnum) { 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pnp_option *dep; 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 3559dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas for (i = 1, dep = dev->dependent; i < depnum; 3569dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas i++, dep = dep->next) 3579dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas if (!dep) 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail; 3599dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas port = dep->port; 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mem = dep->mem; 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds irq = dep->irq; 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dma = dep->dma; 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (port) { 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!pnp_assign_port(dev, port, nport)) 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail; 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nport++; 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port = port->next; 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (mem) { 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!pnp_assign_mem(dev, mem, nmem)) 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail; 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nmem++; 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mem = mem->next; 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (irq) { 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!pnp_assign_irq(dev, irq, nirq)) 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail; 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nirq++; 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds irq = irq->next; 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (dma) { 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!pnp_assign_dma(dev, dma, ndma)) 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail; 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ndma++; 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dma = dma->next; 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (dev->dependent) 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail; 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up(&pnp_res_mutex); 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3939dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas fail: 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pnp_clean_resource_table(&dev->res); 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up(&pnp_res_mutex); 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pnp_manual_config_dev - Disables Auto Config and Manually sets the resource table 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: pointer to the desired device 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @res: pointer to the new resource config 4033d41088fa327782b14b5659dbcfff62ec704c23cMartin Waitz * @mode: 0 or PNP_CONFIG_FORCE 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This function can be used by drivers that want to manually set thier resources. 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4079dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaasint pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table *res, 4089dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas int mode) 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 4119dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas struct pnp_resource_table *bak; 41207d4e9af109221ab731c5aaf832e89776c64b013Bjorn Helgaas 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev || !res) 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!pnp_can_configure(dev)) 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bak = pnp_alloc(sizeof(struct pnp_resource_table)); 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!bak) 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *bak = dev->res; 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds down(&pnp_res_mutex); 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->res = *res; 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(mode & PNP_CONFIG_FORCE)) { 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < PNP_MAX_PORT; i++) { 4269dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas if (!pnp_check_port(dev, i)) 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail; 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < PNP_MAX_MEM; i++) { 4309dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas if (!pnp_check_mem(dev, i)) 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail; 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < PNP_MAX_IRQ; i++) { 4349dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas if (!pnp_check_irq(dev, i)) 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail; 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < PNP_MAX_DMA; i++) { 4389dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas if (!pnp_check_dma(dev, i)) 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail; 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up(&pnp_res_mutex); 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(bak); 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4479dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas fail: 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->res = *bak; 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up(&pnp_res_mutex); 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(bak); 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pnp_auto_config_dev - automatically assigns resources to a device 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: pointer to the desired device 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint pnp_auto_config_dev(struct pnp_dev *dev) 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pnp_option *dep; 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i = 1; 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4639dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas if (!dev) 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4669dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas if (!pnp_can_configure(dev)) { 4679dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas pnp_dbg("Device %s does not support resource configuration.", 4689dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas dev->dev.bus_id); 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev->dependent) { 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pnp_assign_resources(dev, 0)) 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dep = dev->dependent; 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do { 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pnp_assign_resources(dev, i)) 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dep = dep->next; 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i++; 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } while (dep); 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pnp_err("Unable to assign resources to device %s.", dev->dev.bus_id); 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EBUSY; 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 49068094e3251a664ee1389fcf179497237cbf78331Pierre Ossman * pnp_start_dev - low-level start of the PnP device 49168094e3251a664ee1389fcf179497237cbf78331Pierre Ossman * @dev: pointer to the desired device 49268094e3251a664ee1389fcf179497237cbf78331Pierre Ossman * 49307d4e9af109221ab731c5aaf832e89776c64b013Bjorn Helgaas * assumes that resources have already been allocated 49468094e3251a664ee1389fcf179497237cbf78331Pierre Ossman */ 49568094e3251a664ee1389fcf179497237cbf78331Pierre Ossmanint pnp_start_dev(struct pnp_dev *dev) 49668094e3251a664ee1389fcf179497237cbf78331Pierre Ossman{ 49768094e3251a664ee1389fcf179497237cbf78331Pierre Ossman if (!pnp_can_write(dev)) { 4989dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas pnp_dbg("Device %s does not support activation.", 4999dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas dev->dev.bus_id); 50068094e3251a664ee1389fcf179497237cbf78331Pierre Ossman return -EINVAL; 50168094e3251a664ee1389fcf179497237cbf78331Pierre Ossman } 50268094e3251a664ee1389fcf179497237cbf78331Pierre Ossman 5039dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas if (dev->protocol->set(dev, &dev->res) < 0) { 50468094e3251a664ee1389fcf179497237cbf78331Pierre Ossman pnp_err("Failed to activate device %s.", dev->dev.bus_id); 50568094e3251a664ee1389fcf179497237cbf78331Pierre Ossman return -EIO; 50668094e3251a664ee1389fcf179497237cbf78331Pierre Ossman } 50768094e3251a664ee1389fcf179497237cbf78331Pierre Ossman 50868094e3251a664ee1389fcf179497237cbf78331Pierre Ossman pnp_info("Device %s activated.", dev->dev.bus_id); 50968094e3251a664ee1389fcf179497237cbf78331Pierre Ossman return 0; 51068094e3251a664ee1389fcf179497237cbf78331Pierre Ossman} 51168094e3251a664ee1389fcf179497237cbf78331Pierre Ossman 51268094e3251a664ee1389fcf179497237cbf78331Pierre Ossman/** 51368094e3251a664ee1389fcf179497237cbf78331Pierre Ossman * pnp_stop_dev - low-level disable of the PnP device 51468094e3251a664ee1389fcf179497237cbf78331Pierre Ossman * @dev: pointer to the desired device 51568094e3251a664ee1389fcf179497237cbf78331Pierre Ossman * 51668094e3251a664ee1389fcf179497237cbf78331Pierre Ossman * does not free resources 51768094e3251a664ee1389fcf179497237cbf78331Pierre Ossman */ 51868094e3251a664ee1389fcf179497237cbf78331Pierre Ossmanint pnp_stop_dev(struct pnp_dev *dev) 51968094e3251a664ee1389fcf179497237cbf78331Pierre Ossman{ 52068094e3251a664ee1389fcf179497237cbf78331Pierre Ossman if (!pnp_can_disable(dev)) { 5219dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas pnp_dbg("Device %s does not support disabling.", 5229dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas dev->dev.bus_id); 52368094e3251a664ee1389fcf179497237cbf78331Pierre Ossman return -EINVAL; 52468094e3251a664ee1389fcf179497237cbf78331Pierre Ossman } 5259dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas if (dev->protocol->disable(dev) < 0) { 52668094e3251a664ee1389fcf179497237cbf78331Pierre Ossman pnp_err("Failed to disable device %s.", dev->dev.bus_id); 52768094e3251a664ee1389fcf179497237cbf78331Pierre Ossman return -EIO; 52868094e3251a664ee1389fcf179497237cbf78331Pierre Ossman } 52968094e3251a664ee1389fcf179497237cbf78331Pierre Ossman 53068094e3251a664ee1389fcf179497237cbf78331Pierre Ossman pnp_info("Device %s disabled.", dev->dev.bus_id); 53168094e3251a664ee1389fcf179497237cbf78331Pierre Ossman return 0; 53268094e3251a664ee1389fcf179497237cbf78331Pierre Ossman} 53368094e3251a664ee1389fcf179497237cbf78331Pierre Ossman 53468094e3251a664ee1389fcf179497237cbf78331Pierre Ossman/** 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pnp_activate_dev - activates a PnP device for use 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: pointer to the desired device 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * does not validate or set resources so be careful. 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint pnp_activate_dev(struct pnp_dev *dev) 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 54268094e3251a664ee1389fcf179497237cbf78331Pierre Ossman int error; 54368094e3251a664ee1389fcf179497237cbf78331Pierre Ossman 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev) 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 54607d4e9af109221ab731c5aaf832e89776c64b013Bjorn Helgaas if (dev->active) 5479dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas return 0; /* the device is already active */ 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ensure resources are allocated */ 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pnp_auto_config_dev(dev)) 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EBUSY; 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 55368094e3251a664ee1389fcf179497237cbf78331Pierre Ossman error = pnp_start_dev(dev); 55468094e3251a664ee1389fcf179497237cbf78331Pierre Ossman if (error) 55568094e3251a664ee1389fcf179497237cbf78331Pierre Ossman return error; 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->active = 1; 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pnp_disable_dev - disables device 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: pointer to the desired device 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * inform the correct pnp protocol so that resources can be used by other devices 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint pnp_disable_dev(struct pnp_dev *dev) 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 56968094e3251a664ee1389fcf179497237cbf78331Pierre Ossman int error; 57068094e3251a664ee1389fcf179497237cbf78331Pierre Ossman 5719dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas if (!dev) 5729dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas return -EINVAL; 57307d4e9af109221ab731c5aaf832e89776c64b013Bjorn Helgaas if (!dev->active) 5749dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas return 0; /* the device is already disabled */ 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 57668094e3251a664ee1389fcf179497237cbf78331Pierre Ossman error = pnp_stop_dev(dev); 57768094e3251a664ee1389fcf179497237cbf78331Pierre Ossman if (error) 57868094e3251a664ee1389fcf179497237cbf78331Pierre Ossman return error; 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->active = 0; 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* release the resources so that other devices can use them */ 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds down(&pnp_res_mutex); 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pnp_clean_resource_table(&dev->res); 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds up(&pnp_res_mutex); 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pnp_resource_change - change one resource 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @resource: pointer to resource to be changed 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @start: start of region 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @size: size of region 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 596b60ba8343b78b182c03cf239d4342785376c1ad1Greg Kroah-Hartmanvoid pnp_resource_change(struct resource *resource, resource_size_t start, 5979dd78466c956ac4b4f38e12032dc4249ccf57ad1Bjorn Helgaas resource_size_t size) 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (resource == NULL) 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds resource->flags &= ~(IORESOURCE_AUTO | IORESOURCE_UNSET); 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds resource->start = start; 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds resource->end = start + size - 1; 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(pnp_manual_config_dev); 60768094e3251a664ee1389fcf179497237cbf78331Pierre OssmanEXPORT_SYMBOL(pnp_start_dev); 60868094e3251a664ee1389fcf179497237cbf78331Pierre OssmanEXPORT_SYMBOL(pnp_stop_dev); 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(pnp_activate_dev); 6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(pnp_disable_dev); 6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(pnp_resource_change); 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(pnp_init_resource_table); 613