acpi_status pnpacpi_parse_allocated_resource(acpi_handle handle, struct pnp_resource_table * res) { /* Blank the resource table values */ pnp_init_resource_table(res); return acpi_walk_resources(handle, METHOD_NAME__CRS, pnpacpi_allocated_resource, res); }
static int __init pnpacpi_add_device(struct acpi_device *device) { acpi_handle temp = NULL; acpi_status status; struct pnp_id *dev_id; struct pnp_dev *dev; if (!ispnpidacpi(acpi_device_hid(device)) || is_exclusive_device(device)) return 0; pnp_dbg("ACPI device : hid %s", acpi_device_hid(device)); dev = kcalloc(1, sizeof(struct pnp_dev), GFP_KERNEL); if (!dev) { pnp_err("Out of memory"); return -ENOMEM; } dev->data = device->handle; /* .enabled means if the device can decode the resources */ dev->active = device->status.enabled; status = acpi_get_handle(device->handle, "_SRS", &temp); if (ACPI_SUCCESS(status)) dev->capabilities |= PNP_CONFIGURABLE; dev->capabilities |= PNP_READ; if (device->flags.dynamic_status) dev->capabilities |= PNP_WRITE; if (device->flags.removable) dev->capabilities |= PNP_REMOVABLE; status = acpi_get_handle(device->handle, "_DIS", &temp); if (ACPI_SUCCESS(status)) dev->capabilities |= PNP_DISABLE; dev->protocol = &pnpacpi_protocol; if (strlen(acpi_device_name(device))) strncpy(dev->name, acpi_device_name(device), sizeof(dev->name)); else strncpy(dev->name, acpi_device_bid(device), sizeof(dev->name)); dev->number = num; /* set the initial values for the PnP device */ dev_id = kcalloc(1, sizeof(struct pnp_id), GFP_KERNEL); if (!dev_id) goto err; pnpidacpi_to_pnpid(acpi_device_hid(device), dev_id->id); pnp_add_id(dev_id, dev); if(dev->active) { /* parse allocated resource */ status = pnpacpi_parse_allocated_resource(device->handle, &dev->res); if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) { pnp_err("PnPACPI: METHOD_NAME__CRS failure for %s", dev_id->id); goto err1; } } if(dev->capabilities & PNP_CONFIGURABLE) { status = pnpacpi_parse_resource_option_data(device->handle, dev); if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND)) { pnp_err("PnPACPI: METHOD_NAME__PRS failure for %s", dev_id->id); goto err1; } } /* parse compatible ids */ if (device->flags.compatible_ids) { struct acpi_compatible_id_list *cid_list = device->pnp.cid_list; int i; for (i = 0; i < cid_list->count; i++) { if (!ispnpidacpi(cid_list->id[i].value)) continue; dev_id = kcalloc(1, sizeof(struct pnp_id), GFP_KERNEL); if (!dev_id) continue; pnpidacpi_to_pnpid(cid_list->id[i].value, dev_id->id); pnp_add_id(dev_id, dev); } } /* clear out the damaged flags */ if (!dev->active) pnp_init_resource_table(&dev->res); pnp_add_device(dev); num ++; return AE_OK; err1: kfree(dev_id); err: kfree(dev); return -EINVAL; }
static int __devinit snd_wavefront_pnp (int dev, snd_wavefront_card_t *acard, struct pnp_card_link *card, const struct pnp_card_device_id *id) { struct pnp_dev *pdev; struct pnp_resource_table *cfg = kmalloc(sizeof(*cfg), GFP_KERNEL); int err; if (!cfg) return -ENOMEM; /* Check for each logical device. */ /* CS4232 chip (aka "windows sound system") is logical device 0 */ acard->wss = pnp_request_card_device(card, id->devs[0].id, NULL); if (acard->wss == NULL) { kfree(cfg); return -EBUSY; } /* there is a game port at logical device 1, but we ignore it completely */ /* the control interface is logical device 2, but we ignore it completely. in fact, nobody even seems to know what it does. */ /* Only configure the CS4232 MIDI interface if its been specifically requested. It is logical device 3. */ if (use_cs4232_midi[dev]) { acard->mpu = pnp_request_card_device(card, id->devs[2].id, NULL); if (acard->mpu == NULL) { kfree(cfg); return -EBUSY; } } /* The ICS2115 synth is logical device 4 */ acard->synth = pnp_request_card_device(card, id->devs[3].id, NULL); if (acard->synth == NULL) { kfree(cfg); return -EBUSY; } /* PCM/FM initialization */ pdev = acard->wss; pnp_init_resource_table(cfg); /* An interesting note from the Tropez+ FAQ: Q. [Ports] Why is the base address of the WSS I/O ports off by 4? A. WSS I/O requires a block of 8 I/O addresses ("ports"). Of these, the first 4 are used to identify and configure the board. With the advent of PnP, these first 4 addresses have become obsolete, and software applications only use the last 4 addresses to control the codec chip. Therefore, the base address setting "skips past" the 4 unused addresses. */ if (cs4232_pcm_port[dev] != SNDRV_AUTO_PORT) pnp_resource_change(&cfg->port_resource[0], cs4232_pcm_port[dev], 4); if (fm_port[dev] != SNDRV_AUTO_PORT) pnp_resource_change(&cfg->port_resource[1], fm_port[dev], 4); if (dma1[dev] != SNDRV_AUTO_DMA) pnp_resource_change(&cfg->dma_resource[0], dma1[dev], 1); if (dma2[dev] != SNDRV_AUTO_DMA) pnp_resource_change(&cfg->dma_resource[1], dma2[dev], 1); if (cs4232_pcm_irq[dev] != SNDRV_AUTO_IRQ) pnp_resource_change(&cfg->irq_resource[0], cs4232_pcm_irq[dev], 1); if (pnp_manual_config_dev(pdev, cfg, 0) < 0) snd_printk(KERN_ERR "PnP WSS the requested resources are invalid, using auto config\n"); err = pnp_activate_dev(pdev); if (err < 0) { snd_printk(KERN_ERR "PnP WSS pnp configure failure\n"); kfree(cfg); return err; } cs4232_pcm_port[dev] = pnp_port_start(pdev, 0); fm_port[dev] = pnp_port_start(pdev, 1); dma1[dev] = pnp_dma(pdev, 0); dma2[dev] = pnp_dma(pdev, 1); cs4232_pcm_irq[dev] = pnp_irq(pdev, 0); /* Synth initialization */ pdev = acard->synth; pnp_init_resource_table(cfg); if (ics2115_port[dev] != SNDRV_AUTO_PORT) { pnp_resource_change(&cfg->port_resource[0], ics2115_port[dev], 16); } if (ics2115_port[dev] != SNDRV_AUTO_IRQ) { pnp_resource_change(&cfg->irq_resource[0], ics2115_irq[dev], 1); } if (pnp_manual_config_dev(pdev, cfg, 0) < 0) snd_printk(KERN_ERR "PnP ICS2115 the requested resources are invalid, using auto config\n"); err = pnp_activate_dev(pdev); if (err < 0) { snd_printk(KERN_ERR "PnP ICS2115 pnp configure failure\n"); kfree(cfg); return err; } ics2115_port[dev] = pnp_port_start(pdev, 0); ics2115_irq[dev] = pnp_irq(pdev, 0); /* CS4232 MPU initialization. Configure this only if explicitly requested, since its physically inaccessible and consumes another IRQ. */ if (use_cs4232_midi[dev]) { pdev = acard->mpu; pnp_init_resource_table(cfg); if (cs4232_mpu_port[dev] != SNDRV_AUTO_PORT) pnp_resource_change(&cfg->port_resource[0], cs4232_mpu_port[dev], 2); if (cs4232_mpu_irq[dev] != SNDRV_AUTO_IRQ) pnp_resource_change(&cfg->port_resource[0], cs4232_mpu_irq[dev], 1); if (pnp_manual_config_dev(pdev, cfg, 0) < 0) snd_printk(KERN_ERR "PnP MPU401 the requested resources are invalid, using auto config\n"); err = pnp_activate_dev(pdev); if (err < 0) { snd_printk(KERN_ERR "PnP MPU401 pnp configure failure\n"); cs4232_mpu_port[dev] = SNDRV_AUTO_PORT; } else { cs4232_mpu_port[dev] = pnp_port_start(pdev, 0); cs4232_mpu_irq[dev] = pnp_irq(pdev, 0); } snd_printk (KERN_INFO "CS4232 MPU: port=0x%lx, irq=%i\n", cs4232_mpu_port[dev], cs4232_mpu_irq[dev]); } snd_printdd ("CS4232: pcm port=0x%lx, fm port=0x%lx, dma1=%i, dma2=%i, irq=%i\nICS2115: port=0x%lx, irq=%i\n", cs4232_pcm_port[dev], fm_port[dev], dma1[dev], dma2[dev], cs4232_pcm_irq[dev], ics2115_port[dev], ics2115_irq[dev]); kfree(cfg); return 0; }
static ssize_t pnp_set_current_resources(struct device * dmdev, struct device_attribute *attr, const char * ubuf, size_t count) { struct pnp_dev *dev = to_pnp_dev(dmdev); char *buf = (void *)ubuf; int retval = 0; if (dev->status & PNP_ATTACHED) { retval = -EBUSY; pnp_info("Device %s cannot be configured because it is in use.", dev->dev.bus_id); goto done; } while (isspace(*buf)) ++buf; if (!strnicmp(buf,"disable",7)) { retval = pnp_disable_dev(dev); goto done; } if (!strnicmp(buf,"activate",8)) { retval = pnp_activate_dev(dev); goto done; } if (!strnicmp(buf,"fill",4)) { if (dev->active) goto done; retval = pnp_auto_config_dev(dev); goto done; } if (!strnicmp(buf,"auto",4)) { if (dev->active) goto done; pnp_init_resource_table(&dev->res); retval = pnp_auto_config_dev(dev); goto done; } if (!strnicmp(buf,"clear",5)) { if (dev->active) goto done; pnp_init_resource_table(&dev->res); goto done; } if (!strnicmp(buf,"get",3)) { down(&pnp_res_mutex); if (pnp_can_read(dev)) dev->protocol->get(dev, &dev->res); up(&pnp_res_mutex); goto done; } if (!strnicmp(buf,"set",3)) { int nport = 0, nmem = 0, nirq = 0, ndma = 0; if (dev->active) goto done; buf += 3; pnp_init_resource_table(&dev->res); down(&pnp_res_mutex); while (1) { while (isspace(*buf)) ++buf; if (!strnicmp(buf,"io",2)) { buf += 2; while (isspace(*buf)) ++buf; dev->res.port_resource[nport].start = simple_strtoul(buf,&buf,0); while (isspace(*buf)) ++buf; if(*buf == '-') { buf += 1; while (isspace(*buf)) ++buf; dev->res.port_resource[nport].end = simple_strtoul(buf,&buf,0); } else dev->res.port_resource[nport].end = dev->res.port_resource[nport].start; dev->res.port_resource[nport].flags = IORESOURCE_IO; nport++; if (nport >= PNP_MAX_PORT) break; continue; } if (!strnicmp(buf,"mem",3)) { buf += 3; while (isspace(*buf)) ++buf; dev->res.mem_resource[nmem].start = simple_strtoul(buf,&buf,0); while (isspace(*buf)) ++buf; if(*buf == '-') { buf += 1; while (isspace(*buf)) ++buf; dev->res.mem_resource[nmem].end = simple_strtoul(buf,&buf,0); } else dev->res.mem_resource[nmem].end = dev->res.mem_resource[nmem].start; dev->res.mem_resource[nmem].flags = IORESOURCE_MEM; nmem++; if (nmem >= PNP_MAX_MEM) break; continue; } if (!strnicmp(buf,"irq",3)) { buf += 3; while (isspace(*buf)) ++buf; dev->res.irq_resource[nirq].start = dev->res.irq_resource[nirq].end = simple_strtoul(buf,&buf,0); dev->res.irq_resource[nirq].flags = IORESOURCE_IRQ; nirq++; if (nirq >= PNP_MAX_IRQ) break; continue; } if (!strnicmp(buf,"dma",3)) { buf += 3; while (isspace(*buf)) ++buf; dev->res.dma_resource[ndma].start = dev->res.dma_resource[ndma].end = simple_strtoul(buf,&buf,0); dev->res.dma_resource[ndma].flags = IORESOURCE_DMA; ndma++; if (ndma >= PNP_MAX_DMA) break; continue; } break; } up(&pnp_res_mutex); goto done; } done: if (retval < 0) return retval; return count; }