1 /* 2 * manager.c - Resource Management, Conflict Resolution, Activation and Disabling of Devices 3 * 4 * based on isapnp.c resource management (c) Jaroslav Kysela <perex@suse.cz> 5 * Copyright 2003 Adam Belay <ambx1@neo.rr.com> 6 */ 7 8 #include <linux/errno.h> 9 #include <linux/module.h> 10 #include <linux/init.h> 11 #include <linux/kernel.h> 12 #include <linux/pnp.h> 13 #include <linux/slab.h> 14 #include <linux/bitmap.h> 15 #include "base.h" 16 17 DECLARE_MUTEX(pnp_res_mutex); 18 19 static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx) 20 { 21 resource_size_t *start, *end; 22 unsigned long *flags; 23 24 if (idx >= PNP_MAX_PORT) { 25 pnp_err 26 ("More than 4 ports is incompatible with pnp specifications."); 27 /* pretend we were successful so at least the manager won't try again */ 28 return 1; 29 } 30 31 /* check if this resource has been manually set, if so skip */ 32 if (!(dev->res.port_resource[idx].flags & IORESOURCE_AUTO)) 33 return 1; 34 35 start = &dev->res.port_resource[idx].start; 36 end = &dev->res.port_resource[idx].end; 37 flags = &dev->res.port_resource[idx].flags; 38 39 /* set the initial values */ 40 *flags |= rule->flags | IORESOURCE_IO; 41 *flags &= ~IORESOURCE_UNSET; 42 43 if (!rule->size) { 44 *flags |= IORESOURCE_DISABLED; 45 return 1; /* skip disabled resource requests */ 46 } 47 48 *start = rule->min; 49 *end = *start + rule->size - 1; 50 51 /* run through until pnp_check_port is happy */ 52 while (!pnp_check_port(dev, idx)) { 53 *start += rule->align; 54 *end = *start + rule->size - 1; 55 if (*start > rule->max || !rule->align) 56 return 0; 57 } 58 return 1; 59 } 60 61 static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx) 62 { 63 resource_size_t *start, *end; 64 unsigned long *flags; 65 66 if (idx >= PNP_MAX_MEM) { 67 pnp_err 68 ("More than 8 mems is incompatible with pnp specifications."); 69 /* pretend we were successful so at least the manager won't try again */ 70 return 1; 71 } 72 73 /* check if this resource has been manually set, if so skip */ 74 if (!(dev->res.mem_resource[idx].flags & IORESOURCE_AUTO)) 75 return 1; 76 77 start = &dev->res.mem_resource[idx].start; 78 end = &dev->res.mem_resource[idx].end; 79 flags = &dev->res.mem_resource[idx].flags; 80 81 /* set the initial values */ 82 *flags |= rule->flags | IORESOURCE_MEM; 83 *flags &= ~IORESOURCE_UNSET; 84 85 /* convert pnp flags to standard Linux flags */ 86 if (!(rule->flags & IORESOURCE_MEM_WRITEABLE)) 87 *flags |= IORESOURCE_READONLY; 88 if (rule->flags & IORESOURCE_MEM_CACHEABLE) 89 *flags |= IORESOURCE_CACHEABLE; 90 if (rule->flags & IORESOURCE_MEM_RANGELENGTH) 91 *flags |= IORESOURCE_RANGELENGTH; 92 if (rule->flags & IORESOURCE_MEM_SHADOWABLE) 93 *flags |= IORESOURCE_SHADOWABLE; 94 95 if (!rule->size) { 96 *flags |= IORESOURCE_DISABLED; 97 return 1; /* skip disabled resource requests */ 98 } 99 100 *start = rule->min; 101 *end = *start + rule->size - 1; 102 103 /* run through until pnp_check_mem is happy */ 104 while (!pnp_check_mem(dev, idx)) { 105 *start += rule->align; 106 *end = *start + rule->size - 1; 107 if (*start > rule->max || !rule->align) 108 return 0; 109 } 110 return 1; 111 } 112 113 static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx) 114 { 115 resource_size_t *start, *end; 116 unsigned long *flags; 117 int i; 118 119 /* IRQ priority: this table is good for i386 */ 120 static unsigned short xtab[16] = { 121 5, 10, 11, 12, 9, 14, 15, 7, 3, 4, 13, 0, 1, 6, 8, 2 122 }; 123 124 if (idx >= PNP_MAX_IRQ) { 125 pnp_err 126 ("More than 2 irqs is incompatible with pnp specifications."); 127 /* pretend we were successful so at least the manager won't try again */ 128 return 1; 129 } 130 131 /* check if this resource has been manually set, if so skip */ 132 if (!(dev->res.irq_resource[idx].flags & IORESOURCE_AUTO)) 133 return 1; 134 135 start = &dev->res.irq_resource[idx].start; 136 end = &dev->res.irq_resource[idx].end; 137 flags = &dev->res.irq_resource[idx].flags; 138 139 /* set the initial values */ 140 *flags |= rule->flags | IORESOURCE_IRQ; 141 *flags &= ~IORESOURCE_UNSET; 142 143 if (bitmap_empty(rule->map, PNP_IRQ_NR)) { 144 *flags |= IORESOURCE_DISABLED; 145 return 1; /* skip disabled resource requests */ 146 } 147 148 /* TBD: need check for >16 IRQ */ 149 *start = find_next_bit(rule->map, PNP_IRQ_NR, 16); 150 if (*start < PNP_IRQ_NR) { 151 *end = *start; 152 return 1; 153 } 154 for (i = 0; i < 16; i++) { 155 if (test_bit(xtab[i], rule->map)) { 156 *start = *end = xtab[i]; 157 if (pnp_check_irq(dev, idx)) 158 return 1; 159 } 160 } 161 return 0; 162 } 163 164 static int pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx) 165 { 166 resource_size_t *start, *end; 167 unsigned long *flags; 168 int i; 169 170 /* DMA priority: this table is good for i386 */ 171 static unsigned short xtab[8] = { 172 1, 3, 5, 6, 7, 0, 2, 4 173 }; 174 175 if (idx >= PNP_MAX_DMA) { 176 pnp_err 177 ("More than 2 dmas is incompatible with pnp specifications."); 178 /* pretend we were successful so at least the manager won't try again */ 179 return 1; 180 } 181 182 /* check if this resource has been manually set, if so skip */ 183 if (!(dev->res.dma_resource[idx].flags & IORESOURCE_AUTO)) 184 return 1; 185 186 start = &dev->res.dma_resource[idx].start; 187 end = &dev->res.dma_resource[idx].end; 188 flags = &dev->res.dma_resource[idx].flags; 189 190 /* set the initial values */ 191 *flags |= rule->flags | IORESOURCE_DMA; 192 *flags &= ~IORESOURCE_UNSET; 193 194 if (!rule->map) { 195 *flags |= IORESOURCE_DISABLED; 196 return 1; /* skip disabled resource requests */ 197 } 198 199 for (i = 0; i < 8; i++) { 200 if (rule->map & (1 << xtab[i])) { 201 *start = *end = xtab[i]; 202 if (pnp_check_dma(dev, idx)) 203 return 1; 204 } 205 } 206 return 0; 207 } 208 209 /** 210 * pnp_init_resources - Resets a resource table to default values. 211 * @table: pointer to the desired resource table 212 */ 213 void pnp_init_resource_table(struct pnp_resource_table *table) 214 { 215 int idx; 216 217 for (idx = 0; idx < PNP_MAX_IRQ; idx++) { 218 table->irq_resource[idx].name = NULL; 219 table->irq_resource[idx].start = -1; 220 table->irq_resource[idx].end = -1; 221 table->irq_resource[idx].flags = 222 IORESOURCE_IRQ | IORESOURCE_AUTO | IORESOURCE_UNSET; 223 } 224 for (idx = 0; idx < PNP_MAX_DMA; idx++) { 225 table->dma_resource[idx].name = NULL; 226 table->dma_resource[idx].start = -1; 227 table->dma_resource[idx].end = -1; 228 table->dma_resource[idx].flags = 229 IORESOURCE_DMA | IORESOURCE_AUTO | IORESOURCE_UNSET; 230 } 231 for (idx = 0; idx < PNP_MAX_PORT; idx++) { 232 table->port_resource[idx].name = NULL; 233 table->port_resource[idx].start = 0; 234 table->port_resource[idx].end = 0; 235 table->port_resource[idx].flags = 236 IORESOURCE_IO | IORESOURCE_AUTO | IORESOURCE_UNSET; 237 } 238 for (idx = 0; idx < PNP_MAX_MEM; idx++) { 239 table->mem_resource[idx].name = NULL; 240 table->mem_resource[idx].start = 0; 241 table->mem_resource[idx].end = 0; 242 table->mem_resource[idx].flags = 243 IORESOURCE_MEM | IORESOURCE_AUTO | IORESOURCE_UNSET; 244 } 245 } 246 247 /** 248 * pnp_clean_resources - clears resources that were not manually set 249 * @res: the resources to clean 250 */ 251 static void pnp_clean_resource_table(struct pnp_resource_table *res) 252 { 253 int idx; 254 255 for (idx = 0; idx < PNP_MAX_IRQ; idx++) { 256 if (!(res->irq_resource[idx].flags & IORESOURCE_AUTO)) 257 continue; 258 res->irq_resource[idx].start = -1; 259 res->irq_resource[idx].end = -1; 260 res->irq_resource[idx].flags = 261 IORESOURCE_IRQ | IORESOURCE_AUTO | IORESOURCE_UNSET; 262 } 263 for (idx = 0; idx < PNP_MAX_DMA; idx++) { 264 if (!(res->dma_resource[idx].flags & IORESOURCE_AUTO)) 265 continue; 266 res->dma_resource[idx].start = -1; 267 res->dma_resource[idx].end = -1; 268 res->dma_resource[idx].flags = 269 IORESOURCE_DMA | IORESOURCE_AUTO | IORESOURCE_UNSET; 270 } 271 for (idx = 0; idx < PNP_MAX_PORT; idx++) { 272 if (!(res->port_resource[idx].flags & IORESOURCE_AUTO)) 273 continue; 274 res->port_resource[idx].start = 0; 275 res->port_resource[idx].end = 0; 276 res->port_resource[idx].flags = 277 IORESOURCE_IO | IORESOURCE_AUTO | IORESOURCE_UNSET; 278 } 279 for (idx = 0; idx < PNP_MAX_MEM; idx++) { 280 if (!(res->mem_resource[idx].flags & IORESOURCE_AUTO)) 281 continue; 282 res->mem_resource[idx].start = 0; 283 res->mem_resource[idx].end = 0; 284 res->mem_resource[idx].flags = 285 IORESOURCE_MEM | IORESOURCE_AUTO | IORESOURCE_UNSET; 286 } 287 } 288 289 /** 290 * pnp_assign_resources - assigns resources to the device based on the specified dependent number 291 * @dev: pointer to the desired device 292 * @depnum: the dependent function number 293 * 294 * Only set depnum to 0 if the device does not have dependent options. 295 */ 296 static int pnp_assign_resources(struct pnp_dev *dev, int depnum) 297 { 298 struct pnp_port *port; 299 struct pnp_mem *mem; 300 struct pnp_irq *irq; 301 struct pnp_dma *dma; 302 int nport = 0, nmem = 0, nirq = 0, ndma = 0; 303 304 if (!pnp_can_configure(dev)) 305 return -ENODEV; 306 307 down(&pnp_res_mutex); 308 pnp_clean_resource_table(&dev->res); /* start with a fresh slate */ 309 if (dev->independent) { 310 port = dev->independent->port; 311 mem = dev->independent->mem; 312 irq = dev->independent->irq; 313 dma = dev->independent->dma; 314 while (port) { 315 if (!pnp_assign_port(dev, port, nport)) 316 goto fail; 317 nport++; 318 port = port->next; 319 } 320 while (mem) { 321 if (!pnp_assign_mem(dev, mem, nmem)) 322 goto fail; 323 nmem++; 324 mem = mem->next; 325 } 326 while (irq) { 327 if (!pnp_assign_irq(dev, irq, nirq)) 328 goto fail; 329 nirq++; 330 irq = irq->next; 331 } 332 while (dma) { 333 if (!pnp_assign_dma(dev, dma, ndma)) 334 goto fail; 335 ndma++; 336 dma = dma->next; 337 } 338 } 339 340 if (depnum) { 341 struct pnp_option *dep; 342 int i; 343 for (i = 1, dep = dev->dependent; i < depnum; 344 i++, dep = dep->next) 345 if (!dep) 346 goto fail; 347 port = dep->port; 348 mem = dep->mem; 349 irq = dep->irq; 350 dma = dep->dma; 351 while (port) { 352 if (!pnp_assign_port(dev, port, nport)) 353 goto fail; 354 nport++; 355 port = port->next; 356 } 357 while (mem) { 358 if (!pnp_assign_mem(dev, mem, nmem)) 359 goto fail; 360 nmem++; 361 mem = mem->next; 362 } 363 while (irq) { 364 if (!pnp_assign_irq(dev, irq, nirq)) 365 goto fail; 366 nirq++; 367 irq = irq->next; 368 } 369 while (dma) { 370 if (!pnp_assign_dma(dev, dma, ndma)) 371 goto fail; 372 ndma++; 373 dma = dma->next; 374 } 375 } else if (dev->dependent) 376 goto fail; 377 378 up(&pnp_res_mutex); 379 return 1; 380 381 fail: 382 pnp_clean_resource_table(&dev->res); 383 up(&pnp_res_mutex); 384 return 0; 385 } 386 387 /** 388 * pnp_manual_config_dev - Disables Auto Config and Manually sets the resource table 389 * @dev: pointer to the desired device 390 * @res: pointer to the new resource config 391 * @mode: 0 or PNP_CONFIG_FORCE 392 * 393 * This function can be used by drivers that want to manually set thier resources. 394 */ 395 int pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table *res, 396 int mode) 397 { 398 int i; 399 struct pnp_resource_table *bak; 400 401 if (!pnp_can_configure(dev)) 402 return -ENODEV; 403 bak = pnp_alloc(sizeof(struct pnp_resource_table)); 404 if (!bak) 405 return -ENOMEM; 406 *bak = dev->res; 407 408 down(&pnp_res_mutex); 409 dev->res = *res; 410 if (!(mode & PNP_CONFIG_FORCE)) { 411 for (i = 0; i < PNP_MAX_PORT; i++) { 412 if (!pnp_check_port(dev, i)) 413 goto fail; 414 } 415 for (i = 0; i < PNP_MAX_MEM; i++) { 416 if (!pnp_check_mem(dev, i)) 417 goto fail; 418 } 419 for (i = 0; i < PNP_MAX_IRQ; i++) { 420 if (!pnp_check_irq(dev, i)) 421 goto fail; 422 } 423 for (i = 0; i < PNP_MAX_DMA; i++) { 424 if (!pnp_check_dma(dev, i)) 425 goto fail; 426 } 427 } 428 up(&pnp_res_mutex); 429 430 kfree(bak); 431 return 0; 432 433 fail: 434 dev->res = *bak; 435 up(&pnp_res_mutex); 436 kfree(bak); 437 return -EINVAL; 438 } 439 440 /** 441 * pnp_auto_config_dev - automatically assigns resources to a device 442 * @dev: pointer to the desired device 443 */ 444 int pnp_auto_config_dev(struct pnp_dev *dev) 445 { 446 struct pnp_option *dep; 447 int i = 1; 448 449 if (!pnp_can_configure(dev)) { 450 pnp_dbg("Device %s does not support resource configuration.", 451 dev->dev.bus_id); 452 return -ENODEV; 453 } 454 455 if (!dev->dependent) { 456 if (pnp_assign_resources(dev, 0)) 457 return 0; 458 } else { 459 dep = dev->dependent; 460 do { 461 if (pnp_assign_resources(dev, i)) 462 return 0; 463 dep = dep->next; 464 i++; 465 } while (dep); 466 } 467 468 pnp_err("Unable to assign resources to device %s.", dev->dev.bus_id); 469 return -EBUSY; 470 } 471 472 /** 473 * pnp_start_dev - low-level start of the PnP device 474 * @dev: pointer to the desired device 475 * 476 * assumes that resources have already been allocated 477 */ 478 int pnp_start_dev(struct pnp_dev *dev) 479 { 480 if (!pnp_can_write(dev)) { 481 pnp_dbg("Device %s does not support activation.", 482 dev->dev.bus_id); 483 return -EINVAL; 484 } 485 486 if (dev->protocol->set(dev, &dev->res) < 0) { 487 pnp_err("Failed to activate device %s.", dev->dev.bus_id); 488 return -EIO; 489 } 490 491 pnp_info("Device %s activated.", dev->dev.bus_id); 492 return 0; 493 } 494 495 /** 496 * pnp_stop_dev - low-level disable of the PnP device 497 * @dev: pointer to the desired device 498 * 499 * does not free resources 500 */ 501 int pnp_stop_dev(struct pnp_dev *dev) 502 { 503 if (!pnp_can_disable(dev)) { 504 pnp_dbg("Device %s does not support disabling.", 505 dev->dev.bus_id); 506 return -EINVAL; 507 } 508 if (dev->protocol->disable(dev) < 0) { 509 pnp_err("Failed to disable device %s.", dev->dev.bus_id); 510 return -EIO; 511 } 512 513 pnp_info("Device %s disabled.", dev->dev.bus_id); 514 return 0; 515 } 516 517 /** 518 * pnp_activate_dev - activates a PnP device for use 519 * @dev: pointer to the desired device 520 * 521 * does not validate or set resources so be careful. 522 */ 523 int pnp_activate_dev(struct pnp_dev *dev) 524 { 525 int error; 526 527 if (dev->active) 528 return 0; /* the device is already active */ 529 530 /* ensure resources are allocated */ 531 if (pnp_auto_config_dev(dev)) 532 return -EBUSY; 533 534 error = pnp_start_dev(dev); 535 if (error) 536 return error; 537 538 dev->active = 1; 539 return 1; 540 } 541 542 /** 543 * pnp_disable_dev - disables device 544 * @dev: pointer to the desired device 545 * 546 * inform the correct pnp protocol so that resources can be used by other devices 547 */ 548 int pnp_disable_dev(struct pnp_dev *dev) 549 { 550 int error; 551 552 if (!dev->active) 553 return 0; /* the device is already disabled */ 554 555 error = pnp_stop_dev(dev); 556 if (error) 557 return error; 558 559 dev->active = 0; 560 561 /* release the resources so that other devices can use them */ 562 down(&pnp_res_mutex); 563 pnp_clean_resource_table(&dev->res); 564 up(&pnp_res_mutex); 565 566 return 1; 567 } 568 569 /** 570 * pnp_resource_change - change one resource 571 * @resource: pointer to resource to be changed 572 * @start: start of region 573 * @size: size of region 574 */ 575 void pnp_resource_change(struct resource *resource, resource_size_t start, 576 resource_size_t size) 577 { 578 resource->flags &= ~(IORESOURCE_AUTO | IORESOURCE_UNSET); 579 resource->start = start; 580 resource->end = start + size - 1; 581 } 582 583 EXPORT_SYMBOL(pnp_manual_config_dev); 584 EXPORT_SYMBOL(pnp_start_dev); 585 EXPORT_SYMBOL(pnp_stop_dev); 586 EXPORT_SYMBOL(pnp_activate_dev); 587 EXPORT_SYMBOL(pnp_disable_dev); 588 EXPORT_SYMBOL(pnp_resource_change); 589 EXPORT_SYMBOL(pnp_init_resource_table); 590