diff options
Diffstat (limited to 'drivers/pnp/interface.c')
-rw-r--r-- | drivers/pnp/interface.c | 207 |
1 files changed, 89 insertions, 118 deletions
diff --git a/drivers/pnp/interface.c b/drivers/pnp/interface.c index 5695a79f3a52..a876ecf7028c 100644 --- a/drivers/pnp/interface.c +++ b/drivers/pnp/interface.c | |||
@@ -3,6 +3,8 @@ | |||
3 | * | 3 | * |
4 | * Some code, especially possible resource dumping is based on isapnp_proc.c (c) Jaroslav Kysela <perex@perex.cz> | 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> | 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> | ||
6 | */ | 8 | */ |
7 | 9 | ||
8 | #include <linux/pnp.h> | 10 | #include <linux/pnp.h> |
@@ -53,11 +55,13 @@ static int pnp_printf(pnp_info_buffer_t * buffer, char *fmt, ...) | |||
53 | static void pnp_print_port(pnp_info_buffer_t * buffer, char *space, | 55 | static void pnp_print_port(pnp_info_buffer_t * buffer, char *space, |
54 | struct pnp_port *port) | 56 | struct pnp_port *port) |
55 | { | 57 | { |
56 | pnp_printf(buffer, | 58 | pnp_printf(buffer, "%sport %#llx-%#llx, align %#llx, size %#llx, " |
57 | "%sport 0x%x-0x%x, align 0x%x, size 0x%x, %i-bit address decoding\n", | 59 | "%i-bit address decoding\n", space, |
58 | space, port->min, port->max, | 60 | (unsigned long long) port->min, |
59 | port->align ? (port->align - 1) : 0, port->size, | 61 | (unsigned long long) port->max, |
60 | port->flags & PNP_PORT_FLAG_16BITADDR ? 16 : 10); | 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); | ||
61 | } | 65 | } |
62 | 66 | ||
63 | static void pnp_print_irq(pnp_info_buffer_t * buffer, char *space, | 67 | static void pnp_print_irq(pnp_info_buffer_t * buffer, char *space, |
@@ -67,7 +71,7 @@ static void pnp_print_irq(pnp_info_buffer_t * buffer, char *space, | |||
67 | 71 | ||
68 | pnp_printf(buffer, "%sirq ", space); | 72 | pnp_printf(buffer, "%sirq ", space); |
69 | for (i = 0; i < PNP_IRQ_NR; i++) | 73 | for (i = 0; i < PNP_IRQ_NR; i++) |
70 | if (test_bit(i, irq->map)) { | 74 | if (test_bit(i, irq->map.bits)) { |
71 | if (!first) { | 75 | if (!first) { |
72 | pnp_printf(buffer, ","); | 76 | pnp_printf(buffer, ","); |
73 | } else { | 77 | } else { |
@@ -78,7 +82,7 @@ static void pnp_print_irq(pnp_info_buffer_t * buffer, char *space, | |||
78 | else | 82 | else |
79 | pnp_printf(buffer, "%i", i); | 83 | pnp_printf(buffer, "%i", i); |
80 | } | 84 | } |
81 | if (bitmap_empty(irq->map, PNP_IRQ_NR)) | 85 | if (bitmap_empty(irq->map.bits, PNP_IRQ_NR)) |
82 | pnp_printf(buffer, "<none>"); | 86 | pnp_printf(buffer, "<none>"); |
83 | if (irq->flags & IORESOURCE_IRQ_HIGHEDGE) | 87 | if (irq->flags & IORESOURCE_IRQ_HIGHEDGE) |
84 | pnp_printf(buffer, " High-Edge"); | 88 | pnp_printf(buffer, " High-Edge"); |
@@ -88,6 +92,8 @@ static void pnp_print_irq(pnp_info_buffer_t * buffer, char *space, | |||
88 | pnp_printf(buffer, " High-Level"); | 92 | pnp_printf(buffer, " High-Level"); |
89 | if (irq->flags & IORESOURCE_IRQ_LOWLEVEL) | 93 | if (irq->flags & IORESOURCE_IRQ_LOWLEVEL) |
90 | pnp_printf(buffer, " Low-Level"); | 94 | pnp_printf(buffer, " Low-Level"); |
95 | if (irq->flags & IORESOURCE_IRQ_OPTIONAL) | ||
96 | pnp_printf(buffer, " (optional)"); | ||
91 | pnp_printf(buffer, "\n"); | 97 | pnp_printf(buffer, "\n"); |
92 | } | 98 | } |
93 | 99 | ||
@@ -148,8 +154,11 @@ static void pnp_print_mem(pnp_info_buffer_t * buffer, char *space, | |||
148 | { | 154 | { |
149 | char *s; | 155 | char *s; |
150 | 156 | ||
151 | pnp_printf(buffer, "%sMemory 0x%x-0x%x, align 0x%x, size 0x%x", | 157 | pnp_printf(buffer, "%sMemory %#llx-%#llx, align %#llx, size %#llx", |
152 | space, mem->min, mem->max, mem->align, mem->size); | 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); | ||
153 | if (mem->flags & IORESOURCE_MEM_WRITEABLE) | 162 | if (mem->flags & IORESOURCE_MEM_WRITEABLE) |
154 | pnp_printf(buffer, ", writeable"); | 163 | pnp_printf(buffer, ", writeable"); |
155 | if (mem->flags & IORESOURCE_MEM_CACHEABLE) | 164 | if (mem->flags & IORESOURCE_MEM_CACHEABLE) |
@@ -177,65 +186,58 @@ static void pnp_print_mem(pnp_info_buffer_t * buffer, char *space, | |||
177 | } | 186 | } |
178 | 187 | ||
179 | static void pnp_print_option(pnp_info_buffer_t * buffer, char *space, | 188 | static void pnp_print_option(pnp_info_buffer_t * buffer, char *space, |
180 | struct pnp_option *option, int dep) | 189 | struct pnp_option *option) |
181 | { | 190 | { |
182 | char *s; | 191 | switch (option->type) { |
183 | struct pnp_port *port; | 192 | case IORESOURCE_IO: |
184 | struct pnp_irq *irq; | 193 | pnp_print_port(buffer, space, &option->u.port); |
185 | struct pnp_dma *dma; | 194 | break; |
186 | struct pnp_mem *mem; | 195 | case IORESOURCE_MEM: |
187 | 196 | pnp_print_mem(buffer, space, &option->u.mem); | |
188 | if (dep) { | 197 | break; |
189 | switch (option->priority) { | 198 | case IORESOURCE_IRQ: |
190 | case PNP_RES_PRIORITY_PREFERRED: | 199 | pnp_print_irq(buffer, space, &option->u.irq); |
191 | s = "preferred"; | 200 | break; |
192 | break; | 201 | case IORESOURCE_DMA: |
193 | case PNP_RES_PRIORITY_ACCEPTABLE: | 202 | pnp_print_dma(buffer, space, &option->u.dma); |
194 | s = "acceptable"; | 203 | break; |
195 | break; | ||
196 | case PNP_RES_PRIORITY_FUNCTIONAL: | ||
197 | s = "functional"; | ||
198 | break; | ||
199 | default: | ||
200 | s = "invalid"; | ||
201 | } | ||
202 | pnp_printf(buffer, "Dependent: %02i - Priority %s\n", dep, s); | ||
203 | } | 204 | } |
204 | |||
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); | ||
213 | } | 205 | } |
214 | 206 | ||
215 | static ssize_t pnp_show_options(struct device *dmdev, | 207 | static ssize_t pnp_show_options(struct device *dmdev, |
216 | struct device_attribute *attr, char *buf) | 208 | struct device_attribute *attr, char *buf) |
217 | { | 209 | { |
218 | struct pnp_dev *dev = to_pnp_dev(dmdev); | 210 | struct pnp_dev *dev = to_pnp_dev(dmdev); |
219 | struct pnp_option *independent = dev->independent; | 211 | pnp_info_buffer_t *buffer; |
220 | struct pnp_option *dependent = dev->dependent; | 212 | struct pnp_option *option; |
221 | int ret, dep = 1; | 213 | int ret, dep = 0, set = 0; |
214 | char *indent; | ||
222 | 215 | ||
223 | pnp_info_buffer_t *buffer = (pnp_info_buffer_t *) | 216 | buffer = pnp_alloc(sizeof(pnp_info_buffer_t)); |
224 | pnp_alloc(sizeof(pnp_info_buffer_t)); | ||
225 | if (!buffer) | 217 | if (!buffer) |
226 | return -ENOMEM; | 218 | return -ENOMEM; |
227 | 219 | ||
228 | buffer->len = PAGE_SIZE; | 220 | buffer->len = PAGE_SIZE; |
229 | buffer->buffer = buf; | 221 | buffer->buffer = buf; |
230 | buffer->curr = buffer->buffer; | 222 | buffer->curr = buffer->buffer; |
231 | if (independent) | ||
232 | pnp_print_option(buffer, "", independent, 0); | ||
233 | 223 | ||
234 | while (dependent) { | 224 | list_for_each_entry(option, &dev->options, list) { |
235 | pnp_print_option(buffer, " ", dependent, dep); | 225 | if (pnp_option_is_dependent(option)) { |
236 | dependent = dependent->next; | 226 | indent = " "; |
237 | dep++; | 227 | if (!dep || pnp_option_set(option) != set) { |
228 | set = pnp_option_set(option); | ||
229 | dep = 1; | ||
230 | pnp_printf(buffer, "Dependent: %02i - " | ||
231 | "Priority %s\n", set, | ||
232 | pnp_option_priority_name(option)); | ||
233 | } | ||
234 | } else { | ||
235 | dep = 0; | ||
236 | indent = ""; | ||
237 | } | ||
238 | pnp_print_option(buffer, indent, option); | ||
238 | } | 239 | } |
240 | |||
239 | ret = (buffer->curr - buf); | 241 | ret = (buffer->curr - buf); |
240 | kfree(buffer); | 242 | kfree(buffer); |
241 | return ret; | 243 | return ret; |
@@ -248,79 +250,59 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, | |||
248 | char *buf) | 250 | char *buf) |
249 | { | 251 | { |
250 | struct pnp_dev *dev = to_pnp_dev(dmdev); | 252 | struct pnp_dev *dev = to_pnp_dev(dmdev); |
251 | struct resource *res; | ||
252 | int i, ret; | ||
253 | pnp_info_buffer_t *buffer; | 253 | pnp_info_buffer_t *buffer; |
254 | struct pnp_resource *pnp_res; | ||
255 | struct resource *res; | ||
256 | int ret; | ||
254 | 257 | ||
255 | if (!dev) | 258 | if (!dev) |
256 | return -EINVAL; | 259 | return -EINVAL; |
257 | 260 | ||
258 | buffer = (pnp_info_buffer_t *) pnp_alloc(sizeof(pnp_info_buffer_t)); | 261 | buffer = pnp_alloc(sizeof(pnp_info_buffer_t)); |
259 | if (!buffer) | 262 | if (!buffer) |
260 | return -ENOMEM; | 263 | return -ENOMEM; |
264 | |||
261 | buffer->len = PAGE_SIZE; | 265 | buffer->len = PAGE_SIZE; |
262 | buffer->buffer = buf; | 266 | buffer->buffer = buf; |
263 | buffer->curr = buffer->buffer; | 267 | buffer->curr = buffer->buffer; |
264 | 268 | ||
265 | pnp_printf(buffer, "state = "); | 269 | pnp_printf(buffer, "state = %s\n", dev->active ? "active" : "disabled"); |
266 | if (dev->active) | 270 | |
267 | pnp_printf(buffer, "active\n"); | 271 | list_for_each_entry(pnp_res, &dev->resources, list) { |
268 | else | 272 | res = &pnp_res->res; |
269 | pnp_printf(buffer, "disabled\n"); | 273 | |
270 | 274 | pnp_printf(buffer, pnp_resource_type_name(res)); | |
271 | for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_IO, i)); i++) { | 275 | |
272 | if (pnp_resource_valid(res)) { | 276 | if (res->flags & IORESOURCE_DISABLED) { |
273 | pnp_printf(buffer, "io"); | 277 | pnp_printf(buffer, " disabled\n"); |
274 | if (res->flags & IORESOURCE_DISABLED) | 278 | continue; |
275 | pnp_printf(buffer, " disabled\n"); | ||
276 | else | ||
277 | pnp_printf(buffer, " 0x%llx-0x%llx\n", | ||
278 | (unsigned long long) res->start, | ||
279 | (unsigned long long) res->end); | ||
280 | } | ||
281 | } | ||
282 | for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_MEM, i)); i++) { | ||
283 | if (pnp_resource_valid(res)) { | ||
284 | pnp_printf(buffer, "mem"); | ||
285 | if (res->flags & IORESOURCE_DISABLED) | ||
286 | pnp_printf(buffer, " disabled\n"); | ||
287 | else | ||
288 | pnp_printf(buffer, " 0x%llx-0x%llx\n", | ||
289 | (unsigned long long) res->start, | ||
290 | (unsigned long long) res->end); | ||
291 | } | ||
292 | } | ||
293 | for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_IRQ, i)); i++) { | ||
294 | if (pnp_resource_valid(res)) { | ||
295 | pnp_printf(buffer, "irq"); | ||
296 | if (res->flags & IORESOURCE_DISABLED) | ||
297 | pnp_printf(buffer, " disabled\n"); | ||
298 | else | ||
299 | pnp_printf(buffer, " %lld\n", | ||
300 | (unsigned long long) res->start); | ||
301 | } | 279 | } |
302 | } | 280 | |
303 | for (i = 0; (res = pnp_get_resource(dev, IORESOURCE_DMA, i)); i++) { | 281 | switch (pnp_resource_type(res)) { |
304 | if (pnp_resource_valid(res)) { | 282 | case IORESOURCE_IO: |
305 | pnp_printf(buffer, "dma"); | 283 | case IORESOURCE_MEM: |
306 | if (res->flags & IORESOURCE_DISABLED) | 284 | pnp_printf(buffer, " %#llx-%#llx\n", |
307 | pnp_printf(buffer, " disabled\n"); | 285 | (unsigned long long) res->start, |
308 | else | 286 | (unsigned long long) res->end); |
309 | pnp_printf(buffer, " %lld\n", | 287 | break; |
310 | (unsigned long long) res->start); | 288 | case IORESOURCE_IRQ: |
289 | case IORESOURCE_DMA: | ||
290 | pnp_printf(buffer, " %lld\n", | ||
291 | (unsigned long long) res->start); | ||
292 | break; | ||
311 | } | 293 | } |
312 | } | 294 | } |
295 | |||
313 | ret = (buffer->curr - buf); | 296 | ret = (buffer->curr - buf); |
314 | kfree(buffer); | 297 | kfree(buffer); |
315 | return ret; | 298 | return ret; |
316 | } | 299 | } |
317 | 300 | ||
318 | static ssize_t | 301 | static ssize_t pnp_set_current_resources(struct device *dmdev, |
319 | pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, | 302 | struct device_attribute *attr, |
320 | const char *ubuf, size_t count) | 303 | const char *ubuf, size_t count) |
321 | { | 304 | { |
322 | struct pnp_dev *dev = to_pnp_dev(dmdev); | 305 | struct pnp_dev *dev = to_pnp_dev(dmdev); |
323 | struct pnp_resource *pnp_res; | ||
324 | char *buf = (void *)ubuf; | 306 | char *buf = (void *)ubuf; |
325 | int retval = 0; | 307 | int retval = 0; |
326 | resource_size_t start, end; | 308 | resource_size_t start, end; |
@@ -368,7 +350,6 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, | |||
368 | goto done; | 350 | goto done; |
369 | } | 351 | } |
370 | if (!strnicmp(buf, "set", 3)) { | 352 | if (!strnicmp(buf, "set", 3)) { |
371 | int nport = 0, nmem = 0, nirq = 0, ndma = 0; | ||
372 | if (dev->active) | 353 | if (dev->active) |
373 | goto done; | 354 | goto done; |
374 | buf += 3; | 355 | buf += 3; |
@@ -391,10 +372,7 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, | |||
391 | end = simple_strtoul(buf, &buf, 0); | 372 | end = simple_strtoul(buf, &buf, 0); |
392 | } else | 373 | } else |
393 | end = start; | 374 | end = start; |
394 | pnp_res = pnp_add_io_resource(dev, start, end, | 375 | pnp_add_io_resource(dev, start, end, 0); |
395 | 0); | ||
396 | if (pnp_res) | ||
397 | pnp_res->index = nport++; | ||
398 | continue; | 376 | continue; |
399 | } | 377 | } |
400 | if (!strnicmp(buf, "mem", 3)) { | 378 | if (!strnicmp(buf, "mem", 3)) { |
@@ -411,10 +389,7 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, | |||
411 | end = simple_strtoul(buf, &buf, 0); | 389 | end = simple_strtoul(buf, &buf, 0); |
412 | } else | 390 | } else |
413 | end = start; | 391 | end = start; |
414 | pnp_res = pnp_add_mem_resource(dev, start, end, | 392 | pnp_add_mem_resource(dev, start, end, 0); |
415 | 0); | ||
416 | if (pnp_res) | ||
417 | pnp_res->index = nmem++; | ||
418 | continue; | 393 | continue; |
419 | } | 394 | } |
420 | if (!strnicmp(buf, "irq", 3)) { | 395 | if (!strnicmp(buf, "irq", 3)) { |
@@ -422,9 +397,7 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, | |||
422 | while (isspace(*buf)) | 397 | while (isspace(*buf)) |
423 | ++buf; | 398 | ++buf; |
424 | start = simple_strtoul(buf, &buf, 0); | 399 | start = simple_strtoul(buf, &buf, 0); |
425 | pnp_res = pnp_add_irq_resource(dev, start, 0); | 400 | pnp_add_irq_resource(dev, start, 0); |
426 | if (pnp_res) | ||
427 | pnp_res->index = nirq++; | ||
428 | continue; | 401 | continue; |
429 | } | 402 | } |
430 | if (!strnicmp(buf, "dma", 3)) { | 403 | if (!strnicmp(buf, "dma", 3)) { |
@@ -432,9 +405,7 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, | |||
432 | while (isspace(*buf)) | 405 | while (isspace(*buf)) |
433 | ++buf; | 406 | ++buf; |
434 | start = simple_strtoul(buf, &buf, 0); | 407 | start = simple_strtoul(buf, &buf, 0); |
435 | pnp_res = pnp_add_dma_resource(dev, start, 0); | 408 | pnp_add_dma_resource(dev, start, 0); |
436 | if (pnp_res) | ||
437 | pnp_res->index = ndma++; | ||
438 | continue; | 409 | continue; |
439 | } | 410 | } |
440 | break; | 411 | break; |