int pnpacpi_parse_allocated_resource(struct pnp_dev *dev) { struct acpi_device *acpi_dev = dev->data; acpi_handle handle = acpi_dev->handle; acpi_status status; pnp_dbg(&dev->dev, "parse allocated resources\n"); pnp_init_resources(dev); status = acpi_walk_resources(handle, METHOD_NAME__CRS, pnpacpi_allocated_resource, dev); if (ACPI_FAILURE(status)) { if (status != AE_NOT_FOUND) dev_err(&dev->dev, "can't evaluate _CRS: %d", status); return -EPERM; } return 0; }
int __init pnpacpi_parse_resource_option_data(struct pnp_dev *dev) { acpi_handle handle = dev->data; acpi_status status; struct acpipnp_parse_option_s parse_data; pnp_dbg(&dev->dev, "parse resource options\n"); parse_data.dev = dev; parse_data.option_flags = 0; status = acpi_walk_resources(handle, METHOD_NAME__PRS, pnpacpi_option_resource, &parse_data); if (ACPI_FAILURE(status)) { if (status != AE_NOT_FOUND) dev_err(&dev->dev, "can't evaluate _PRS: %d", status); return -EPERM; } return 0; }
static void pnpacpi_encode_fixed_mem32(struct pnp_dev *dev, struct acpi_resource *resource, struct resource *p) { struct acpi_resource_fixed_memory32 *fixed_memory32 = &resource->data.fixed_memory32; if (pnp_resource_enabled(p)) { fixed_memory32->write_protect = p->flags & IORESOURCE_MEM_WRITEABLE ? ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY; fixed_memory32->address = p->start; fixed_memory32->address_length = resource_size(p); } else { fixed_memory32->address = 0; fixed_memory32->address_length = 0; } pnp_dbg(&dev->dev, " encode fixed_mem32 %#x-%#x write_protect %#x\n", fixed_memory32->address, fixed_memory32->address + fixed_memory32->address_length - 1, fixed_memory32->write_protect); }
static void pnpacpi_encode_io(struct pnp_dev *dev, struct acpi_resource *resource, struct resource *p) { struct acpi_resource_io *io = &resource->data.io; if (pnp_resource_enabled(p)) { /* Note: pnp_assign_port copies pnp_port->flags into p->flags */ io->io_decode = (p->flags & IORESOURCE_IO_16BIT_ADDR) ? ACPI_DECODE_16 : ACPI_DECODE_10; io->minimum = p->start; io->maximum = p->end; io->alignment = 0; /* Correct? */ io->address_length = resource_size(p); } else { io->minimum = 0; io->address_length = 0; } pnp_dbg(&dev->dev, " encode io %#x-%#x decode %#x\n", io->minimum, io->minimum + io->address_length - 1, io->io_decode); }
static void pnpacpi_encode_io(struct pnp_dev *dev, struct acpi_resource *resource, struct resource *p) { struct acpi_resource_io *io = &resource->data.io; if (pnp_resource_enabled(p)) { io->io_decode = (p->flags & IORESOURCE_IO_16BIT_ADDR) ? ACPI_DECODE_16 : ACPI_DECODE_10; io->minimum = p->start; io->maximum = p->end; io->alignment = 0; io->address_length = p->end - p->start + 1; } else { io->minimum = 0; io->address_length = 0; } pnp_dbg(&dev->dev, " encode io %#x-%#x decode %#x\n", io->minimum, io->minimum + io->address_length - 1, io->io_decode); }
static int pnpacpi_set_resources(struct pnp_dev *dev) { acpi_handle handle = dev->data; struct acpi_buffer buffer; int ret; pnp_dbg(&dev->dev, "set resources\n"); ret = pnpacpi_build_resource_template(dev, &buffer); if (ret) return ret; ret = pnpacpi_encode_resources(dev, &buffer); if (ret) { kfree(buffer.pointer); return ret; } if (ACPI_FAILURE(acpi_set_current_resources(handle, &buffer))) ret = -EINVAL; else if (acpi_bus_power_manageable(handle)) ret = acpi_bus_set_power(handle, ACPI_STATE_D0); kfree(buffer.pointer); return ret; }
static void pnpacpi_encode_mem32(struct pnp_dev *dev, struct acpi_resource *resource, struct resource *p) { struct acpi_resource_memory32 *memory32 = &resource->data.memory32; if (pnp_resource_enabled(p)) { memory32->write_protect = p->flags & IORESOURCE_MEM_WRITEABLE ? ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY; memory32->minimum = p->start; memory32->maximum = p->end; memory32->alignment = 0; memory32->address_length = resource_size(p); } else { memory32->minimum = 0; memory32->alignment = 0; } pnp_dbg(&dev->dev, " encode mem32 %#x-%#x write_protect %#x\n", memory32->minimum, memory32->minimum + memory32->address_length - 1, memory32->write_protect); }
static void pnpacpi_encode_mem24(struct pnp_dev *dev, struct acpi_resource *resource, struct resource *p) { struct acpi_resource_memory24 *memory24 = &resource->data.memory24; if (pnp_resource_enabled(p)) { /* Note: pnp_assign_mem copies pnp_mem->flags into p->flags */ memory24->write_protect = p->flags & IORESOURCE_MEM_WRITEABLE ? ACPI_READ_WRITE_MEMORY : ACPI_READ_ONLY_MEMORY; memory24->minimum = p->start; memory24->maximum = p->end; memory24->alignment = 0; memory24->address_length = p->end - p->start + 1; } else { memory24->minimum = 0; memory24->address_length = 0; } pnp_dbg(&dev->dev, " encode mem24 %#x-%#x write_protect %#x\n", memory24->minimum, memory24->minimum + memory24->address_length - 1, memory24->write_protect); }
int pnpacpi_encode_resources(struct pnp_dev *dev, struct acpi_buffer *buffer) { int i = 0; /* pnpacpi_build_resource_template allocates extra mem */ int res_cnt = (buffer->length - 1) / sizeof(struct acpi_resource) - 1; struct acpi_resource *resource = buffer->pointer; int port = 0, irq = 0, dma = 0, mem = 0; pnp_dbg(&dev->dev, "encode %d resources\n", res_cnt); while (i < res_cnt) { switch (resource->type) { case ACPI_RESOURCE_TYPE_IRQ: pnpacpi_encode_irq(dev, resource, pnp_get_resource(dev, IORESOURCE_IRQ, irq)); irq++; break; case ACPI_RESOURCE_TYPE_DMA: pnpacpi_encode_dma(dev, resource, pnp_get_resource(dev, IORESOURCE_DMA, dma)); dma++; break; case ACPI_RESOURCE_TYPE_IO: pnpacpi_encode_io(dev, resource, pnp_get_resource(dev, IORESOURCE_IO, port)); port++; break; case ACPI_RESOURCE_TYPE_FIXED_IO: pnpacpi_encode_fixed_io(dev, resource, pnp_get_resource(dev, IORESOURCE_IO, port)); port++; break; case ACPI_RESOURCE_TYPE_MEMORY24: pnpacpi_encode_mem24(dev, resource, pnp_get_resource(dev, IORESOURCE_MEM, mem)); mem++; break; case ACPI_RESOURCE_TYPE_MEMORY32: pnpacpi_encode_mem32(dev, resource, pnp_get_resource(dev, IORESOURCE_MEM, mem)); mem++; break; case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: pnpacpi_encode_fixed_mem32(dev, resource, pnp_get_resource(dev, IORESOURCE_MEM, mem)); mem++; break; case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: pnpacpi_encode_ext_irq(dev, resource, pnp_get_resource(dev, IORESOURCE_IRQ, irq)); irq++; break; case ACPI_RESOURCE_TYPE_START_DEPENDENT: case ACPI_RESOURCE_TYPE_END_DEPENDENT: case ACPI_RESOURCE_TYPE_VENDOR: case ACPI_RESOURCE_TYPE_END_TAG: case ACPI_RESOURCE_TYPE_ADDRESS16: case ACPI_RESOURCE_TYPE_ADDRESS32: case ACPI_RESOURCE_TYPE_ADDRESS64: case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: case ACPI_RESOURCE_TYPE_GENERIC_REGISTER: default: /* other type */ dev_warn(&dev->dev, "can't encode unknown resource " "type %d\n", resource->type); return -EINVAL; } resource++; i++; } return 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; }
int pnpacpi_encode_resources(struct pnp_resource_table *res_table, struct acpi_buffer *buffer) { int i = 0; /* pnpacpi_build_resource_template allocates extra mem */ int res_cnt = (buffer->length - 1)/sizeof(struct acpi_resource) - 1; struct acpi_resource *resource = (struct acpi_resource*)buffer->pointer; int port = 0, irq = 0, dma = 0, mem = 0; pnp_dbg("res cnt %d", res_cnt); while (i < res_cnt) { switch(resource->id) { case ACPI_RSTYPE_IRQ: pnp_dbg("Encode irq"); pnpacpi_encode_irq(resource, &res_table->irq_resource[irq]); irq++; break; case ACPI_RSTYPE_EXT_IRQ: pnp_dbg("Encode ext irq"); pnpacpi_encode_ext_irq(resource, &res_table->irq_resource[irq]); irq++; break; case ACPI_RSTYPE_DMA: pnp_dbg("Encode dma"); pnpacpi_encode_dma(resource, &res_table->dma_resource[dma]); dma ++; break; case ACPI_RSTYPE_IO: pnp_dbg("Encode io"); pnpacpi_encode_io(resource, &res_table->port_resource[port]); port ++; break; case ACPI_RSTYPE_FIXED_IO: pnp_dbg("Encode fixed io"); pnpacpi_encode_fixed_io(resource, &res_table->port_resource[port]); port ++; break; case ACPI_RSTYPE_MEM24: pnp_dbg("Encode mem24"); pnpacpi_encode_mem24(resource, &res_table->mem_resource[mem]); mem ++; break; case ACPI_RSTYPE_MEM32: pnp_dbg("Encode mem32"); pnpacpi_encode_mem32(resource, &res_table->mem_resource[mem]); mem ++; break; case ACPI_RSTYPE_FIXED_MEM32: pnp_dbg("Encode fixed mem32"); pnpacpi_encode_fixed_mem32(resource, &res_table->mem_resource[mem]); mem ++; break; default: /* other type */ pnp_warn("Invalid type"); return -EINVAL; } resource ++; i ++; } return 0; }
int pnpacpi_encode_resources(struct pnp_resource_table *res_table, struct acpi_buffer *buffer) { int i = 0; /* pnpacpi_build_resource_template allocates extra mem */ int res_cnt = (buffer->length - 1)/sizeof(struct acpi_resource) - 1; struct acpi_resource *resource = (struct acpi_resource*)buffer->pointer; int port = 0, irq = 0, dma = 0, mem = 0; pnp_dbg("res cnt %d", res_cnt); while (i < res_cnt) { switch(resource->type) { case ACPI_RESOURCE_TYPE_IRQ: pnp_dbg("Encode irq"); pnpacpi_encode_irq(resource, &res_table->irq_resource[irq]); irq++; break; case ACPI_RESOURCE_TYPE_DMA: pnp_dbg("Encode dma"); pnpacpi_encode_dma(resource, &res_table->dma_resource[dma]); dma++; break; case ACPI_RESOURCE_TYPE_IO: pnp_dbg("Encode io"); pnpacpi_encode_io(resource, &res_table->port_resource[port]); port++; break; case ACPI_RESOURCE_TYPE_FIXED_IO: pnp_dbg("Encode fixed io"); pnpacpi_encode_fixed_io(resource, &res_table->port_resource[port]); port++; break; case ACPI_RESOURCE_TYPE_MEMORY24: pnp_dbg("Encode mem24"); pnpacpi_encode_mem24(resource, &res_table->mem_resource[mem]); mem++; break; case ACPI_RESOURCE_TYPE_MEMORY32: pnp_dbg("Encode mem32"); pnpacpi_encode_mem32(resource, &res_table->mem_resource[mem]); mem++; break; case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: pnp_dbg("Encode fixed mem32"); pnpacpi_encode_fixed_mem32(resource, &res_table->mem_resource[mem]); mem++; break; case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: pnp_dbg("Encode ext irq"); pnpacpi_encode_ext_irq(resource, &res_table->irq_resource[irq]); irq++; break; case ACPI_RESOURCE_TYPE_START_DEPENDENT: case ACPI_RESOURCE_TYPE_END_DEPENDENT: case ACPI_RESOURCE_TYPE_VENDOR: case ACPI_RESOURCE_TYPE_END_TAG: case ACPI_RESOURCE_TYPE_ADDRESS16: case ACPI_RESOURCE_TYPE_ADDRESS32: case ACPI_RESOURCE_TYPE_ADDRESS64: case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: case ACPI_RESOURCE_TYPE_GENERIC_REGISTER: default: /* other type */ pnp_warn("unknown resource type %d", resource->type); return -EINVAL; } resource++; i++; } return 0; }
static int pnpacpi_get_resources(struct pnp_dev *dev) { pnp_dbg(&dev->dev, "get resources\n"); return pnpacpi_parse_allocated_resource(dev); }
void pnp_unregister_driver(struct pnp_driver *drv) { driver_unregister(&drv->driver); pnp_dbg("the driver '%s' has been unregistered", drv->name); }