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 * 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_activate_dev - activates a PnP device for use 478 * @dev: pointer to the desired device 479 * 480 * does not validate or set resources so be careful. 481 */ 482 int pnp_activate_dev(struct pnp_dev *dev) 483 { 484 if (!dev) 485 return -EINVAL; 486 if (dev->active) { 487 return 0; /* the device is already active */ 488 } 489 490 /* ensure resources are allocated */ 491 if (pnp_auto_config_dev(dev)) 492 return -EBUSY; 493 494 if (!pnp_can_write(dev)) { 495 pnp_info("Device %s does not supported activation.", dev->dev.bus_id); 496 return -EINVAL; 497 } 498 499 if (dev->protocol->set(dev, &dev->res)<0) { 500 pnp_err("Failed to activate device %s.", dev->dev.bus_id); 501 return -EIO; 502 } 503 504 dev->active = 1; 505 pnp_info("Device %s activated.", dev->dev.bus_id); 506 507 return 1; 508 } 509 510 /** 511 * pnp_disable_dev - disables device 512 * @dev: pointer to the desired device 513 * 514 * inform the correct pnp protocol so that resources can be used by other devices 515 */ 516 int pnp_disable_dev(struct pnp_dev *dev) 517 { 518 if (!dev) 519 return -EINVAL; 520 if (!dev->active) { 521 return 0; /* the device is already disabled */ 522 } 523 524 if (!pnp_can_disable(dev)) { 525 pnp_info("Device %s does not supported disabling.", dev->dev.bus_id); 526 return -EINVAL; 527 } 528 if (dev->protocol->disable(dev)<0) { 529 pnp_err("Failed to disable device %s.", dev->dev.bus_id); 530 return -EIO; 531 } 532 533 dev->active = 0; 534 pnp_info("Device %s disabled.", dev->dev.bus_id); 535 536 /* release the resources so that other devices can use them */ 537 down(&pnp_res_mutex); 538 pnp_clean_resource_table(&dev->res); 539 up(&pnp_res_mutex); 540 541 return 1; 542 } 543 544 /** 545 * pnp_resource_change - change one resource 546 * @resource: pointer to resource to be changed 547 * @start: start of region 548 * @size: size of region 549 * 550 */ 551 void pnp_resource_change(struct resource *resource, unsigned long start, unsigned long size) 552 { 553 if (resource == NULL) 554 return; 555 resource->flags &= ~(IORESOURCE_AUTO | IORESOURCE_UNSET); 556 resource->start = start; 557 resource->end = start + size - 1; 558 } 559 560 561 EXPORT_SYMBOL(pnp_manual_config_dev); 562 EXPORT_SYMBOL(pnp_auto_config_dev); 563 EXPORT_SYMBOL(pnp_activate_dev); 564 EXPORT_SYMBOL(pnp_disable_dev); 565 EXPORT_SYMBOL(pnp_resource_change); 566 EXPORT_SYMBOL(pnp_init_resource_table); 567