1 /* 2 * interface.c - contains everything related to the user interface 3 * 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 */ 7 8 #include <linux/pnp.h> 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> 17 18 #include "base.h" 19 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 */ 27 }; 28 29 typedef struct pnp_info_buffer pnp_info_buffer_t; 30 31 static int pnp_printf(pnp_info_buffer_t * buffer, char *fmt, ...) 32 { 33 va_list args; 34 int res; 35 36 if (buffer->stop || buffer->error) 37 return 0; 38 va_start(args, fmt); 39 res = vsnprintf(buffer->curr, buffer->len - buffer->size, fmt, args); 40 va_end(args); 41 if (buffer->size + res >= buffer->len) { 42 buffer->stop = 1; 43 return 0; 44 } 45 buffer->curr += res; 46 buffer->size += res; 47 return res; 48 } 49 50 static void pnp_print_port(pnp_info_buffer_t * buffer, char *space, 51 struct pnp_port *port) 52 { 53 pnp_printf(buffer, 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); 58 } 59 60 static void pnp_print_irq(pnp_info_buffer_t * buffer, char *space, 61 struct pnp_irq *irq) 62 { 63 int first = 1, i; 64 65 pnp_printf(buffer, "%sirq ", space); 66 for (i = 0; i < PNP_IRQ_NR; i++) 67 if (test_bit(i, irq->map)) { 68 if (!first) { 69 pnp_printf(buffer, ","); 70 } else { 71 first = 0; 72 } 73 if (i == 2 || i == 9) 74 pnp_printf(buffer, "2/9"); 75 else 76 pnp_printf(buffer, "%i", i); 77 } 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"); 89 } 90 91 static void pnp_print_dma(pnp_info_buffer_t * buffer, char *space, 92 struct pnp_dma *dma) 93 { 94 int first = 1, i; 95 char *s; 96 97 pnp_printf(buffer, "%sdma ", space); 98 for (i = 0; i < 8; i++) 99 if (dma->map & (1 << i)) { 100 if (!first) { 101 pnp_printf(buffer, ","); 102 } else { 103 first = 0; 104 } 105 pnp_printf(buffer, "%i", i); 106 } 107 if (!dma->map) 108 pnp_printf(buffer, "<none>"); 109 switch (dma->flags & IORESOURCE_DMA_TYPE_MASK) { 110 case IORESOURCE_DMA_8BIT: 111 s = "8-bit"; 112 break; 113 case IORESOURCE_DMA_8AND16BIT: 114 s = "8-bit&16-bit"; 115 break; 116 default: 117 s = "16-bit"; 118 } 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: 128 s = "type-A"; 129 break; 130 case IORESOURCE_DMA_TYPEB: 131 s = "type-B"; 132 break; 133 case IORESOURCE_DMA_TYPEF: 134 s = "type-F"; 135 break; 136 default: 137 s = "compatible"; 138 break; 139 } 140 pnp_printf(buffer, " %s\n", s); 141 } 142 143 static void pnp_print_mem(pnp_info_buffer_t * buffer, char *space, 144 struct pnp_mem *mem) 145 { 146 char *s; 147 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: 162 s = "8-bit"; 163 break; 164 case IORESOURCE_MEM_8AND16BIT: 165 s = "8-bit&16-bit"; 166 break; 167 case IORESOURCE_MEM_32BIT: 168 s = "32-bit"; 169 break; 170 default: 171 s = "16-bit"; 172 } 173 pnp_printf(buffer, ", %s\n", s); 174 } 175 176 static void pnp_print_option(pnp_info_buffer_t * buffer, char *space, 177 struct pnp_option *option, int dep) 178 { 179 char *s; 180 struct pnp_port *port; 181 struct pnp_irq *irq; 182 struct pnp_dma *dma; 183 struct pnp_mem *mem; 184 185 if (dep) { 186 switch (option->priority) { 187 case PNP_RES_PRIORITY_PREFERRED: 188 s = "preferred"; 189 break; 190 case PNP_RES_PRIORITY_ACCEPTABLE: 191 s = "acceptable"; 192 break; 193 case PNP_RES_PRIORITY_FUNCTIONAL: 194 s = "functional"; 195 break; 196 default: 197 s = "invalid"; 198 } 199 pnp_printf(buffer, "Dependent: %02i - Priority %s\n", dep, s); 200 } 201 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); 210 } 211 212 static ssize_t pnp_show_options(struct device *dmdev, 213 struct device_attribute *attr, char *buf) 214 { 215 struct pnp_dev *dev = to_pnp_dev(dmdev); 216 struct pnp_option *independent = dev->independent; 217 struct pnp_option *dependent = dev->dependent; 218 int ret, dep = 1; 219 220 pnp_info_buffer_t *buffer = (pnp_info_buffer_t *) 221 pnp_alloc(sizeof(pnp_info_buffer_t)); 222 if (!buffer) 223 return -ENOMEM; 224 225 buffer->len = PAGE_SIZE; 226 buffer->buffer = buf; 227 buffer->curr = buffer->buffer; 228 if (independent) 229 pnp_print_option(buffer, "", independent, 0); 230 231 while (dependent) { 232 pnp_print_option(buffer, " ", dependent, dep); 233 dependent = dependent->next; 234 dep++; 235 } 236 ret = (buffer->curr - buf); 237 kfree(buffer); 238 return ret; 239 } 240 241 static DEVICE_ATTR(options, S_IRUGO, pnp_show_options, NULL); 242 243 static ssize_t pnp_show_current_resources(struct device *dmdev, 244 struct device_attribute *attr, 245 char *buf) 246 { 247 struct pnp_dev *dev = to_pnp_dev(dmdev); 248 int i, ret; 249 pnp_info_buffer_t *buffer; 250 251 if (!dev) 252 return -EINVAL; 253 254 buffer = (pnp_info_buffer_t *) pnp_alloc(sizeof(pnp_info_buffer_t)); 255 if (!buffer) 256 return -ENOMEM; 257 buffer->len = PAGE_SIZE; 258 buffer->buffer = buf; 259 buffer->curr = buffer->buffer; 260 261 pnp_printf(buffer, "state = "); 262 if (dev->active) 263 pnp_printf(buffer, "active\n"); 264 else 265 pnp_printf(buffer, "disabled\n"); 266 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"); 272 else 273 pnp_printf(buffer, " 0x%llx-0x%llx\n", 274 (unsigned long long) 275 pnp_port_start(dev, i), 276 (unsigned long long)pnp_port_end(dev, 277 i)); 278 } 279 } 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"); 285 else 286 pnp_printf(buffer, " 0x%llx-0x%llx\n", 287 (unsigned long long) 288 pnp_mem_start(dev, i), 289 (unsigned long long)pnp_mem_end(dev, 290 i)); 291 } 292 } 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"); 298 else 299 pnp_printf(buffer, " %lld\n", 300 (unsigned long long)pnp_irq(dev, i)); 301 } 302 } 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"); 308 else 309 pnp_printf(buffer, " %lld\n", 310 (unsigned long long)pnp_dma(dev, i)); 311 } 312 } 313 ret = (buffer->curr - buf); 314 kfree(buffer); 315 return ret; 316 } 317 318 extern struct semaphore pnp_res_mutex; 319 320 static ssize_t 321 pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, 322 const char *ubuf, size_t count) 323 { 324 struct pnp_dev *dev = to_pnp_dev(dmdev); 325 char *buf = (void *)ubuf; 326 int retval = 0; 327 328 if (dev->status & PNP_ATTACHED) { 329 retval = -EBUSY; 330 dev_info(&dev->dev, "in use; can't configure\n"); 331 goto done; 332 } 333 334 while (isspace(*buf)) 335 ++buf; 336 if (!strnicmp(buf, "disable", 7)) { 337 retval = pnp_disable_dev(dev); 338 goto done; 339 } 340 if (!strnicmp(buf, "activate", 8)) { 341 retval = pnp_activate_dev(dev); 342 goto done; 343 } 344 if (!strnicmp(buf, "fill", 4)) { 345 if (dev->active) 346 goto done; 347 retval = pnp_auto_config_dev(dev); 348 goto done; 349 } 350 if (!strnicmp(buf, "auto", 4)) { 351 if (dev->active) 352 goto done; 353 pnp_init_resource_table(&dev->res); 354 retval = pnp_auto_config_dev(dev); 355 goto done; 356 } 357 if (!strnicmp(buf, "clear", 5)) { 358 if (dev->active) 359 goto done; 360 pnp_init_resource_table(&dev->res); 361 goto done; 362 } 363 if (!strnicmp(buf, "get", 3)) { 364 down(&pnp_res_mutex); 365 if (pnp_can_read(dev)) 366 dev->protocol->get(dev, &dev->res); 367 up(&pnp_res_mutex); 368 goto done; 369 } 370 if (!strnicmp(buf, "set", 3)) { 371 int nport = 0, nmem = 0, nirq = 0, ndma = 0; 372 if (dev->active) 373 goto done; 374 buf += 3; 375 pnp_init_resource_table(&dev->res); 376 down(&pnp_res_mutex); 377 while (1) { 378 while (isspace(*buf)) 379 ++buf; 380 if (!strnicmp(buf, "io", 2)) { 381 buf += 2; 382 while (isspace(*buf)) 383 ++buf; 384 dev->res.port_resource[nport].start = 385 simple_strtoul(buf, &buf, 0); 386 while (isspace(*buf)) 387 ++buf; 388 if (*buf == '-') { 389 buf += 1; 390 while (isspace(*buf)) 391 ++buf; 392 dev->res.port_resource[nport].end = 393 simple_strtoul(buf, &buf, 0); 394 } else 395 dev->res.port_resource[nport].end = 396 dev->res.port_resource[nport].start; 397 dev->res.port_resource[nport].flags = 398 IORESOURCE_IO; 399 nport++; 400 if (nport >= PNP_MAX_PORT) 401 break; 402 continue; 403 } 404 if (!strnicmp(buf, "mem", 3)) { 405 buf += 3; 406 while (isspace(*buf)) 407 ++buf; 408 dev->res.mem_resource[nmem].start = 409 simple_strtoul(buf, &buf, 0); 410 while (isspace(*buf)) 411 ++buf; 412 if (*buf == '-') { 413 buf += 1; 414 while (isspace(*buf)) 415 ++buf; 416 dev->res.mem_resource[nmem].end = 417 simple_strtoul(buf, &buf, 0); 418 } else 419 dev->res.mem_resource[nmem].end = 420 dev->res.mem_resource[nmem].start; 421 dev->res.mem_resource[nmem].flags = 422 IORESOURCE_MEM; 423 nmem++; 424 if (nmem >= PNP_MAX_MEM) 425 break; 426 continue; 427 } 428 if (!strnicmp(buf, "irq", 3)) { 429 buf += 3; 430 while (isspace(*buf)) 431 ++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 = 436 IORESOURCE_IRQ; 437 nirq++; 438 if (nirq >= PNP_MAX_IRQ) 439 break; 440 continue; 441 } 442 if (!strnicmp(buf, "dma", 3)) { 443 buf += 3; 444 while (isspace(*buf)) 445 ++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 = 450 IORESOURCE_DMA; 451 ndma++; 452 if (ndma >= PNP_MAX_DMA) 453 break; 454 continue; 455 } 456 break; 457 } 458 up(&pnp_res_mutex); 459 goto done; 460 } 461 462 done: 463 if (retval < 0) 464 return retval; 465 return count; 466 } 467 468 static DEVICE_ATTR(resources, S_IRUGO | S_IWUSR, 469 pnp_show_current_resources, pnp_set_current_resources); 470 471 static ssize_t pnp_show_current_ids(struct device *dmdev, 472 struct device_attribute *attr, char *buf) 473 { 474 char *str = buf; 475 struct pnp_dev *dev = to_pnp_dev(dmdev); 476 struct pnp_id *pos = dev->id; 477 478 while (pos) { 479 str += sprintf(str, "%s\n", pos->id); 480 pos = pos->next; 481 } 482 return (str - buf); 483 } 484 485 static DEVICE_ATTR(id, S_IRUGO, pnp_show_current_ids, NULL); 486 487 int pnp_interface_attach_device(struct pnp_dev *dev) 488 { 489 int rc = device_create_file(&dev->dev, &dev_attr_options); 490 491 if (rc) 492 goto err; 493 rc = device_create_file(&dev->dev, &dev_attr_resources); 494 if (rc) 495 goto err_opt; 496 rc = device_create_file(&dev->dev, &dev_attr_id); 497 if (rc) 498 goto err_res; 499 500 return 0; 501 502 err_res: 503 device_remove_file(&dev->dev, &dev_attr_resources); 504 err_opt: 505 device_remove_file(&dev->dev, &dev_attr_options); 506 err: 507 return rc; 508 } 509