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; |
