1 /* 2 * resource.c - Contains functions for registering and analyzing resource information 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/module.h> 11 #include <linux/errno.h> 12 #include <linux/interrupt.h> 13 #include <linux/kernel.h> 14 #include <asm/io.h> 15 #include <asm/dma.h> 16 #include <asm/irq.h> 17 #include <linux/pci.h> 18 #include <linux/ioport.h> 19 #include <linux/init.h> 20 21 #include <linux/pnp.h> 22 #include "base.h" 23 24 static int pnp_reserve_irq[16] = { [0 ... 15] = -1 }; /* reserve (don't use) some IRQ */ 25 static int pnp_reserve_dma[8] = { [0 ... 7] = -1 }; /* reserve (don't use) some DMA */ 26 static int pnp_reserve_io[16] = { [0 ... 15] = -1 }; /* reserve (don't use) some I/O region */ 27 static int pnp_reserve_mem[16] = { [0 ... 15] = -1 }; /* reserve (don't use) some memory region */ 28 29 30 /* 31 * option registration 32 */ 33 34 static struct pnp_option * pnp_build_option(int priority) 35 { 36 struct pnp_option *option = pnp_alloc(sizeof(struct pnp_option)); 37 38 /* check if pnp_alloc ran out of memory */ 39 if (!option) 40 return NULL; 41 42 option->priority = priority & 0xff; 43 /* make sure the priority is valid */ 44 if (option->priority > PNP_RES_PRIORITY_FUNCTIONAL) 45 option->priority = PNP_RES_PRIORITY_INVALID; 46 47 return option; 48 } 49 50 struct pnp_option * pnp_register_independent_option(struct pnp_dev *dev) 51 { 52 struct pnp_option *option; 53 if (!dev) 54 return NULL; 55 56 option = pnp_build_option(PNP_RES_PRIORITY_PREFERRED); 57 58 /* this should never happen but if it does we'll try to continue */ 59 if (dev->independent) 60 pnp_err("independent resource already registered"); 61 dev->independent = option; 62 return option; 63 } 64 65 struct pnp_option * pnp_register_dependent_option(struct pnp_dev *dev, int priority) 66 { 67 struct pnp_option *option; 68 if (!dev) 69 return NULL; 70 71 option = pnp_build_option(priority); 72 73 if (dev->dependent) { 74 struct pnp_option *parent = dev->dependent; 75 while (parent->next) 76 parent = parent->next; 77 parent->next = option; 78 } else 79 dev->dependent = option; 80 return option; 81 } 82 83 int pnp_register_irq_resource(struct pnp_option *option, struct pnp_irq *data) 84 { 85 struct pnp_irq *ptr; 86 if (!option) 87 return -EINVAL; 88 if (!data) 89 return -EINVAL; 90 91 ptr = option->irq; 92 while (ptr && ptr->next) 93 ptr = ptr->next; 94 if (ptr) 95 ptr->next = data; 96 else 97 option->irq = data; 98 99 #ifdef CONFIG_PCI 100 { 101 int i; 102 103 for (i = 0; i < 16; i++) 104 if (test_bit(i, data->map)) 105 pcibios_penalize_isa_irq(i, 0); 106 } 107 #endif 108 return 0; 109 } 110 111 int pnp_register_dma_resource(struct pnp_option *option, struct pnp_dma *data) 112 { 113 struct pnp_dma *ptr; 114 if (!option) 115 return -EINVAL; 116 if (!data) 117 return -EINVAL; 118 119 ptr = option->dma; 120 while (ptr && ptr->next) 121 ptr = ptr->next; 122 if (ptr) 123 ptr->next = data; 124 else 125 option->dma = data; 126 127 return 0; 128 } 129 130 int pnp_register_port_resource(struct pnp_option *option, struct pnp_port *data) 131 { 132 struct pnp_port *ptr; 133 if (!option) 134 return -EINVAL; 135 if (!data) 136 return -EINVAL; 137 138 ptr = option->port; 139 while (ptr && ptr->next) 140 ptr = ptr->next; 141 if (ptr) 142 ptr->next = data; 143 else 144 option->port = data; 145 146 return 0; 147 } 148 149 int pnp_register_mem_resource(struct pnp_option *option, struct pnp_mem *data) 150 { 151 struct pnp_mem *ptr; 152 if (!option) 153 return -EINVAL; 154 if (!data) 155 return -EINVAL; 156 157 ptr = option->mem; 158 while (ptr && ptr->next) 159 ptr = ptr->next; 160 if (ptr) 161 ptr->next = data; 162 else 163 option->mem = data; 164 return 0; 165 } 166 167 static void pnp_free_port(struct pnp_port *port) 168 { 169 struct pnp_port *next; 170 171 while (port) { 172 next = port->next; 173 kfree(port); 174 port = next; 175 } 176 } 177 178 static void pnp_free_irq(struct pnp_irq *irq) 179 { 180 struct pnp_irq *next; 181 182 while (irq) { 183 next = irq->next; 184 kfree(irq); 185 irq = next; 186 } 187 } 188 189 static void pnp_free_dma(struct pnp_dma *dma) 190 { 191 struct pnp_dma *next; 192 193 while (dma) { 194 next = dma->next; 195 kfree(dma); 196 dma = next; 197 } 198 } 199 200 static void pnp_free_mem(struct pnp_mem *mem) 201 { 202 struct pnp_mem *next; 203 204 while (mem) { 205 next = mem->next; 206 kfree(mem); 207 mem = next; 208 } 209 } 210 211 void pnp_free_option(struct pnp_option *option) 212 { 213 struct pnp_option *next; 214 215 while (option) { 216 next = option->next; 217 pnp_free_port(option->port); 218 pnp_free_irq(option->irq); 219 pnp_free_dma(option->dma); 220 pnp_free_mem(option->mem); 221 kfree(option); 222 option = next; 223 } 224 } 225 226 227 /* 228 * resource validity checking 229 */ 230 231 #define length(start, end) (*(end) - *(start) + 1) 232 233 /* Two ranges conflict if one doesn't end before the other starts */ 234 #define ranged_conflict(starta, enda, startb, endb) \ 235 !((*(enda) < *(startb)) || (*(endb) < *(starta))) 236 237 #define cannot_compare(flags) \ 238 ((flags) & (IORESOURCE_UNSET | IORESOURCE_DISABLED)) 239 240 int pnp_check_port(struct pnp_dev * dev, int idx) 241 { 242 int tmp; 243 struct pnp_dev *tdev; 244 unsigned long *port, *end, *tport, *tend; 245 port = &dev->res.port_resource[idx].start; 246 end = &dev->res.port_resource[idx].end; 247 248 /* if the resource doesn't exist, don't complain about it */ 249 if (cannot_compare(dev->res.port_resource[idx].flags)) 250 return 1; 251 252 /* check if the resource is already in use, skip if the 253 * device is active because it itself may be in use */ 254 if(!dev->active) { 255 if (__check_region(&ioport_resource, *port, length(port,end))) 256 return 0; 257 } 258 259 /* check if the resource is reserved */ 260 for (tmp = 0; tmp < 8; tmp++) { 261 int rport = pnp_reserve_io[tmp << 1]; 262 int rend = pnp_reserve_io[(tmp << 1) + 1] + rport - 1; 263 if (ranged_conflict(port,end,&rport,&rend)) 264 return 0; 265 } 266 267 /* check for internal conflicts */ 268 for (tmp = 0; tmp < PNP_MAX_PORT && tmp != idx; tmp++) { 269 if (dev->res.port_resource[tmp].flags & IORESOURCE_IO) { 270 tport = &dev->res.port_resource[tmp].start; 271 tend = &dev->res.port_resource[tmp].end; 272 if (ranged_conflict(port,end,tport,tend)) 273 return 0; 274 } 275 } 276 277 /* check for conflicts with other pnp devices */ 278 pnp_for_each_dev(tdev) { 279 if (tdev == dev) 280 continue; 281 for (tmp = 0; tmp < PNP_MAX_PORT; tmp++) { 282 if (tdev->res.port_resource[tmp].flags & IORESOURCE_IO) { 283 if (cannot_compare(tdev->res.port_resource[tmp].flags)) 284 continue; 285 tport = &tdev->res.port_resource[tmp].start; 286 tend = &tdev->res.port_resource[tmp].end; 287 if (ranged_conflict(port,end,tport,tend)) 288 return 0; 289 } 290 } 291 } 292 293 return 1; 294 } 295 296 int pnp_check_mem(struct pnp_dev * dev, int idx) 297 { 298 int tmp; 299 struct pnp_dev *tdev; 300 unsigned long *addr, *end, *taddr, *tend; 301 addr = &dev->res.mem_resource[idx].start; 302 end = &dev->res.mem_resource[idx].end; 303 304 /* if the resource doesn't exist, don't complain about it */ 305 if (cannot_compare(dev->res.mem_resource[idx].flags)) 306 return 1; 307 308 /* check if the resource is already in use, skip if the 309 * device is active because it itself may be in use */ 310 if(!dev->active) { 311 if (check_mem_region(*addr, length(addr,end))) 312 return 0; 313 } 314 315 /* check if the resource is reserved */ 316 for (tmp = 0; tmp < 8; tmp++) { 317 int raddr = pnp_reserve_mem[tmp << 1]; 318 int rend = pnp_reserve_mem[(tmp << 1) + 1] + raddr - 1; 319 if (ranged_conflict(addr,end,&raddr,&rend)) 320 return 0; 321 } 322 323 /* check for internal conflicts */ 324 for (tmp = 0; tmp < PNP_MAX_MEM && tmp != idx; tmp++) { 325 if (dev->res.mem_resource[tmp].flags & IORESOURCE_MEM) { 326 taddr = &dev->res.mem_resource[tmp].start; 327 tend = &dev->res.mem_resource[tmp].end; 328 if (ranged_conflict(addr,end,taddr,tend)) 329 return 0; 330 } 331 } 332 333 /* check for conflicts with other pnp devices */ 334 pnp_for_each_dev(tdev) { 335 if (tdev == dev) 336 continue; 337 for (tmp = 0; tmp < PNP_MAX_MEM; tmp++) { 338 if (tdev->res.mem_resource[tmp].flags & IORESOURCE_MEM) { 339 if (cannot_compare(tdev->res.mem_resource[tmp].flags)) 340 continue; 341 taddr = &tdev->res.mem_resource[tmp].start; 342 tend = &tdev->res.mem_resource[tmp].end; 343 if (ranged_conflict(addr,end,taddr,tend)) 344 return 0; 345 } 346 } 347 } 348 349 return 1; 350 } 351 352 static irqreturn_t pnp_test_handler(int irq, void *dev_id, struct pt_regs *regs) 353 { 354 return IRQ_HANDLED; 355 } 356 357 int pnp_check_irq(struct pnp_dev * dev, int idx) 358 { 359 int tmp; 360 struct pnp_dev *tdev; 361 unsigned long * irq = &dev->res.irq_resource[idx].start; 362 363 /* if the resource doesn't exist, don't complain about it */ 364 if (cannot_compare(dev->res.irq_resource[idx].flags)) 365 return 1; 366 367 /* check if the resource is valid */ 368 if (*irq < 0 || *irq > 15) 369 return 0; 370 371 /* check if the resource is reserved */ 372 for (tmp = 0; tmp < 16; tmp++) { 373 if (pnp_reserve_irq[tmp] == *irq) 374 return 0; 375 } 376 377 /* check for internal conflicts */ 378 for (tmp = 0; tmp < PNP_MAX_IRQ && tmp != idx; tmp++) { 379 if (dev->res.irq_resource[tmp].flags & IORESOURCE_IRQ) { 380 if (dev->res.irq_resource[tmp].start == *irq) 381 return 0; 382 } 383 } 384 385 #ifdef CONFIG_PCI 386 /* check if the resource is being used by a pci device */ 387 { 388 struct pci_dev *pci = NULL; 389 for_each_pci_dev(pci) { 390 if (pci->irq == *irq) 391 return 0; 392 } 393 } 394 #endif 395 396 /* check if the resource is already in use, skip if the 397 * device is active because it itself may be in use */ 398 if(!dev->active) { 399 if (request_irq(*irq, pnp_test_handler, SA_INTERRUPT, "pnp", NULL)) 400 return 0; 401 free_irq(*irq, NULL); 402 } 403 404 /* check for conflicts with other pnp devices */ 405 pnp_for_each_dev(tdev) { 406 if (tdev == dev) 407 continue; 408 for (tmp = 0; tmp < PNP_MAX_IRQ; tmp++) { 409 if (tdev->res.irq_resource[tmp].flags & IORESOURCE_IRQ) { 410 if (cannot_compare(tdev->res.irq_resource[tmp].flags)) 411 continue; 412 if ((tdev->res.irq_resource[tmp].start == *irq)) 413 return 0; 414 } 415 } 416 } 417 418 return 1; 419 } 420 421 int pnp_check_dma(struct pnp_dev * dev, int idx) 422 { 423 #ifndef CONFIG_IA64 424 int tmp; 425 struct pnp_dev *tdev; 426 unsigned long * dma = &dev->res.dma_resource[idx].start; 427 428 /* if the resource doesn't exist, don't complain about it */ 429 if (cannot_compare(dev->res.dma_resource[idx].flags)) 430 return 1; 431 432 /* check if the resource is valid */ 433 if (*dma < 0 || *dma == 4 || *dma > 7) 434 return 0; 435 436 /* check if the resource is reserved */ 437 for (tmp = 0; tmp < 8; tmp++) { 438 if (pnp_reserve_dma[tmp] == *dma) 439 return 0; 440 } 441 442 /* check for internal conflicts */ 443 for (tmp = 0; tmp < PNP_MAX_DMA && tmp != idx; tmp++) { 444 if (dev->res.dma_resource[tmp].flags & IORESOURCE_DMA) { 445 if (dev->res.dma_resource[tmp].start == *dma) 446 return 0; 447 } 448 } 449 450 /* check if the resource is already in use, skip if the 451 * device is active because it itself may be in use */ 452 if(!dev->active) { 453 if (request_dma(*dma, "pnp")) 454 return 0; 455 free_dma(*dma); 456 } 457 458 /* check for conflicts with other pnp devices */ 459 pnp_for_each_dev(tdev) { 460 if (tdev == dev) 461 continue; 462 for (tmp = 0; tmp < PNP_MAX_DMA; tmp++) { 463 if (tdev->res.dma_resource[tmp].flags & IORESOURCE_DMA) { 464 if (cannot_compare(tdev->res.dma_resource[tmp].flags)) 465 continue; 466 if ((tdev->res.dma_resource[tmp].start == *dma)) 467 return 0; 468 } 469 } 470 } 471 472 return 1; 473 #else 474 /* IA64 hasn't legacy DMA */ 475 return 0; 476 #endif 477 } 478 479 480 #if 0 481 EXPORT_SYMBOL(pnp_register_dependent_option); 482 EXPORT_SYMBOL(pnp_register_independent_option); 483 EXPORT_SYMBOL(pnp_register_irq_resource); 484 EXPORT_SYMBOL(pnp_register_dma_resource); 485 EXPORT_SYMBOL(pnp_register_port_resource); 486 EXPORT_SYMBOL(pnp_register_mem_resource); 487 #endif /* 0 */ 488 489 490 /* format is: pnp_reserve_irq=irq1[,irq2] .... */ 491 492 static int __init pnp_setup_reserve_irq(char *str) 493 { 494 int i; 495 496 for (i = 0; i < 16; i++) 497 if (get_option(&str,&pnp_reserve_irq[i]) != 2) 498 break; 499 return 1; 500 } 501 502 __setup("pnp_reserve_irq=", pnp_setup_reserve_irq); 503 504 /* format is: pnp_reserve_dma=dma1[,dma2] .... */ 505 506 static int __init pnp_setup_reserve_dma(char *str) 507 { 508 int i; 509 510 for (i = 0; i < 8; i++) 511 if (get_option(&str,&pnp_reserve_dma[i]) != 2) 512 break; 513 return 1; 514 } 515 516 __setup("pnp_reserve_dma=", pnp_setup_reserve_dma); 517 518 /* format is: pnp_reserve_io=io1,size1[,io2,size2] .... */ 519 520 static int __init pnp_setup_reserve_io(char *str) 521 { 522 int i; 523 524 for (i = 0; i < 16; i++) 525 if (get_option(&str,&pnp_reserve_io[i]) != 2) 526 break; 527 return 1; 528 } 529 530 __setup("pnp_reserve_io=", pnp_setup_reserve_io); 531 532 /* format is: pnp_reserve_mem=mem1,size1[,mem2,size2] .... */ 533 534 static int __init pnp_setup_reserve_mem(char *str) 535 { 536 int i; 537 538 for (i = 0; i < 16; i++) 539 if (get_option(&str,&pnp_reserve_mem[i]) != 2) 540 break; 541 return 1; 542 } 543 544 __setup("pnp_reserve_mem=", pnp_setup_reserve_mem); 545