1 /*- 2 * Copyright (c) 2000 Michael Smith 3 * Copyright (c) 2000 BSDi 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include <sys/cdefs.h> 29 __FBSDID("$FreeBSD$"); 30 31 #include "opt_acpi.h" 32 #include <sys/param.h> 33 #include <sys/kernel.h> 34 #include <sys/bus.h> 35 36 #include <machine/bus.h> 37 #include <machine/resource.h> 38 #include <sys/rman.h> 39 40 #include "acpi.h" 41 #include <dev/acpica/acpivar.h> 42 43 /* Hooks for the ACPI CA debugging infrastructure */ 44 #define _COMPONENT ACPI_BUS 45 ACPI_MODULE_NAME("RESOURCE") 46 47 /* 48 * Fetch a device's resources and associate them with the device. 49 * 50 * Note that it might be nice to also locate ACPI-specific resource items, such 51 * as GPE bits. 52 * 53 * We really need to split the resource-fetching code out from the 54 * resource-parsing code, since we may want to use the parsing 55 * code for _PRS someday. 56 */ 57 ACPI_STATUS 58 acpi_parse_resources(device_t dev, ACPI_HANDLE handle, 59 struct acpi_parse_resource_set *set) 60 { 61 ACPI_BUFFER buf; 62 ACPI_RESOURCE *res; 63 char *curr, *last; 64 ACPI_STATUS status; 65 void *context; 66 67 ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); 68 69 /* 70 * Special-case some devices that abuse _PRS/_CRS to mean 71 * something other than "I consume this resource". 72 * 73 * XXX do we really need this? It's only relevant once 74 * we start always-allocating these resources, and even 75 * then, the only special-cased device is likely to be 76 * the PCI interrupt link. 77 */ 78 79 /* Fetch the device's current resources. */ 80 buf.Length = ACPI_ALLOCATE_BUFFER; 81 if (ACPI_FAILURE((status = AcpiGetCurrentResources(handle, &buf)))) { 82 if (status != AE_NOT_FOUND) 83 printf("can't fetch resources for %s - %s\n", 84 acpi_name(handle), AcpiFormatException(status)); 85 return_ACPI_STATUS (status); 86 } 87 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "%s - got %ld bytes of resources\n", 88 acpi_name(handle), (long)buf.Length)); 89 set->set_init(dev, &context); 90 91 /* Iterate through the resources */ 92 curr = buf.Pointer; 93 last = (char *)buf.Pointer + buf.Length; 94 while (curr < last) { 95 res = (ACPI_RESOURCE *)curr; 96 curr += res->Length; 97 98 /* Handle the individual resource types */ 99 switch(res->Id) { 100 case ACPI_RSTYPE_END_TAG: 101 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "EndTag\n")); 102 curr = last; 103 break; 104 case ACPI_RSTYPE_FIXED_IO: 105 if (res->Data.FixedIo.RangeLength <= 0) 106 break; 107 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "FixedIo 0x%x/%d\n", 108 res->Data.FixedIo.BaseAddress, 109 res->Data.FixedIo.RangeLength)); 110 set->set_ioport(dev, context, 111 res->Data.FixedIo.BaseAddress, 112 res->Data.FixedIo.RangeLength); 113 break; 114 case ACPI_RSTYPE_IO: 115 if (res->Data.Io.RangeLength <= 0) 116 break; 117 if (res->Data.Io.MinBaseAddress == res->Data.Io.MaxBaseAddress) { 118 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Io 0x%x/%d\n", 119 res->Data.Io.MinBaseAddress, 120 res->Data.Io.RangeLength)); 121 set->set_ioport(dev, context, 122 res->Data.Io.MinBaseAddress, 123 res->Data.Io.RangeLength); 124 } else { 125 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Io 0x%x-0x%x/%d\n", 126 res->Data.Io.MinBaseAddress, 127 res->Data.Io.MaxBaseAddress, 128 res->Data.Io.RangeLength)); 129 set->set_iorange(dev, context, 130 res->Data.Io.MinBaseAddress, 131 res->Data.Io.MaxBaseAddress, 132 res->Data.Io.RangeLength, 133 res->Data.Io.Alignment); 134 } 135 break; 136 case ACPI_RSTYPE_FIXED_MEM32: 137 if (res->Data.FixedMemory32.RangeLength <= 0) 138 break; 139 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "FixedMemory32 0x%x/%d\n", 140 res->Data.FixedMemory32.RangeBaseAddress, 141 res->Data.FixedMemory32.RangeLength)); 142 set->set_memory(dev, context, 143 res->Data.FixedMemory32.RangeBaseAddress, 144 res->Data.FixedMemory32.RangeLength); 145 break; 146 case ACPI_RSTYPE_MEM32: 147 if (res->Data.Memory32.RangeLength <= 0) 148 break; 149 if (res->Data.Memory32.MinBaseAddress == 150 res->Data.Memory32.MaxBaseAddress) { 151 152 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory32 0x%x/%d\n", 153 res->Data.Memory32.MinBaseAddress, 154 res->Data.Memory32.RangeLength)); 155 set->set_memory(dev, context, 156 res->Data.Memory32.MinBaseAddress, 157 res->Data.Memory32.RangeLength); 158 } else { 159 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory32 0x%x-0x%x/%d\n", 160 res->Data.Memory32.MinBaseAddress, 161 res->Data.Memory32.MaxBaseAddress, 162 res->Data.Memory32.RangeLength)); 163 set->set_memoryrange(dev, context, 164 res->Data.Memory32.MinBaseAddress, 165 res->Data.Memory32.MaxBaseAddress, 166 res->Data.Memory32.RangeLength, 167 res->Data.Memory32.Alignment); 168 } 169 break; 170 case ACPI_RSTYPE_MEM24: 171 if (res->Data.Memory24.RangeLength <= 0) 172 break; 173 if (res->Data.Memory24.MinBaseAddress == 174 res->Data.Memory24.MaxBaseAddress) { 175 176 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory24 0x%x/%d\n", 177 res->Data.Memory24.MinBaseAddress, 178 res->Data.Memory24.RangeLength)); 179 set->set_memory(dev, context, res->Data.Memory24.MinBaseAddress, 180 res->Data.Memory24.RangeLength); 181 } else { 182 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Memory24 0x%x-0x%x/%d\n", 183 res->Data.Memory24.MinBaseAddress, 184 res->Data.Memory24.MaxBaseAddress, 185 res->Data.Memory24.RangeLength)); 186 set->set_memoryrange(dev, context, 187 res->Data.Memory24.MinBaseAddress, 188 res->Data.Memory24.MaxBaseAddress, 189 res->Data.Memory24.RangeLength, 190 res->Data.Memory24.Alignment); 191 } 192 break; 193 case ACPI_RSTYPE_IRQ: 194 /* 195 * from 1.0b 6.4.2 196 * "This structure is repeated for each separate interrupt 197 * required" 198 */ 199 set->set_irq(dev, context, res->Data.Irq.Interrupts, 200 res->Data.Irq.NumberOfInterrupts, res->Data.Irq.EdgeLevel, 201 res->Data.Irq.ActiveHighLow); 202 break; 203 case ACPI_RSTYPE_DMA: 204 /* 205 * from 1.0b 6.4.3 206 * "This structure is repeated for each separate dma channel 207 * required" 208 */ 209 set->set_drq(dev, context, res->Data.Dma.Channels, 210 res->Data.Dma.NumberOfChannels); 211 break; 212 case ACPI_RSTYPE_START_DPF: 213 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "start dependant functions\n")); 214 set->set_start_dependant(dev, context, 215 res->Data.StartDpf.CompatibilityPriority); 216 break; 217 case ACPI_RSTYPE_END_DPF: 218 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "end dependant functions\n")); 219 set->set_end_dependant(dev, context); 220 break; 221 case ACPI_RSTYPE_ADDRESS32: 222 if (res->Data.Address32.AddressLength <= 0) 223 break; 224 if (res->Data.Address32.ProducerConsumer != ACPI_CONSUMER) { 225 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 226 "ignored Address32 %s producer\n", 227 res->Data.Address32.ResourceType == ACPI_IO_RANGE ? 228 "IO" : "Memory")); 229 break; 230 } 231 if (res->Data.Address32.ResourceType != ACPI_MEMORY_RANGE && 232 res->Data.Address32.ResourceType != ACPI_IO_RANGE) { 233 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 234 "ignored Address32 for non-memory, non-I/O\n")); 235 break; 236 } 237 238 if (res->Data.Address32.MinAddressFixed == ACPI_ADDRESS_FIXED && 239 res->Data.Address32.MaxAddressFixed == ACPI_ADDRESS_FIXED) { 240 241 if (res->Data.Address32.ResourceType == ACPI_MEMORY_RANGE) { 242 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 243 "Address32/Memory 0x%x/%d\n", 244 res->Data.Address32.MinAddressRange, 245 res->Data.Address32.AddressLength)); 246 set->set_memory(dev, context, 247 res->Data.Address32.MinAddressRange, 248 res->Data.Address32.AddressLength); 249 } else { 250 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 251 "Address32/IO 0x%x/%d\n", 252 res->Data.Address32.MinAddressRange, 253 res->Data.Address32.AddressLength)); 254 set->set_ioport(dev, context, 255 res->Data.Address32.MinAddressRange, 256 res->Data.Address32.AddressLength); 257 } 258 } else { 259 if (res->Data.Address32.ResourceType == ACPI_MEMORY_RANGE) { 260 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 261 "Address32/Memory 0x%x-0x%x/%d\n", 262 res->Data.Address32.MinAddressRange, 263 res->Data.Address32.MaxAddressRange, 264 res->Data.Address32.AddressLength)); 265 set->set_memoryrange(dev, context, 266 res->Data.Address32.MinAddressRange, 267 res->Data.Address32.MaxAddressRange, 268 res->Data.Address32.AddressLength, 269 res->Data.Address32.Granularity); 270 } else { 271 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 272 "Address32/IO 0x%x-0x%x/%d\n", 273 res->Data.Address32.MinAddressRange, 274 res->Data.Address32.MaxAddressRange, 275 res->Data.Address32.AddressLength)); 276 set->set_iorange(dev, context, 277 res->Data.Address32.MinAddressRange, 278 res->Data.Address32.MaxAddressRange, 279 res->Data.Address32.AddressLength, 280 res->Data.Address32.Granularity); 281 } 282 } 283 break; 284 case ACPI_RSTYPE_ADDRESS16: 285 if (res->Data.Address16.AddressLength <= 0) 286 break; 287 if (res->Data.Address16.ProducerConsumer != ACPI_CONSUMER) { 288 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 289 "ignored Address16 %s producer\n", 290 res->Data.Address16.ResourceType == ACPI_IO_RANGE ? 291 "IO" : "Memory")); 292 break; 293 } 294 if (res->Data.Address16.ResourceType != ACPI_MEMORY_RANGE && 295 res->Data.Address16.ResourceType != ACPI_IO_RANGE) { 296 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 297 "ignored Address16 for non-memory, non-I/O\n")); 298 break; 299 } 300 301 if (res->Data.Address16.MinAddressFixed == ACPI_ADDRESS_FIXED && 302 res->Data.Address16.MaxAddressFixed == ACPI_ADDRESS_FIXED) { 303 304 if (res->Data.Address16.ResourceType == ACPI_MEMORY_RANGE) { 305 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 306 "Address16/Memory 0x%x/%d\n", 307 res->Data.Address16.MinAddressRange, 308 res->Data.Address16.AddressLength)); 309 set->set_memory(dev, context, 310 res->Data.Address16.MinAddressRange, 311 res->Data.Address16.AddressLength); 312 } else { 313 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 314 "Address16/IO 0x%x/%d\n", 315 res->Data.Address16.MinAddressRange, 316 res->Data.Address16.AddressLength)); 317 set->set_ioport(dev, context, 318 res->Data.Address16.MinAddressRange, 319 res->Data.Address16.AddressLength); 320 } 321 } else { 322 if (res->Data.Address16.ResourceType == ACPI_MEMORY_RANGE) { 323 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 324 "Address16/Memory 0x%x-0x%x/%d\n", 325 res->Data.Address16.MinAddressRange, 326 res->Data.Address16.MaxAddressRange, 327 res->Data.Address16.AddressLength)); 328 set->set_memoryrange(dev, context, 329 res->Data.Address16.MinAddressRange, 330 res->Data.Address16.MaxAddressRange, 331 res->Data.Address16.AddressLength, 332 res->Data.Address16.Granularity); 333 } else { 334 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 335 "Address16/IO 0x%x-0x%x/%d\n", 336 res->Data.Address16.MinAddressRange, 337 res->Data.Address16.MaxAddressRange, 338 res->Data.Address16.AddressLength)); 339 set->set_iorange(dev, context, 340 res->Data.Address16.MinAddressRange, 341 res->Data.Address16.MaxAddressRange, 342 res->Data.Address16.AddressLength, 343 res->Data.Address16.Granularity); 344 } 345 } 346 break; 347 case ACPI_RSTYPE_ADDRESS64: 348 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 349 "unimplemented Address64 resource\n")); 350 break; 351 case ACPI_RSTYPE_EXT_IRQ: 352 /* XXX special handling? */ 353 set->set_irq(dev, context,res->Data.ExtendedIrq.Interrupts, 354 res->Data.ExtendedIrq.NumberOfInterrupts, 355 res->Data.ExtendedIrq.EdgeLevel, 356 res->Data.ExtendedIrq.ActiveHighLow); 357 break; 358 case ACPI_RSTYPE_VENDOR: 359 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 360 "unimplemented VendorSpecific resource\n")); 361 break; 362 default: 363 break; 364 } 365 } 366 367 AcpiOsFree(buf.Pointer); 368 set->set_done(dev, context); 369 return_ACPI_STATUS (AE_OK); 370 } 371 372 /* 373 * Resource-set vectors used to attach _CRS-derived resources 374 * to an ACPI device. 375 */ 376 static void acpi_res_set_init(device_t dev, void **context); 377 static void acpi_res_set_done(device_t dev, void *context); 378 static void acpi_res_set_ioport(device_t dev, void *context, 379 u_int32_t base, u_int32_t length); 380 static void acpi_res_set_iorange(device_t dev, void *context, 381 u_int32_t low, u_int32_t high, 382 u_int32_t length, u_int32_t align); 383 static void acpi_res_set_memory(device_t dev, void *context, 384 u_int32_t base, u_int32_t length); 385 static void acpi_res_set_memoryrange(device_t dev, void *context, 386 u_int32_t low, u_int32_t high, 387 u_int32_t length, u_int32_t align); 388 static void acpi_res_set_irq(device_t dev, void *context, u_int32_t *irq, 389 int count, int trig, int pol); 390 static void acpi_res_set_drq(device_t dev, void *context, u_int32_t *drq, 391 int count); 392 static void acpi_res_set_start_dependant(device_t dev, void *context, 393 int preference); 394 static void acpi_res_set_end_dependant(device_t dev, void *context); 395 396 struct acpi_parse_resource_set acpi_res_parse_set = { 397 acpi_res_set_init, 398 acpi_res_set_done, 399 acpi_res_set_ioport, 400 acpi_res_set_iorange, 401 acpi_res_set_memory, 402 acpi_res_set_memoryrange, 403 acpi_res_set_irq, 404 acpi_res_set_drq, 405 acpi_res_set_start_dependant, 406 acpi_res_set_end_dependant 407 }; 408 409 struct acpi_res_context { 410 int ar_nio; 411 int ar_nmem; 412 int ar_nirq; 413 int ar_ndrq; 414 }; 415 416 static void 417 acpi_res_set_init(device_t dev, void **context) 418 { 419 struct acpi_res_context *cp; 420 421 if ((cp = AcpiOsAllocate(sizeof(*cp))) != NULL) { 422 bzero(cp, sizeof(*cp)); 423 *context = cp; 424 } 425 } 426 427 static void 428 acpi_res_set_done(device_t dev, void *context) 429 { 430 struct acpi_res_context *cp = (struct acpi_res_context *)context; 431 432 if (cp == NULL) 433 return; 434 AcpiOsFree(cp); 435 } 436 437 static void 438 acpi_res_set_ioport(device_t dev, void *context, u_int32_t base, 439 u_int32_t length) 440 { 441 struct acpi_res_context *cp = (struct acpi_res_context *)context; 442 443 if (cp == NULL) 444 return; 445 bus_set_resource(dev, SYS_RES_IOPORT, cp->ar_nio++, base, length); 446 } 447 448 static void 449 acpi_res_set_iorange(device_t dev, void *context, u_int32_t low, 450 u_int32_t high, u_int32_t length, u_int32_t align) 451 { 452 struct acpi_res_context *cp = (struct acpi_res_context *)context; 453 454 if (cp == NULL) 455 return; 456 device_printf(dev, "I/O range not supported\n"); 457 } 458 459 static void 460 acpi_res_set_memory(device_t dev, void *context, u_int32_t base, 461 u_int32_t length) 462 { 463 struct acpi_res_context *cp = (struct acpi_res_context *)context; 464 465 if (cp == NULL) 466 return; 467 468 bus_set_resource(dev, SYS_RES_MEMORY, cp->ar_nmem++, base, length); 469 } 470 471 static void 472 acpi_res_set_memoryrange(device_t dev, void *context, u_int32_t low, 473 u_int32_t high, u_int32_t length, u_int32_t align) 474 { 475 struct acpi_res_context *cp = (struct acpi_res_context *)context; 476 477 if (cp == NULL) 478 return; 479 device_printf(dev, "memory range not supported\n"); 480 } 481 482 static void 483 acpi_res_set_irq(device_t dev, void *context, u_int32_t *irq, int count, 484 int trig, int pol) 485 { 486 struct acpi_res_context *cp = (struct acpi_res_context *)context; 487 488 if (cp == NULL || irq == NULL) 489 return; 490 491 /* This implements no resource relocation. */ 492 if (count != 1) 493 return; 494 495 bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, *irq, 1); 496 BUS_CONFIG_INTR(dev, *irq, (trig == ACPI_EDGE_SENSITIVE) ? 497 INTR_TRIGGER_EDGE : INTR_TRIGGER_LEVEL, (pol == ACPI_ACTIVE_HIGH) ? 498 INTR_POLARITY_HIGH : INTR_POLARITY_LOW); 499 } 500 501 static void 502 acpi_res_set_drq(device_t dev, void *context, u_int32_t *drq, int count) 503 { 504 struct acpi_res_context *cp = (struct acpi_res_context *)context; 505 506 if (cp == NULL || drq == NULL) 507 return; 508 509 /* This implements no resource relocation. */ 510 if (count != 1) 511 return; 512 513 bus_set_resource(dev, SYS_RES_DRQ, cp->ar_ndrq++, *drq, 1); 514 } 515 516 static void 517 acpi_res_set_start_dependant(device_t dev, void *context, int preference) 518 { 519 struct acpi_res_context *cp = (struct acpi_res_context *)context; 520 521 if (cp == NULL) 522 return; 523 device_printf(dev, "dependant functions not supported\n"); 524 } 525 526 static void 527 acpi_res_set_end_dependant(device_t dev, void *context) 528 { 529 struct acpi_res_context *cp = (struct acpi_res_context *)context; 530 531 if (cp == NULL) 532 return; 533 device_printf(dev, "dependant functions not supported\n"); 534 } 535 536 /* 537 * Resource-owning placeholders. 538 * 539 * This code "owns" system resource objects that aren't 540 * otherwise useful to devices, and which shouldn't be 541 * considered "free". 542 * 543 * Note that some systems claim *all* of the physical address space 544 * with a PNP0C01 device, so we cannot correctly "own" system memory 545 * here (must be done in the SMAP handler on x86 systems, for 546 * example). 547 */ 548 549 static int acpi_sysresource_probe(device_t dev); 550 static int acpi_sysresource_attach(device_t dev); 551 552 static device_method_t acpi_sysresource_methods[] = { 553 /* Device interface */ 554 DEVMETHOD(device_probe, acpi_sysresource_probe), 555 DEVMETHOD(device_attach, acpi_sysresource_attach), 556 557 {0, 0} 558 }; 559 560 static driver_t acpi_sysresource_driver = { 561 "acpi_sysresource", 562 acpi_sysresource_methods, 563 0, 564 }; 565 566 static devclass_t acpi_sysresource_devclass; 567 DRIVER_MODULE(acpi_sysresource, acpi, acpi_sysresource_driver, 568 acpi_sysresource_devclass, 0, 0); 569 570 static int 571 acpi_sysresource_probe(device_t dev) 572 { 573 if (!acpi_disabled("sysresource") && acpi_MatchHid(dev, "PNP0C02")) 574 device_set_desc(dev, "system resource"); 575 else 576 return (ENXIO); 577 578 device_quiet(dev); 579 return (-100); 580 } 581 582 static int 583 acpi_sysresource_attach(device_t dev) 584 { 585 struct resource *res; 586 int i, rid; 587 588 /* 589 * Suck up all the resources that might have been assigned to us. 590 * Note that it's impossible to tell the difference between a 591 * resource that someone else has claimed, and one that doesn't 592 * exist. 593 */ 594 for (i = 0; i < 100; i++) { 595 rid = i; 596 res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, 0); 597 rid = i; 598 res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 0, ~0, 1, 0); 599 rid = i; 600 res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, 601 RF_SHAREABLE); 602 } 603 604 return (0); 605 } 606