/** * pnp_auto_config_dev - automatically assigns resources to a device * @dev: pointer to the desired device * */ int pnp_auto_config_dev(struct pnp_dev *dev) { struct pnp_option *dep; int i = 1; if(!dev) return -EINVAL; if(!pnp_can_configure(dev)) { pnp_info("Device %s does not support resource configuration.", dev->dev.bus_id); return -ENODEV; } if (!dev->dependent) { if (pnp_assign_resources(dev, 0)) return 0; } else { dep = dev->dependent; do { if (pnp_assign_resources(dev, i)) return 0; dep = dep->next; i++; } while (dep); } pnp_err("Unable to assign resources to device %s.", dev->dev.bus_id); return -EBUSY; }
/** * pnp_auto_config_dev - automatically assigns resources to a device * @dev: pointer to the desired device */ int pnp_auto_config_dev(struct pnp_dev *dev) { struct pnp_option *dep; int i = 1; if (!pnp_can_configure(dev)) { dev_dbg(&dev->dev, "configuration not supported\n"); return -ENODEV; } if (!dev->dependent) { if (pnp_assign_resources(dev, 0)) return 0; } else { dep = dev->dependent; do { if (pnp_assign_resources(dev, i)) return 0; dep = dep->next; i++; } while (dep); } dev_err(&dev->dev, "unable to assign resources\n"); return -EBUSY; }
/** * pnp_manual_config_dev - Disables Auto Config and Manually sets the resource table * @dev: pointer to the desired device * @res: pointer to the new resource config * @mode: 0 or PNP_CONFIG_FORCE * * This function can be used by drivers that want to manually set thier resources. */ int pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table * res, int mode) { int i; struct pnp_resource_table * bak; if (!dev || !res) return -EINVAL; if (!pnp_can_configure(dev)) return -ENODEV; bak = pnp_alloc(sizeof(struct pnp_resource_table)); if (!bak) return -ENOMEM; *bak = dev->res; down(&pnp_res_mutex); dev->res = *res; if (!(mode & PNP_CONFIG_FORCE)) { for (i = 0; i < PNP_MAX_PORT; i++) { if(!pnp_check_port(dev,i)) goto fail; } for (i = 0; i < PNP_MAX_MEM; i++) { if(!pnp_check_mem(dev,i)) goto fail; } for (i = 0; i < PNP_MAX_IRQ; i++) { if(!pnp_check_irq(dev,i)) goto fail; } for (i = 0; i < PNP_MAX_DMA; i++) { if(!pnp_check_dma(dev,i)) goto fail; } } up(&pnp_res_mutex); kfree(bak); return 0; fail: dev->res = *bak; up(&pnp_res_mutex); kfree(bak); return -EINVAL; }
/** * pnp_assign_resources - assigns resources to the device based on the specified dependent number * @dev: pointer to the desired device * @depnum: the dependent function number * * Only set depnum to 0 if the device does not have dependent options. */ static int pnp_assign_resources(struct pnp_dev *dev, int depnum) { struct pnp_port *port; struct pnp_mem *mem; struct pnp_irq *irq; struct pnp_dma *dma; int nport = 0, nmem = 0, nirq = 0, ndma = 0; if (!pnp_can_configure(dev)) return -ENODEV; down(&pnp_res_mutex); pnp_clean_resource_table(&dev->res); /* start with a fresh slate */ if (dev->independent) { port = dev->independent->port; mem = dev->independent->mem; irq = dev->independent->irq; dma = dev->independent->dma; while (port) { if (!pnp_assign_port(dev, port, nport)) goto fail; nport++; port = port->next; } while (mem) { if (!pnp_assign_mem(dev, mem, nmem)) goto fail; nmem++; mem = mem->next; } while (irq) { if (!pnp_assign_irq(dev, irq, nirq)) goto fail; nirq++; irq = irq->next; } while (dma) { if (!pnp_assign_dma(dev, dma, ndma)) goto fail; ndma++; dma = dma->next; } } if (depnum) { struct pnp_option *dep; int i; for (i=1,dep=dev->dependent; i<depnum; i++, dep=dep->next) if(!dep) goto fail; port =dep->port; mem = dep->mem; irq = dep->irq; dma = dep->dma; while (port) { if (!pnp_assign_port(dev, port, nport)) goto fail; nport++; port = port->next; } while (mem) { if (!pnp_assign_mem(dev, mem, nmem)) goto fail; nmem++; mem = mem->next; } while (irq) { if (!pnp_assign_irq(dev, irq, nirq)) goto fail; nirq++; irq = irq->next; } while (dma) { if (!pnp_assign_dma(dev, dma, ndma)) goto fail; ndma++; dma = dma->next; } } else if (dev->dependent) goto fail; up(&pnp_res_mutex); return 1; fail: pnp_clean_resource_table(&dev->res); up(&pnp_res_mutex); return 0; }
/** * pnp_assign_resources - assigns resources to the device based on the specified dependent number * @dev: pointer to the desired device * @depnum: the dependent function number * * Only set depnum to 0 if the device does not have dependent options. */ static int pnp_assign_resources(struct pnp_dev *dev, int depnum) { struct pnp_port *port; struct pnp_mem *mem; struct pnp_irq *irq; struct pnp_dma *dma; int nport = 0, nmem = 0, nirq = 0, ndma = 0; if (!pnp_can_configure(dev)) return -ENODEV; dbg_pnp_show_resources(dev, "before pnp_assign_resources"); mutex_lock(&pnp_res_mutex); pnp_clean_resource_table(dev); if (dev->independent) { dev_dbg(&dev->dev, "assigning independent options\n"); port = dev->independent->port; mem = dev->independent->mem; irq = dev->independent->irq; dma = dev->independent->dma; while (port) { if (!pnp_assign_port(dev, port, nport)) goto fail; nport++; port = port->next; } while (mem) { if (!pnp_assign_mem(dev, mem, nmem)) goto fail; nmem++; mem = mem->next; } while (irq) { if (!pnp_assign_irq(dev, irq, nirq)) goto fail; nirq++; irq = irq->next; } while (dma) { pnp_assign_dma(dev, dma, ndma); ndma++; dma = dma->next; } } if (depnum) { struct pnp_option *dep; int i; dev_dbg(&dev->dev, "assigning dependent option %d\n", depnum); for (i = 1, dep = dev->dependent; i < depnum; i++, dep = dep->next) if (!dep) goto fail; port = dep->port; mem = dep->mem; irq = dep->irq; dma = dep->dma; while (port) { if (!pnp_assign_port(dev, port, nport)) goto fail; nport++; port = port->next; } while (mem) { if (!pnp_assign_mem(dev, mem, nmem)) goto fail; nmem++; mem = mem->next; } while (irq) { if (!pnp_assign_irq(dev, irq, nirq)) goto fail; nirq++; irq = irq->next; } while (dma) { pnp_assign_dma(dev, dma, ndma); ndma++; dma = dma->next; } } else if (dev->dependent) goto fail; mutex_unlock(&pnp_res_mutex); dbg_pnp_show_resources(dev, "after pnp_assign_resources"); return 1; fail: pnp_clean_resource_table(dev); mutex_unlock(&pnp_res_mutex); dbg_pnp_show_resources(dev, "after pnp_assign_resources (failed)"); return 0; }