Example #1
0
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);
}
Example #2
0
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;
}
Example #3
0
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;
}
Example #4
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;
}