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>
9 #include <linux/string.h>
10 #include <linux/errno.h>
11 #include <linux/list.h>
12 #include <linux/types.h>
13 #include <linux/pnp.h>
14 #include <linux/stat.h>
15 #include <linux/ctype.h>
16 #include <linux/slab.h>
17 #include <linux/mutex.h>
19 #include <asm/uaccess.h>
23 struct pnp_info_buffer
{
24 char *buffer
; /* pointer to begin of buffer */
25 char *curr
; /* current position in buffer */
26 unsigned long size
; /* current size */
27 unsigned long len
; /* total length of buffer */
28 int stop
; /* stop flag */
29 int error
; /* error code */
32 typedef struct pnp_info_buffer pnp_info_buffer_t
;
34 static int pnp_printf(pnp_info_buffer_t
* buffer
, char *fmt
, ...)
39 if (buffer
->stop
|| buffer
->error
)
42 res
= vsnprintf(buffer
->curr
, buffer
->len
- buffer
->size
, fmt
, args
);
44 if (buffer
->size
+ res
>= buffer
->len
) {
53 static void pnp_print_port(pnp_info_buffer_t
* buffer
, char *space
,
54 struct pnp_port
*port
)
57 "%sport 0x%x-0x%x, align 0x%x, size 0x%x, %i-bit address decoding\n",
58 space
, port
->min
, port
->max
,
59 port
->align
? (port
->align
- 1) : 0, port
->size
,
60 port
->flags
& PNP_PORT_FLAG_16BITADDR
? 16 : 10);
63 static void pnp_print_irq(pnp_info_buffer_t
* buffer
, char *space
,
68 pnp_printf(buffer
, "%sirq ", space
);
69 for (i
= 0; i
< PNP_IRQ_NR
; i
++)
70 if (test_bit(i
, irq
->map
)) {
72 pnp_printf(buffer
, ",");
77 pnp_printf(buffer
, "2/9");
79 pnp_printf(buffer
, "%i", i
);
81 if (bitmap_empty(irq
->map
, PNP_IRQ_NR
))
82 pnp_printf(buffer
, "<none>");
83 if (irq
->flags
& IORESOURCE_IRQ_HIGHEDGE
)
84 pnp_printf(buffer
, " High-Edge");
85 if (irq
->flags
& IORESOURCE_IRQ_LOWEDGE
)
86 pnp_printf(buffer
, " Low-Edge");
87 if (irq
->flags
& IORESOURCE_IRQ_HIGHLEVEL
)
88 pnp_printf(buffer
, " High-Level");
89 if (irq
->flags
& IORESOURCE_IRQ_LOWLEVEL
)
90 pnp_printf(buffer
, " Low-Level");
91 pnp_printf(buffer
, "\n");
94 static void pnp_print_dma(pnp_info_buffer_t
* buffer
, char *space
,
100 pnp_printf(buffer
, "%sdma ", space
);
101 for (i
= 0; i
< 8; i
++)
102 if (dma
->map
& (1 << i
)) {
104 pnp_printf(buffer
, ",");
108 pnp_printf(buffer
, "%i", i
);
111 pnp_printf(buffer
, "<none>");
112 switch (dma
->flags
& IORESOURCE_DMA_TYPE_MASK
) {
113 case IORESOURCE_DMA_8BIT
:
116 case IORESOURCE_DMA_8AND16BIT
:
122 pnp_printf(buffer
, " %s", s
);
123 if (dma
->flags
& IORESOURCE_DMA_MASTER
)
124 pnp_printf(buffer
, " master");
125 if (dma
->flags
& IORESOURCE_DMA_BYTE
)
126 pnp_printf(buffer
, " byte-count");
127 if (dma
->flags
& IORESOURCE_DMA_WORD
)
128 pnp_printf(buffer
, " word-count");
129 switch (dma
->flags
& IORESOURCE_DMA_SPEED_MASK
) {
130 case IORESOURCE_DMA_TYPEA
:
133 case IORESOURCE_DMA_TYPEB
:
136 case IORESOURCE_DMA_TYPEF
:
143 pnp_printf(buffer
, " %s\n", s
);
146 static void pnp_print_mem(pnp_info_buffer_t
* buffer
, char *space
,
151 pnp_printf(buffer
, "%sMemory 0x%x-0x%x, align 0x%x, size 0x%x",
152 space
, mem
->min
, mem
->max
, mem
->align
, mem
->size
);
153 if (mem
->flags
& IORESOURCE_MEM_WRITEABLE
)
154 pnp_printf(buffer
, ", writeable");
155 if (mem
->flags
& IORESOURCE_MEM_CACHEABLE
)
156 pnp_printf(buffer
, ", cacheable");
157 if (mem
->flags
& IORESOURCE_MEM_RANGELENGTH
)
158 pnp_printf(buffer
, ", range-length");
159 if (mem
->flags
& IORESOURCE_MEM_SHADOWABLE
)
160 pnp_printf(buffer
, ", shadowable");
161 if (mem
->flags
& IORESOURCE_MEM_EXPANSIONROM
)
162 pnp_printf(buffer
, ", expansion ROM");
163 switch (mem
->flags
& IORESOURCE_MEM_TYPE_MASK
) {
164 case IORESOURCE_MEM_8BIT
:
167 case IORESOURCE_MEM_8AND16BIT
:
170 case IORESOURCE_MEM_32BIT
:
176 pnp_printf(buffer
, ", %s\n", s
);
179 static void pnp_print_option(pnp_info_buffer_t
* buffer
, char *space
,
180 struct pnp_option
*option
, int dep
)
183 struct pnp_port
*port
;
189 switch (option
->priority
) {
190 case PNP_RES_PRIORITY_PREFERRED
:
193 case PNP_RES_PRIORITY_ACCEPTABLE
:
196 case PNP_RES_PRIORITY_FUNCTIONAL
:
202 pnp_printf(buffer
, "Dependent: %02i - Priority %s\n", dep
, s
);
205 for (port
= option
->port
; port
; port
= port
->next
)
206 pnp_print_port(buffer
, space
, port
);
207 for (irq
= option
->irq
; irq
; irq
= irq
->next
)
208 pnp_print_irq(buffer
, space
, irq
);
209 for (dma
= option
->dma
; dma
; dma
= dma
->next
)
210 pnp_print_dma(buffer
, space
, dma
);
211 for (mem
= option
->mem
; mem
; mem
= mem
->next
)
212 pnp_print_mem(buffer
, space
, mem
);
215 static ssize_t
pnp_show_options(struct device
*dmdev
,
216 struct device_attribute
*attr
, char *buf
)
218 struct pnp_dev
*dev
= to_pnp_dev(dmdev
);
219 struct pnp_option
*independent
= dev
->independent
;
220 struct pnp_option
*dependent
= dev
->dependent
;
223 pnp_info_buffer_t
*buffer
= (pnp_info_buffer_t
*)
224 pnp_alloc(sizeof(pnp_info_buffer_t
));
228 buffer
->len
= PAGE_SIZE
;
229 buffer
->buffer
= buf
;
230 buffer
->curr
= buffer
->buffer
;
232 pnp_print_option(buffer
, "", independent
, 0);
235 pnp_print_option(buffer
, " ", dependent
, dep
);
236 dependent
= dependent
->next
;
239 ret
= (buffer
->curr
- buf
);
244 static DEVICE_ATTR(options
, S_IRUGO
, pnp_show_options
, NULL
);
246 static ssize_t
pnp_show_current_resources(struct device
*dmdev
,
247 struct device_attribute
*attr
,
250 struct pnp_dev
*dev
= to_pnp_dev(dmdev
);
252 pnp_info_buffer_t
*buffer
;
257 buffer
= (pnp_info_buffer_t
*) pnp_alloc(sizeof(pnp_info_buffer_t
));
260 buffer
->len
= PAGE_SIZE
;
261 buffer
->buffer
= buf
;
262 buffer
->curr
= buffer
->buffer
;
264 pnp_printf(buffer
, "state = ");
266 pnp_printf(buffer
, "active\n");
268 pnp_printf(buffer
, "disabled\n");
270 for (i
= 0; i
< PNP_MAX_PORT
; i
++) {
271 if (pnp_port_valid(dev
, i
)) {
272 pnp_printf(buffer
, "io");
273 if (pnp_port_flags(dev
, i
) & IORESOURCE_DISABLED
)
274 pnp_printf(buffer
, " disabled\n");
276 pnp_printf(buffer
, " 0x%llx-0x%llx\n",
278 pnp_port_start(dev
, i
),
279 (unsigned long long)pnp_port_end(dev
,
283 for (i
= 0; i
< PNP_MAX_MEM
; i
++) {
284 if (pnp_mem_valid(dev
, i
)) {
285 pnp_printf(buffer
, "mem");
286 if (pnp_mem_flags(dev
, i
) & IORESOURCE_DISABLED
)
287 pnp_printf(buffer
, " disabled\n");
289 pnp_printf(buffer
, " 0x%llx-0x%llx\n",
291 pnp_mem_start(dev
, i
),
292 (unsigned long long)pnp_mem_end(dev
,
296 for (i
= 0; i
< PNP_MAX_IRQ
; i
++) {
297 if (pnp_irq_valid(dev
, i
)) {
298 pnp_printf(buffer
, "irq");
299 if (pnp_irq_flags(dev
, i
) & IORESOURCE_DISABLED
)
300 pnp_printf(buffer
, " disabled\n");
302 pnp_printf(buffer
, " %lld\n",
303 (unsigned long long)pnp_irq(dev
, i
));
306 for (i
= 0; i
< PNP_MAX_DMA
; i
++) {
307 if (pnp_dma_valid(dev
, i
)) {
308 pnp_printf(buffer
, "dma");
309 if (pnp_dma_flags(dev
, i
) & IORESOURCE_DISABLED
)
310 pnp_printf(buffer
, " disabled\n");
312 pnp_printf(buffer
, " %lld\n",
313 (unsigned long long)pnp_dma(dev
, i
));
316 ret
= (buffer
->curr
- buf
);
322 pnp_set_current_resources(struct device
*dmdev
, struct device_attribute
*attr
,
323 const char *ubuf
, size_t count
)
325 struct pnp_dev
*dev
= to_pnp_dev(dmdev
);
326 char *buf
= (void *)ubuf
;
329 if (dev
->status
& PNP_ATTACHED
) {
331 dev_info(&dev
->dev
, "in use; can't configure\n");
335 while (isspace(*buf
))
337 if (!strnicmp(buf
, "disable", 7)) {
338 retval
= pnp_disable_dev(dev
);
341 if (!strnicmp(buf
, "activate", 8)) {
342 retval
= pnp_activate_dev(dev
);
345 if (!strnicmp(buf
, "fill", 4)) {
348 retval
= pnp_auto_config_dev(dev
);
351 if (!strnicmp(buf
, "auto", 4)) {
354 pnp_init_resource_table(&dev
->res
);
355 retval
= pnp_auto_config_dev(dev
);
358 if (!strnicmp(buf
, "clear", 5)) {
361 pnp_init_resource_table(&dev
->res
);
364 if (!strnicmp(buf
, "get", 3)) {
365 mutex_lock(&pnp_res_mutex
);
366 if (pnp_can_read(dev
))
367 dev
->protocol
->get(dev
, &dev
->res
);
368 mutex_unlock(&pnp_res_mutex
);
371 if (!strnicmp(buf
, "set", 3)) {
372 int nport
= 0, nmem
= 0, nirq
= 0, ndma
= 0;
376 pnp_init_resource_table(&dev
->res
);
377 mutex_lock(&pnp_res_mutex
);
379 while (isspace(*buf
))
381 if (!strnicmp(buf
, "io", 2)) {
383 while (isspace(*buf
))
385 dev
->res
.port_resource
[nport
].start
=
386 simple_strtoul(buf
, &buf
, 0);
387 while (isspace(*buf
))
391 while (isspace(*buf
))
393 dev
->res
.port_resource
[nport
].end
=
394 simple_strtoul(buf
, &buf
, 0);
396 dev
->res
.port_resource
[nport
].end
=
397 dev
->res
.port_resource
[nport
].start
;
398 dev
->res
.port_resource
[nport
].flags
=
401 if (nport
>= PNP_MAX_PORT
)
405 if (!strnicmp(buf
, "mem", 3)) {
407 while (isspace(*buf
))
409 dev
->res
.mem_resource
[nmem
].start
=
410 simple_strtoul(buf
, &buf
, 0);
411 while (isspace(*buf
))
415 while (isspace(*buf
))
417 dev
->res
.mem_resource
[nmem
].end
=
418 simple_strtoul(buf
, &buf
, 0);
420 dev
->res
.mem_resource
[nmem
].end
=
421 dev
->res
.mem_resource
[nmem
].start
;
422 dev
->res
.mem_resource
[nmem
].flags
=
425 if (nmem
>= PNP_MAX_MEM
)
429 if (!strnicmp(buf
, "irq", 3)) {
431 while (isspace(*buf
))
433 dev
->res
.irq_resource
[nirq
].start
=
434 dev
->res
.irq_resource
[nirq
].end
=
435 simple_strtoul(buf
, &buf
, 0);
436 dev
->res
.irq_resource
[nirq
].flags
=
439 if (nirq
>= PNP_MAX_IRQ
)
443 if (!strnicmp(buf
, "dma", 3)) {
445 while (isspace(*buf
))
447 dev
->res
.dma_resource
[ndma
].start
=
448 dev
->res
.dma_resource
[ndma
].end
=
449 simple_strtoul(buf
, &buf
, 0);
450 dev
->res
.dma_resource
[ndma
].flags
=
453 if (ndma
>= PNP_MAX_DMA
)
459 mutex_unlock(&pnp_res_mutex
);
469 static DEVICE_ATTR(resources
, S_IRUGO
| S_IWUSR
,
470 pnp_show_current_resources
, pnp_set_current_resources
);
472 static ssize_t
pnp_show_current_ids(struct device
*dmdev
,
473 struct device_attribute
*attr
, char *buf
)
476 struct pnp_dev
*dev
= to_pnp_dev(dmdev
);
477 struct pnp_id
*pos
= dev
->id
;
480 str
+= sprintf(str
, "%s\n", pos
->id
);
486 static DEVICE_ATTR(id
, S_IRUGO
, pnp_show_current_ids
, NULL
);
488 int pnp_interface_attach_device(struct pnp_dev
*dev
)
490 int rc
= device_create_file(&dev
->dev
, &dev_attr_options
);
494 rc
= device_create_file(&dev
->dev
, &dev_attr_resources
);
497 rc
= device_create_file(&dev
->dev
, &dev_attr_id
);
504 device_remove_file(&dev
->dev
, &dev_attr_resources
);
506 device_remove_file(&dev
->dev
, &dev_attr_options
);