2 * interface.c - contains everything related to the user interface
4 * Some code, especially possible resource dumping is based on isapnp_proc.c (c) Jaroslav Kysela <perex@perex.cz>
5 * Copyright 2002 Adam Belay <ambx1@neo.rr.com>
6 * Copyright (C) 2008 Hewlett-Packard Development Company, L.P.
7 * Bjorn Helgaas <bjorn.helgaas@hp.com>
10 #include <linux/pnp.h>
11 #include <linux/string.h>
12 #include <linux/errno.h>
13 #include <linux/list.h>
14 #include <linux/types.h>
15 #include <linux/stat.h>
16 #include <linux/ctype.h>
17 #include <linux/slab.h>
18 #include <linux/mutex.h>
20 #include <asm/uaccess.h>
24 struct pnp_info_buffer
{
25 char *buffer
; /* pointer to begin of buffer */
26 char *curr
; /* current position in buffer */
27 unsigned long size
; /* current size */
28 unsigned long len
; /* total length of buffer */
29 int stop
; /* stop flag */
30 int error
; /* error code */
33 typedef struct pnp_info_buffer pnp_info_buffer_t
;
35 static int pnp_printf(pnp_info_buffer_t
* buffer
, char *fmt
, ...)
40 if (buffer
->stop
|| buffer
->error
)
43 res
= vsnprintf(buffer
->curr
, buffer
->len
- buffer
->size
, fmt
, args
);
45 if (buffer
->size
+ res
>= buffer
->len
) {
54 static void pnp_print_port(pnp_info_buffer_t
* buffer
, char *space
,
55 struct pnp_port
*port
)
57 pnp_printf(buffer
, "%sport %#llx-%#llx, align %#llx, size %#llx, "
58 "%i-bit address decoding\n", space
,
59 (unsigned long long) port
->min
,
60 (unsigned long long) port
->max
,
61 port
->align
? ((unsigned long long) port
->align
- 1) : 0,
62 (unsigned long long) port
->size
,
63 port
->flags
& IORESOURCE_IO_16BIT_ADDR
? 16 : 10);
66 static void pnp_print_irq(pnp_info_buffer_t
* buffer
, char *space
,
71 pnp_printf(buffer
, "%sirq ", space
);
72 for (i
= 0; i
< PNP_IRQ_NR
; i
++)
73 if (test_bit(i
, irq
->map
.bits
)) {
75 pnp_printf(buffer
, ",");
80 pnp_printf(buffer
, "2/9");
82 pnp_printf(buffer
, "%i", i
);
84 if (bitmap_empty(irq
->map
.bits
, PNP_IRQ_NR
))
85 pnp_printf(buffer
, "<none>");
86 if (irq
->flags
& IORESOURCE_IRQ_HIGHEDGE
)
87 pnp_printf(buffer
, " High-Edge");
88 if (irq
->flags
& IORESOURCE_IRQ_LOWEDGE
)
89 pnp_printf(buffer
, " Low-Edge");
90 if (irq
->flags
& IORESOURCE_IRQ_HIGHLEVEL
)
91 pnp_printf(buffer
, " High-Level");
92 if (irq
->flags
& IORESOURCE_IRQ_LOWLEVEL
)
93 pnp_printf(buffer
, " Low-Level");
94 if (irq
->flags
& IORESOURCE_IRQ_OPTIONAL
)
95 pnp_printf(buffer
, " (optional)");
96 pnp_printf(buffer
, "\n");
99 static void pnp_print_dma(pnp_info_buffer_t
* buffer
, char *space
,
105 pnp_printf(buffer
, "%sdma ", space
);
106 for (i
= 0; i
< 8; i
++)
107 if (dma
->map
& (1 << i
)) {
109 pnp_printf(buffer
, ",");
113 pnp_printf(buffer
, "%i", i
);
116 pnp_printf(buffer
, "<none>");
117 switch (dma
->flags
& IORESOURCE_DMA_TYPE_MASK
) {
118 case IORESOURCE_DMA_8BIT
:
121 case IORESOURCE_DMA_8AND16BIT
:
127 pnp_printf(buffer
, " %s", s
);
128 if (dma
->flags
& IORESOURCE_DMA_MASTER
)
129 pnp_printf(buffer
, " master");
130 if (dma
->flags
& IORESOURCE_DMA_BYTE
)
131 pnp_printf(buffer
, " byte-count");
132 if (dma
->flags
& IORESOURCE_DMA_WORD
)
133 pnp_printf(buffer
, " word-count");
134 switch (dma
->flags
& IORESOURCE_DMA_SPEED_MASK
) {
135 case IORESOURCE_DMA_TYPEA
:
138 case IORESOURCE_DMA_TYPEB
:
141 case IORESOURCE_DMA_TYPEF
:
148 pnp_printf(buffer
, " %s\n", s
);
151 static void pnp_print_mem(pnp_info_buffer_t
* buffer
, char *space
,
156 pnp_printf(buffer
, "%sMemory %#llx-%#llx, align %#llx, size %#llx",
157 space
, (unsigned long long) mem
->min
,
158 (unsigned long long) mem
->max
,
159 (unsigned long long) mem
->align
,
160 (unsigned long long) mem
->size
);
161 if (mem
->flags
& IORESOURCE_MEM_WRITEABLE
)
162 pnp_printf(buffer
, ", writeable");
163 if (mem
->flags
& IORESOURCE_MEM_CACHEABLE
)
164 pnp_printf(buffer
, ", cacheable");
165 if (mem
->flags
& IORESOURCE_MEM_RANGELENGTH
)
166 pnp_printf(buffer
, ", range-length");
167 if (mem
->flags
& IORESOURCE_MEM_SHADOWABLE
)
168 pnp_printf(buffer
, ", shadowable");
169 if (mem
->flags
& IORESOURCE_MEM_EXPANSIONROM
)
170 pnp_printf(buffer
, ", expansion ROM");
171 switch (mem
->flags
& IORESOURCE_MEM_TYPE_MASK
) {
172 case IORESOURCE_MEM_8BIT
:
175 case IORESOURCE_MEM_8AND16BIT
:
178 case IORESOURCE_MEM_32BIT
:
184 pnp_printf(buffer
, ", %s\n", s
);
187 static void pnp_print_option(pnp_info_buffer_t
* buffer
, char *space
,
188 struct pnp_option
*option
)
190 switch (option
->type
) {
192 pnp_print_port(buffer
, space
, &option
->u
.port
);
195 pnp_print_mem(buffer
, space
, &option
->u
.mem
);
198 pnp_print_irq(buffer
, space
, &option
->u
.irq
);
201 pnp_print_dma(buffer
, space
, &option
->u
.dma
);
206 static ssize_t
pnp_show_options(struct device
*dmdev
,
207 struct device_attribute
*attr
, char *buf
)
209 struct pnp_dev
*dev
= to_pnp_dev(dmdev
);
210 pnp_info_buffer_t
*buffer
;
211 struct pnp_option
*option
;
212 int ret
, dep
= 0, set
= 0;
215 buffer
= pnp_alloc(sizeof(pnp_info_buffer_t
));
219 buffer
->len
= PAGE_SIZE
;
220 buffer
->buffer
= buf
;
221 buffer
->curr
= buffer
->buffer
;
223 list_for_each_entry(option
, &dev
->options
, list
) {
224 if (pnp_option_is_dependent(option
)) {
226 if (!dep
|| pnp_option_set(option
) != set
) {
227 set
= pnp_option_set(option
);
229 pnp_printf(buffer
, "Dependent: %02i - "
230 "Priority %s\n", set
,
231 pnp_option_priority_name(option
));
237 pnp_print_option(buffer
, indent
, option
);
240 ret
= (buffer
->curr
- buf
);
245 static ssize_t
pnp_show_current_resources(struct device
*dmdev
,
246 struct device_attribute
*attr
,
249 struct pnp_dev
*dev
= to_pnp_dev(dmdev
);
250 pnp_info_buffer_t
*buffer
;
251 struct pnp_resource
*pnp_res
;
252 struct resource
*res
;
258 buffer
= pnp_alloc(sizeof(pnp_info_buffer_t
));
262 buffer
->len
= PAGE_SIZE
;
263 buffer
->buffer
= buf
;
264 buffer
->curr
= buffer
->buffer
;
266 pnp_printf(buffer
, "state = %s\n", dev
->active
? "active" : "disabled");
268 list_for_each_entry(pnp_res
, &dev
->resources
, list
) {
271 pnp_printf(buffer
, pnp_resource_type_name(res
));
273 if (res
->flags
& IORESOURCE_DISABLED
) {
274 pnp_printf(buffer
, " disabled\n");
278 switch (pnp_resource_type(res
)) {
282 pnp_printf(buffer
, " %#llx-%#llx%s\n",
283 (unsigned long long) res
->start
,
284 (unsigned long long) res
->end
,
285 res
->flags
& IORESOURCE_WINDOW
?
290 pnp_printf(buffer
, " %lld\n",
291 (unsigned long long) res
->start
);
296 ret
= (buffer
->curr
- buf
);
301 static char *pnp_get_resource_value(char *buf
,
303 resource_size_t
*start
,
304 resource_size_t
*end
,
305 unsigned long *flags
)
314 /* TBD: allow for disabled resources */
316 buf
= skip_spaces(buf
);
318 *start
= simple_strtoull(buf
, &buf
, 0);
320 buf
= skip_spaces(buf
);
322 buf
= skip_spaces(buf
+ 1);
323 *end
= simple_strtoull(buf
, &buf
, 0);
329 /* TBD: allow for additional flags, e.g., IORESOURCE_WINDOW */
334 static ssize_t
pnp_set_current_resources(struct device
*dmdev
,
335 struct device_attribute
*attr
,
336 const char *ubuf
, size_t count
)
338 struct pnp_dev
*dev
= to_pnp_dev(dmdev
);
339 char *buf
= (void *)ubuf
;
342 if (dev
->status
& PNP_ATTACHED
) {
344 dev_info(&dev
->dev
, "in use; can't configure\n");
348 buf
= skip_spaces(buf
);
349 if (!strnicmp(buf
, "disable", 7)) {
350 retval
= pnp_disable_dev(dev
);
353 if (!strnicmp(buf
, "activate", 8)) {
354 retval
= pnp_activate_dev(dev
);
357 if (!strnicmp(buf
, "fill", 4)) {
360 retval
= pnp_auto_config_dev(dev
);
363 if (!strnicmp(buf
, "auto", 4)) {
366 pnp_init_resources(dev
);
367 retval
= pnp_auto_config_dev(dev
);
370 if (!strnicmp(buf
, "clear", 5)) {
373 pnp_init_resources(dev
);
376 if (!strnicmp(buf
, "get", 3)) {
377 mutex_lock(&pnp_res_mutex
);
378 if (pnp_can_read(dev
))
379 dev
->protocol
->get(dev
);
380 mutex_unlock(&pnp_res_mutex
);
383 if (!strnicmp(buf
, "set", 3)) {
384 resource_size_t start
;
391 pnp_init_resources(dev
);
392 mutex_lock(&pnp_res_mutex
);
394 buf
= skip_spaces(buf
);
395 if (!strnicmp(buf
, "io", 2)) {
396 buf
= pnp_get_resource_value(buf
+ 2,
400 pnp_add_io_resource(dev
, start
, end
, flags
);
401 } else if (!strnicmp(buf
, "mem", 3)) {
402 buf
= pnp_get_resource_value(buf
+ 3,
406 pnp_add_mem_resource(dev
, start
, end
, flags
);
407 } else if (!strnicmp(buf
, "irq", 3)) {
408 buf
= pnp_get_resource_value(buf
+ 3,
412 pnp_add_irq_resource(dev
, start
, flags
);
413 } else if (!strnicmp(buf
, "dma", 3)) {
414 buf
= pnp_get_resource_value(buf
+ 3,
418 pnp_add_dma_resource(dev
, start
, flags
);
419 } else if (!strnicmp(buf
, "bus", 3)) {
420 buf
= pnp_get_resource_value(buf
+ 3,
424 pnp_add_bus_resource(dev
, start
, end
);
428 mutex_unlock(&pnp_res_mutex
);
438 static ssize_t
pnp_show_current_ids(struct device
*dmdev
,
439 struct device_attribute
*attr
, char *buf
)
442 struct pnp_dev
*dev
= to_pnp_dev(dmdev
);
443 struct pnp_id
*pos
= dev
->id
;
446 str
+= sprintf(str
, "%s\n", pos
->id
);
452 struct device_attribute pnp_interface_attrs
[] = {
453 __ATTR(resources
, S_IRUGO
| S_IWUSR
,
454 pnp_show_current_resources
,
455 pnp_set_current_resources
),
456 __ATTR(options
, S_IRUGO
, pnp_show_options
, NULL
),
457 __ATTR(id
, S_IRUGO
, pnp_show_current_ids
, NULL
),