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/stat.h>
14 #include <linux/ctype.h>
15 #include <linux/slab.h>
16 #include <asm/uaccess.h>
20 struct pnp_info_buffer
{
21 char *buffer
; /* pointer to begin of buffer */
22 char *curr
; /* current position in buffer */
23 unsigned long size
; /* current size */
24 unsigned long len
; /* total length of buffer */
25 int stop
; /* stop flag */
26 int error
; /* error code */
29 typedef struct pnp_info_buffer pnp_info_buffer_t
;
31 static int pnp_printf(pnp_info_buffer_t
* buffer
, char *fmt
, ...)
36 if (buffer
->stop
|| buffer
->error
)
39 res
= vsnprintf(buffer
->curr
, buffer
->len
- buffer
->size
, fmt
, args
);
41 if (buffer
->size
+ res
>= buffer
->len
) {
50 static void pnp_print_port(pnp_info_buffer_t
* buffer
, char *space
,
51 struct pnp_port
*port
)
54 "%sport 0x%x-0x%x, align 0x%x, size 0x%x, %i-bit address decoding\n",
55 space
, port
->min
, port
->max
,
56 port
->align
? (port
->align
- 1) : 0, port
->size
,
57 port
->flags
& PNP_PORT_FLAG_16BITADDR
? 16 : 10);
60 static void pnp_print_irq(pnp_info_buffer_t
* buffer
, char *space
,
65 pnp_printf(buffer
, "%sirq ", space
);
66 for (i
= 0; i
< PNP_IRQ_NR
; i
++)
67 if (test_bit(i
, irq
->map
)) {
69 pnp_printf(buffer
, ",");
74 pnp_printf(buffer
, "2/9");
76 pnp_printf(buffer
, "%i", i
);
78 if (bitmap_empty(irq
->map
, PNP_IRQ_NR
))
79 pnp_printf(buffer
, "<none>");
80 if (irq
->flags
& IORESOURCE_IRQ_HIGHEDGE
)
81 pnp_printf(buffer
, " High-Edge");
82 if (irq
->flags
& IORESOURCE_IRQ_LOWEDGE
)
83 pnp_printf(buffer
, " Low-Edge");
84 if (irq
->flags
& IORESOURCE_IRQ_HIGHLEVEL
)
85 pnp_printf(buffer
, " High-Level");
86 if (irq
->flags
& IORESOURCE_IRQ_LOWLEVEL
)
87 pnp_printf(buffer
, " Low-Level");
88 pnp_printf(buffer
, "\n");
91 static void pnp_print_dma(pnp_info_buffer_t
* buffer
, char *space
,
97 pnp_printf(buffer
, "%sdma ", space
);
98 for (i
= 0; i
< 8; i
++)
99 if (dma
->map
& (1 << i
)) {
101 pnp_printf(buffer
, ",");
105 pnp_printf(buffer
, "%i", i
);
108 pnp_printf(buffer
, "<none>");
109 switch (dma
->flags
& IORESOURCE_DMA_TYPE_MASK
) {
110 case IORESOURCE_DMA_8BIT
:
113 case IORESOURCE_DMA_8AND16BIT
:
119 pnp_printf(buffer
, " %s", s
);
120 if (dma
->flags
& IORESOURCE_DMA_MASTER
)
121 pnp_printf(buffer
, " master");
122 if (dma
->flags
& IORESOURCE_DMA_BYTE
)
123 pnp_printf(buffer
, " byte-count");
124 if (dma
->flags
& IORESOURCE_DMA_WORD
)
125 pnp_printf(buffer
, " word-count");
126 switch (dma
->flags
& IORESOURCE_DMA_SPEED_MASK
) {
127 case IORESOURCE_DMA_TYPEA
:
130 case IORESOURCE_DMA_TYPEB
:
133 case IORESOURCE_DMA_TYPEF
:
140 pnp_printf(buffer
, " %s\n", s
);
143 static void pnp_print_mem(pnp_info_buffer_t
* buffer
, char *space
,
148 pnp_printf(buffer
, "%sMemory 0x%x-0x%x, align 0x%x, size 0x%x",
149 space
, mem
->min
, mem
->max
, mem
->align
, mem
->size
);
150 if (mem
->flags
& IORESOURCE_MEM_WRITEABLE
)
151 pnp_printf(buffer
, ", writeable");
152 if (mem
->flags
& IORESOURCE_MEM_CACHEABLE
)
153 pnp_printf(buffer
, ", cacheable");
154 if (mem
->flags
& IORESOURCE_MEM_RANGELENGTH
)
155 pnp_printf(buffer
, ", range-length");
156 if (mem
->flags
& IORESOURCE_MEM_SHADOWABLE
)
157 pnp_printf(buffer
, ", shadowable");
158 if (mem
->flags
& IORESOURCE_MEM_EXPANSIONROM
)
159 pnp_printf(buffer
, ", expansion ROM");
160 switch (mem
->flags
& IORESOURCE_MEM_TYPE_MASK
) {
161 case IORESOURCE_MEM_8BIT
:
164 case IORESOURCE_MEM_8AND16BIT
:
167 case IORESOURCE_MEM_32BIT
:
173 pnp_printf(buffer
, ", %s\n", s
);
176 static void pnp_print_option(pnp_info_buffer_t
* buffer
, char *space
,
177 struct pnp_option
*option
, int dep
)
180 struct pnp_port
*port
;
186 switch (option
->priority
) {
187 case PNP_RES_PRIORITY_PREFERRED
:
190 case PNP_RES_PRIORITY_ACCEPTABLE
:
193 case PNP_RES_PRIORITY_FUNCTIONAL
:
199 pnp_printf(buffer
, "Dependent: %02i - Priority %s\n", dep
, s
);
202 for (port
= option
->port
; port
; port
= port
->next
)
203 pnp_print_port(buffer
, space
, port
);
204 for (irq
= option
->irq
; irq
; irq
= irq
->next
)
205 pnp_print_irq(buffer
, space
, irq
);
206 for (dma
= option
->dma
; dma
; dma
= dma
->next
)
207 pnp_print_dma(buffer
, space
, dma
);
208 for (mem
= option
->mem
; mem
; mem
= mem
->next
)
209 pnp_print_mem(buffer
, space
, mem
);
212 static ssize_t
pnp_show_options(struct device
*dmdev
,
213 struct device_attribute
*attr
, char *buf
)
215 struct pnp_dev
*dev
= to_pnp_dev(dmdev
);
216 struct pnp_option
*independent
= dev
->independent
;
217 struct pnp_option
*dependent
= dev
->dependent
;
220 pnp_info_buffer_t
*buffer
= (pnp_info_buffer_t
*)
221 pnp_alloc(sizeof(pnp_info_buffer_t
));
225 buffer
->len
= PAGE_SIZE
;
226 buffer
->buffer
= buf
;
227 buffer
->curr
= buffer
->buffer
;
229 pnp_print_option(buffer
, "", independent
, 0);
232 pnp_print_option(buffer
, " ", dependent
, dep
);
233 dependent
= dependent
->next
;
236 ret
= (buffer
->curr
- buf
);
241 static DEVICE_ATTR(options
, S_IRUGO
, pnp_show_options
, NULL
);
243 static ssize_t
pnp_show_current_resources(struct device
*dmdev
,
244 struct device_attribute
*attr
,
247 struct pnp_dev
*dev
= to_pnp_dev(dmdev
);
249 pnp_info_buffer_t
*buffer
;
254 buffer
= (pnp_info_buffer_t
*) pnp_alloc(sizeof(pnp_info_buffer_t
));
257 buffer
->len
= PAGE_SIZE
;
258 buffer
->buffer
= buf
;
259 buffer
->curr
= buffer
->buffer
;
261 pnp_printf(buffer
, "state = ");
263 pnp_printf(buffer
, "active\n");
265 pnp_printf(buffer
, "disabled\n");
267 for (i
= 0; i
< PNP_MAX_PORT
; i
++) {
268 if (pnp_port_valid(dev
, i
)) {
269 pnp_printf(buffer
, "io");
270 if (pnp_port_flags(dev
, i
) & IORESOURCE_DISABLED
)
271 pnp_printf(buffer
, " disabled\n");
273 pnp_printf(buffer
, " 0x%llx-0x%llx\n",
275 pnp_port_start(dev
, i
),
276 (unsigned long long)pnp_port_end(dev
,
280 for (i
= 0; i
< PNP_MAX_MEM
; i
++) {
281 if (pnp_mem_valid(dev
, i
)) {
282 pnp_printf(buffer
, "mem");
283 if (pnp_mem_flags(dev
, i
) & IORESOURCE_DISABLED
)
284 pnp_printf(buffer
, " disabled\n");
286 pnp_printf(buffer
, " 0x%llx-0x%llx\n",
288 pnp_mem_start(dev
, i
),
289 (unsigned long long)pnp_mem_end(dev
,
293 for (i
= 0; i
< PNP_MAX_IRQ
; i
++) {
294 if (pnp_irq_valid(dev
, i
)) {
295 pnp_printf(buffer
, "irq");
296 if (pnp_irq_flags(dev
, i
) & IORESOURCE_DISABLED
)
297 pnp_printf(buffer
, " disabled\n");
299 pnp_printf(buffer
, " %lld\n",
300 (unsigned long long)pnp_irq(dev
, i
));
303 for (i
= 0; i
< PNP_MAX_DMA
; i
++) {
304 if (pnp_dma_valid(dev
, i
)) {
305 pnp_printf(buffer
, "dma");
306 if (pnp_dma_flags(dev
, i
) & IORESOURCE_DISABLED
)
307 pnp_printf(buffer
, " disabled\n");
309 pnp_printf(buffer
, " %lld\n",
310 (unsigned long long)pnp_dma(dev
, i
));
313 ret
= (buffer
->curr
- buf
);
318 extern struct semaphore pnp_res_mutex
;
321 pnp_set_current_resources(struct device
*dmdev
, struct device_attribute
*attr
,
322 const char *ubuf
, size_t count
)
324 struct pnp_dev
*dev
= to_pnp_dev(dmdev
);
325 char *buf
= (void *)ubuf
;
328 if (dev
->status
& PNP_ATTACHED
) {
330 dev_info(&dev
->dev
, "in use; can't configure\n");
334 while (isspace(*buf
))
336 if (!strnicmp(buf
, "disable", 7)) {
337 retval
= pnp_disable_dev(dev
);
340 if (!strnicmp(buf
, "activate", 8)) {
341 retval
= pnp_activate_dev(dev
);
344 if (!strnicmp(buf
, "fill", 4)) {
347 retval
= pnp_auto_config_dev(dev
);
350 if (!strnicmp(buf
, "auto", 4)) {
353 pnp_init_resource_table(&dev
->res
);
354 retval
= pnp_auto_config_dev(dev
);
357 if (!strnicmp(buf
, "clear", 5)) {
360 pnp_init_resource_table(&dev
->res
);
363 if (!strnicmp(buf
, "get", 3)) {
364 down(&pnp_res_mutex
);
365 if (pnp_can_read(dev
))
366 dev
->protocol
->get(dev
, &dev
->res
);
370 if (!strnicmp(buf
, "set", 3)) {
371 int nport
= 0, nmem
= 0, nirq
= 0, ndma
= 0;
375 pnp_init_resource_table(&dev
->res
);
376 down(&pnp_res_mutex
);
378 while (isspace(*buf
))
380 if (!strnicmp(buf
, "io", 2)) {
382 while (isspace(*buf
))
384 dev
->res
.port_resource
[nport
].start
=
385 simple_strtoul(buf
, &buf
, 0);
386 while (isspace(*buf
))
390 while (isspace(*buf
))
392 dev
->res
.port_resource
[nport
].end
=
393 simple_strtoul(buf
, &buf
, 0);
395 dev
->res
.port_resource
[nport
].end
=
396 dev
->res
.port_resource
[nport
].start
;
397 dev
->res
.port_resource
[nport
].flags
=
400 if (nport
>= PNP_MAX_PORT
)
404 if (!strnicmp(buf
, "mem", 3)) {
406 while (isspace(*buf
))
408 dev
->res
.mem_resource
[nmem
].start
=
409 simple_strtoul(buf
, &buf
, 0);
410 while (isspace(*buf
))
414 while (isspace(*buf
))
416 dev
->res
.mem_resource
[nmem
].end
=
417 simple_strtoul(buf
, &buf
, 0);
419 dev
->res
.mem_resource
[nmem
].end
=
420 dev
->res
.mem_resource
[nmem
].start
;
421 dev
->res
.mem_resource
[nmem
].flags
=
424 if (nmem
>= PNP_MAX_MEM
)
428 if (!strnicmp(buf
, "irq", 3)) {
430 while (isspace(*buf
))
432 dev
->res
.irq_resource
[nirq
].start
=
433 dev
->res
.irq_resource
[nirq
].end
=
434 simple_strtoul(buf
, &buf
, 0);
435 dev
->res
.irq_resource
[nirq
].flags
=
438 if (nirq
>= PNP_MAX_IRQ
)
442 if (!strnicmp(buf
, "dma", 3)) {
444 while (isspace(*buf
))
446 dev
->res
.dma_resource
[ndma
].start
=
447 dev
->res
.dma_resource
[ndma
].end
=
448 simple_strtoul(buf
, &buf
, 0);
449 dev
->res
.dma_resource
[ndma
].flags
=
452 if (ndma
>= PNP_MAX_DMA
)
468 static DEVICE_ATTR(resources
, S_IRUGO
| S_IWUSR
,
469 pnp_show_current_resources
, pnp_set_current_resources
);
471 static ssize_t
pnp_show_current_ids(struct device
*dmdev
,
472 struct device_attribute
*attr
, char *buf
)
475 struct pnp_dev
*dev
= to_pnp_dev(dmdev
);
476 struct pnp_id
*pos
= dev
->id
;
479 str
+= sprintf(str
, "%s\n", pos
->id
);
485 static DEVICE_ATTR(id
, S_IRUGO
, pnp_show_current_ids
, NULL
);
487 int pnp_interface_attach_device(struct pnp_dev
*dev
)
489 int rc
= device_create_file(&dev
->dev
, &dev_attr_options
);
493 rc
= device_create_file(&dev
->dev
, &dev_attr_resources
);
496 rc
= device_create_file(&dev
->dev
, &dev_attr_id
);
503 device_remove_file(&dev
->dev
, &dev_attr_resources
);
505 device_remove_file(&dev
->dev
, &dev_attr_options
);