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