Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 008238b5 authored by Len Brown's avatar Len Brown
Browse files

Merge branch 'pnp' into release

parents 96916090 dfd2e1b4
Loading
Loading
Loading
Loading
+70 −4
Original line number Diff line number Diff line
extern spinlock_t pnp_lock;
void *pnp_alloc(long size);

int pnp_register_protocol(struct pnp_protocol *protocol);
void pnp_unregister_protocol(struct pnp_protocol *protocol);

#define PNP_EISA_ID_MASK 0x7fffffff
void pnp_eisa_id_to_string(u32 id, char *str);
struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *, int id, char *pnpid);
struct pnp_card *pnp_alloc_card(struct pnp_protocol *, int id, char *pnpid);

int pnp_add_device(struct pnp_dev *dev);
struct pnp_id *pnp_add_id(struct pnp_dev *dev, char *id);
int pnp_interface_attach_device(struct pnp_dev *dev);

int pnp_add_card(struct pnp_card *card);
struct pnp_id *pnp_add_card_id(struct pnp_card *card, char *id);
void pnp_remove_card(struct pnp_card *card);
int pnp_add_card_device(struct pnp_card *card, struct pnp_dev *dev);
void pnp_remove_card_device(struct pnp_dev *dev);

struct pnp_option *pnp_register_independent_option(struct pnp_dev *dev);
struct pnp_option *pnp_register_dependent_option(struct pnp_dev *dev,
						 int priority);
int pnp_register_irq_resource(struct pnp_dev *dev, struct pnp_option *option,
			      struct pnp_irq *data);
int pnp_register_dma_resource(struct pnp_dev *dev, struct pnp_option *option,
			      struct pnp_dma *data);
int pnp_register_port_resource(struct pnp_dev *dev, struct pnp_option *option,
			       struct pnp_port *data);
int pnp_register_mem_resource(struct pnp_dev *dev, struct pnp_option *option,
			      struct pnp_mem *data);
void pnp_init_resources(struct pnp_dev *dev);

void pnp_fixup_device(struct pnp_dev *dev);
void pnp_free_option(struct pnp_option *option);
int __pnp_add_device(struct pnp_dev *dev);
void __pnp_remove_device(struct pnp_dev *dev);

int pnp_check_port(struct pnp_dev * dev, int idx);
int pnp_check_mem(struct pnp_dev * dev, int idx);
int pnp_check_irq(struct pnp_dev * dev, int idx);
int pnp_check_dma(struct pnp_dev * dev, int idx);
int pnp_check_port(struct pnp_dev *dev, struct resource *res);
int pnp_check_mem(struct pnp_dev *dev, struct resource *res);
int pnp_check_irq(struct pnp_dev *dev, struct resource *res);
int pnp_check_dma(struct pnp_dev *dev, struct resource *res);

void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc);

void pnp_init_resource(struct resource *res);

struct pnp_resource *pnp_get_pnp_resource(struct pnp_dev *dev,
					  unsigned int type, unsigned int num);

#define PNP_MAX_PORT		40
#define PNP_MAX_MEM		24
#define PNP_MAX_IRQ		 2
#define PNP_MAX_DMA		 2

struct pnp_resource {
	struct resource res;
	unsigned int index;		/* ISAPNP config register index */
};

struct pnp_resource_table {
	struct pnp_resource port[PNP_MAX_PORT];
	struct pnp_resource mem[PNP_MAX_MEM];
	struct pnp_resource dma[PNP_MAX_DMA];
	struct pnp_resource irq[PNP_MAX_IRQ];
};

struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq,
					  int flags);
struct pnp_resource *pnp_add_dma_resource(struct pnp_dev *dev, int dma,
					  int flags);
struct pnp_resource *pnp_add_io_resource(struct pnp_dev *dev,
					 resource_size_t start,
					 resource_size_t end, int flags);
struct pnp_resource *pnp_add_mem_resource(struct pnp_dev *dev,
					  resource_size_t start,
					  resource_size_t end, int flags);
+46 −9
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@
 */

#include <linux/module.h>
#include <linux/ctype.h>
#include <linux/slab.h>
#include <linux/pnp.h>
#include "base.h"
@@ -100,19 +101,33 @@ static int card_probe(struct pnp_card *card, struct pnp_card_driver *drv)
 * @id: pointer to a pnp_id structure
 * @card: pointer to the desired card
 */
int pnp_add_card_id(struct pnp_id *id, struct pnp_card *card)
struct pnp_id *pnp_add_card_id(struct pnp_card *card, char *id)
{
	struct pnp_id *ptr;
	struct pnp_id *dev_id, *ptr;

	id->next = NULL;
	dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL);
	if (!dev_id)
		return NULL;

	dev_id->id[0] = id[0];
	dev_id->id[1] = id[1];
	dev_id->id[2] = id[2];
	dev_id->id[3] = tolower(id[3]);
	dev_id->id[4] = tolower(id[4]);
	dev_id->id[5] = tolower(id[5]);
	dev_id->id[6] = tolower(id[6]);
	dev_id->id[7] = '\0';

	dev_id->next = NULL;
	ptr = card->id;
	while (ptr && ptr->next)
		ptr = ptr->next;
	if (ptr)
		ptr->next = id;
		ptr->next = dev_id;
	else
		card->id = id;
	return 0;
		card->id = dev_id;

	return dev_id;
}

static void pnp_free_card_ids(struct pnp_card *card)
@@ -136,6 +151,31 @@ static void pnp_release_card(struct device *dmdev)
	kfree(card);
}

struct pnp_card *pnp_alloc_card(struct pnp_protocol *protocol, int id, char *pnpid)
{
	struct pnp_card *card;
	struct pnp_id *dev_id;

	card = kzalloc(sizeof(struct pnp_card), GFP_KERNEL);
	if (!card)
		return NULL;

	card->protocol = protocol;
	card->number = id;

	card->dev.parent = &card->protocol->dev;
	sprintf(card->dev.bus_id, "%02x:%02x", card->protocol->number,
		card->number);

	dev_id = pnp_add_card_id(card, pnpid);
	if (!dev_id) {
		kfree(card);
		return NULL;
	}

	return card;
}

static ssize_t pnp_show_card_name(struct device *dmdev,
				  struct device_attribute *attr, char *buf)
{
@@ -191,9 +231,6 @@ int pnp_add_card(struct pnp_card *card)
	int error;
	struct list_head *pos, *temp;

	sprintf(card->dev.bus_id, "%02x:%02x", card->protocol->number,
		card->number);
	card->dev.parent = &card->protocol->dev;
	card->dev.bus = NULL;
	card->dev.release = &pnp_release_card;
	error = device_register(&card->dev);
+39 −7
Original line number Diff line number Diff line
@@ -106,18 +106,53 @@ static void pnp_release_device(struct device *dmdev)
	pnp_free_option(dev->independent);
	pnp_free_option(dev->dependent);
	pnp_free_ids(dev);
	kfree(dev->res);
	kfree(dev);
}

int __pnp_add_device(struct pnp_dev *dev)
struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *protocol, int id, char *pnpid)
{
	int ret;
	struct pnp_dev *dev;
	struct pnp_id *dev_id;

	pnp_fixup_device(dev);
	dev = kzalloc(sizeof(struct pnp_dev), GFP_KERNEL);
	if (!dev)
		return NULL;

	dev->res = kzalloc(sizeof(struct pnp_resource_table), GFP_KERNEL);
	if (!dev->res) {
		kfree(dev);
		return NULL;
	}

	dev->protocol = protocol;
	dev->number = id;
	dev->dma_mask = DMA_24BIT_MASK;

	dev->dev.parent = &dev->protocol->dev;
	dev->dev.bus = &pnp_bus_type;
	dev->dev.dma_mask = &dev->dma_mask;
	dev->dma_mask = dev->dev.coherent_dma_mask = DMA_24BIT_MASK;
	dev->dev.coherent_dma_mask = dev->dma_mask;
	dev->dev.release = &pnp_release_device;

	sprintf(dev->dev.bus_id, "%02x:%02x", dev->protocol->number,
		dev->number);

	dev_id = pnp_add_id(dev, pnpid);
	if (!dev_id) {
		kfree(dev->res);
		kfree(dev);
		return NULL;
	}

	return dev;
}

int __pnp_add_device(struct pnp_dev *dev)
{
	int ret;

	pnp_fixup_device(dev);
	dev->status = PNP_READY;
	spin_lock(&pnp_lock);
	list_add_tail(&dev->global_list, &pnp_global);
@@ -145,9 +180,6 @@ int pnp_add_device(struct pnp_dev *dev)
	if (dev->card)
		return -EINVAL;

	dev->dev.parent = &dev->protocol->dev;
	sprintf(dev->dev.bus_id, "%02x:%02x", dev->protocol->number,
		dev->number);
	ret = __pnp_add_device(dev);
	if (ret)
		return ret;
+21 −7
Original line number Diff line number Diff line
@@ -226,22 +226,36 @@ void pnp_unregister_driver(struct pnp_driver *drv)

/**
 * pnp_add_id - adds an EISA id to the specified device
 * @id: pointer to a pnp_id structure
 * @dev: pointer to the desired device
 * @id: pointer to an EISA id string
 */
int pnp_add_id(struct pnp_id *id, struct pnp_dev *dev)
struct pnp_id *pnp_add_id(struct pnp_dev *dev, char *id)
{
	struct pnp_id *ptr;
	struct pnp_id *dev_id, *ptr;

	id->next = NULL;
	dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL);
	if (!dev_id)
		return NULL;

	dev_id->id[0] = id[0];
	dev_id->id[1] = id[1];
	dev_id->id[2] = id[2];
	dev_id->id[3] = tolower(id[3]);
	dev_id->id[4] = tolower(id[4]);
	dev_id->id[5] = tolower(id[5]);
	dev_id->id[6] = tolower(id[6]);
	dev_id->id[7] = '\0';

	dev_id->next = NULL;
	ptr = dev->id;
	while (ptr && ptr->next)
		ptr = ptr->next;
	if (ptr)
		ptr->next = id;
		ptr->next = dev_id;
	else
		dev->id = id;
	return 0;
		dev->id = dev_id;

	return dev_id;
}

EXPORT_SYMBOL(pnp_register_driver);
+47 −64
Original line number Diff line number Diff line
@@ -248,6 +248,7 @@ static ssize_t pnp_show_current_resources(struct device *dmdev,
					  char *buf)
{
	struct pnp_dev *dev = to_pnp_dev(dmdev);
	struct resource *res;
	int i, ret;
	pnp_info_buffer_t *buffer;

@@ -267,50 +268,46 @@ static ssize_t pnp_show_current_resources(struct device *dmdev,
	else
		pnp_printf(buffer, "disabled\n");

	for (i = 0; i < PNP_MAX_PORT; i++) {
		if (pnp_port_valid(dev, i)) {
	for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_IO, i)); i++) {
		if (pnp_resource_valid(res)) {
			pnp_printf(buffer, "io");
			if (pnp_port_flags(dev, i) & IORESOURCE_DISABLED)
			if (res->flags & IORESOURCE_DISABLED)
				pnp_printf(buffer, " disabled\n");
			else
				pnp_printf(buffer, " 0x%llx-0x%llx\n",
					   (unsigned long long)
					   pnp_port_start(dev, i),
					   (unsigned long long)pnp_port_end(dev,
									    i));
					   (unsigned long long) res->start,
					   (unsigned long long) res->end);
		}
	}
	for (i = 0; i < PNP_MAX_MEM; i++) {
		if (pnp_mem_valid(dev, i)) {
	for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_MEM, i)); i++) {
		if (pnp_resource_valid(res)) {
			pnp_printf(buffer, "mem");
			if (pnp_mem_flags(dev, i) & IORESOURCE_DISABLED)
			if (res->flags & IORESOURCE_DISABLED)
				pnp_printf(buffer, " disabled\n");
			else
				pnp_printf(buffer, " 0x%llx-0x%llx\n",
					   (unsigned long long)
					   pnp_mem_start(dev, i),
					   (unsigned long long)pnp_mem_end(dev,
									   i));
					   (unsigned long long) res->start,
					   (unsigned long long) res->end);
		}
	}
	for (i = 0; i < PNP_MAX_IRQ; i++) {
		if (pnp_irq_valid(dev, i)) {
	for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_IRQ, i)); i++) {
		if (pnp_resource_valid(res)) {
			pnp_printf(buffer, "irq");
			if (pnp_irq_flags(dev, i) & IORESOURCE_DISABLED)
			if (res->flags & IORESOURCE_DISABLED)
				pnp_printf(buffer, " disabled\n");
			else
				pnp_printf(buffer, " %lld\n",
					   (unsigned long long)pnp_irq(dev, i));
					   (unsigned long long) res->start);
		}
	}
	for (i = 0; i < PNP_MAX_DMA; i++) {
		if (pnp_dma_valid(dev, i)) {
	for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_DMA, i)); i++) {
		if (pnp_resource_valid(res)) {
			pnp_printf(buffer, "dma");
			if (pnp_dma_flags(dev, i) & IORESOURCE_DISABLED)
			if (res->flags & IORESOURCE_DISABLED)
				pnp_printf(buffer, " disabled\n");
			else
				pnp_printf(buffer, " %lld\n",
					   (unsigned long long)pnp_dma(dev, i));
					   (unsigned long long) res->start);
		}
	}
	ret = (buffer->curr - buf);
@@ -323,8 +320,10 @@ 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);
	struct pnp_resource *pnp_res;
	char *buf = (void *)ubuf;
	int retval = 0;
	resource_size_t start, end;

	if (dev->status & PNP_ATTACHED) {
		retval = -EBUSY;
@@ -351,20 +350,20 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr,
	if (!strnicmp(buf, "auto", 4)) {
		if (dev->active)
			goto done;
		pnp_init_resource_table(&dev->res);
		pnp_init_resources(dev);
		retval = pnp_auto_config_dev(dev);
		goto done;
	}
	if (!strnicmp(buf, "clear", 5)) {
		if (dev->active)
			goto done;
		pnp_init_resource_table(&dev->res);
		pnp_init_resources(dev);
		goto done;
	}
	if (!strnicmp(buf, "get", 3)) {
		mutex_lock(&pnp_res_mutex);
		if (pnp_can_read(dev))
			dev->protocol->get(dev, &dev->res);
			dev->protocol->get(dev);
		mutex_unlock(&pnp_res_mutex);
		goto done;
	}
@@ -373,7 +372,7 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr,
		if (dev->active)
			goto done;
		buf += 3;
		pnp_init_resource_table(&dev->res);
		pnp_init_resources(dev);
		mutex_lock(&pnp_res_mutex);
		while (1) {
			while (isspace(*buf))
@@ -382,76 +381,60 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr,
				buf += 2;
				while (isspace(*buf))
					++buf;
				dev->res.port_resource[nport].start =
				    simple_strtoul(buf, &buf, 0);
				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);
					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;
					end = start;
				pnp_res = pnp_add_io_resource(dev, start, end,
							      0);
				if (pnp_res)
					pnp_res->index = nport++;
				continue;
			}
			if (!strnicmp(buf, "mem", 3)) {
				buf += 3;
				while (isspace(*buf))
					++buf;
				dev->res.mem_resource[nmem].start =
				    simple_strtoul(buf, &buf, 0);
				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);
					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;
					end = start;
				pnp_res = pnp_add_mem_resource(dev, start, end,
							       0);
				if (pnp_res)
					pnp_res->index = nmem++;
				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;
				start = simple_strtoul(buf, &buf, 0);
				pnp_res = pnp_add_irq_resource(dev, start, 0);
				if (pnp_res)
					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;
				start = simple_strtoul(buf, &buf, 0);
				pnp_res = pnp_add_dma_resource(dev, start, 0);
				if (pnp_res)
					pnp_res->index = ndma++;
				continue;
			}
			break;
Loading