1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds * interface.c - contains everything related to the user interface
41da177e4SLinus Torvalds *
5c1017a4cSJaroslav Kysela * Some code, especially possible resource dumping is based on isapnp_proc.c (c) Jaroslav Kysela <perex@perex.cz>
61da177e4SLinus Torvalds * Copyright 2002 Adam Belay <ambx1@neo.rr.com>
71f32ca31SBjorn Helgaas * Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
81f32ca31SBjorn Helgaas * Bjorn Helgaas <bjorn.helgaas@hp.com>
91da177e4SLinus Torvalds */
101da177e4SLinus Torvalds
111da177e4SLinus Torvalds #include <linux/pnp.h>
121da177e4SLinus Torvalds #include <linux/string.h>
131da177e4SLinus Torvalds #include <linux/errno.h>
141da177e4SLinus Torvalds #include <linux/list.h>
151da177e4SLinus Torvalds #include <linux/types.h>
161da177e4SLinus Torvalds #include <linux/stat.h>
171da177e4SLinus Torvalds #include <linux/ctype.h>
181da177e4SLinus Torvalds #include <linux/slab.h>
19b3bd86e2SDaniel Walker #include <linux/mutex.h>
20b3bd86e2SDaniel Walker
217c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
221da177e4SLinus Torvalds
231da177e4SLinus Torvalds #include "base.h"
241da177e4SLinus Torvalds
251da177e4SLinus Torvalds struct pnp_info_buffer {
261da177e4SLinus Torvalds char *buffer; /* pointer to begin of buffer */
271da177e4SLinus Torvalds char *curr; /* current position in buffer */
281da177e4SLinus Torvalds unsigned long size; /* current size */
291da177e4SLinus Torvalds unsigned long len; /* total length of buffer */
301da177e4SLinus Torvalds int stop; /* stop flag */
311da177e4SLinus Torvalds int error; /* error code */
321da177e4SLinus Torvalds };
331da177e4SLinus Torvalds
341da177e4SLinus Torvalds typedef struct pnp_info_buffer pnp_info_buffer_t;
351da177e4SLinus Torvalds
36b1f4213cSTom Rix __printf(2, 3)
pnp_printf(pnp_info_buffer_t * buffer,char * fmt,...)371da177e4SLinus Torvalds static int pnp_printf(pnp_info_buffer_t * buffer, char *fmt, ...)
381da177e4SLinus Torvalds {
391da177e4SLinus Torvalds va_list args;
401da177e4SLinus Torvalds int res;
411da177e4SLinus Torvalds
421da177e4SLinus Torvalds if (buffer->stop || buffer->error)
431da177e4SLinus Torvalds return 0;
441da177e4SLinus Torvalds va_start(args, fmt);
451da177e4SLinus Torvalds res = vsnprintf(buffer->curr, buffer->len - buffer->size, fmt, args);
461da177e4SLinus Torvalds va_end(args);
471da177e4SLinus Torvalds if (buffer->size + res >= buffer->len) {
481da177e4SLinus Torvalds buffer->stop = 1;
491da177e4SLinus Torvalds return 0;
501da177e4SLinus Torvalds }
511da177e4SLinus Torvalds buffer->curr += res;
521da177e4SLinus Torvalds buffer->size += res;
531da177e4SLinus Torvalds return res;
541da177e4SLinus Torvalds }
551da177e4SLinus Torvalds
pnp_print_port(pnp_info_buffer_t * buffer,char * space,struct pnp_port * port)569dd78466SBjorn Helgaas static void pnp_print_port(pnp_info_buffer_t * buffer, char *space,
579dd78466SBjorn Helgaas struct pnp_port *port)
581da177e4SLinus Torvalds {
59169aaffeSBjorn Helgaas pnp_printf(buffer, "%sport %#llx-%#llx, align %#llx, size %#llx, "
60169aaffeSBjorn Helgaas "%i-bit address decoding\n", space,
61169aaffeSBjorn Helgaas (unsigned long long) port->min,
62169aaffeSBjorn Helgaas (unsigned long long) port->max,
63169aaffeSBjorn Helgaas port->align ? ((unsigned long long) port->align - 1) : 0,
64169aaffeSBjorn Helgaas (unsigned long long) port->size,
6508c9f262SBjorn Helgaas port->flags & IORESOURCE_IO_16BIT_ADDR ? 16 : 10);
661da177e4SLinus Torvalds }
671da177e4SLinus Torvalds
pnp_print_irq(pnp_info_buffer_t * buffer,char * space,struct pnp_irq * irq)689dd78466SBjorn Helgaas static void pnp_print_irq(pnp_info_buffer_t * buffer, char *space,
699dd78466SBjorn Helgaas struct pnp_irq *irq)
701da177e4SLinus Torvalds {
711da177e4SLinus Torvalds int first = 1, i;
721da177e4SLinus Torvalds
731da177e4SLinus Torvalds pnp_printf(buffer, "%sirq ", space);
741da177e4SLinus Torvalds for (i = 0; i < PNP_IRQ_NR; i++)
757aefff51SBjorn Helgaas if (test_bit(i, irq->map.bits)) {
761da177e4SLinus Torvalds if (!first) {
771da177e4SLinus Torvalds pnp_printf(buffer, ",");
781da177e4SLinus Torvalds } else {
791da177e4SLinus Torvalds first = 0;
801da177e4SLinus Torvalds }
811da177e4SLinus Torvalds if (i == 2 || i == 9)
821da177e4SLinus Torvalds pnp_printf(buffer, "2/9");
831da177e4SLinus Torvalds else
841da177e4SLinus Torvalds pnp_printf(buffer, "%i", i);
851da177e4SLinus Torvalds }
867aefff51SBjorn Helgaas if (bitmap_empty(irq->map.bits, PNP_IRQ_NR))
871da177e4SLinus Torvalds pnp_printf(buffer, "<none>");
881da177e4SLinus Torvalds if (irq->flags & IORESOURCE_IRQ_HIGHEDGE)
891da177e4SLinus Torvalds pnp_printf(buffer, " High-Edge");
901da177e4SLinus Torvalds if (irq->flags & IORESOURCE_IRQ_LOWEDGE)
911da177e4SLinus Torvalds pnp_printf(buffer, " Low-Edge");
921da177e4SLinus Torvalds if (irq->flags & IORESOURCE_IRQ_HIGHLEVEL)
931da177e4SLinus Torvalds pnp_printf(buffer, " High-Level");
941da177e4SLinus Torvalds if (irq->flags & IORESOURCE_IRQ_LOWLEVEL)
951da177e4SLinus Torvalds pnp_printf(buffer, " Low-Level");
96d5ebde6eSBjorn Helgaas if (irq->flags & IORESOURCE_IRQ_OPTIONAL)
97d5ebde6eSBjorn Helgaas pnp_printf(buffer, " (optional)");
981da177e4SLinus Torvalds pnp_printf(buffer, "\n");
991da177e4SLinus Torvalds }
1001da177e4SLinus Torvalds
pnp_print_dma(pnp_info_buffer_t * buffer,char * space,struct pnp_dma * dma)1019dd78466SBjorn Helgaas static void pnp_print_dma(pnp_info_buffer_t * buffer, char *space,
1029dd78466SBjorn Helgaas struct pnp_dma *dma)
1031da177e4SLinus Torvalds {
1041da177e4SLinus Torvalds int first = 1, i;
1051da177e4SLinus Torvalds char *s;
1061da177e4SLinus Torvalds
1071da177e4SLinus Torvalds pnp_printf(buffer, "%sdma ", space);
1081da177e4SLinus Torvalds for (i = 0; i < 8; i++)
1091da177e4SLinus Torvalds if (dma->map & (1 << i)) {
1101da177e4SLinus Torvalds if (!first) {
1111da177e4SLinus Torvalds pnp_printf(buffer, ",");
1121da177e4SLinus Torvalds } else {
1131da177e4SLinus Torvalds first = 0;
1141da177e4SLinus Torvalds }
1151da177e4SLinus Torvalds pnp_printf(buffer, "%i", i);
1161da177e4SLinus Torvalds }
1171da177e4SLinus Torvalds if (!dma->map)
1181da177e4SLinus Torvalds pnp_printf(buffer, "<none>");
1191da177e4SLinus Torvalds switch (dma->flags & IORESOURCE_DMA_TYPE_MASK) {
1201da177e4SLinus Torvalds case IORESOURCE_DMA_8BIT:
1211da177e4SLinus Torvalds s = "8-bit";
1221da177e4SLinus Torvalds break;
1231da177e4SLinus Torvalds case IORESOURCE_DMA_8AND16BIT:
1241da177e4SLinus Torvalds s = "8-bit&16-bit";
1251da177e4SLinus Torvalds break;
1261da177e4SLinus Torvalds default:
1271da177e4SLinus Torvalds s = "16-bit";
1281da177e4SLinus Torvalds }
1291da177e4SLinus Torvalds pnp_printf(buffer, " %s", s);
1301da177e4SLinus Torvalds if (dma->flags & IORESOURCE_DMA_MASTER)
1311da177e4SLinus Torvalds pnp_printf(buffer, " master");
1321da177e4SLinus Torvalds if (dma->flags & IORESOURCE_DMA_BYTE)
1331da177e4SLinus Torvalds pnp_printf(buffer, " byte-count");
1341da177e4SLinus Torvalds if (dma->flags & IORESOURCE_DMA_WORD)
1351da177e4SLinus Torvalds pnp_printf(buffer, " word-count");
1361da177e4SLinus Torvalds switch (dma->flags & IORESOURCE_DMA_SPEED_MASK) {
1371da177e4SLinus Torvalds case IORESOURCE_DMA_TYPEA:
1381da177e4SLinus Torvalds s = "type-A";
1391da177e4SLinus Torvalds break;
1401da177e4SLinus Torvalds case IORESOURCE_DMA_TYPEB:
1411da177e4SLinus Torvalds s = "type-B";
1421da177e4SLinus Torvalds break;
1431da177e4SLinus Torvalds case IORESOURCE_DMA_TYPEF:
1441da177e4SLinus Torvalds s = "type-F";
1451da177e4SLinus Torvalds break;
1461da177e4SLinus Torvalds default:
1471da177e4SLinus Torvalds s = "compatible";
1481da177e4SLinus Torvalds break;
1491da177e4SLinus Torvalds }
1501da177e4SLinus Torvalds pnp_printf(buffer, " %s\n", s);
1511da177e4SLinus Torvalds }
1521da177e4SLinus Torvalds
pnp_print_mem(pnp_info_buffer_t * buffer,char * space,struct pnp_mem * mem)1539dd78466SBjorn Helgaas static void pnp_print_mem(pnp_info_buffer_t * buffer, char *space,
1549dd78466SBjorn Helgaas struct pnp_mem *mem)
1551da177e4SLinus Torvalds {
1561da177e4SLinus Torvalds char *s;
1571da177e4SLinus Torvalds
158169aaffeSBjorn Helgaas pnp_printf(buffer, "%sMemory %#llx-%#llx, align %#llx, size %#llx",
159169aaffeSBjorn Helgaas space, (unsigned long long) mem->min,
160169aaffeSBjorn Helgaas (unsigned long long) mem->max,
161169aaffeSBjorn Helgaas (unsigned long long) mem->align,
162169aaffeSBjorn Helgaas (unsigned long long) mem->size);
1631da177e4SLinus Torvalds if (mem->flags & IORESOURCE_MEM_WRITEABLE)
1641da177e4SLinus Torvalds pnp_printf(buffer, ", writeable");
1651da177e4SLinus Torvalds if (mem->flags & IORESOURCE_MEM_CACHEABLE)
1661da177e4SLinus Torvalds pnp_printf(buffer, ", cacheable");
1671da177e4SLinus Torvalds if (mem->flags & IORESOURCE_MEM_RANGELENGTH)
1681da177e4SLinus Torvalds pnp_printf(buffer, ", range-length");
1691da177e4SLinus Torvalds if (mem->flags & IORESOURCE_MEM_SHADOWABLE)
1701da177e4SLinus Torvalds pnp_printf(buffer, ", shadowable");
1711da177e4SLinus Torvalds if (mem->flags & IORESOURCE_MEM_EXPANSIONROM)
1721da177e4SLinus Torvalds pnp_printf(buffer, ", expansion ROM");
1731da177e4SLinus Torvalds switch (mem->flags & IORESOURCE_MEM_TYPE_MASK) {
1741da177e4SLinus Torvalds case IORESOURCE_MEM_8BIT:
1751da177e4SLinus Torvalds s = "8-bit";
1761da177e4SLinus Torvalds break;
1771da177e4SLinus Torvalds case IORESOURCE_MEM_8AND16BIT:
1781da177e4SLinus Torvalds s = "8-bit&16-bit";
1791da177e4SLinus Torvalds break;
1801da177e4SLinus Torvalds case IORESOURCE_MEM_32BIT:
1811da177e4SLinus Torvalds s = "32-bit";
1821da177e4SLinus Torvalds break;
1831da177e4SLinus Torvalds default:
1841da177e4SLinus Torvalds s = "16-bit";
1851da177e4SLinus Torvalds }
1861da177e4SLinus Torvalds pnp_printf(buffer, ", %s\n", s);
1871da177e4SLinus Torvalds }
1881da177e4SLinus Torvalds
pnp_print_option(pnp_info_buffer_t * buffer,char * space,struct pnp_option * option)1891da177e4SLinus Torvalds static void pnp_print_option(pnp_info_buffer_t * buffer, char *space,
1901f32ca31SBjorn Helgaas struct pnp_option *option)
1911da177e4SLinus Torvalds {
1921f32ca31SBjorn Helgaas switch (option->type) {
1931f32ca31SBjorn Helgaas case IORESOURCE_IO:
1941f32ca31SBjorn Helgaas pnp_print_port(buffer, space, &option->u.port);
1951da177e4SLinus Torvalds break;
1961f32ca31SBjorn Helgaas case IORESOURCE_MEM:
1971f32ca31SBjorn Helgaas pnp_print_mem(buffer, space, &option->u.mem);
1981da177e4SLinus Torvalds break;
1991f32ca31SBjorn Helgaas case IORESOURCE_IRQ:
2001f32ca31SBjorn Helgaas pnp_print_irq(buffer, space, &option->u.irq);
2011da177e4SLinus Torvalds break;
2021f32ca31SBjorn Helgaas case IORESOURCE_DMA:
2031f32ca31SBjorn Helgaas pnp_print_dma(buffer, space, &option->u.dma);
2041f32ca31SBjorn Helgaas break;
2051da177e4SLinus Torvalds }
2061da177e4SLinus Torvalds }
2071da177e4SLinus Torvalds
options_show(struct device * dmdev,struct device_attribute * attr,char * buf)2082df43901SGreg Kroah-Hartman static ssize_t options_show(struct device *dmdev, struct device_attribute *attr,
2092df43901SGreg Kroah-Hartman char *buf)
2101da177e4SLinus Torvalds {
2111da177e4SLinus Torvalds struct pnp_dev *dev = to_pnp_dev(dmdev);
212b72ee1f1SBjorn Helgaas pnp_info_buffer_t *buffer;
2131f32ca31SBjorn Helgaas struct pnp_option *option;
2141f32ca31SBjorn Helgaas int ret, dep = 0, set = 0;
2151f32ca31SBjorn Helgaas char *indent;
2161da177e4SLinus Torvalds
217*b15fc7c2SHeiner Kallweit buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
2181da177e4SLinus Torvalds if (!buffer)
2191da177e4SLinus Torvalds return -ENOMEM;
2201da177e4SLinus Torvalds
2211da177e4SLinus Torvalds buffer->len = PAGE_SIZE;
2221da177e4SLinus Torvalds buffer->buffer = buf;
2231da177e4SLinus Torvalds buffer->curr = buffer->buffer;
2241da177e4SLinus Torvalds
2251f32ca31SBjorn Helgaas list_for_each_entry(option, &dev->options, list) {
2261f32ca31SBjorn Helgaas if (pnp_option_is_dependent(option)) {
2271f32ca31SBjorn Helgaas indent = " ";
2281f32ca31SBjorn Helgaas if (!dep || pnp_option_set(option) != set) {
2291f32ca31SBjorn Helgaas set = pnp_option_set(option);
2301f32ca31SBjorn Helgaas dep = 1;
2311f32ca31SBjorn Helgaas pnp_printf(buffer, "Dependent: %02i - "
2321f32ca31SBjorn Helgaas "Priority %s\n", set,
2331f32ca31SBjorn Helgaas pnp_option_priority_name(option));
2341da177e4SLinus Torvalds }
2351f32ca31SBjorn Helgaas } else {
2361f32ca31SBjorn Helgaas dep = 0;
2371f32ca31SBjorn Helgaas indent = "";
2381f32ca31SBjorn Helgaas }
2391f32ca31SBjorn Helgaas pnp_print_option(buffer, indent, option);
2401f32ca31SBjorn Helgaas }
2411f32ca31SBjorn Helgaas
2421da177e4SLinus Torvalds ret = (buffer->curr - buf);
2431da177e4SLinus Torvalds kfree(buffer);
2441da177e4SLinus Torvalds return ret;
2451da177e4SLinus Torvalds }
2462df43901SGreg Kroah-Hartman static DEVICE_ATTR_RO(options);
2471da177e4SLinus Torvalds
resources_show(struct device * dmdev,struct device_attribute * attr,char * buf)2482df43901SGreg Kroah-Hartman static ssize_t resources_show(struct device *dmdev,
2492df43901SGreg Kroah-Hartman struct device_attribute *attr, char *buf)
2501da177e4SLinus Torvalds {
2511da177e4SLinus Torvalds struct pnp_dev *dev = to_pnp_dev(dmdev);
252b72ee1f1SBjorn Helgaas pnp_info_buffer_t *buffer;
253f61ed7e3SBjorn Helgaas struct pnp_resource *pnp_res;
25495ab3669SBjorn Helgaas struct resource *res;
255f61ed7e3SBjorn Helgaas int ret;
2561da177e4SLinus Torvalds
2571da177e4SLinus Torvalds if (!dev)
2581da177e4SLinus Torvalds return -EINVAL;
2591da177e4SLinus Torvalds
260*b15fc7c2SHeiner Kallweit buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
2611da177e4SLinus Torvalds if (!buffer)
2621da177e4SLinus Torvalds return -ENOMEM;
263b72ee1f1SBjorn Helgaas
2641da177e4SLinus Torvalds buffer->len = PAGE_SIZE;
2651da177e4SLinus Torvalds buffer->buffer = buf;
2661da177e4SLinus Torvalds buffer->curr = buffer->buffer;
2671da177e4SLinus Torvalds
268f61ed7e3SBjorn Helgaas pnp_printf(buffer, "state = %s\n", dev->active ? "active" : "disabled");
2691da177e4SLinus Torvalds
270f61ed7e3SBjorn Helgaas list_for_each_entry(pnp_res, &dev->resources, list) {
271f61ed7e3SBjorn Helgaas res = &pnp_res->res;
272f61ed7e3SBjorn Helgaas
273f61ed7e3SBjorn Helgaas pnp_printf(buffer, pnp_resource_type_name(res));
274f61ed7e3SBjorn Helgaas
275f61ed7e3SBjorn Helgaas if (res->flags & IORESOURCE_DISABLED) {
2761da177e4SLinus Torvalds pnp_printf(buffer, " disabled\n");
277f61ed7e3SBjorn Helgaas continue;
278f61ed7e3SBjorn Helgaas }
279f61ed7e3SBjorn Helgaas
280f61ed7e3SBjorn Helgaas switch (pnp_resource_type(res)) {
281f61ed7e3SBjorn Helgaas case IORESOURCE_IO:
282f61ed7e3SBjorn Helgaas case IORESOURCE_MEM:
2837e0e9c04SBjorn Helgaas case IORESOURCE_BUS:
284fa35b492SBjorn Helgaas pnp_printf(buffer, " %#llx-%#llx%s\n",
28595ab3669SBjorn Helgaas (unsigned long long) res->start,
286fa35b492SBjorn Helgaas (unsigned long long) res->end,
287fa35b492SBjorn Helgaas res->flags & IORESOURCE_WINDOW ?
288fa35b492SBjorn Helgaas " window" : "");
289f61ed7e3SBjorn Helgaas break;
290f61ed7e3SBjorn Helgaas case IORESOURCE_IRQ:
291f61ed7e3SBjorn Helgaas case IORESOURCE_DMA:
292b60ba834SGreg Kroah-Hartman pnp_printf(buffer, " %lld\n",
29395ab3669SBjorn Helgaas (unsigned long long) res->start);
294f61ed7e3SBjorn Helgaas break;
2951da177e4SLinus Torvalds }
2961da177e4SLinus Torvalds }
297f61ed7e3SBjorn Helgaas
2981da177e4SLinus Torvalds ret = (buffer->curr - buf);
2991da177e4SLinus Torvalds kfree(buffer);
3001da177e4SLinus Torvalds return ret;
3011da177e4SLinus Torvalds }
3021da177e4SLinus Torvalds
pnp_get_resource_value(char * buf,unsigned long type,resource_size_t * start,resource_size_t * end,unsigned long * flags)303c9377667SWitold Szczeponik static char *pnp_get_resource_value(char *buf,
304c9377667SWitold Szczeponik unsigned long type,
305c9377667SWitold Szczeponik resource_size_t *start,
306c9377667SWitold Szczeponik resource_size_t *end,
307c9377667SWitold Szczeponik unsigned long *flags)
308c9377667SWitold Szczeponik {
309c9377667SWitold Szczeponik if (start)
310c9377667SWitold Szczeponik *start = 0;
311c9377667SWitold Szczeponik if (end)
312c9377667SWitold Szczeponik *end = 0;
313c9377667SWitold Szczeponik if (flags)
314c9377667SWitold Szczeponik *flags = 0;
315c9377667SWitold Szczeponik
316c9377667SWitold Szczeponik /* TBD: allow for disabled resources */
317c9377667SWitold Szczeponik
318c9377667SWitold Szczeponik buf = skip_spaces(buf);
319c9377667SWitold Szczeponik if (start) {
320c9377667SWitold Szczeponik *start = simple_strtoull(buf, &buf, 0);
321c9377667SWitold Szczeponik if (end) {
322c9377667SWitold Szczeponik buf = skip_spaces(buf);
323c9377667SWitold Szczeponik if (*buf == '-') {
324c9377667SWitold Szczeponik buf = skip_spaces(buf + 1);
325c9377667SWitold Szczeponik *end = simple_strtoull(buf, &buf, 0);
326c9377667SWitold Szczeponik } else
327c9377667SWitold Szczeponik *end = *start;
328c9377667SWitold Szczeponik }
329c9377667SWitold Szczeponik }
330c9377667SWitold Szczeponik
331c9377667SWitold Szczeponik /* TBD: allow for additional flags, e.g., IORESOURCE_WINDOW */
332c9377667SWitold Szczeponik
333c9377667SWitold Szczeponik return buf;
334c9377667SWitold Szczeponik }
335c9377667SWitold Szczeponik
resources_store(struct device * dmdev,struct device_attribute * attr,const char * ubuf,size_t count)3362df43901SGreg Kroah-Hartman static ssize_t resources_store(struct device *dmdev,
3372df43901SGreg Kroah-Hartman struct device_attribute *attr, const char *ubuf,
3382df43901SGreg Kroah-Hartman size_t count)
3391da177e4SLinus Torvalds {
3401da177e4SLinus Torvalds struct pnp_dev *dev = to_pnp_dev(dmdev);
3411da177e4SLinus Torvalds char *buf = (void *)ubuf;
3421da177e4SLinus Torvalds int retval = 0;
3431da177e4SLinus Torvalds
3441da177e4SLinus Torvalds if (dev->status & PNP_ATTACHED) {
3451da177e4SLinus Torvalds retval = -EBUSY;
346a05d0781SBjorn Helgaas dev_info(&dev->dev, "in use; can't configure\n");
3471da177e4SLinus Torvalds goto done;
3481da177e4SLinus Torvalds }
3491da177e4SLinus Torvalds
350e7d2860bSAndré Goddard Rosa buf = skip_spaces(buf);
3517fb1cab4SRasmus Villemoes if (!strncasecmp(buf, "disable", 7)) {
3521da177e4SLinus Torvalds retval = pnp_disable_dev(dev);
3531da177e4SLinus Torvalds goto done;
3541da177e4SLinus Torvalds }
3557fb1cab4SRasmus Villemoes if (!strncasecmp(buf, "activate", 8)) {
3561da177e4SLinus Torvalds retval = pnp_activate_dev(dev);
3571da177e4SLinus Torvalds goto done;
3581da177e4SLinus Torvalds }
3597fb1cab4SRasmus Villemoes if (!strncasecmp(buf, "fill", 4)) {
3601da177e4SLinus Torvalds if (dev->active)
3611da177e4SLinus Torvalds goto done;
3621da177e4SLinus Torvalds retval = pnp_auto_config_dev(dev);
3631da177e4SLinus Torvalds goto done;
3641da177e4SLinus Torvalds }
3657fb1cab4SRasmus Villemoes if (!strncasecmp(buf, "auto", 4)) {
3661da177e4SLinus Torvalds if (dev->active)
3671da177e4SLinus Torvalds goto done;
368f4490002SBjorn Helgaas pnp_init_resources(dev);
3691da177e4SLinus Torvalds retval = pnp_auto_config_dev(dev);
3701da177e4SLinus Torvalds goto done;
3711da177e4SLinus Torvalds }
3727fb1cab4SRasmus Villemoes if (!strncasecmp(buf, "clear", 5)) {
3731da177e4SLinus Torvalds if (dev->active)
3741da177e4SLinus Torvalds goto done;
375f4490002SBjorn Helgaas pnp_init_resources(dev);
3761da177e4SLinus Torvalds goto done;
3771da177e4SLinus Torvalds }
3787fb1cab4SRasmus Villemoes if (!strncasecmp(buf, "get", 3)) {
379b3bd86e2SDaniel Walker mutex_lock(&pnp_res_mutex);
3801da177e4SLinus Torvalds if (pnp_can_read(dev))
38159284cb4SBjorn Helgaas dev->protocol->get(dev);
382b3bd86e2SDaniel Walker mutex_unlock(&pnp_res_mutex);
3831da177e4SLinus Torvalds goto done;
3841da177e4SLinus Torvalds }
3857fb1cab4SRasmus Villemoes if (!strncasecmp(buf, "set", 3)) {
386c9377667SWitold Szczeponik resource_size_t start;
387c9377667SWitold Szczeponik resource_size_t end;
388c9377667SWitold Szczeponik unsigned long flags;
389c9377667SWitold Szczeponik
3901da177e4SLinus Torvalds if (dev->active)
3911da177e4SLinus Torvalds goto done;
3921da177e4SLinus Torvalds buf += 3;
393f4490002SBjorn Helgaas pnp_init_resources(dev);
394b3bd86e2SDaniel Walker mutex_lock(&pnp_res_mutex);
3951da177e4SLinus Torvalds while (1) {
396e7d2860bSAndré Goddard Rosa buf = skip_spaces(buf);
3977fb1cab4SRasmus Villemoes if (!strncasecmp(buf, "io", 2)) {
398c9377667SWitold Szczeponik buf = pnp_get_resource_value(buf + 2,
399c9377667SWitold Szczeponik IORESOURCE_IO,
400c9377667SWitold Szczeponik &start, &end,
401c9377667SWitold Szczeponik &flags);
402c9377667SWitold Szczeponik pnp_add_io_resource(dev, start, end, flags);
4037fb1cab4SRasmus Villemoes } else if (!strncasecmp(buf, "mem", 3)) {
404c9377667SWitold Szczeponik buf = pnp_get_resource_value(buf + 3,
405c9377667SWitold Szczeponik IORESOURCE_MEM,
406c9377667SWitold Szczeponik &start, &end,
407c9377667SWitold Szczeponik &flags);
408c9377667SWitold Szczeponik pnp_add_mem_resource(dev, start, end, flags);
4097fb1cab4SRasmus Villemoes } else if (!strncasecmp(buf, "irq", 3)) {
410c9377667SWitold Szczeponik buf = pnp_get_resource_value(buf + 3,
411c9377667SWitold Szczeponik IORESOURCE_IRQ,
412c9377667SWitold Szczeponik &start, NULL,
413c9377667SWitold Szczeponik &flags);
414c9377667SWitold Szczeponik pnp_add_irq_resource(dev, start, flags);
4157fb1cab4SRasmus Villemoes } else if (!strncasecmp(buf, "dma", 3)) {
416c9377667SWitold Szczeponik buf = pnp_get_resource_value(buf + 3,
417c9377667SWitold Szczeponik IORESOURCE_DMA,
418c9377667SWitold Szczeponik &start, NULL,
419c9377667SWitold Szczeponik &flags);
420c9377667SWitold Szczeponik pnp_add_dma_resource(dev, start, flags);
4217fb1cab4SRasmus Villemoes } else if (!strncasecmp(buf, "bus", 3)) {
422c9377667SWitold Szczeponik buf = pnp_get_resource_value(buf + 3,
423c9377667SWitold Szczeponik IORESOURCE_BUS,
424c9377667SWitold Szczeponik &start, &end,
425c9377667SWitold Szczeponik NULL);
426c9377667SWitold Szczeponik pnp_add_bus_resource(dev, start, end);
4271da177e4SLinus Torvalds } else
4281da177e4SLinus Torvalds break;
4291da177e4SLinus Torvalds }
430b3bd86e2SDaniel Walker mutex_unlock(&pnp_res_mutex);
4311da177e4SLinus Torvalds goto done;
4321da177e4SLinus Torvalds }
4331e0aa9adSBjorn Helgaas
4341da177e4SLinus Torvalds done:
4351da177e4SLinus Torvalds if (retval < 0)
4361da177e4SLinus Torvalds return retval;
4371da177e4SLinus Torvalds return count;
4381da177e4SLinus Torvalds }
4392df43901SGreg Kroah-Hartman static DEVICE_ATTR_RW(resources);
4401da177e4SLinus Torvalds
id_show(struct device * dmdev,struct device_attribute * attr,char * buf)4412df43901SGreg Kroah-Hartman static ssize_t id_show(struct device *dmdev, struct device_attribute *attr,
4422df43901SGreg Kroah-Hartman char *buf)
4431da177e4SLinus Torvalds {
4441da177e4SLinus Torvalds char *str = buf;
4451da177e4SLinus Torvalds struct pnp_dev *dev = to_pnp_dev(dmdev);
4461da177e4SLinus Torvalds struct pnp_id *pos = dev->id;
4471da177e4SLinus Torvalds
4481da177e4SLinus Torvalds while (pos) {
4491da177e4SLinus Torvalds str += sprintf(str, "%s\n", pos->id);
4501da177e4SLinus Torvalds pos = pos->next;
4511da177e4SLinus Torvalds }
4521da177e4SLinus Torvalds return (str - buf);
4531da177e4SLinus Torvalds }
4542df43901SGreg Kroah-Hartman static DEVICE_ATTR_RO(id);
4551da177e4SLinus Torvalds
4562df43901SGreg Kroah-Hartman static struct attribute *pnp_dev_attrs[] = {
4572df43901SGreg Kroah-Hartman &dev_attr_resources.attr,
4582df43901SGreg Kroah-Hartman &dev_attr_options.attr,
4592df43901SGreg Kroah-Hartman &dev_attr_id.attr,
4602df43901SGreg Kroah-Hartman NULL,
4612df43901SGreg Kroah-Hartman };
4622df43901SGreg Kroah-Hartman
4632df43901SGreg Kroah-Hartman static const struct attribute_group pnp_dev_group = {
4642df43901SGreg Kroah-Hartman .attrs = pnp_dev_attrs,
4652df43901SGreg Kroah-Hartman };
4662df43901SGreg Kroah-Hartman
4672df43901SGreg Kroah-Hartman const struct attribute_group *pnp_dev_groups[] = {
4682df43901SGreg Kroah-Hartman &pnp_dev_group,
4692df43901SGreg Kroah-Hartman NULL,
4708a89efd1SDrew Moseley };
471