1 // SPDX-License-Identifier: GPL-2.0
3 * interface.c - contains everything related to the user interface
5 * Some code, especially possible resource dumping is based on isapnp_proc.c (c) Jaroslav Kysela <perex@perex.cz>
6 * Copyright 2002 Adam Belay <ambx1@neo.rr.com>
7 * Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
8 * Bjorn Helgaas <bjorn.helgaas@hp.com>
11 #include <linux/pnp.h>
12 #include <linux/string.h>
13 #include <linux/errno.h>
14 #include <linux/list.h>
15 #include <linux/types.h>
16 #include <linux/stat.h>
17 #include <linux/ctype.h>
18 #include <linux/slab.h>
19 #include <linux/mutex.h>
21 #include <linux/uaccess.h>
25 struct pnp_info_buffer
{
26 char *buffer
; /* pointer to begin of buffer */
27 char *curr
; /* current position in buffer */
28 unsigned long size
; /* current size */
29 unsigned long len
; /* total length of buffer */
30 int stop
; /* stop flag */
31 int error
; /* error code */
34 typedef struct pnp_info_buffer pnp_info_buffer_t
;
36 static int pnp_printf(pnp_info_buffer_t
* buffer
, char *fmt
, ...)
41 if (buffer
->stop
|| buffer
->error
)
44 res
= vsnprintf(buffer
->curr
, buffer
->len
- buffer
->size
, fmt
, args
);
46 if (buffer
->size
+ res
>= buffer
->len
) {
55 static void pnp_print_port(pnp_info_buffer_t
* buffer
, char *space
,
56 struct pnp_port
*port
)
58 pnp_printf(buffer
, "%sport %#llx-%#llx, align %#llx, size %#llx, "
59 "%i-bit address decoding\n", space
,
60 (unsigned long long) port
->min
,
61 (unsigned long long) port
->max
,
62 port
->align
? ((unsigned long long) port
->align
- 1) : 0,
63 (unsigned long long) port
->size
,
64 port
->flags
& IORESOURCE_IO_16BIT_ADDR
? 16 : 10);
67 static void pnp_print_irq(pnp_info_buffer_t
* buffer
, char *space
,
72 pnp_printf(buffer
, "%sirq ", space
);
73 for (i
= 0; i
< PNP_IRQ_NR
; i
++)
74 if (test_bit(i
, irq
->map
.bits
)) {
76 pnp_printf(buffer
, ",");
81 pnp_printf(buffer
, "2/9");
83 pnp_printf(buffer
, "%i", i
);
85 if (bitmap_empty(irq
->map
.bits
, PNP_IRQ_NR
))
86 pnp_printf(buffer
, "<none>");
87 if (irq
->flags
& IORESOURCE_IRQ_HIGHEDGE
)
88 pnp_printf(buffer
, " High-Edge");
89 if (irq
->flags
& IORESOURCE_IRQ_LOWEDGE
)
90 pnp_printf(buffer
, " Low-Edge");
91 if (irq
->flags
& IORESOURCE_IRQ_HIGHLEVEL
)
92 pnp_printf(buffer
, " High-Level");
93 if (irq
->flags
& IORESOURCE_IRQ_LOWLEVEL
)
94 pnp_printf(buffer
, " Low-Level");
95 if (irq
->flags
& IORESOURCE_IRQ_OPTIONAL
)
96 pnp_printf(buffer
, " (optional)");
97 pnp_printf(buffer
, "\n");
100 static void pnp_print_dma(pnp_info_buffer_t
* buffer
, char *space
,
106 pnp_printf(buffer
, "%sdma ", space
);
107 for (i
= 0; i
< 8; i
++)
108 if (dma
->map
& (1 << i
)) {
110 pnp_printf(buffer
, ",");
114 pnp_printf(buffer
, "%i", i
);
117 pnp_printf(buffer
, "<none>");
118 switch (dma
->flags
& IORESOURCE_DMA_TYPE_MASK
) {
119 case IORESOURCE_DMA_8BIT
:
122 case IORESOURCE_DMA_8AND16BIT
:
128 pnp_printf(buffer
, " %s", s
);
129 if (dma
->flags
& IORESOURCE_DMA_MASTER
)
130 pnp_printf(buffer
, " master");
131 if (dma
->flags
& IORESOURCE_DMA_BYTE
)
132 pnp_printf(buffer
, " byte-count");
133 if (dma
->flags
& IORESOURCE_DMA_WORD
)
134 pnp_printf(buffer
, " word-count");
135 switch (dma
->flags
& IORESOURCE_DMA_SPEED_MASK
) {
136 case IORESOURCE_DMA_TYPEA
:
139 case IORESOURCE_DMA_TYPEB
:
142 case IORESOURCE_DMA_TYPEF
:
149 pnp_printf(buffer
, " %s\n", s
);
152 static void pnp_print_mem(pnp_info_buffer_t
* buffer
, char *space
,
157 pnp_printf(buffer
, "%sMemory %#llx-%#llx, align %#llx, size %#llx",
158 space
, (unsigned long long) mem
->min
,
159 (unsigned long long) mem
->max
,
160 (unsigned long long) mem
->align
,
161 (unsigned long long) mem
->size
);
162 if (mem
->flags
& IORESOURCE_MEM_WRITEABLE
)
163 pnp_printf(buffer
, ", writeable");
164 if (mem
->flags
& IORESOURCE_MEM_CACHEABLE
)
165 pnp_printf(buffer
, ", cacheable");
166 if (mem
->flags
& IORESOURCE_MEM_RANGELENGTH
)
167 pnp_printf(buffer
, ", range-length");
168 if (mem
->flags
& IORESOURCE_MEM_SHADOWABLE
)
169 pnp_printf(buffer
, ", shadowable");
170 if (mem
->flags
& IORESOURCE_MEM_EXPANSIONROM
)
171 pnp_printf(buffer
, ", expansion ROM");
172 switch (mem
->flags
& IORESOURCE_MEM_TYPE_MASK
) {
173 case IORESOURCE_MEM_8BIT
:
176 case IORESOURCE_MEM_8AND16BIT
:
179 case IORESOURCE_MEM_32BIT
:
185 pnp_printf(buffer
, ", %s\n", s
);
188 static void pnp_print_option(pnp_info_buffer_t
* buffer
, char *space
,
189 struct pnp_option
*option
)
191 switch (option
->type
) {
193 pnp_print_port(buffer
, space
, &option
->u
.port
);
196 pnp_print_mem(buffer
, space
, &option
->u
.mem
);
199 pnp_print_irq(buffer
, space
, &option
->u
.irq
);
202 pnp_print_dma(buffer
, space
, &option
->u
.dma
);
207 static ssize_t
options_show(struct device
*dmdev
, struct device_attribute
*attr
,
210 struct pnp_dev
*dev
= to_pnp_dev(dmdev
);
211 pnp_info_buffer_t
*buffer
;
212 struct pnp_option
*option
;
213 int ret
, dep
= 0, set
= 0;
216 buffer
= pnp_alloc(sizeof(pnp_info_buffer_t
));
220 buffer
->len
= PAGE_SIZE
;
221 buffer
->buffer
= buf
;
222 buffer
->curr
= buffer
->buffer
;
224 list_for_each_entry(option
, &dev
->options
, list
) {
225 if (pnp_option_is_dependent(option
)) {
227 if (!dep
|| pnp_option_set(option
) != set
) {
228 set
= pnp_option_set(option
);
230 pnp_printf(buffer
, "Dependent: %02i - "
231 "Priority %s\n", set
,
232 pnp_option_priority_name(option
));
238 pnp_print_option(buffer
, indent
, option
);
241 ret
= (buffer
->curr
- buf
);
245 static DEVICE_ATTR_RO(options
);
247 static ssize_t
resources_show(struct device
*dmdev
,
248 struct device_attribute
*attr
, char *buf
)
250 struct pnp_dev
*dev
= to_pnp_dev(dmdev
);
251 pnp_info_buffer_t
*buffer
;
252 struct pnp_resource
*pnp_res
;
253 struct resource
*res
;
259 buffer
= pnp_alloc(sizeof(pnp_info_buffer_t
));
263 buffer
->len
= PAGE_SIZE
;
264 buffer
->buffer
= buf
;
265 buffer
->curr
= buffer
->buffer
;
267 pnp_printf(buffer
, "state = %s\n", dev
->active
? "active" : "disabled");
269 list_for_each_entry(pnp_res
, &dev
->resources
, list
) {
272 pnp_printf(buffer
, pnp_resource_type_name(res
));
274 if (res
->flags
& IORESOURCE_DISABLED
) {
275 pnp_printf(buffer
, " disabled\n");
279 switch (pnp_resource_type(res
)) {
283 pnp_printf(buffer
, " %#llx-%#llx%s\n",
284 (unsigned long long) res
->start
,
285 (unsigned long long) res
->end
,
286 res
->flags
& IORESOURCE_WINDOW
?
291 pnp_printf(buffer
, " %lld\n",
292 (unsigned long long) res
->start
);
297 ret
= (buffer
->curr
- buf
);
302 static char *pnp_get_resource_value(char *buf
,
304 resource_size_t
*start
,
305 resource_size_t
*end
,
306 unsigned long *flags
)
315 /* TBD: allow for disabled resources */
317 buf
= skip_spaces(buf
);
319 *start
= simple_strtoull(buf
, &buf
, 0);
321 buf
= skip_spaces(buf
);
323 buf
= skip_spaces(buf
+ 1);
324 *end
= simple_strtoull(buf
, &buf
, 0);
330 /* TBD: allow for additional flags, e.g., IORESOURCE_WINDOW */
335 static ssize_t
resources_store(struct device
*dmdev
,
336 struct device_attribute
*attr
, const char *ubuf
,
339 struct pnp_dev
*dev
= to_pnp_dev(dmdev
);
340 char *buf
= (void *)ubuf
;
343 if (dev
->status
& PNP_ATTACHED
) {
345 dev_info(&dev
->dev
, "in use; can't configure\n");
349 buf
= skip_spaces(buf
);
350 if (!strncasecmp(buf
, "disable", 7)) {
351 retval
= pnp_disable_dev(dev
);
354 if (!strncasecmp(buf
, "activate", 8)) {
355 retval
= pnp_activate_dev(dev
);
358 if (!strncasecmp(buf
, "fill", 4)) {
361 retval
= pnp_auto_config_dev(dev
);
364 if (!strncasecmp(buf
, "auto", 4)) {
367 pnp_init_resources(dev
);
368 retval
= pnp_auto_config_dev(dev
);
371 if (!strncasecmp(buf
, "clear", 5)) {
374 pnp_init_resources(dev
);
377 if (!strncasecmp(buf
, "get", 3)) {
378 mutex_lock(&pnp_res_mutex
);
379 if (pnp_can_read(dev
))
380 dev
->protocol
->get(dev
);
381 mutex_unlock(&pnp_res_mutex
);
384 if (!strncasecmp(buf
, "set", 3)) {
385 resource_size_t start
;
392 pnp_init_resources(dev
);
393 mutex_lock(&pnp_res_mutex
);
395 buf
= skip_spaces(buf
);
396 if (!strncasecmp(buf
, "io", 2)) {
397 buf
= pnp_get_resource_value(buf
+ 2,
401 pnp_add_io_resource(dev
, start
, end
, flags
);
402 } else if (!strncasecmp(buf
, "mem", 3)) {
403 buf
= pnp_get_resource_value(buf
+ 3,
407 pnp_add_mem_resource(dev
, start
, end
, flags
);
408 } else if (!strncasecmp(buf
, "irq", 3)) {
409 buf
= pnp_get_resource_value(buf
+ 3,
413 pnp_add_irq_resource(dev
, start
, flags
);
414 } else if (!strncasecmp(buf
, "dma", 3)) {
415 buf
= pnp_get_resource_value(buf
+ 3,
419 pnp_add_dma_resource(dev
, start
, flags
);
420 } else if (!strncasecmp(buf
, "bus", 3)) {
421 buf
= pnp_get_resource_value(buf
+ 3,
425 pnp_add_bus_resource(dev
, start
, end
);
429 mutex_unlock(&pnp_res_mutex
);
438 static DEVICE_ATTR_RW(resources
);
440 static ssize_t
id_show(struct device
*dmdev
, struct device_attribute
*attr
,
444 struct pnp_dev
*dev
= to_pnp_dev(dmdev
);
445 struct pnp_id
*pos
= dev
->id
;
448 str
+= sprintf(str
, "%s\n", pos
->id
);
453 static DEVICE_ATTR_RO(id
);
455 static struct attribute
*pnp_dev_attrs
[] = {
456 &dev_attr_resources
.attr
,
457 &dev_attr_options
.attr
,
462 static const struct attribute_group pnp_dev_group
= {
463 .attrs
= pnp_dev_attrs
,
466 const struct attribute_group
*pnp_dev_groups
[] = {