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