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
;
37 static int pnp_printf(pnp_info_buffer_t
* buffer
, char *fmt
, ...)
42 if (buffer
->stop
|| buffer
->error
)
45 res
= vsnprintf(buffer
->curr
, buffer
->len
- buffer
->size
, fmt
, args
);
47 if (buffer
->size
+ res
>= buffer
->len
) {
56 static void pnp_print_port(pnp_info_buffer_t
* buffer
, char *space
,
57 struct pnp_port
*port
)
59 pnp_printf(buffer
, "%sport %#llx-%#llx, align %#llx, size %#llx, "
60 "%i-bit address decoding\n", space
,
61 (unsigned long long) port
->min
,
62 (unsigned long long) port
->max
,
63 port
->align
? ((unsigned long long) port
->align
- 1) : 0,
64 (unsigned long long) port
->size
,
65 port
->flags
& IORESOURCE_IO_16BIT_ADDR
? 16 : 10);
68 static void pnp_print_irq(pnp_info_buffer_t
* buffer
, char *space
,
73 pnp_printf(buffer
, "%sirq ", space
);
74 for (i
= 0; i
< PNP_IRQ_NR
; i
++)
75 if (test_bit(i
, irq
->map
.bits
)) {
77 pnp_printf(buffer
, ",");
82 pnp_printf(buffer
, "2/9");
84 pnp_printf(buffer
, "%i", i
);
86 if (bitmap_empty(irq
->map
.bits
, PNP_IRQ_NR
))
87 pnp_printf(buffer
, "<none>");
88 if (irq
->flags
& IORESOURCE_IRQ_HIGHEDGE
)
89 pnp_printf(buffer
, " High-Edge");
90 if (irq
->flags
& IORESOURCE_IRQ_LOWEDGE
)
91 pnp_printf(buffer
, " Low-Edge");
92 if (irq
->flags
& IORESOURCE_IRQ_HIGHLEVEL
)
93 pnp_printf(buffer
, " High-Level");
94 if (irq
->flags
& IORESOURCE_IRQ_LOWLEVEL
)
95 pnp_printf(buffer
, " Low-Level");
96 if (irq
->flags
& IORESOURCE_IRQ_OPTIONAL
)
97 pnp_printf(buffer
, " (optional)");
98 pnp_printf(buffer
, "\n");
101 static void pnp_print_dma(pnp_info_buffer_t
* buffer
, char *space
,
107 pnp_printf(buffer
, "%sdma ", space
);
108 for (i
= 0; i
< 8; i
++)
109 if (dma
->map
& (1 << i
)) {
111 pnp_printf(buffer
, ",");
115 pnp_printf(buffer
, "%i", i
);
118 pnp_printf(buffer
, "<none>");
119 switch (dma
->flags
& IORESOURCE_DMA_TYPE_MASK
) {
120 case IORESOURCE_DMA_8BIT
:
123 case IORESOURCE_DMA_8AND16BIT
:
129 pnp_printf(buffer
, " %s", s
);
130 if (dma
->flags
& IORESOURCE_DMA_MASTER
)
131 pnp_printf(buffer
, " master");
132 if (dma
->flags
& IORESOURCE_DMA_BYTE
)
133 pnp_printf(buffer
, " byte-count");
134 if (dma
->flags
& IORESOURCE_DMA_WORD
)
135 pnp_printf(buffer
, " word-count");
136 switch (dma
->flags
& IORESOURCE_DMA_SPEED_MASK
) {
137 case IORESOURCE_DMA_TYPEA
:
140 case IORESOURCE_DMA_TYPEB
:
143 case IORESOURCE_DMA_TYPEF
:
150 pnp_printf(buffer
, " %s\n", s
);
153 static void pnp_print_mem(pnp_info_buffer_t
* buffer
, char *space
,
158 pnp_printf(buffer
, "%sMemory %#llx-%#llx, align %#llx, size %#llx",
159 space
, (unsigned long long) mem
->min
,
160 (unsigned long long) mem
->max
,
161 (unsigned long long) mem
->align
,
162 (unsigned long long) mem
->size
);
163 if (mem
->flags
& IORESOURCE_MEM_WRITEABLE
)
164 pnp_printf(buffer
, ", writeable");
165 if (mem
->flags
& IORESOURCE_MEM_CACHEABLE
)
166 pnp_printf(buffer
, ", cacheable");
167 if (mem
->flags
& IORESOURCE_MEM_RANGELENGTH
)
168 pnp_printf(buffer
, ", range-length");
169 if (mem
->flags
& IORESOURCE_MEM_SHADOWABLE
)
170 pnp_printf(buffer
, ", shadowable");
171 if (mem
->flags
& IORESOURCE_MEM_EXPANSIONROM
)
172 pnp_printf(buffer
, ", expansion ROM");
173 switch (mem
->flags
& IORESOURCE_MEM_TYPE_MASK
) {
174 case IORESOURCE_MEM_8BIT
:
177 case IORESOURCE_MEM_8AND16BIT
:
180 case IORESOURCE_MEM_32BIT
:
186 pnp_printf(buffer
, ", %s\n", s
);
189 static void pnp_print_option(pnp_info_buffer_t
* buffer
, char *space
,
190 struct pnp_option
*option
)
192 switch (option
->type
) {
194 pnp_print_port(buffer
, space
, &option
->u
.port
);
197 pnp_print_mem(buffer
, space
, &option
->u
.mem
);
200 pnp_print_irq(buffer
, space
, &option
->u
.irq
);
203 pnp_print_dma(buffer
, space
, &option
->u
.dma
);
208 static ssize_t
options_show(struct device
*dmdev
, struct device_attribute
*attr
,
211 struct pnp_dev
*dev
= to_pnp_dev(dmdev
);
212 pnp_info_buffer_t
*buffer
;
213 struct pnp_option
*option
;
214 int ret
, dep
= 0, set
= 0;
217 buffer
= kzalloc(sizeof(*buffer
), GFP_KERNEL
);
221 buffer
->len
= PAGE_SIZE
;
222 buffer
->buffer
= buf
;
223 buffer
->curr
= buffer
->buffer
;
225 list_for_each_entry(option
, &dev
->options
, list
) {
226 if (pnp_option_is_dependent(option
)) {
228 if (!dep
|| pnp_option_set(option
) != set
) {
229 set
= pnp_option_set(option
);
231 pnp_printf(buffer
, "Dependent: %02i - "
232 "Priority %s\n", set
,
233 pnp_option_priority_name(option
));
239 pnp_print_option(buffer
, indent
, option
);
242 ret
= (buffer
->curr
- buf
);
246 static DEVICE_ATTR_RO(options
);
248 static ssize_t
resources_show(struct device
*dmdev
,
249 struct device_attribute
*attr
, char *buf
)
251 struct pnp_dev
*dev
= to_pnp_dev(dmdev
);
252 pnp_info_buffer_t
*buffer
;
253 struct pnp_resource
*pnp_res
;
254 struct resource
*res
;
260 buffer
= kzalloc(sizeof(*buffer
), GFP_KERNEL
);
264 buffer
->len
= PAGE_SIZE
;
265 buffer
->buffer
= buf
;
266 buffer
->curr
= buffer
->buffer
;
268 pnp_printf(buffer
, "state = %s\n", dev
->active
? "active" : "disabled");
270 list_for_each_entry(pnp_res
, &dev
->resources
, list
) {
273 pnp_printf(buffer
, pnp_resource_type_name(res
));
275 if (res
->flags
& IORESOURCE_DISABLED
) {
276 pnp_printf(buffer
, " disabled\n");
280 switch (pnp_resource_type(res
)) {
284 pnp_printf(buffer
, " %#llx-%#llx%s\n",
285 (unsigned long long) res
->start
,
286 (unsigned long long) res
->end
,
287 res
->flags
& IORESOURCE_WINDOW
?
292 pnp_printf(buffer
, " %lld\n",
293 (unsigned long long) res
->start
);
298 ret
= (buffer
->curr
- buf
);
303 static char *pnp_get_resource_value(char *buf
,
305 resource_size_t
*start
,
306 resource_size_t
*end
,
307 unsigned long *flags
)
316 /* TBD: allow for disabled resources */
318 buf
= skip_spaces(buf
);
320 *start
= simple_strtoull(buf
, &buf
, 0);
322 buf
= skip_spaces(buf
);
324 buf
= skip_spaces(buf
+ 1);
325 *end
= simple_strtoull(buf
, &buf
, 0);
331 /* TBD: allow for additional flags, e.g., IORESOURCE_WINDOW */
336 static ssize_t
resources_store(struct device
*dmdev
,
337 struct device_attribute
*attr
, const char *ubuf
,
340 struct pnp_dev
*dev
= to_pnp_dev(dmdev
);
341 char *buf
= (void *)ubuf
;
344 if (dev
->status
& PNP_ATTACHED
) {
346 dev_info(&dev
->dev
, "in use; can't configure\n");
350 buf
= skip_spaces(buf
);
351 if (!strncasecmp(buf
, "disable", 7)) {
352 retval
= pnp_disable_dev(dev
);
355 if (!strncasecmp(buf
, "activate", 8)) {
356 retval
= pnp_activate_dev(dev
);
359 if (!strncasecmp(buf
, "fill", 4)) {
362 retval
= pnp_auto_config_dev(dev
);
365 if (!strncasecmp(buf
, "auto", 4)) {
368 pnp_init_resources(dev
);
369 retval
= pnp_auto_config_dev(dev
);
372 if (!strncasecmp(buf
, "clear", 5)) {
375 pnp_init_resources(dev
);
378 if (!strncasecmp(buf
, "get", 3)) {
379 mutex_lock(&pnp_res_mutex
);
380 if (pnp_can_read(dev
))
381 dev
->protocol
->get(dev
);
382 mutex_unlock(&pnp_res_mutex
);
385 if (!strncasecmp(buf
, "set", 3)) {
386 resource_size_t start
;
393 pnp_init_resources(dev
);
394 mutex_lock(&pnp_res_mutex
);
396 buf
= skip_spaces(buf
);
397 if (!strncasecmp(buf
, "io", 2)) {
398 buf
= pnp_get_resource_value(buf
+ 2,
402 pnp_add_io_resource(dev
, start
, end
, flags
);
403 } else if (!strncasecmp(buf
, "mem", 3)) {
404 buf
= pnp_get_resource_value(buf
+ 3,
408 pnp_add_mem_resource(dev
, start
, end
, flags
);
409 } else if (!strncasecmp(buf
, "irq", 3)) {
410 buf
= pnp_get_resource_value(buf
+ 3,
414 pnp_add_irq_resource(dev
, start
, flags
);
415 } else if (!strncasecmp(buf
, "dma", 3)) {
416 buf
= pnp_get_resource_value(buf
+ 3,
420 pnp_add_dma_resource(dev
, start
, flags
);
421 } else if (!strncasecmp(buf
, "bus", 3)) {
422 buf
= pnp_get_resource_value(buf
+ 3,
426 pnp_add_bus_resource(dev
, start
, end
);
430 mutex_unlock(&pnp_res_mutex
);
439 static DEVICE_ATTR_RW(resources
);
441 static ssize_t
id_show(struct device
*dmdev
, struct device_attribute
*attr
,
445 struct pnp_dev
*dev
= to_pnp_dev(dmdev
);
446 struct pnp_id
*pos
= dev
->id
;
449 str
+= sprintf(str
, "%s\n", pos
->id
);
454 static DEVICE_ATTR_RO(id
);
456 static struct attribute
*pnp_dev_attrs
[] = {
457 &dev_attr_resources
.attr
,
458 &dev_attr_options
.attr
,
463 static const struct attribute_group pnp_dev_group
= {
464 .attrs
= pnp_dev_attrs
,
467 const struct attribute_group
*pnp_dev_groups
[] = {